Exemple #1
0
 private void DoEachPrep(StackFrame frame, uint eachVar)
 {
     LayeGenerator gen;
     var value = frame.Pop();
     if (!(value is LayeGenerator))
     {
         var genObj = value[this, "enumerator", false];
         gen = genObj as LayeGenerator;
         if (gen == null)
         {
             RaiseException("Failed to get a generator from type {0} to enumerate. There should be an instance property called \"enumerator\" that returns a generator.", genObj.TypeName);
             return;
         }
     }
     else gen = value as LayeGenerator;
     // eachVar is the var the user has access to, eachVar + 1 is our temp store, and eachVar + 2 is the generator
     frame[eachVar + 1] = gen;
 }
Exemple #2
0
 private void DoIEachPrep(StackFrame frame, uint eachIndex)
 {
     LayeGenerator gen;
     var value = frame.Pop();
     if (!(value is LayeGenerator))
     {
         var genObj = value[this, "enumerator", false];
         gen = genObj as LayeGenerator;
         if (gen == null)
         {
             RaiseException("Failed to get a generator from type {0} to enumerate. There should be an instance property called \"enumerator\" that returns a generator.", genObj.TypeName);
             return;
         }
     }
     else gen = value as LayeGenerator;
     frame[eachIndex + 1] = ICONST0;
     frame[eachIndex + 3] = gen;
 }
Exemple #3
0
 private void DoRes(StackFrame frame)
 {
     var value = frame.Pop();
     var gen = value as LayeGenerator;
     if (gen == null)
     {
         RaiseException("Expected a generator to resume, got a(n) {0}.", value.TypeName);
         return;
     }
     LayeObject result;
     var success = gen.Resume(this, out result);
     if (success)
     {
         if (result == null)
             frame.Push(NULL);
         else frame.Push(result);
     }
 }
Exemple #4
0
 //[MethodImpl(MethodImplOptions.AggressiveInlining)]
 private void DoIterPrep(StackFrame frame, uint iterVar, bool hasStep)
 {
     // step, limit, init -> iter (iterVar = init to limit by step)
     var step  = hasStep ? frame.Pop().As(this, LayeInt.TYPE) as LayeInt : null;
     var limit = frame.Pop().As(this, LayeInt.TYPE) as LayeInt;
     var init  = frame.Pop().As(this, LayeInt.TYPE) as LayeInt;
     if (!hasStep)
         step = init.value < limit.value ? ICONST1 : ICONSTM1;
     // Now check what we popped, make sure they're valid
     if (init == null)
     {
         RaiseException("iter initial value must be an Int or convertible to an Int.");
         return;
     }
     if (limit == null)
     {
         RaiseException("iter limit must be an Int or convertible to an Int.");
         return;
     }
     if (step == null)
     {
         RaiseException("iter step must be an Int or convertible to an Int.");
         return;
     }
     if (step.value == 0)
     {
         RaiseException("iter step cannot be zero.");
         return;
     }
     if (init.value < limit.value ? step.value < 0 : step.value > 0)
     {
         RaiseException("Invalid iter step. The given step will lead the index away from the limit, dooming the loop to never complete.");
         return;
     }
     // Prep the init value
     init = LayeInt.ValueOf(init.value - step.value);
     // Store each value where it should go:
     // We double the first one because + 0 is the visible value, + 1 is the internal value for safety.
     // We don't want the user messing with our internal counter, we reset it each iteration.
     frame[iterVar] = init;
     frame[iterVar + 1] = init;
     frame[iterVar + 2] = limit;
     frame[iterVar + 3] = step;
 }
Exemple #5
0
 private void DoMethodInvoke(StackFrame frame, string methodName, uint insn)
 {
     var args = frame.PopCount((int)Insn.GET_A(insn));
     frame.Push(frame.Pop().MethodInvoke(this, methodName, args));
 }
Exemple #6
0
 private void DoInvoke(StackFrame frame, uint insn)
 {
     var args = frame.PopCount((int)Insn.GET_C(insn));
     frame.Push(frame.Pop().Invoke(this, args));
 }
Exemple #7
0
 private void DoIStore(StackFrame frame, uint insn)
 {
     var value = frame.Pop();
     var args = frame.PopCount((int)Insn.GET_C(insn));
     frame.Pop()[this, args] = value;
     frame.Push(value);
 }
Exemple #8
0
 private void DoILoad(StackFrame frame, uint insn)
 {
     var args = frame.PopCount((int)Insn.GET_C(insn));
     frame.Push(frame.Pop()[this, args]);
 }
Exemple #9
0
        internal LayeObject Execute(StackFrame frame, LayeClosure closure, LayeObject ths = null, params LayeObject[] args)
        {
            if (frame == null)
                frame = stack.PushFrame(closure, ths, args);
            else stack.PushFrame(frame);

        reentry:
            var kit = closure.kit;

            var outers = closure.outers;
            var nested = closure.proto.nested;
            var strings = closure.proto.strings;
            var numericConsts = closure.proto.numericConsts;

            var code = closure.proto.code;
            var codeLen = (uint)code.Length;

            var paramc = closure.proto.numParams;
            var argc = args.Length;
            var vargs = closure.proto.hasVargs;

            var openOuters = frame.openOuters;

            uint insn;
            OpCode op;

            for (; frame.ip < codeLen && !frame.Aborted && !frame.yielded; frame.ip++)
            {
                op = (OpCode)((insn = code[frame.ip]) & Insn.MAX_OP);
#if DEBUG_STACK
                Console.WriteLine(frame.ip + " " + op);
                frame.PrintLocals(this);
                frame.PrintStack(this);
#endif
                switch (op)
                {
                    default: RaiseException(string.Format("Unhandled op code {0}.", op)); return NULL;

                    case OpCode.NOP: continue;
                    case OpCode.POP: frame.Pop(); continue;
                    case OpCode.DUP: frame.Dup(); continue;

                    case OpCode.CLOSE: CloseOuters(openOuters, Insn.GET_C(insn)); continue;

                        // These all do n - 1 because frame.ip++ happens anyway. I hate it, but oh well.
                    case OpCode.JUMP: frame.ip = Insn.GET_C(insn) - 1; continue;
                    case OpCode.JUMPEQ: if (frame.SwapPop().Equals(frame.Pop())) frame.ip = Insn.GET_C(insn) - 1; continue;
                    case OpCode.JUMPNEQ: if (!frame.SwapPop().Equals(frame.Pop())) frame.ip = Insn.GET_C(insn) - 1; continue;
                    case OpCode.JUMPT: if (frame.Pop().ToBool(this)) frame.ip = Insn.GET_C(insn) - 1; continue;
                    case OpCode.JUMPF: if (!frame.Pop().ToBool(this)) frame.ip = Insn.GET_C(insn) - 1; continue;

                    case OpCode.LLOAD: frame.Push(frame[Insn.GET_C(insn)]); continue;
                    case OpCode.LSTORE: frame[Insn.GET_C(insn)] = frame.Top; continue;
                    case OpCode.OLOAD: frame.Push(outers[Insn.GET_C(insn)].Value); continue;
                    case OpCode.OSTORE: outers[Insn.GET_C(insn)].Set(this, frame.Top); continue;
                    case OpCode.KLOAD: frame.Push(kit[this, strings[Insn.GET_C(insn)]]); continue;
                    case OpCode.KSTORE: kit[this, strings[Insn.GET_C(insn)]] = frame.Top; continue;
                    case OpCode.GLOAD: frame.Push(kit.GetGlobal(this, strings[Insn.GET_C(insn)])); continue;
                    case OpCode.GSTORE: kit.SetGlobal(this, strings[Insn.GET_C(insn)], frame.Top); continue;
                    case OpCode.ILOAD: DoILoad(frame, insn); continue;
                    case OpCode.ISTORE: DoIStore(frame, insn); continue;
                    case OpCode.OILOAD: frame.Push(frame.Pop().OperatorIndexGet(this, strings[Insn.GET_C(insn)])); continue;
                    case OpCode.OISTORE: frame.SwapPop().OperatorIndexSet(this, strings[Insn.GET_C(insn)], frame.Top); continue;
                    case OpCode.FLOAD: frame.Push(frame.Pop()[this, strings[Insn.GET_C(insn)]]); continue;
                    case OpCode.FSTORE: frame.SwapPop()[this, strings[Insn.GET_C(insn)]] = frame.Top; continue;
                    case OpCode.LOAD: DoLoad(frame, kit, strings[Insn.GET_C(insn)]); continue;
                    case OpCode.STORE: DoStore(frame, kit, strings[Insn.GET_C(insn)]); continue;

                    case OpCode.NULL: frame.Push(NULL); continue;
                    case OpCode.TRUE: frame.Push(TRUE); continue;
                    case OpCode.FALSE: frame.Push(FALSE); continue;
                    case OpCode.ENDL: frame.Push(ENDL); continue;
                    case OpCode.NCONST: frame.Push(numericConsts[Insn.GET_C(insn)]); continue;
                    case OpCode.SCONST: frame.Push(Insn.GET_B(insn) == 0 ? new LayeString(strings[Insn.GET_A(insn)]) as LayeObject : LayeSymbol.getUnsafe(strings[Insn.GET_A(insn)])); continue;

                    case OpCode.ICONSTM1: frame.Push(ICONSTM1); continue;
                    case OpCode.ICONST0: frame.Push(ICONST0); continue;
                    case OpCode.ICONST1: frame.Push(ICONST1); continue;
                    case OpCode.ICONST2: frame.Push(ICONST2); continue;
                    case OpCode.ICONST3: frame.Push(ICONST3); continue;
                    case OpCode.ICONST4: frame.Push(ICONST4); continue;
                    case OpCode.ICONST5: frame.Push(ICONST5); continue;

                    case OpCode.FCONSTM1: frame.Push(FCONSTM1); continue;
                    case OpCode.FCONST0: frame.Push(FCONST0); continue;
                    case OpCode.FCONST1: frame.Push(FCONST1); continue;
                    case OpCode.FCONST2: frame.Push(FCONST2); continue;

                    case OpCode.LIST: frame.Push(new LayeList(frame.PopCount((int)Insn.GET_C(insn)))); continue;
                    case OpCode.TUPLE: frame.Push(new LayeTuple(frame.PopCount((int)Insn.GET_C(insn)))); continue;

                    case OpCode.CLOSURE: frame.Push(BuildClosure(nested[Insn.GET_A(insn)], openOuters, null, frame.PopCount((int)Insn.GET_B(insn)))); continue;
                    case OpCode.GENERATOR: frame.Push(new LayeClosureGeneratorSpawner(frame.Pop() as LayeClosure)); continue;

                    case OpCode.INVOKE: DoInvoke(frame, insn); continue;
                    case OpCode.MINVOKE: DoMethodInvoke(frame, strings[Insn.GET_B(insn)], insn); continue;
                    case OpCode.TINVOKE: DoThisInvoke(frame, ths, strings[Insn.GET_B(insn)], insn); continue;
                    case OpCode.TAILINVOKE:
                        var saveArgs = frame.PopCount((int)Insn.GET_C(insn));
                        EndCall(frame, openOuters);
                        frame.Reset();
                        frame.SetArgs(saveArgs);
                        goto reentry;

                    case OpCode.YIELD: frame.yielded = true; continue;
                    case OpCode.RES: DoRes(frame); continue;

                    case OpCode.KIT: frame.Push(kit); continue;
                    case OpCode.THIS: frame.Push(ths); continue;
                    case OpCode.SELF: frame.Push(closure); continue;
                    case OpCode.STATIC: frame.Push(closure.definedType); continue;

                    case OpCode.PREFIX: frame.Push(frame.Pop().Prefix(this, strings[Insn.GET_C(insn)])); continue;
                    case OpCode.INFIX: frame.Push(frame.SwapPop().Infix(this, strings[Insn.GET_C(insn)], frame.Pop())); continue;
                    case OpCode.AS: frame.Push(frame.SwapPop().As(this, frame.Pop())); continue;

                    case OpCode.NOT: frame.Push(frame.Pop().ToBool(this) ? FALSE : TRUE); continue;
                    case OpCode.AND: if (frame.Top.ToBool(this)) frame.Pop(); else frame.ip = Insn.GET_C(insn) - 1; continue;
                    case OpCode.OR: if (frame.Top.ToBool(this)) frame.ip = Insn.GET_C(insn) - 1; else frame.Pop(); continue;
                    case OpCode.XOR: frame.Push((frame.Pop().ToBool(this) != frame.Pop().ToBool(this)) ? TRUE : FALSE); continue;

                    case OpCode.COMPIS: frame.Push((LayeBool)ReferenceEquals(frame.Pop(), frame.Pop())); continue;
                    case OpCode.COMPNOTIS: frame.Push((LayeBool)!ReferenceEquals(frame.Pop(), frame.Pop())); continue;
                    case OpCode.COMPTYPEOF: frame.Push((LayeBool)frame.SwapPop().TypeOf(this, frame.Pop())); continue;
                    case OpCode.COMPNOTTYPEOF: frame.Push((LayeBool)!frame.SwapPop().TypeOf(this, frame.Pop())); continue;
                    case OpCode.TYPEOF: frame.Push(frame.Pop().TypeDef); continue;

                    case OpCode.THROW: RaiseException(frame.Pop()); continue;
                    case OpCode.STOREEX: frame[Insn.GET_C(insn)] = lastException; continue;
                    case OpCode.BEGINEXH: var c = Insn.GET_C(insn); while (frame.stackPointer >= c) frame.Pop(); continue;
                    case OpCode.PUSHEXH: frame.activeExceptionHandlers++; exceptionHandlers.Push(new ExceptionHandler(stack.FrameCount, Insn.GET_C(insn))); continue;
                    case OpCode.POPEXH: frame.activeExceptionHandlers--; exceptionHandlers.Pop(); continue;

                    case OpCode.ITERPREP: DoIterPrep(frame, Insn.GET_A(insn), Insn.GET_B(insn) != 0); continue;
                    case OpCode.ITERLOOP: DoIterLoop(frame, Insn.GET_A(insn), Insn.GET_B(insn)); continue;
                    case OpCode.EACHPREP: DoEachPrep(frame, Insn.GET_A(insn)); continue;
                    case OpCode.EACHLOOP: DoEachLoop(frame, Insn.GET_A(insn), Insn.GET_B(insn)); continue;
                    case OpCode.IEACHPREP: DoIEachPrep(frame, Insn.GET_A(insn)); continue;
                    case OpCode.IEACHLOOP: DoIEachLoop(frame, Insn.GET_A(insn), Insn.GET_B(insn)); continue;
                } // end switch
            } // end for

            EndCall(frame, openOuters);

#if DEBUG_STACK
            frame.PrintStack(this);
#endif
            if (frame.Aborted)
                return NULL;
            stack.PopFrame();

            return frame.HasValue() ? frame.Top : NULL;
        }