public void DoCALL(UInt32 instruction) { int numArgs = (int)((instruction & OpCodes.OP1_MASK) >> OpCodes.OP1_SHIFT); int numPop = (int)((instruction & OpCodes.OP2_MASK) >> OpCodes.OP2_SHIFT); VarArgs args = new VarArgs(); for (int i = 0; i < numArgs; i++) { if (i == 0) { args.PushLastArg(CurrentThread.PopStack()); } else { args.PushArg(CurrentThread.PopStack()); } } Object o = CurrentThread.PopStack(); if (o is Closure) { Closure closure = (Closure)o; Function f = closure.Func; InstructionPointer newIP = null; newIP = new InstructionPointer(f, closure.ClosedVars, 0); ReturnPoint retPoint = new ReturnPoint(CurrentIP, numPop); CurrentThread.PushStack(retPoint); CurrentThread.PushStack(CurrentThread.BasePosition); CurrentThread.BasePosition = CurrentThread.StackPosition - 1; CurrentThread.PushStack(args); CurrentIP = newIP; } else if (o is NativeFuncDelegate) { NativeFuncDelegate nativeFunc = (NativeFuncDelegate)o; VarArgs returnArgs = nativeFunc(args, Engine); CurrentThread.PushStack(returnArgs); CurrentIP.InstructionIndex++; } else if (o is NativeCoreFuncDelegate) { NativeCoreFuncDelegate nativeFunc = (NativeCoreFuncDelegate)o; nativeFunc(args, Engine); } else { throw new VMException(); } }
private void DoRET(UInt32 instruction) { int oldBaseIndex = (int)CurrentThread.GetStackAtIndex(CurrentThread.BasePosition); VarArgs args = new VarArgs(); int numArgs = (int)((instruction & OpCodes.OP1_MASK) >> OpCodes.OP1_SHIFT); for (int i = 0; i < numArgs; i++) { if (i == 0) { args.PushLastArg(CurrentThread.PopStack()); } else { args.PushArg(CurrentThread.PopStack()); } } while (CurrentThread.StackPosition > CurrentThread.BasePosition) { CurrentThread.PopStack(); } CurrentThread.BasePosition = oldBaseIndex; Object retObj = CurrentThread.PopStack(); if (retObj is ReturnPoint) // Returning inside a thread { ReturnPoint retPoint = (ReturnPoint)retObj; CurrentIP = retPoint.instructionPointer; if (CurrentIP != null) { CurrentIP.InstructionIndex++; } if (retPoint.popArgs > 0) { for (int i = 0; i < retPoint.popArgs; i++) { CurrentThread.PushStack(args.PopArg()); } } else { CurrentThread.PushStack(args); } } else if (retObj is YieldPoint) // Returning across a thread boundary { YieldThread(args); } else { throw new VMException(); } }