Exemple #1
0
        bool ProcessForNextState(Interpreter interpreter, ForNextLoopState forNextState, VariableNameToken variableNameToken = null)
        {
            // For NEXT with a variable name, check the variable name matches the one stored in the stack
//            if (variableNameToken != null && (forNextState.VariableNameToken.Name != variableNameToken.Name))
//                throw new Exceptions.NextWithoutForException();

            if (variableNameToken != null && (forNextState.VariableNameToken.Name != variableNameToken.Name))
            {
                /* Get Calendar from David Ahl's BASIC Computer Games to work without producing
                 * a NEXT WITHOUT FOR error. If the variable in NEXT [x] is not on top of the stack
                 * like it should be, then pop variables off the stack until a name match is found.
                 * If still no match, only then produce a NEXT WITHOUT FOR error. This supports the case
                 * where the program GOTOs out of an inner loop to an outer loop.
                 */
                interpreter.ForNextLoops.Pop();

                while (interpreter.ForNextLoops.Count > 0)
                {
                    forNextState = interpreter.ForNextLoops.Peek();
                    if (forNextState.VariableNameToken.Name == variableNameToken.Name)
                    {
                        break;
                    }

                    // Discard this loop and try matching the next one
                    interpreter.ForNextLoops.Pop();
                }

                if (interpreter.ForNextLoops.Count == 0)
                {
                    throw new Exceptions.NextWithoutForException();
                }
            }

            var newValue = forNextState.CurrentValue.RealValue + forNextState.StepValue.RealValue;

            bool forNextLoopIsDone = false;

            if (forNextState.StepValue.RealValue >= 0)
            {
                forNextLoopIsDone = (newValue > forNextState.EndValue.RealValue);
            }
            else
            {
                forNextLoopIsDone = (newValue < forNextState.EndValue.RealValue);
            }

            if (forNextLoopIsDone)
            {
                interpreter.ForNextLoops.Pop();
                return(true);
            }
#if false
            // If done, pop the stack and return true
            if (forNextState.StartValue.RealValue <= forNextState.EndValue.RealValue)
            {
                if (newValue > forNextState.EndValue.RealValue)
                {
                    interpreter.ForNextLoops.Pop();
                    return(true);
                }
            }
            else
            {
                var  endValue   = forNextState.EndValue.RealValue;
                bool isLessThan = (newValue < endValue);

                if (newValue > forNextState.EndValue.RealValue)
                {
                    interpreter.ForNextLoops.Pop();
                    return(true);
                }
            }
#endif
            // Keep going, set the NEXT variable and goto the first statement after the FOR
            forNextState.CurrentValue = interpreter.TokensProvider.CreateRealValueToken(newValue);
            interpreter.VariablesEnvironment.SetVariableValue(forNextState.VariableNameToken, forNextState.CurrentValue);

            if (forNextState.LoopMarker != null)
            {
                // If in immediate mode, there may be no valid statement to loop to.
                if (forNextState.LoopMarker.Valid)
                {
                    var forNextStatement = new StatementMarker(forNextState.LoopMarker);
                    interpreter.NextStatementMarker = forNextStatement;
                }
            }
            else
            {
                var index = forNextState.ImmediateModeStatementIndex;
                interpreter.CurrentImmediateModeStatementMarker.MoveTo(index);
            }

            // Not done
            return(false);
        }
Exemple #2
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            if (!(tokenMarker.Token is VariableNameToken variableNameToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (variableNameToken.VariableType != VariableValueType.RealNumber)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (!(tokenMarker.GetNextToken() is EqualToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            tokenMarker.MoveNext();

            NumericValueToken startValue;

            try
            {
                startValue = (NumericValueToken)interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
            }
            catch (InvalidCastException)
            {
                throw new Exceptions.TypeMismatchException();
            }

            if (!(tokenMarker.Token is ToToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            tokenMarker.MoveNext();

            NumericValueToken endValue;

            try
            {
                endValue = (NumericValueToken)interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
            }
            catch (InvalidCastException)
            {
                throw new Exceptions.TypeMismatchException();
            }

            NumericValueToken stepValueToken = null;

            if (tokenMarker.Token != null)
            {
                if (!(tokenMarker.Token is StepToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                tokenMarker.MoveNext();
                var result = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
                if (!(result is NumericValueToken))
                {
                    throw new Exceptions.TypeMismatchException();
                }
                stepValueToken = (NumericValueToken)result;
            }
            else
            {
                // Default step is 1 or -1
//                if (startValue.RealValue <= endValue.RealValue)
                stepValueToken = interpreter.TokensProvider.CreateRealValueToken(1);
//                else
//                    stepValueToken = interpreter.TokensProvider.CreateRealValueToken(-1);
            }

            ForNextLoopState forNextLoopState;

            if (interpreter.InterpreterMode == InterpreterMode.Running)
            {
                var forNextMarker = interpreter.CopyCurrentStatementMarker();

                // In immediate mode, FOR may not neccessarily be followed by a statement.
                if (forNextMarker.Valid)
                {
                    forNextMarker.MoveToNextStatement();
                }

                forNextLoopState = new ForNextLoopState(forNextMarker, variableNameToken, startValue, endValue, stepValueToken);
            }
            else
            {
                var index = interpreter.CurrentImmediateModeStatementMarker.StatementIndex;
                forNextLoopState = new ForNextLoopState(index, variableNameToken, startValue, endValue, stepValueToken);
            }

            interpreter.ForNextLoops.Push(forNextLoopState);
            interpreter.VariablesEnvironment.SetVariableValue(variableNameToken, startValue);
        }