예제 #1
0
파일: State.cs 프로젝트: stroan/Lamn
        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();
            }
        }
예제 #2
0
파일: State.cs 프로젝트: stroan/Lamn
        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();
            }
        }