Ejemplo n.º 1
0
        public void Execute(string function)
        {
            // get the current function
            Function?currentFunction = null;

            foreach (Function f in _functions)
            {
                if (f.Name == function)
                {
                    currentFunction = f;
                    break;
                }
            }

            if (currentFunction.HasValue == false)
            {
                throw new ArgumentException("Function not found: " + function);
            }

            int instructionPtr = 0;

            byte[] code       = currentFunction.Value.Code;
            uint   codeOffset = currentFunction.Value.CodeOffset;

            while (instructionPtr < code.Length)
            {
                byte        op = code[instructionPtr++];
                int         param;
                Parameter[] functionParams;

                switch (op)
                {
                case 0x00:     // SitnSpin
                    // do nothing
                    break;

                case 0x02:     // CallSysFunctionV
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    SheepMachine.CallVoidSystemFunction(Imports[param].Name, functionParams);
                    _state.PushStack(0);
                    break;

                case 0x03:     // CallSysFunctionI
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    _state.PushStack(SheepMachine.CallIntSystemFunction(Imports[param].Name, functionParams));
                    break;

                case 0x05:     // CallSysFunctionS
                    param          = getIntFromBytes(code, ref instructionPtr);
                    functionParams = buildParameterArray();
                    SheepMachine.CallStringSystemFunction(Imports[param].Name, functionParams);
                    _state.PushString(0);
                    break;

                case 0x06:     // Branch
                    param          = getIntFromBytes(code, ref instructionPtr);
                    instructionPtr = param - (int)codeOffset;
                    break;

                case 0x08:     // BranchIfZero
                    param = getIntFromBytes(code, ref instructionPtr);
                    if (_state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("stack is bad");
                    }
                    if (_state.PopStack().Integer == 0)
                    {
                        instructionPtr = param - (int)codeOffset;
                    }
                    break;

                case 0x09:     // BeginWait
                    // do nothing
                    break;

                case 0x0A:     // EndWait
                    // do nothing
                    break;

                case 0x0B:     // ReturnV
                    return;

                case 0x13:     // PushI
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushStack(param);
                    break;

                case 0x15:     // PushS
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushString(param);
                    break;

                case 0x16:     // Pop
                    _state.PopStack();
                    break;

                case 0x21:     // IsEqualI
                    if (_state.PeekStack().Type != ParameterType.Integer ||
                        _state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("IsLessI found two non-integers on the stack");
                    }
                    if (_state.PopStack().Integer == _state.PopStack().Integer)
                    {
                        _state.PushStack(1);
                    }
                    else
                    {
                        _state.PushStack(0);
                    }
                    break;

                case 0x27:     // IsLessI
                    if (_state.PeekStack().Type != ParameterType.Integer ||
                        _state.PeekStack().Type != ParameterType.Integer)
                    {
                        throw new InvalidOperationException("IsLessI found two non-integers on the stack");
                    }
                    if (_state.PopStack().Integer >= _state.PopStack().Integer)
                    {
                        _state.PushStack(1);
                    }
                    else
                    {
                        _state.PushStack(0);
                    }
                    break;

                case 0x2D:
                    param = getIntFromBytes(code, ref instructionPtr);
                    _state.PushStack((float)param);
                    break;

                case 0x30:
                    // do nothing
                    break;

                case 0x31:
                    // do nothing
                    break;

                case 0x33:     // GetString
                {
                    if (_state.PeekStack().Type != ParameterType.String)
                    {
                        throw new InvalidOperationException("GetString failed because value on stack isn't a string");
                    }

                    param = _state.PopStack().Integer;
                    Parameter p = new Parameter();
                    p.Type    = ParameterType.String;
                    p.Integer = param;
                    p.String  = Constants[_constantOffsetIndexMap[param]];

                    _state.PushStack(p);
                }
                break;

                default:
                    throw new NotImplementedException("Instruction " +
                                                      op.ToString("X") + " not implemented");
                }
            }

            return;
        }