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, }); }
public static Frame_t NewFrame(Object.Closure cl, int basePointer) { Frame_t f = new Frame_t { cl = cl, ip = -1, basePointer = basePointer, }; return(f); }
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); }
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)); }
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); }