Esempio n. 1
0
        public static VM_t New(compiler.Bytecode bytecode)
        {
            Object.CompiledFunction mainFn = new Object.CompiledFunction {
                Instructions = bytecode.Instructions
            };
            Object.Closure mainClosure = new Object.Closure {
                Fn = mainFn
            };
            Frame_t mainFrame = Frame.NewFrame(mainClosure, 0);

            Frame_t[] frames = new Frame_t[MaxFrames];
            frames[0] = mainFrame;

            return(new VM_t
            {
                constants = bytecode.Constants,

                stack = new List <Object.Object>(new Object.Object[StackSize]),
                sp = 0,

                globals = new List <Object.Object>(new Object.Object[GlobalSize]),

                frames = frames,
                frameIndex = 1,
            });
        }
Esempio n. 2
0
        public static Frame_t NewFrame(Object.Closure cl, int basePointer)
        {
            Frame_t f = new Frame_t
            {
                cl          = cl,
                ip          = -1,
                basePointer = basePointer,
            };

            return(f);
        }
Esempio n. 3
0
        static error callClosure(Object.Closure cl, int numArgs)
        {
            if (numArgs != cl.Fn.NumParameters)
            {
                return(string.Format("wrong number of arguments: want = {0:D}, got = {1:D}", cl.Fn.NumParameters, numArgs));
            }

            Frame_t frame = Frame.NewFrame(cl, vm.sp - numArgs);

            pushFrame(frame);

            vm.sp = frame.basePointer + cl.Fn.NumLocals;

            return(null);
        }
Esempio n. 4
0
        static error pushClosure(int constIndex, int numFree)
        {
            Object.Object constant = vm.constants[constIndex];
            if (!(constant is Object.CompiledFunction))
            {
                return(string.Format("not a function {0}", constant.ToString()));
            }
            Object.CompiledFunction function = (Object.CompiledFunction)constant;

            List <Object.Object> free = new List <Object.Object>(new Object.Object[numFree]);

            for (int i = 0; i < numFree; i++)
            {
                free[i] = vm.stack[vm.sp - numFree - i];
            }
            vm.sp = vm.sp - numFree;

            Object.Closure closure = new Object.Closure {
                Fn = function, Free = free
            };
            return(push(closure));
        }
Esempio n. 5
0
        public static error Run()
        {
            int          ip;
            Instructions ins;
            Opcode       op;

            while (currentFrame().ip < Frame.Instructions(currentFrame()).Count - 1)
            {
                vm.frames[vm.frameIndex - 1].ip++;

                ip  = currentFrame().ip;
                ins = Frame.Instructions(currentFrame());
                op  = (Opcode)ins[ip];

                switch (op)
                {
                case code.OpConstant:
                {
                    int constIndex = code.ReadUint16(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 2;

                    error err = push(vm.constants[constIndex]);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpPop:
                    pop();
                    break;

                case code.OpAdd:
                case code.OpSub:
                case code.OpMul:
                case code.OpDiv:
                {
                    error err = executeBinaryOperation(op);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpTrue:
                {
                    error err = push(True);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpFalse:
                {
                    error err = push(False);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpEqual:
                case code.OpNotEqual:
                case code.OpGreaterThan:
                {
                    error err = executeComparison(op);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpBang:
                {
                    error err = executeBangOperator();
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpMinus:
                {
                    error err = executeMinusOperator();
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpJump:
                {
                    int pos = (int)code.ReadUint16(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip = pos - 1;
                }
                break;

                case code.OpJumpNotTruthy:
                {
                    int pos = (int)code.ReadUint16(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 2;

                    Object.Object condition = pop();
                    if (!isTruthy(condition))
                    {
                        vm.frames[vm.frameIndex - 1].ip = pos - 1;
                    }
                }
                break;

                case code.OpNull:
                {
                    error err = push(Null);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpSetGlobal:
                {
                    int globalIndex = code.ReadUint16(ins, ip + 1);

                    vm.frames[vm.frameIndex - 1].ip += 2;

                    vm.globals[globalIndex] = pop();
                }
                break;

                case code.OpGetGlobal:
                {
                    int globalIndex = code.ReadUint16(ins, ip + 1);

                    vm.frames[vm.frameIndex - 1].ip += 2;

                    error err = push(vm.globals[globalIndex]);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpArray:
                {
                    int numElements = (int)code.ReadUint16(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 2;

                    Object.Object array = buildArray(vm.sp - numElements, vm.sp);
                    vm.sp = vm.sp - numElements;

                    error err = push(array);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpHash:
                {
                    int numElements = (int)code.ReadUint16(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 2;

                    error         err;
                    Object.Object hash = buildHash(vm.sp - numElements, vm.sp, out err);
                    if (err != null)
                    {
                        return(err);
                    }
                    vm.sp = vm.sp - numElements;

                    err = push(hash);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpIndex:
                {
                    Object.Object index = pop();
                    Object.Object left  = pop();

                    error err = executeIndexExpression(left, index);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpCall:
                {
                    int numArgs = (int)code.ReadUint8(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 1;

                    error err = executeCall(numArgs);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpReturnValue:
                {
                    Object.Object returnValue = pop();

                    Frame_t frame = popFrame();
                    vm.sp = frame.basePointer - 1;

                    error err = push(returnValue);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpReturn:
                {
                    Frame_t frame = popFrame();
                    vm.sp = frame.basePointer - 1;

                    error err = push(Null);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpSetLocal:
                {
                    int localIndex = (int)code.ReadUint8(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 1;

                    Frame_t frame = currentFrame();

                    vm.stack[frame.basePointer + localIndex] = pop();
                }

                break;

                case code.OpGetLocal:
                {
                    int localIndex = (int)code.ReadUint8(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 1;

                    Frame_t frame = currentFrame();

                    error err = push(vm.stack[frame.basePointer + localIndex]);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpGetBuiltin:
                {
                    int builtinIndex = (int)code.ReadUint8(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 1;

                    Object._BuiltinDefinition definition = Object.builtins.Builtins[builtinIndex];

                    error err = push(definition.Builtin);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpClosure:
                {
                    int constIndex = (int)code.ReadUint16(ins, ip + 1);
                    int numFree    = (int)code.ReadUint8(ins, ip + 3);
                    vm.frames[vm.frameIndex - 1].ip += 3;

                    error err = pushClosure(constIndex, numFree);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpGetFree:
                {
                    int freeIndex = (int)code.ReadUint8(ins, ip + 1);
                    vm.frames[vm.frameIndex - 1].ip += 1;

                    Object.Closure curentClosure = currentFrame().cl;
                    error          err           = push(curentClosure.Free[freeIndex]);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;

                case code.OpCurrentClosure:
                {
                    Object.Closure currentClosure = currentFrame().cl;
                    error          err            = push(currentClosure);
                    if (err != null)
                    {
                        return(err);
                    }
                }
                break;
                }
            }

            return(null);
        }