예제 #1
0
        public VM()
        {
            Interpreter = new InterpreterBackend(this);
            JIT         = new JITBackend(this);

            modules       = new Dictionary <string, Scope>();
            loadedModules = new Dictionary <string, NeoChunk>();

            frames            = new Stack <Frame>();
            importSearchPaths = new Stack <string>();

            NativeModuleLoader.LoadNativeModules(Assembly.GetExecutingAssembly());

            try {
                FFILib.Register(new [] { NeoString.ValueOf("mscorlib"), NeoString.ValueOf("System"), NeoString.ValueOf("neo") });

                baseLib = LoadSTDModule("std/base");

                PushFrame("base.neo", "___init", -1);
                baseLib.Get("___init").Call(new[] { new FFITypeProxy(this) });
                PopFrame();
            } catch (NeoError e) {
                PrintStackTrace(e);
                Environment.Exit(1);
            }
        }
예제 #2
0
        public NeoChunk LoadFile(string rawPath)
        {
            var path  = SanatizePath(rawPath);
            var lpath = path.Replace(".neo", "");

            if (!File.Exists(path))
            {
                throw new Exception($"file not found: {path} ({rawPath})");
            }
            if (loadedModules.ContainsKey(lpath))
            {
                // Console.WriteLine("HIT " + rawPath); // TODO: what was I debugging here?...
                return(loadedModules[lpath]);
            }
            // Console.WriteLine("MISS " + rawPath); // TODO: what was I debugging here?...

            importSearchPaths.Push(importSearchPath);
            importSearchPath = Directory.GetParent(path).FullName;

            var code  = File.ReadAllText(path);
            var name  = Path.GetFileName(path);
            var chunk = LoadString(code, name);

            chunk.Scope.Declare("__FILE__", VariableFlags.VAL);
            chunk.Scope.Set("__FILE__", NeoString.ValueOf(path));

            loadedModules[lpath] = chunk;

            importSearchPath = importSearchPaths.Pop();

            return(chunk);
        }
예제 #3
0
        public NeoChunk LoadFile(string rawPath)
        {
            var path = SanatizePath(rawPath);

            if (!File.Exists(path))
            {
                throw new Exception($"file not found: {rawPath}");
            }
            if (loadedModules.ContainsKey(path))
            {
                return(loadedModules[path]);
            }

            importSearchPaths.Push(importSearchPath);
            importSearchPath = Directory.GetParent(path).FullName;

            var code  = File.ReadAllText(path);
            var name  = Path.GetFileName(path);
            var chunk = LoadString(code, name);

            chunk.Scope.Declare("__FILE__", VariableFlags.FINAL);
            chunk.Scope.Set("__FILE__", NeoString.ValueOf(path));

            loadedModules[path.Replace(".neo", "")] = chunk;

            importSearchPath = importSearchPaths.Pop();

            return(chunk);
        }
예제 #4
0
 public static NeoValue TryCatch(NeoProcedure @try, NeoProcedure @catch)
 {
     try {
         return(@try.Call(new NeoValue[0]));
     } catch (NeoError e) {
         return(@catch.Call(new[] { NeoString.ValueOf(e.Message) }));
     }
 }
예제 #5
0
 public static NeoValue Type(NeoValue[] args)
 {
     if (args.Length != 1)
     {
         throw new NeoError("exit expects one argument");                              // @TODO @Untested
     }
     return(NeoString.ValueOf(args[0].Type));
 }
예제 #6
0
 public static NeoValue ToString(NeoValue[] args)
 {
     if (args.Length != 1)
     {
         throw new NeoError("toString expects a single argument");                              // @TODO @Untested
     }
     return(NeoString.ValueOf(args[0].ToNeoString()));
 }
예제 #7
0
 public static NeoValue ToLower(NeoValue[] args)
 {
     if (args.Length != 1)
     {
         throw new NeoError("lower expects a single string parameter");                      // @TODO @Untested
     }
     return(NeoString.ValueOf(args[0].CheckString().Value.ToLower()));
 }
예제 #8
0
        public static NeoValue ReadAllText(NeoValue[] args)
        {
            if (args.Length != 1)
            {
                throw new NeoError("readAllText expects a single string argument");                              //@TODO @Untested
            }
            var path = args[0].CheckString().Value;

            return(NeoString.ValueOf(File.ReadAllText(Path.GetFullPath(path))));
        }
예제 #9
0
        public static NeoValue ToChar(NeoValue[] args)
        {
            if (args.Length != 1)
            {
                throw new NeoError("char expects a single int parameter");                      // @TODO @Untested
            }
            var val = args[0].CheckInt().Value;

            return(NeoString.ValueOf(char.ToString((char)val)));
        }
예제 #10
0
        public static NeoValue GetParent(NeoValue[] args)
        {
            if (args.Length != 1)
            {
                throw new NeoError("getParent expects a single string argument");                              //@TODO @Untested
            }
            var path = args[0].CheckString().Value;

            return(NeoString.ValueOf(Directory.GetParent(Path.GetFullPath(path)).FullName));
        }
예제 #11
0
        public static NeoValue GetName(NeoValue[] args)
        {
            if (args.Length != 1)
            {
                throw new NeoError("getName expects a single string argument");                              //@TODO @Untested
            }
            var path = args[0].CheckString().Value;

            return(NeoString.ValueOf(Path.GetFileName(path)));
        }
예제 #12
0
        public void SetUpValue(string name)
        {
            if (!usedUpvalues.Contains(name))
            {
                usedUpvalues.Add(name);
            }

            WriteOpCode(OpCode.SET_UPVALUE);
            writer.Write(constants[NeoString.ValueOf(name)]);
        }
예제 #13
0
        public void Run(string file, string[] args)
        {
            try {
                LoadEnvironment();

                var path = Path.GetFullPath(file);
                sourceRoot = Directory.GetParent(path).FullName;


                if (Verbose)
                {
                    Console.WriteLine($"Source Root: {sourceRoot}");
                    Console.WriteLine("Extra Seach Paths:");
                    foreach (var p in extraSourceSearchPaths)
                    {
                        Console.WriteLine($"    {p}");
                    }
                }


                if (Verbose)
                {
                    Console.WriteLine($"Main File: {path}");
                }
                var chunk = LoadFile(path);

                var mainv = chunk.Scope.Get("main");
                if (!mainv.IsProcedure)
                {
                    Console.WriteLine("No 'main' procedure found");
                    return;
                }
                var main = mainv.CheckProcedure();

                ((NeoBackendProcedure)main).JIT();

                var argsa = new NeoArray();
                foreach (var arg in args)
                {
                    argsa.Insert(NeoString.ValueOf(arg));
                }

                PushFrame(chunk.Chunk.Name, main.Name(), -1);
                main.Call(new[] { argsa });
                PopFrame();
            } catch (NeoError e) {
                PrintStackTrace(e);
                Environment.Exit(1);
            } catch (StackOverflowException e) {
                PrintStackTrace(e);
                Environment.Exit(1);
            }
        }
예제 #14
0
파일: FFILib.cs 프로젝트: sci4me/Neo-old
 public static NeoValue ToNeo(object v)
 {
     if (v == null)
     {
         return(NeoNil.NIL);
     }
     else if (v is Int32 i)
     {
         return(NeoInt.ValueOf(i));
     }
     else if (v is Int64 l)
     {
         return(NeoInt.ValueOf((int)l));
     }
     else if (v is Single f)
     {
         return(NeoFloat.ValueOf(f));
     }
     else if (v is Double d)
     {
         return(NeoFloat.ValueOf(d));
     }
     else if (v is Boolean b)
     {
         return(NeoBool.ValueOf(b));
     }
     else if (v is String s)
     {
         return(NeoString.ValueOf(s));
     }
     else if (v is object[] a)
     {
         // @TODO: is this where we want to do this? or do we just want an FFITypeProxy?
         var r = new NeoArray();
         foreach (object o in a)
         {
             r.Insert(ToNeo(o));
         }
         return(r);
     }
     else if (v is Dictionary <object, object> m)
     {
         throw new NotImplementedException();
     }
     else
     {
         return(new FFITypeProxy(v));
     }
 }
예제 #15
0
        public static NeoValue List(NeoValue[] args)
        {
            if (args.Length != 1)
            {
                throw new NeoError("list expects a single string argument");                              //@TODO @Untested
            }
            var path   = args[0].CheckString().Value;
            var result = new NeoArray();

            foreach (var file in Directory.GetFiles(Path.GetFullPath(path)))
            {
                result.Insert(NeoString.ValueOf(file));
            }
            return(result);
        }
예제 #16
0
        public void VisitEnum(EnumNode node)
        {
            UpdateLine(node);
            asm.NewObject();

            var elements = node.Elements.ToArray();

            for (var i = 0; i < elements.Length; i++)
            {
                asm.Dup();
                asm.PushConstant(NeoString.ValueOf(elements[i]));
                asm.PushConstant(NeoInt.ValueOf(i));
                asm.Set();

                asm.Dup();
                asm.PushConstant(NeoInt.ValueOf(i));
                asm.PushConstant(NeoString.ValueOf(elements[i]));
                asm.Set();
            }

            asm.Frozen();
        }
예제 #17
0
파일: Procedure.cs 프로젝트: sci4me/Neo-old
        internal Procedure(BinaryReader reader)
        {
            Name     = reader.ReadString();
            Exported = reader.ReadBoolean();

            UpValues = new string[reader.ReadInt32()];
            for (var i = 0; i < UpValues.Length; i++)
            {
                UpValues[i] = reader.ReadString();
            }

            Parameters = new Parameter[reader.ReadInt32()];
            for (var i = 0; i < Parameters.Length; i++)
            {
                Parameters[i] = new Parameter(reader.ReadString(), reader.ReadBoolean());
            }

            Varargs = reader.ReadBoolean();

            Lines = new LineRange[reader.ReadInt32()];
            for (var i = 0; i < Lines.Length; i++)
            {
                Lines[i] = new LineRange(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
            }

            Line = reader.ReadInt32();

            Instructions = new byte[reader.ReadInt32()];
            for (var i = 0; i < Instructions.Length; i++)
            {
                Instructions[i] = reader.ReadByte();
            }

            Constants = new NeoValue[reader.ReadInt32()];
            for (var i = 0; i < Constants.Length; i++)
            {
                var type = reader.ReadByte();
                switch (type)
                {
                case (byte)ConstantType.STRING:
                    Constants[i] = NeoString.ValueOf(reader.ReadString());
                    break;

                case (byte)ConstantType.INT:
                    Constants[i] = NeoInt.ValueOf(reader.ReadInt32());
                    break;

                case (byte)ConstantType.FLOAT:
                    Constants[i] = NeoFloat.ValueOf(reader.ReadDouble());
                    break;

                default:
                    throw new Exception("invalid chunk");
                }
            }

            Procedures = new Procedure[reader.ReadInt32()];
            for (var i = 0; i < Procedures.Length; i++)
            {
                Procedures[i] = new Procedure(reader);
            }
        }
예제 #18
0
 public void Closure(string proc)
 {
     WriteOpCode(OpCode.CLOSURE);
     writer.Write(constants[NeoString.ValueOf(proc)]);
 }
예제 #19
0
 public void Close(string name)
 {
     WriteOpCode(OpCode.CLOSE);
     writer.Write(constants[NeoString.ValueOf(name)]);
 }
예제 #20
0
 public void VisitString(StringNode node)
 {
     UpdateLine(node);
     asm.PushConstant(NeoString.ValueOf(node.Value));
 }
예제 #21
0
        public NeoValue Call(NeoValue[] arguments)
        {
            var scope = new Scope(ParentScope);
            var level = scope.Level;

            var pargs = new List <NeoValue>();

            foreach (var arg in arguments)
            {
                if (arg is NeoSpreadValue va)
                {
                    for (var i = 0; i < va.Array.Count; i++)
                    {
                        pargs.Add(va.Array[i]);
                    }
                }
                else
                {
                    pargs.Add(arg);
                }
            }

            var varargs   = new NeoArray();
            var extraArgs = pargs.Count - Procedure.Parameters.Length;

            if (extraArgs > 0)
            {
                for (var i = 0; i < extraArgs; i++)
                {
                    varargs.Insert(pargs[Procedure.Parameters.Length + i]);
                }
            }

            for (var i = 0; i < Procedure.Parameters.Length; i++)
            {
                var name = Procedure.Parameters[i].Name;
                scope.Declare(name, VariableFlags.NONE);

                var value = i < pargs.Count ? pargs[i] : NeoNil.NIL;

                if (Procedure.Parameters[i].Frozen)
                {
                    value = value.Frozen();
                }

                scope.Set(name, value);
            }

            var code  = Procedure.Instructions;
            var ip    = 4;
            var stack = new Stack <NeoValue>();

            var rootScopeLevel = scope.Level;

            var openUps = new Dictionary <string, UpValue>();

            var defers = new Stack <NeoProcedure>();

            byte ReadByte() => code[ip++];
            OpCode ReadOpCode() => (OpCode)ReadByte();
            short ReadShort() => (short)(ReadByte() | (ReadByte() << 8));
            int ReadInt() => ReadByte() | (ReadByte() << 8) | (ReadByte() << 16) | (ReadByte() << 24);
            NeoValue ReadConstant() => Procedure.Constants[ReadInt()];

            while (ip < code.Length)
            {
                var op = ReadOpCode();

                try {
                    switch (op)
                    {
                    case OpCode.NOP:
                        break;

                    case OpCode.INC: {
                        stack.Push(stack.Pop().Inc());
                    }
                    break;

                    case OpCode.DEC: {
                        stack.Push(stack.Pop().Dec());
                    }
                    break;

                    case OpCode.ADD: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Add(b));
                    }
                    break;

                    case OpCode.SUB: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Sub(b));
                    }
                    break;

                    case OpCode.MUL: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Mul(b));
                    }
                    break;

                    case OpCode.DIV: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Div(b));
                    }
                    break;

                    case OpCode.POW: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Pow(b));
                    }
                    break;

                    case OpCode.MOD: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Mod(b));
                    }
                    break;

                    case OpCode.LSH: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Lsh(b));
                    }
                    break;

                    case OpCode.RSH: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Rsh(b));
                    }
                    break;

                    case OpCode.BIT_NOT: {
                        stack.Push(stack.Pop().BitNot());
                    }
                    break;

                    case OpCode.BIT_AND: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.BitAnd(b));
                    }
                    break;

                    case OpCode.BIT_OR: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.BitOr(b));
                    }
                    break;

                    case OpCode.BIT_XOR: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.BitXor(b));
                    }
                    break;

                    case OpCode.NOT: {
                        stack.Push(stack.Pop().Not());
                    }
                    break;

                    case OpCode.NEG: {
                        stack.Push(stack.Pop().Neg());
                    }
                    break;

                    case OpCode.CONCAT: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Concat(b));
                    }
                    break;

                    case OpCode.LENGTH: {
                        stack.Push(stack.Pop().Length());
                    }
                    break;

                    case OpCode.ARRAY_NEW: {
                        stack.Push(new NeoArray());
                    }
                    break;

                    case OpCode.ARRAY_ADD: {
                        var element = stack.Pop();
                        var array   = stack.Pop().CheckArray();
                        array.Insert(element);
                    }
                    break;

                    case OpCode.OBJECT_NEW: {
                        stack.Push(new NeoObject());
                    }
                    break;

                    case OpCode.OBJECT_INDEX: {
                        var index = stack.Pop().CheckInt();
                        var obj   = stack.Pop().CheckObject();
                        stack.Push(obj.Index(index.Value));
                        stack.Push(obj.Get(obj.Index(index.Value)));
                    }
                    break;

                    case OpCode.GET: {
                        var key = stack.Pop();
                        var obj = stack.Pop();
                        stack.Push(obj.Get(key));
                    }
                    break;

                    case OpCode.SET: {
                        var value = stack.Pop();
                        var key   = stack.Pop();
                        var obj   = stack.Pop();
                        obj.Set(key, value);
                    }
                    break;

                    case OpCode.SLICE: {
                        var end   = stack.Pop();
                        var start = stack.Pop();
                        stack.Push(stack.Pop().Slice(start, end));
                    }
                    break;

                    case OpCode.EQ: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Eq(b));
                    }
                    break;

                    case OpCode.NE: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Ne(b));
                    }
                    break;

                    case OpCode.DEEP_EQ: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.DeepEq(b));
                    }
                    break;

                    case OpCode.DEEP_NE: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.DeepNe(b));
                    }
                    break;

                    case OpCode.LT: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Lt(b));
                    }
                    break;

                    case OpCode.GT: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Gt(b));
                    }
                    break;

                    case OpCode.LTE: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Lte(b));
                    }
                    break;

                    case OpCode.GTE: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(a.Gte(b));
                    }
                    break;

                    case OpCode.CMP: {
                        var b = stack.Pop();
                        var a = stack.Pop();
                        stack.Push(NeoInt.ValueOf(a.Compare(b)));
                    }
                    break;

                    case OpCode.JUMP: {
                        ip = ReadInt();
                    }
                    break;

                    case OpCode.JUMP_IF: {
                        var addr = ReadInt();
                        if (stack.Pop().CheckBool().Value)
                        {
                            ip = addr;
                        }
                    }
                    break;

                    case OpCode.CALL: {
                        var line  = Procedure.FindLine(ip);
                        var nargs = ReadShort();

                        var args = new NeoValue[nargs];
                        for (var i = nargs - 1; i >= 0; i--)
                        {
                            args[i] = stack.Pop();
                        }

                        var callee = stack.Pop();
                        if (callee.IsProcedure)
                        {
                            var proc = callee.CheckProcedure();
                            VM.PushFrame(proc.ChunkName(), proc.Name(), line);
                            stack.Push(proc.Call(args));
                            VM.PopFrame();
                        }
                        else
                        {
                            VM.PushFrame("<unknown>", "<unknown>", line);
                            stack.Push(callee.Call(args));
                            VM.PopFrame();
                        }
                    }
                    break;

                    case OpCode.RETURN: {
                        foreach (var up in openUps.Values)
                        {
                            up.Close();
                        }

                        NeoValue rvalue = null;
                        if (ReadByte() == 1)
                        {
                            rvalue = stack.Pop();
                        }
                        else
                        {
                            if (stack.Count > 0)
                            {
                                throw new Exception("VM error: stack not empty");
                            }

                            rvalue = NeoNil.NIL;
                        }

                        while (defers.Count > 0)
                        {
                            defers.Pop().Call(new NeoValue[0]);
                        }

                        return(rvalue);
                    }

                    case OpCode.DEFER: {
                        defers.Push(stack.Pop().CheckProcedure());
                    }
                    break;

                    case OpCode.VARARGS: {
                        if (!Procedure.Varargs)
                        {
                            stack.Push(NeoNil.NIL);
                        }
                        else
                        {
                            stack.Push(varargs);
                        }
                    }
                    break;

                    case OpCode.PUSH_TRUE: {
                        stack.Push(NeoBool.TRUE);
                    }
                    break;

                    case OpCode.PUSH_FALSE: {
                        stack.Push(NeoBool.FALSE);
                    }
                    break;

                    case OpCode.PUSH_NIL: {
                        stack.Push(NeoNil.NIL);
                    }
                    break;

                    case OpCode.PUSH_CONSTANT: {
                        stack.Push(ReadConstant());
                    }
                    break;

                    case OpCode.DUP: {
                        var a = stack.Pop();
                        stack.Push(a);
                        stack.Push(a);
                    }
                    break;

                    case OpCode.SWAP: {
                        var a = stack.Pop();
                        var b = stack.Pop();
                        stack.Push(a);
                        stack.Push(b);
                    }
                    break;

                    case OpCode.POP: {
                        stack.Pop();
                    }
                    break;

                    case OpCode.CLOSURE: {
                        var name = ReadConstant().CheckString().Value;
                        var proc = Procedure.Procedures.First(p => p.Name == name);

                        var upvalues = new UpValue[proc.UpValues.Length];
                        for (var i = 0; i < upvalues.Length; i++)
                        {
                            var pop = ReadOpCode();
                            if (pop != OpCode.GET_LOCAL && pop != OpCode.GET_UPVALUE)
                            {
                                throw new Exception(pop.ToString());
                            }

                            var upname = ReadConstant().CheckString().Value;

                            switch (pop)
                            {
                            case OpCode.GET_LOCAL: {
                                if (!openUps.ContainsKey(upname))
                                {
                                    openUps[upname] = new UpValue(scope, upname);
                                }
                                upvalues[i] = openUps[upname];
                            }
                            break;

                            case OpCode.GET_UPVALUE: {
                                upvalues[i] = this.upvalues.First(up => up.Name == upname);
                            }
                            break;
                            }
                        }

                        stack.Push(new NeoBackendProcedure(VM, VM.Interpreter.Compile(scope, Chunk, proc, upvalues)));
                    }
                    break;

                    case OpCode.CLOSE: {
                        var name = ReadConstant().CheckString().Value;
                        if (openUps.ContainsKey(name))
                        {
                            openUps[name].Close();
                            openUps.Remove(name);
                        }
                    }
                    break;

                    case OpCode.GET_LOCAL: {;
                                            stack.Push(scope.Get(ReadConstant().CheckString().Value)); }
                                            break;

                    case OpCode.SET_LOCAL: {
                        var name  = ReadConstant().CheckString().Value;
                        var value = stack.Pop();
                        scope.Set(name, value);
                    }
                    break;

                    case OpCode.GET_GLOBAL: {
                        stack.Push(ParentScope.Get(ReadConstant().CheckString().Value));
                    }
                    break;

                    case OpCode.SET_GLOBAL: {
                        ParentScope.Set(ReadConstant().CheckString().Value, stack.Pop());
                    }
                    break;

                    case OpCode.GET_UPVALUE: {
                        var name = ReadConstant().CheckString().Value;
                        var up   = upvalues.First(u => u.Name == name);
                        stack.Push(up.Get());
                    }
                    break;

                    case OpCode.SET_UPVALUE: {
                        var name = ReadConstant().CheckString().Value;

                        var index = 0;
                        for (var i = 0; i < upvalues.Length; i++)
                        {
                            if (upvalues[i].Name == name)
                            {
                                index = i;
                                break;
                            }
                        }

                        upvalues[index].Set(stack.Pop());
                    }
                    break;

                    case OpCode.SPREAD: {
                        stack.Push(new NeoSpreadValue(stack.Pop().CheckArray()));
                    }
                    break;

                    case OpCode.FROZEN: {
                        stack.Push(stack.Pop().Frozen());
                    }
                    break;

                    case OpCode.TRY: {
                        var @catch = stack.Pop().CheckProcedure();
                        var @try   = stack.Pop().CheckProcedure();

                        NeoValue r;

                        try {
                            r = @try.Call(new NeoValue[0]);
                        } catch (NeoError e) {
                            r = @catch.Call(new[] { NeoString.ValueOf(e.Message) });
                        }

                        if (!r.IsNil)
                        {
                            foreach (var up in openUps.Values)
                            {
                                up.Close();
                            }

                            while (defers.Count > 0)
                            {
                                defers.Pop().Call(new NeoValue[0]);
                            }

                            return(r);
                        }
                    }
                    break;

                    case OpCode.THROW: {
                        var line = Procedure.FindLine(ip);
                        throw new NeoError(stack.Pop().CheckString().Value, line);
                    }

                    case OpCode.DECLARE: {
                        var name  = ReadConstant().CheckString().Value;
                        var flags = ReadByte();
                        scope.Declare(name, (VariableFlags)flags);
                    }
                    break;

                    case OpCode.PUSH_SCOPE: {
                        scope = new Scope(scope);
                    }
                    break;

                    case OpCode.POP_SCOPE: {
                        scope = scope.Parent;
                    }
                    break;

                    default: {
                        throw new Exception($"Unexpected opcode: {op}");
                    }
                    }
                } catch (NeoError e) {
                    if (e.Line == -1)
                    {
                        e.Line = Procedure.FindLine(ip);
                    }
                    throw e;
                }
            }

            throw new Exception("VM error");
        }
예제 #22
0
 public void Declare(string name, VariableFlags flags)
 {
     WriteOpCode(OpCode.DECLARE);
     writer.Write(constants[NeoString.ValueOf(name)]);
     writer.Write((byte)flags);
 }
예제 #23
0
 public void SetGlobal(string name)
 {
     WriteOpCode(OpCode.SET_GLOBAL);
     writer.Write(constants[NeoString.ValueOf(name)]);
 }
예제 #24
0
 public void SetLocal(string name)
 {
     WriteOpCode(OpCode.SET_LOCAL);
     writer.Write(constants[NeoString.ValueOf(name)]);
 }