Esempio n. 1
0
        public ThreadState Execute()
        {
            if (State != ThreadState.Running)
            {
                return(State);
            }

            for (; ;)
            {
                if (_instructionPtr >= _instructionList.Count)
                {
                    break;
                }

                var inst = _instructionList[_instructionPtr++];

                switch (inst.OpCode)
                {
                case ByteCode.Opcode.Pop:
                {
                    _stack.Pop();
                    break;
                }

                case ByteCode.Opcode.Pop2:
                {
                    _stack.Pop(2);
                    break;
                }

                case ByteCode.Opcode.Dup:
                {
                    _stack.Push(_stack.Peek());
                    break;
                }

                case ByteCode.Opcode.Call:
                {
                    // pop arg count from stack
                    ThreadState res = PushStackFrame(inst[0].GetInteger());

                    switch (res)
                    {
                    case ThreadState.Running:
                    {
                        break;
                    }

                    case ThreadState.Sys_Yield:
                    {
                        return(ThreadState.Running);
                    }

                    case ThreadState.Exception:
                    {
                        _machine.SwitchThreadState(this, ThreadState.Killed);
                        return(ThreadState.Exception);
                    }

                    case ThreadState.Killed:
                    {
                        _machine.SwitchThreadState(this, ThreadState.Killed);
                        break;
                    }

                    default:
                    {
                        break;
                    }
                    }


                    break;
                }

                    #region Push Operations
                case ByteCode.Opcode.PushNull:
                {
                    Push(Variable.Null);
                    break;
                }

                case ByteCode.Opcode.PushThis:
                {
                    Push(This);
                    break;
                }

                case ByteCode.Opcode.PushInt0:
                case ByteCode.Opcode.PushInt1:
                case ByteCode.Opcode.PushInt:
                case ByteCode.Opcode.PushFp:
                case ByteCode.Opcode.PushStr:
                case ByteCode.Opcode.PushFn:
                {
                    Push(inst[0]);
                    break;
                }

                case ByteCode.Opcode.PushTbl:
                {
                    Push(new TableObject());
                    break;
                }

                    #endregion
                case ByteCode.Opcode.Ret:              // Ret pushes a null
                {
                    Push(Variable.Null);
                    ThreadState res = PopStackFrame();
                    switch (res)
                    {
                    case ThreadState.Exception:
                    case ThreadState.Killed:
                    {
                        _machine.SwitchThreadState(this, res);
                        return(res);
                    }

                    default:
                    {
                        break;
                    }
                    }
                    break;
                }

                case ByteCode.Opcode.Retv:
                {
                    ThreadState res = PopStackFrame();
                    if (res == ThreadState.Killed)
                    {
                        return(res);
                    }
                    break;
                }

                case ByteCode.Opcode.SetGlobal:
                {
                    Variable v1 = inst[0];
                    if (v1.Type != VariableType.String)
                    {
                        throw new Exception("String required");
                    }

                    Variable v2 = _stack.Pop();
                    _machine.Globals[v1] = v2;
                    break;
                }

                case ByteCode.Opcode.GetGlobal:
                {
                    Variable v1 = inst[0];          // global name
                    // TODO: Check for string
                    if (v1.Type != VariableType.String)
                    {
                        throw new Exception("String required");
                    }
                    var global = _machine.Globals[v1];
                    Push(global);
                    break;
                }

                case ByteCode.Opcode.SetLocal:
                {
                    int offset = inst[0].GetInteger();
                    _stack.PokeBase(offset, _stack.Pop());
                    break;
                }

                case ByteCode.Opcode.GetLocal:
                {
                    int offset = inst[0].GetInteger();
                    Push(_stack.PeekBase(offset));
                    break;
                }

                    #region Operators
                case ByteCode.Opcode.OpEq:
                case ByteCode.Opcode.OpNeq:
                case ByteCode.Opcode.OpLt:
                case ByteCode.Opcode.OpLte:
                case ByteCode.Opcode.OpGt:
                case ByteCode.Opcode.OpGte:
                case ByteCode.Opcode.OpRem:
                case ByteCode.Opcode.OpAdd:
                case ByteCode.Opcode.OpSub:
                case ByteCode.Opcode.OpMul:
                case ByteCode.Opcode.OpDiv:
                {
                    Operator o = Operator._MAX;
                    switch (inst.OpCode)
                    {
                        #region fold
                    case ByteCode.Opcode.OpAdd:
                    {
                        o = Operator.Add;
                        break;
                    }

                    case ByteCode.Opcode.OpSub:
                    {
                        o = Operator.Sub;
                        break;
                    }

                    case ByteCode.Opcode.OpMul:
                    {
                        o = Operator.Mul;
                        break;
                    }

                    case ByteCode.Opcode.OpDiv:
                    {
                        o = Operator.Div;
                        break;
                    }

                    case ByteCode.Opcode.GetInd:
                    {
                        o = Operator.GetInd;
                        break;
                    }

                    case ByteCode.Opcode.OpEq:
                    {
                        o = Operator.Eq;
                        break;
                    }

                    case ByteCode.Opcode.OpNeq:
                    {
                        o = Operator.Neq;
                        break;
                    }

                    case ByteCode.Opcode.OpLt:
                    {
                        o = Operator.Lt;
                        break;
                    }

                    case ByteCode.Opcode.OpLte:
                    {
                        o = Operator.Lte;
                        break;
                    }

                    case ByteCode.Opcode.OpGt:
                    {
                        o = Operator.Gt;
                        break;
                    }

                    case ByteCode.Opcode.OpGte:
                    {
                        o = Operator.Gte;
                        break;
                    }

                    case ByteCode.Opcode.OpRem:
                    {
                        o = Operator.Rem;
                        break;
                    }
                        #endregion
                    }
                    if (o == Operator._MAX)
                    {
                        throw new NotImplementedException("Operator not mapped or implemented");
                    }
                    var t1 = _stack.Peek(-1).TypeCode;
                    var t2 = _stack.Peek(-2).TypeCode;
                    if (t2 > t1)
                    {
                        t1 = t2;
                    }

                    OperatorCallback op = Machine.GetTypeOperator(t1, o);
                    if (op != null)
                    {
                        var operand = _stack.StackPointer--;
                        _stack.PokeAbs(operand - 2, op(this, _stack.PeekAbs(operand - 2), _stack.PeekAbs(operand - 1), _stack.PeekAbs(operand)));
                    }
                    else
                    {
                        throw new Exception("Operator not defined");
                    }
                    break;
                }

                case ByteCode.Opcode.GetInd:
                {
                    var type = _stack.Peek(-2).TypeCode;
                    var op   = Machine.GetTypeOperator(type, Operator.GetInd);
                    if (op != null)
                    {
                        var operand = _stack.StackPointer--;
                        _stack.PokeAbs(operand - 2, op(this, _stack.PeekAbs(operand - 2), _stack.PeekAbs(operand - 1), _stack.PeekAbs(operand)));
                    }
                    else
                    {
                        throw new Exception("Operator not defined");
                    }
                    break;
                }

                case ByteCode.Opcode.SetInd:
                {
                    var topMin3         = _stack.Peek(-3);
                    OperatorCallback op = Machine.GetTypeOperator(topMin3.TypeCode, Operator.SetInd);
                    if (op != null)
                    {
                        _stack.Poke(-3, op(this, topMin3, _stack.Peek(-2), _stack.Peek(-1)));
                        _stack.StackPointer -= 3;
                    }
                    else
                    {
                        throw new Exception("Operator not defined");
                    }
                    break;
                }

                case ByteCode.Opcode.ForEach:
                {
                    var topMin2 = _stack.Peek(-2);
                    TypeIteratorCallback itr = Machine.GetTypeIterator(topMin2.TypeCode);
                    if (itr == null)
                    {
                        _machine.Log.LogEntry("Undefined iterator for type");
                        return(ThreadState.Exception);
                    }

                    var iteratorPos = _stack.Peek(-1).GetInteger();
                    var obj         = _stack.Peek(-2).GetReference();
                    iteratorPos = itr(this, obj, iteratorPos, _stack.PeekBase(inst[1].GetInteger()), _stack.PeekBase(inst[0].GetInteger()));
                    if (iteratorPos != -1)
                    {
                        //_Stack2[_Base + Inst[1].GetInteger()] = Key;
                        //_Stack2[_Base + Inst[0].GetInteger()] = Item;
                        _stack.Poke(Variable.Zero);
                    }
                    else
                    {
                        _stack.Poke(Variable.Zero);
                    }
                    _stack.Poke(-1, iteratorPos);
                    ++_stack.StackPointer;


                    break;
                }

                    #region Dot Operators
                case ByteCode.Opcode.GetDot:
                {
                    var v1 = _stack.Peek(-1);
                    OperatorCallback op = Machine.GetTypeOperator(v1.TypeCode, Operator.GetDot);
                    _stack.Poke(inst[0]);
                    if (op != null)
                    {
                        _stack.Poke(-1, op(this, v1, _stack.Peek(), _stack.Peek()));
                    }
                    else
                    {
                        throw new Exception("Operator not defined");
                    }
                    break;
                }

                case ByteCode.Opcode.SetDot:
                {
                    var v1 = _stack.Peek(-2);
                    OperatorCallback op = Machine.GetTypeOperator(v1.TypeCode, Operator.SetDot);
                    _stack.Poke(inst[0]);
                    if (op != null)
                    {
                        _stack.Poke(-2, op(this, _stack.Peek(-2), _stack.Peek(-1), _stack.Peek()));
                        _stack.StackPointer -= 2;
                    }
                    else
                    {
                        throw new Exception("Operator not defined");
                    }
                    break;
                }

                    #endregion
                    #endregion
                    #region Branch
                case ByteCode.Opcode.Brz:
                {
                    var v = _stack.Pop();
                    if (v.IsZero)
                    {
                        var newIp = inst[0].GetInteger();

                        if (newIp >= _instructionList.Count)
                        {
                            throw new Exception("BRZ: Corrupt IP");
                        }

                        _instructionPtr = newIp;
                    }
                    break;
                }

                case ByteCode.Opcode.Brnz:
                {
                    var v = _stack.Pop();
                    if (!v.IsZero)
                    {
                        var newIp = inst[0].GetInteger();

                        if (newIp >= _instructionList.Count)
                        {
                            throw new Exception("BRZ: Corrupt IP");
                        }

                        _instructionPtr = newIp;
                    }
                    break;
                }

                case ByteCode.Opcode.Brzk:
                {
                    var v = _stack.Peek(-1);
                    if (v.IsZero)
                    {
                        var newIp = inst[0].GetInteger();

                        if (newIp >= _instructionList.Count)
                        {
                            throw new Exception("BRZ: Corrupt IP");
                        }

                        _instructionPtr = newIp;
                    }
                    break;
                }

                case ByteCode.Opcode.Brnzk:
                {
                    var v = _stack.Peek(-1);
                    if (!v.IsZero)
                    {
                        var newIp = inst[0].GetInteger();

                        if (newIp >= _instructionList.Count)
                        {
                            throw new Exception("BRNZK: Corrupt IP");
                        }

                        _instructionPtr = newIp;
                    }
                    break;
                }

                case ByteCode.Opcode.Bra:
                {
                    var newIp = inst[0].GetInteger();

                    if (newIp >= _instructionList.Count)
                    {
                        throw new Exception("BRA: Corrupt IP");
                    }

                    _instructionPtr = newIp;
                    break;
                }

                    #endregion
                default:
                {
                    throw new Exception("Unknown instr");
                }
                } // end switch instruction
            }     // end loop

            return(ThreadState.Exception);
        }
Esempio n. 2
0
 public void SetIterator(TypeIteratorCallback Itr)
 {
     _IteratorFunction = Itr;
 }