Example #1
0
 static int RunFile(string path)
 {
     if (File.Exists(path))
     {
         _loadedFile = path;
         string source = File.ReadAllText(path);
         SophieVM vm = new SophieVM { LoadModuleFn = LoadModule };
         return (int)vm.Interpret(path, source);
     }
     return 66; // File Not Found
 }
Example #2
0
        static void RunRepl()
        {
            SophieVM vm = new SophieVM();

            Console.WriteLine("-- sophie v0.0.0");

            string line = "";

            for (; line != "/exit"; )
            {
                Console.Write("> ");
                line = Console.ReadLine();

                // TODO: Handle failure.
                vm.Interpret("Prompt", line);
            }
        }
Example #3
0
 static bool WriteString(SophieVM vm, Obj[] stack, int argStart)
 {
     if (stack[argStart + 1] != null && stack[argStart + 1].Type == ObjType.Obj)
     {
         string s = stack[argStart + 1].ToString();
         Console.Write(s);
     }
     stack[argStart] = Obj.Null;
     return true;
 }
Example #4
0
 static bool Time(SophieVM vm, Obj[] stack, int argStart)
 {
     stack[argStart] = new Obj((double)DateTime.Now.Ticks / 10000000);
     return true;
 }
Example #5
0
 static bool Read(SophieVM vm, Obj[] stack, int argStart)
 {
     stack[argStart] = Obj.MakeString(Console.ReadLine());
     if (((ObjString)stack[argStart]).Str == "")
     {
         stack[argStart] = Obj.Null;
     }
     return true;
 }
Example #6
0
 public static void LoadSystemLibrary(SophieVM vm)
 {
     vm.Interpret("", SystemLibSource);
     ObjClass system = (ObjClass)vm.FindVariable("System");
     vm.Primitive(system.ClassObj, "writeString_(_)", WriteString);
     vm.Primitive(system.ClassObj, "read", Read);
     vm.Primitive(system.ClassObj, "clock", Clock);
     vm.Primitive(system.ClassObj, "time", Time);
 }
Example #7
0
        public static string DumpByteCode(SophieVM vm, ObjFn fn)
        {
            string s = "";
            int ip = 0;
            byte[] bytecode = fn.Bytecode;
            while (ip < bytecode.Length)
            {
                s += ip + ": ";
                Instruction instruction = (Instruction)bytecode[ip++];
                s += (instruction + " ");
                switch (instruction)
                {
                    case Instruction.Null:
                    case Instruction.False:
                    case Instruction.True:
                    case Instruction.Zero:
                    case Instruction.One:
                    case Instruction.Pop:
                    case Instruction.Dup:
                    case Instruction.CloseUpvalue:
                    case Instruction.Return:
                    case Instruction.End:
                    case Instruction.LoadLocal0:
                    case Instruction.LoadLocal1:
                    case Instruction.LoadLocal2:
                    case Instruction.LoadLocal3:
                    case Instruction.LoadLocal4:
                    case Instruction.LoadLocal5:
                    case Instruction.LoadLocal6:
                    case Instruction.LoadLocal7:
                    case Instruction.LoadLocal8:
                        s += ("\n");
                        break;

                    case Instruction.LoadLocal:
                    case Instruction.StoreLocal:
                    case Instruction.LoadUpvalue:
                    case Instruction.StoreUpvalue:
                    case Instruction.LoadFieldThis:
                    case Instruction.StoreFieldThis:
                    case Instruction.LoadField:
                    case Instruction.StoreField:
                    case Instruction.Class:
                    case Instruction.SmallConstant:
                        s += (bytecode[ip++] + "\n");
                        break;

                    case Instruction.Call0:
                    case Instruction.Call1:
                    case Instruction.Call2:
                    case Instruction.Call3:
                    case Instruction.Call4:
                    case Instruction.Call5:
                    case Instruction.Call6:
                    case Instruction.Call7:
                    case Instruction.Call8:
                    case Instruction.Call9:
                    case Instruction.Call10:
                    case Instruction.Call11:
                    case Instruction.Call12:
                    case Instruction.Call13:
                    case Instruction.Call14:
                    case Instruction.Call15:
                    case Instruction.Call16:
                        int method = (bytecode[ip] << 8) + bytecode[ip + 1];
                        s += vm.MethodNames[method] + "\n";
                        ip += 2;
                        break;
                    case Instruction.Constant:
                    case Instruction.LoadModuleVar:
                    case Instruction.StoreModuleVar:
                    case Instruction.Jump:
                    case Instruction.Loop:
                    case Instruction.JumpIf:
                    case Instruction.And:
                    case Instruction.Or:
                    case Instruction.MethodInstance:
                    case Instruction.MethodStatic:
                    case Instruction.LoadModule:
                        int method1 = (bytecode[ip] << 8) + bytecode[ip + 1];
                        s += method1 + "\n";
                        ip += 2;
                        break;

                    case Instruction.Super0:
                    case Instruction.Super1:
                    case Instruction.Super2:
                    case Instruction.Super3:
                    case Instruction.Super4:
                    case Instruction.Super5:
                    case Instruction.Super6:
                    case Instruction.Super7:
                    case Instruction.Super8:
                    case Instruction.Super9:
                    case Instruction.Super10:
                    case Instruction.Super11:
                    case Instruction.Super12:
                    case Instruction.Super13:
                    case Instruction.Super14:
                    case Instruction.Super15:
                    case Instruction.Super16:
                    case Instruction.ImportVariable:
                        s += (bytecode[ip++]);
                        s += (" ");
                        s += (bytecode[ip++]);
                        s += (" ");
                        s += (bytecode[ip++]);
                        s += (" ");
                        s += (bytecode[ip++] + "\n");
                        break;

                    case Instruction.Closure:
                        {
                            int constant = (bytecode[ip + 1] << 8) | bytecode[ip + 2];
                            ObjFn loadedFn = (ObjFn)fn.Constants[constant];

                            // There are two bytes for the constant, then two for each upvalue.
                            int j = 2 + (loadedFn.NumUpvalues * 2);
                            while (j > 0)
                            {
                                s += (bytecode[ip++]);
                                s += (" ");
                                j--;
                            }
                            s += "\n";
                        }
                        break;
                }
            }
            return s;
        }
Example #8
0
        public static ObjFn Compile(SophieVM vm, ObjModule module, string sourcePath, string source, bool printErrors)
        {
            Parser parser = new Parser
            {
                Vm = vm,
                Module = module,
                SourcePath = sourcePath,
                Source = source,
                TokenStart = 0,
                CurrentChar = 0,
                CurrentLine = 1,
                Current = { Type = TokenType.Error, Start = 0, Length = 0, Line = 0 },
                PrintErrors = printErrors,
                HasError = false,
                Raw = ""
            };

            Compiler compiler = new Compiler(parser, null, true);

            // Read the first token.
            compiler.NextToken();

            compiler.IgnoreNewlines();

            while (!compiler.Match(TokenType.Eof))
            {
                compiler.Definition();

                // If there is no newline, it must be the end of the block on the same line.
                if (!compiler.MatchLine())
                {
                    compiler.Consume(TokenType.Eof, "Expect end of file.");
                    break;
                }
            }

            compiler.Emit(Instruction.Null);
            compiler.Emit(Instruction.Return);

            // See if there are any implicitly declared module-level variables that never
            // got an explicit definition.
            // TODO: It would be nice if the error was on the line where it was used.
            for (int i = 0; i < parser.Module.Variables.Count; i++)
            {
                ModuleVariable t = parser.Module.Variables[i];
                if (t.Container == Obj.Undefined)
                {
                    compiler.Error(string.Format("Variable '{0}' is used but not defined.", t.Name));
                }
            }

            return compiler.EndCompiler();
        }
Example #9
0
 // Creates a string containing an appropriate method not found error for a
 // method with [symbol] on [classObj].
 static void MethodNotFound(SophieVM vm, ObjClass classObj, int symbol)
 {
     vm.Fiber.Error = Obj.MakeString(string.Format("{0} does not implement '{1}'.", classObj.Name, vm.MethodNames[symbol]));
 }