예제 #1
0
        /// <summary>
        ///		Parses a looping expression that is dependent on an expression
        ///		evaluating to true.
        ///		Syntax:
        ///			"While" "{" Expression "}" Statement
        /// </summary>
        private void ParseWhile()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "While statments are only valid inside a function's or event's scope.", false, 0);

            // Create some jump target symbols.
            JumpTargetSymbol startJumpTarget = null, endJumpTarget = null;
            Instruction instruction;

            // Bind the starting jump target to here.
            if (_currentPass == 1)
            {
                startJumpTarget = new JumpTargetSymbol(_currentScope);
                endJumpTarget = new JumpTargetSymbol(_currentScope);
            }

            // Read in the expression to evaluate
            ExpectToken(TokenID.CharOpenParenthesis);
            DataTypeValue expressionDataType = ParseExpression();
            ExpectToken(TokenID.CharCloseParenthesis);

            // Make sure we can cast between the expression type and boolean.
            if (!CanImplicitlyCast(new DataTypeValue(DataType.Bool, false, false), expressionDataType))
                Error(ErrorCode.InvalidCast, "Can't implicitly cast between \"Bool\" and \"" + expressionDataType.ToString() + "\"", false, 0);

            // Emit evaluation byte code.
            if (_currentPass == 1)
            {
                // Pop the result of the expression into arith register 1.
                instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.POP), _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);

                // Cast it to boolean if its not already boolean
                if (expressionDataType != new DataTypeValue(DataType.Bool, false, false))
                {
                    instruction = CreateInstruction(OpCode.CAST_BOOL, _currentScope, _currentToken);
                    new Operand(instruction, Register.Arithmetic1);
                }

                // Compare the expression result to 0.
                instruction = CreateInstruction(OpCode.CMP_BOOL, _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);
                new Operand(instruction, false);

                // Jump to finish jump target if comparison is equal to false.
                instruction = CreateInstruction(OpCode.JMP_EQ, _currentScope, _currentToken);
                new Operand(instruction, endJumpTarget);

                // Push a new loop tracker onto the loop stack.
                _loopTrackerStack.Push(new LoopTracker(startJumpTarget, endJumpTarget));
            }

            // Parse the statements contained in this while block.
            ParseStatement();

            // Emit finishing byte code.
            if (_currentPass == 1)
            {
                // Pop the loop tracker of the loop stack.
                _loopTrackerStack.Pop();

                // Jump to the start of the loop.
                instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                new Operand(instruction, startJumpTarget);

                // Bind exit jump target.
                endJumpTarget.Bind();
            }
        }
예제 #2
0
        /// <summary>
        ///		Parses a label, which is used in conjunction with the goto statement to jump 
        ///		to specific areas in the code.
        ///		Syntax:
        ///			Identifier ":"
        /// </summary>
        private void ParseLabel()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "Label statments are only valid inside a function's or event's scope.", false, 0);

            // Create a jump target for this label.
            JumpTargetSymbol jumpTarget = null;
            if (_currentPass == 0)
            {
                jumpTarget = new JumpTargetSymbol(_currentScope);
                jumpTarget.Identifier = _currentToken.Ident;
            }
            else if (_currentPass == 1)
            {
                jumpTarget = _currentScope.FindSymbol(_currentToken.Ident, SymbolType.JumpTarget) as JumpTargetSymbol;
                jumpTarget.Bind();
            }

            // Read in the colon that ends this label.
            ExpectToken(TokenID.CharColon);
        }
예제 #3
0
        /// <summary>
        ///		Parses a switch statement, a switch statement is essentially a 
        ///		nicer way of write a list of if/elseif blocks.
        ///		Syntax:
        ///			"Switch" "(" Expression ")" "{" { [ "case" Expresion ":" Statement ] [ "default" ":" Statement ] } "}" 
        ///		
        ///		Output byte code example:
        ///			[expression]
        ///			pop a1
        ///			
        ///			[expression]
        ///			pop a2
        ///			cmp a2, a1
        ///			jmp_ne case1exit
        ///			[block]
        ///			jmp exit	
        ///		case1exit:
        /// 
        ///			[expression]
        ///			pop a2
        ///			cmp a2, a1
        ///			jmp_ne case2exit
        ///			[block]
        ///			jmp exit
        ///		case2exit:
        ///		
        ///		default:
        ///			jmp exit
        /// 
        ///		exit:
        ///			
        /// </summary>
        private void ParseSwitch()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "Switch statements are only valid inside a function's or event's scope.", false, 0);

            // Declare variables used within this function.
            JumpTargetSymbol defaultJumpTarget = null, exitJumpTarget = null;
            JumpTargetSymbol exitCaseJumpTarget = null;
            Instruction instruction = null;

            // If we are in pass 2 then create the jump targets.
            if (_currentPass == 1)
            {
                defaultJumpTarget = new JumpTargetSymbol(_currentScope);
                exitJumpTarget = new JumpTargetSymbol(_currentScope);
            }

            // Read in the main expression.
            ExpectToken(TokenID.CharOpenParenthesis);
            DataTypeValue expressionDataType = ParseExpression();
            ExpectToken(TokenID.CharCloseParenthesis);

            // Pop the expression into reserved register 3.
            if (_currentPass == 1)
            {
                instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.POP), _currentScope, _currentToken);
                new Operand(instruction, Register.Reserved3);
            }

            // Read in opening brace.
            ExpectToken(TokenID.CharOpenBrace);

            // Create and push a new loop tracker into the tracker stack.
            if (_currentPass == 1)
                _loopTrackerStack.Push(new LoopTracker(null, exitJumpTarget));

            // Keep looping until we find the end of this switch statement.
            bool foundDefault = false;
            while (true)
            {
                // If the next token is a closing brace then exit loop.
                if (LookAheadToken().ID == TokenID.CharCloseBrace)
                    break;

                // Read in a case block.
                if (LookAheadToken().ID == TokenID.KeywordCase)
                {
                    NextToken(); // Read in the case keyword.

                    // Create a exit-case jump target.
                    if (_currentPass == 1) exitCaseJumpTarget = new JumpTargetSymbol(_currentScope);

                    // Read in the case expression.
                    DataTypeValue caseResultDataType = ParseExpression();

                    // Cast the value into the correct type.
                    if (CanImplicitlyCast(expressionDataType, caseResultDataType) == false)
                        Error(ErrorCode.InvalidCast, "Can't implicitly cast between \"" + expressionDataType.ToString() + "\" and \"" + caseResultDataType.ToString() + "\"");

                    if (_currentPass == 1)
                    {
                        // Pop the value into arith register 1.
                        instruction = CreateInstruction(OpCodeByType(caseResultDataType, OpCodeType.POP), _currentScope, _currentToken);
                        new Operand(instruction, Register.Arithmetic1);

                        // Cast to the correct type if its not already it.
                        if (expressionDataType != caseResultDataType)
                        {
                            instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.CAST), _currentScope, _currentToken);
                            new Operand(instruction, Register.Arithmetic1);
                        }

                        // Compare the expression and this case's expression.
                        instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.CMP), _currentScope, _currentToken);
                        new Operand(instruction, Register.Reserved3);
                        new Operand(instruction, Register.Arithmetic1);

                        // If its not equal to the expression then jump to the case
                        // exit jump target.
                        instruction = CreateInstruction(OpCode.JMP_NE, _currentScope, _currentToken);
                        new Operand(instruction, exitCaseJumpTarget);
                    }

                    ExpectToken(TokenID.CharColon); // Read in the colon.

                    // Parse the case statement.
                    ParseStatement();

                    if (_currentPass == 1)
                    {
                        // Jump to the default block.
                        instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                        new Operand(instruction, exitJumpTarget);

                        // Bind the case exit jump target.
                        exitCaseJumpTarget.Bind();
                    }
                }

                // Its not a case so check if its a default block.
                if (LookAheadToken().ID == TokenID.KeywordDefault)
                {
                    NextToken(); // Read in the deault keyword.
                    ExpectToken(TokenID.CharColon); // Read in the colon.

                    // Check we haven't already found a default block.
                    if (foundDefault == true) Error(ErrorCode.DuplicateDefault, "Switch statements can't contain duplicate default blocks.");
                    foundDefault = true;

                    if (_currentPass == 1)
                    {
                        // Create a exit-case jump target.
                        exitCaseJumpTarget = new JumpTargetSymbol(_currentScope);

                        // Jump past the default block.
                        instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                        new Operand(instruction, exitCaseJumpTarget);

                        // Bind the default jump target.
                        defaultJumpTarget.Bind();
                    }

                    // Parses the default block's statement.
                    ParseStatement();

                    if (_currentPass == 1)
                    {
                        // Jump to the exit jump target.
                        instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                        new Operand(instruction, exitJumpTarget);

                        // Bind the case exit jump target.
                        exitCaseJumpTarget.Bind();
                    }
                }
            }

            // Read in closing brace.
            ExpectToken(TokenID.CharCloseBrace);

            // Pop the loop tracker off the tracker stack.
            if (_currentPass == 1)
                _loopTrackerStack.Pop();

            if (_currentPass == 1)
            {
                // Jump to the default block if its defined.
                if (foundDefault == true)
                {
                    instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                    new Operand(instruction, defaultJumpTarget);
                }

                // Bind the exit jump target.
                exitJumpTarget.Bind();
            }
        }
예제 #4
0
        /// <summary>
        ///		Parses a flow-of-control if statement, which will preform the given action
        ///		if the expression evaluates to true. Optional Else and ElseIf block's will be
        ///		preformed if expression evaluates to false.
        ///		Syntax:
        ///			"if" "(" Expression ")" Statement { [ "elseif" Block ] } [ "else" Block ] 
        /// </summary>
        private void ParseIf()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "If statments are only valid inside a function's or event's scope.", false, 0);

            // Generate a false jump target.
            Instruction instruction = null;
            JumpTargetSymbol falseJumpTarget = null;
            JumpTargetSymbol skipFalseJumpTarget = null;

            // Parse the expression.
            ExpectToken(TokenID.CharOpenParenthesis);
            DataTypeValue expressionDataType = ParseExpression();
            ExpectToken(TokenID.CharCloseParenthesis);

            // Make sure we can cast between the expression type and boolean.
            if (!CanImplicitlyCast(new DataTypeValue(DataType.Bool, false, false), expressionDataType))
                Error(ErrorCode.InvalidCast, "Can't implicitly cast between \"Bool\" and \"" + expressionDataType.ToString() + "\"", false, 0);

            // Generate comparison byte code.
            if (_currentPass == 1)
            {
                // Generate false jump target
                falseJumpTarget = new JumpTargetSymbol(_currentScope);

                // Pop the result into arith register 1
                instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.POP), _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);

                // Cast it to boolean if its not already boolean
                if (expressionDataType != new DataTypeValue(DataType.Bool, false, false))
                {
                    instruction = CreateInstruction(OpCode.CAST_BOOL,_currentScope,_currentToken);
                    new Operand(instruction, Register.Arithmetic1);
                }

                // Compare result with 0
                instruction = CreateInstruction(OpCode.CMP_BOOL, _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);
                new Operand(instruction, false);

                // Jump to false jump target if comparison is equal.
                instruction = CreateInstruction(OpCode.JMP_EQ, _currentScope, _currentToken);
                new Operand(instruction, falseJumpTarget);
            }

            // Parse the true statement.
            ParseStatement();

            // Check for the else keyword.
            if (LookAheadToken().ID == TokenID.KeywordElse)
            {
                // Read in the else keyword.
                NextToken();

                if (_currentPass == 1)
                {
                    // Append an unconditional jump past the false
                    // block to the true block.
                    skipFalseJumpTarget = new JumpTargetSymbol(_currentScope);
                    instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                    new Operand(instruction, skipFalseJumpTarget);

                    // Bind the false jump target.
                    falseJumpTarget.Bind();
                }

                // Parse the else statement.
                ParseStatement();

                if (_currentPass == 1) skipFalseJumpTarget.Bind();
            }
            else
                if (_currentPass == 1) falseJumpTarget.Bind();
        }
예제 #5
0
        /// <summary>
        ///		Parses a for loop, which is similar to the while statement but keeps the initialization,
        ///		incrementation and comparison in a more intuative format.
        ///		Syntax:
        ///			"For" "(" Initialization ";" Expression ";" Expression ")" Statement
        /// 
        ///		Output byte code example:
        ///         [initialization]
        ///     start:
        ///         [expression]
        /// 		pop a1
        ///			cmp a1, 0
        ///			jmp_eq exit
        ///         [statement block]
        ///         [increment]
        ///         jmp start
        ///     
        /// </summary>
        private void ParseFor()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "For statements are only valid inside a function's or event's scope.", false, 0);

            // Declare some important variables.
            JumpTargetSymbol startJumpTarget = null;
            JumpTargetSymbol finishJumpTarget = null;
            JumpTargetSymbol incrementJumpTarget = null;
            Instruction instruction = null;

            // Create jump targets if we are in pass 2.
            if (_currentPass == 1)
            {
                startJumpTarget = new JumpTargetSymbol(_currentScope);
                incrementJumpTarget = new JumpTargetSymbol(_currentScope);
                finishJumpTarget = new JumpTargetSymbol(_currentScope);
            }

            // Read in the variable declaration.
            ExpectToken(TokenID.CharOpenParenthesis);
            NextToken();
            if (_currentToken.ID == TokenID.KeywordBool || _currentToken.ID == TokenID.KeywordByte ||
                _currentToken.ID == TokenID.KeywordDouble || _currentToken.ID == TokenID.KeywordObject ||
                _currentToken.ID == TokenID.KeywordFloat || _currentToken.ID == TokenID.KeywordInt ||
                _currentToken.ID == TokenID.KeywordLong || _currentToken.ID == TokenID.KeywordShort ||
                _currentToken.ID == TokenID.KeywordString || _currentToken.ID == TokenID.KeywordVoid ||
                _currentToken.ID == TokenID.KeywordConst || _currentToken.ID == TokenID.KeywordStatic)
                ParseVariable();

            // Its not a variable declaration so read it in as a assignment.
            else
                ParseAssignment();

            // Bind the starting target.
            if (_currentPass == 1)
                startJumpTarget.Bind();

            // Parse the expression block.
            DataTypeValue expressionType = ParseExpression();
            ExpectToken(TokenID.CharSemiColon);

            // Create the expression evaluation instruction's.
            if (_currentPass == 1)
            {
                // Pop the result of the expression into arith register 1.
                instruction = CreateInstruction(OpCodeByType(expressionType, OpCodeType.POP), _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);

                // Cast it to boolean if its not already boolean.
                if (expressionType != new DataTypeValue(DataType.Bool, false, false))
                {
                    instruction = CreateInstruction(OpCode.CAST_BOOL, _currentScope, _currentToken);
                    new Operand(instruction, Register.Arithmetic1);
                }

                // Compare the result of the expression to false.
                instruction = CreateInstruction(OpCode.CMP_BOOL, _currentScope, _currentToken);
                new Operand(instruction, Register.Arithmetic1);
                new Operand(instruction, false);

                // If its equal jump out of this loop.
                instruction = CreateInstruction(OpCode.JMP_EQ, _currentScope, _currentToken);
                new Operand(instruction, finishJumpTarget);
            }

            // Skip the increment and parse the block.
            int incrementTokenIndex = _tokenIndex;
            Token incrementToken = _currentToken;
            while (EndOfTokenStream() == false && LookAheadToken().ID != TokenID.CharCloseParenthesis)
                NextToken();
            NextToken(); // Read in closing brace.

            // Push a loop tracker into the tracker stack.
            if (_currentPass == 1)
                _loopTrackerStack.Push(new LoopTracker(incrementJumpTarget, finishJumpTarget));

            // Parse the loop's body.
            ParseStatement();

            // Pop the loop tracker of the tracker state.
            if (_currentPass == 1)
                _loopTrackerStack.Pop();

            // Note down the current token index / token.
            int finishTokenIndex = _tokenIndex;
            Token finishToken = _currentToken;

            // Go back to the increment block and parse it.
            _tokenIndex = incrementTokenIndex;
            _currentToken = incrementToken;
            NextToken();

            // Bind the increment jump target.
            if (_currentPass == 1)
                incrementJumpTarget.Bind();

            // Parse the increment.
            ParseAssignment();

            // Go back to the end.
            _tokenIndex = finishTokenIndex;
            _currentToken = finishToken;

            // Jump to the start block.
            if (_currentPass == 1)
            {
                instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                new Operand(instruction, startJumpTarget);
            }

            // Bind the finishing target.
            if (_currentPass == 1)
                finishJumpTarget.Bind();
        }
예제 #6
0
        /// <summary>
        ///		Parses a do looping statment. The do loop comes in 2 flavours do and do/while; The do 
        ///		loop will loop through the statements body for x amount of times, where x is the result
        ///		of the expression. The Do/While loop works just like the While loop but gets evaluated
        ///		at the end rather than the start.
        ///		Syntax:
        ///			"Do" ["(" Expression ")"] Statement [ "While" "(" Expression ")" ]
        /// </summary>
        private void ParseDo()
        {
            // Check we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                Error(ErrorCode.InvalidScope, "Do statments are only valid inside a function's or event's scope.", false, 0);

            bool whileLoop = true;
            VariableSymbol doTrackerVariable = null;
            Instruction instruction = null;

            // Bind the starting jump target.
            JumpTargetSymbol startJumpTarget = null, endJumpTarget = null;
            if (_currentPass == 1)
            {
                startJumpTarget = new JumpTargetSymbol(_currentScope);
                endJumpTarget = new JumpTargetSymbol(_currentScope);
            }

            // Check if there is an expression next, if there is its a do loop.
            if (LookAheadToken().ID == TokenID.CharOpenParenthesis)
            {
                // Create an internal variable to count number of loops.
                if (_currentPass == 0)
                {
                    doTrackerVariable = new VariableSymbol(_currentScope);
                    doTrackerVariable.Identifier = "$" + _internalVariableIndex++;
                    doTrackerVariable.IsUsed = true;
                    doTrackerVariable.DataType = new DataTypeValue(DataType.Int, false, false);
                    doTrackerVariable.VariableType = VariableType.Local;
                    if (_currentScope.Type == SymbolType.Function)
                    {
                        doTrackerVariable.StackIndex = -(((FunctionSymbol)_currentScope).LocalDataSize + 2);
                        ((FunctionSymbol)_currentScope).LocalDataSize++;
                    }
                }
                else
                {
                    doTrackerVariable = _currentScope.FindSymbol("$" + _internalVariableIndex++, SymbolType.Variable) as VariableSymbol;

                    // Reset the tracker variable to 0.
                    instruction = CreateInstruction(OpCode.MOV_INT, _currentScope, _currentToken);
                    Operand.DirectStackOperand(instruction, doTrackerVariable.StackIndex);
                    new Operand(instruction, (long)0);
                }

                // Bind the jump target to here.
                if (_currentPass == 1) startJumpTarget.Bind();

                // Read in do expression.
                whileLoop = false;
                NextToken();
                DataTypeValue expressionDataType = ParseExpression();
                ExpectToken(TokenID.CharCloseParenthesis);

                // Make sure we can cast between the expression type and boolean.
                if (!CanImplicitlyCast(new DataTypeValue(DataType.Int, false, false), expressionDataType))
                    Error(ErrorCode.InvalidCast, "Can't implicitly cast between \"Int\" and \"" + expressionDataType.ToString() + "\"", false, 0);

                // If we are in pass 2 emit byte code to check value.
                if (_currentPass == 1)
                {
                    // Pop the amount of times to loop into the reserved register 1.
                    instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.POP), _currentScope, _currentToken);
                    new Operand(instruction, Register.Reserved1);

                    // If the value is not a long then cast it into one.
                    if (expressionDataType != new DataTypeValue(DataType.Int, false, false))
                    {
                        instruction = CreateInstruction(OpCode.CAST_INT, _currentScope, _currentToken);
                        new Operand(instruction, Register.Reserved1);
                    }

                    // Compare the loop tracker to the number of times to loop.
                    instruction = CreateInstruction(OpCode.CMP_INT, _currentScope, _currentToken);
                    Operand.DirectStackOperand(instruction, doTrackerVariable.StackIndex);
                    new Operand(instruction, Register.Reserved1);

                    // If its above or equal to the number of times we want to loop for, then exit.
                    instruction = CreateInstruction(OpCode.JMP_GE, _currentScope, _currentToken);
                    new Operand(instruction, endJumpTarget);

                    // Increment the loop tracker variable.
                    instruction = CreateInstruction(OpCode.INC_INT, _currentScope, _currentToken);
                    Operand.DirectStackOperand(instruction, doTrackerVariable.StackIndex);
                }
            }
            else
            {
                // Bind the jump target to here.
                if (_currentPass == 1) startJumpTarget.Bind();
            }

            // Push a loop tracker onto the loop stack.
            if (_currentPass == 1)
                _loopTrackerStack.Push(new LoopTracker(startJumpTarget, endJumpTarget));

            // Parse the body of this statement.
            bool indexerLoop = _insideIndexerLoop;
            int indexerIndex = _indexerLoopIndex;
            if (whileLoop == false)
            {
                _insideIndexerLoop = true;
                _indexerLoopIndex = _internalVariableIndex - 1;
            }
            ParseStatement();
            _insideIndexerLoop = indexerLoop;
            _indexerLoopIndex = indexerIndex;

            // Pop the loop tracker of the loop stack
            if (_currentPass == 1)
                _loopTrackerStack.Pop();

            // If its a while loop then read in the while expression and output evaluation code.
            if (whileLoop == true)
            {
                // Parse the expression.
                ExpectToken(TokenID.KeywordWhile);
                ExpectToken(TokenID.CharOpenParenthesis);
                DataTypeValue expressionDataType = ParseExpression();
                ExpectToken(TokenID.CharCloseParenthesis);

                if (_currentPass == 1)
                {
                    // Pop the result of the expression into arith register 1.
                    instruction = CreateInstruction(OpCodeByType(expressionDataType, OpCodeType.POP), _currentScope, _currentToken);
                    new Operand(instruction, Register.Arithmetic1);

                    // Cast it to boolean if its not already boolean
                    if (expressionDataType != new DataTypeValue(DataType.Bool, false, false))
                    {
                        instruction = CreateInstruction(OpCode.CAST_BOOL, _currentScope, _currentToken);
                        new Operand(instruction, Register.Arithmetic1);
                    }

                    // Compare the expression result to 0.
                    instruction = CreateInstruction(OpCode.CMP_BOOL, _currentScope, _currentToken);
                    new Operand(instruction, Register.Arithmetic1);
                    new Operand(instruction, false);

                    // Jump to finish jump target if comparison is equal to false.
                    instruction = CreateInstruction(OpCode.JMP_EQ, _currentScope, _currentToken);
                    new Operand(instruction, endJumpTarget);
                }
            }

            // Create an instruction to jump back to the start of the loop.
            if (_currentPass == 1)
            {
                instruction = CreateInstruction(OpCode.JMP, _currentScope, _currentToken);
                new Operand(instruction, startJumpTarget);

                // Bind the end jump target to here.
                endJumpTarget.Bind();
            }
        }
예제 #7
0
 public Operand(Instruction instruction, JumpTargetSymbol value)
 {
     _opType = OperandType.JumpTarget;
     _jumpTarget = value;
     instruction[instruction.OperandCount] = this;
 }
예제 #8
0
 /// <summary>
 ///		Initializes a new instance of this class and sets it start
 ///		and end jump targets as those given.
 /// </summary>
 /// <param name="start">Jump target pointing to the start of the loop.</param>
 /// <param name="end">Jump target pointing to the end of the loop.</param>
 public LoopTracker(JumpTargetSymbol start, JumpTargetSymbol end)
 {
     _startJumpTarget = start;
     _endJumpTarget = end;
 }