예제 #1
0
        /// <summary>
        /// Executes a user defined function.
        /// </summary>
        /// <param name="parameter">new parameter value.</param>
        /// <param name="runEnvironment">Run evironment.</param>
        /// <param name="expressionEvaluator">Expression evaluator.</param>
        /// <param name="variableRepository">Variable repository.</param>
        /// <returns>Value of function.</returns>
        public Accumulator Execute(
            Accumulator parameter,
            IRunEnvironment runEnvironment,
            IExpressionEvaluator expressionEvaluator,
            IVariableRepository variableRepository)
        {
            // Save the variable and program line.
            var savedVariable    = variableRepository.GetOrCreateVariable(VariableName, new short[] { }).GetValue();
            var savedProgramLine = runEnvironment.CurrentLine;

            // Change the variable to be our parameter.
            variableRepository.GetOrCreateVariable(VariableName, new short[] { }).SetValue(parameter);
            runEnvironment.CurrentLine = Line;
            runEnvironment.CurrentLine.CurrentToken = LineToken;

            // Evaluate the expression.
            var returnValue = expressionEvaluator.GetExpression();

            // Restore the variable and program line.
            variableRepository.GetOrCreateVariable(VariableName, new short[] { }).SetValue(savedVariable);
            runEnvironment.CurrentLine = savedProgramLine;

            // return the value.
            return(returnValue);
        }
예제 #2
0
        public void GetWorksWithStringVariable()
        {
            SetupSut();
            _mockTeletypeWithPosition.Setup(mtwp => mtwp.ReadChar()).Returns('1');
            var variableReference = _variableRepository.GetOrCreateVariable("A$", new short[] { });

            _mockExpressionEvaluator.Setup(mee => mee.GetLeftValue()).Returns(variableReference);
            _sut.Execute();
            Assert.AreEqual("1", variableReference.GetValue().ValueAsString());
        }
예제 #3
0
        public void ReadTest()
        {
            SetupSut();

            var variableA = _variableRepository.GetOrCreateVariable("A", new short[] { });

            _runEnvironment.CurrentLine = new ProgramLine(10, new List <IToken>());
            _mockExpressionEvaluator.SetupSequence(mee => mee.GetLeftValue())
            .Returns(variableA);
            _sut.Execute();
            _mockReadInputParser.Verify(mrip => mrip.ReadVariables(new List <VariableReference> {
                variableA
            }), Times.Once);
        }
예제 #4
0
        private void SetupSut()
        {
            _runEnvironment          = new RunEnvironment();
            _mockExpressionEvaluator = new Mock <IExpressionEvaluator>();
            _variableRepository      = new VariableRepository();
            _variableReference       = _variableRepository.GetOrCreateVariable("A", new short[] { });

            _mockExpressionEvaluator.Setup(mre => mre.GetLeftValue()).Returns(_variableReference);
            _mockExpressionEvaluator.Setup(mre => mre.GetExpression()).Returns(new Accumulator(3.0));
            _sut = new Let(_runEnvironment, _mockExpressionEvaluator.Object);
        }
예제 #5
0
        /// <summary>
        /// Execute the NEXT command.
        /// </summary>
        public void Execute()
        {
            StackEntry currentLoop = null;

            while (true)
            {
                currentLoop = FindForEntry(currentLoop);
                var loopVar = _variableRepository.GetOrCreateVariable(currentLoop.VariableName, new short[] { });
                loopVar.SetValue(new Accumulator(loopVar.GetValue().ValueAsDouble() + currentLoop.Step));
                bool finished;
                if (currentLoop.Step > 0.0)
                {
                    finished = loopVar.GetValue().ValueAsDouble() > currentLoop.Target;
                }
                else
                {
                    finished = loopVar.GetValue().ValueAsDouble() < currentLoop.Target;
                }

                if (!finished)
                {
                    _runEnvironment.CurrentLine = currentLoop.Line;
                    _runEnvironment.CurrentLine.CurrentToken = currentLoop.LineToken;
                    return;
                }

                _runEnvironment.ProgramStack.Pop();

                var token = _runEnvironment.CurrentLine.NextToken();
                if (token.Seperator != TokenType.Comma)
                {
                    _runEnvironment.CurrentLine.PushToken(token);
                    return;
                }

                token = _runEnvironment.CurrentLine.NextToken();
                if (token.TokenClass == TokenClass.Variable)
                {
                    _runEnvironment.CurrentLine.PushToken(token);
                }
                else
                {
                    throw new Exceptions.SyntaxErrorException();
                }
            }
        }
 private void SetupSut()
 {
     _inputQueue = new Queue <string>();
     _sut        = new ReadInputParser(() => _inputQueue.Dequeue());
     _sut.Clear();
     _variableRepository  = new VariableRepository();
     _numericVariables[0] = _variableRepository.GetOrCreateVariable("A", new short[] { });
     _numericVariables[1] = _variableRepository.GetOrCreateVariable("B", new short[] { });
     _numericVariables[2] = _variableRepository.GetOrCreateVariable("C", new short[] { });
     _stringVariables[0]  = _variableRepository.GetOrCreateVariable("A$", new short[] { });
     _stringVariables[1]  = _variableRepository.GetOrCreateVariable("B$", new short[] { });
     _stringVariables[2]  = _variableRepository.GetOrCreateVariable("C$", new short[] { });
 }
예제 #7
0
 private void SetupSut()
 {
     _mockProgramRepository = new Mock <IProgramRepository>();
     _runEnvironment        = new RunEnvironment();
     _sut = new DataStatementReader(_runEnvironment, _mockProgramRepository.Object);
     _variableRepository  = new VariableRepository();
     _numericVariables[0] = _variableRepository.GetOrCreateVariable("A", new short[] { });
     _numericVariables[1] = _variableRepository.GetOrCreateVariable("B", new short[] { });
     _numericVariables[2] = _variableRepository.GetOrCreateVariable("C", new short[] { });
     _stringVariables[0]  = _variableRepository.GetOrCreateVariable("A$", new short[] { });
     _stringVariables[1]  = _variableRepository.GetOrCreateVariable("B$", new short[] { });
     _stringVariables[2]  = _variableRepository.GetOrCreateVariable("C$", new short[] { });
 }
예제 #8
0
        /// <summary>
        /// Executes the FOR command.
        /// </summary>
        public void Execute()
        {
            var stackEntry = new StackEntry();

            // We need the name and the classic MS interpreter only supports
            // non-array double variables, so we'll do the same.
            var token = _runEnvironment.CurrentLine.NextToken();

            if (token.TokenClass != TokenClass.Variable)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            stackEntry.VariableName = token.Text;
            var variableRef = _variableRepository.GetOrCreateVariable(token.Text, new short[] { });

            token = _runEnvironment.CurrentLine.NextToken();
            if (token.Seperator != TokenType.Equal)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            Accumulator startValue = _expressionEvaluator.GetExpression();

            variableRef.SetValue(startValue);

            token = _runEnvironment.CurrentLine.NextToken();
            if (token.Statement != TokenType.To)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            stackEntry.Target = _expressionEvaluator.GetExpression().ValueAsDouble();

            token = _runEnvironment.CurrentLine.NextToken();
            if (token.Statement != TokenType.Step)
            {
                _runEnvironment.CurrentLine.PushToken(token);
                stackEntry.Step = 1.0;
            }
            else
            {
                stackEntry.Step = _expressionEvaluator.GetExpression().ValueAsDouble();
            }

            stackEntry.Line      = _runEnvironment.CurrentLine;
            stackEntry.LineToken = _runEnvironment.CurrentLine.CurrentToken;

            bool doDelete = false;

            foreach (var entry in _runEnvironment.ProgramStack)
            {
                // Gosub / Return stop searching
                if (entry.VariableName == null)
                {
                    break;
                }

                // Name matches we should overwrite.
                if (entry.VariableName == stackEntry.VariableName)
                {
                    doDelete = true;
                    break;
                }
            }

            if (doDelete)
            {
                // Pop entries off the stack until we find us.
                while (_runEnvironment.ProgramStack.Pop().VariableName != stackEntry.VariableName)
                {
                }
            }

            _runEnvironment.ProgramStack.Push(stackEntry);
            _runEnvironment.TestForStackOverflow();
        }
예제 #9
0
        public void ForNextTest()
        {
            SetupSut();
            var forCmd  = new For(_runEnvironment, _mockExpressionEvaluator.Object, _variableRepository);
            var nextCmd = new Next(_runEnvironment, _variableRepository);

            _mockExpressionEvaluator.SetupSequence(mee => mee.GetExpression())
            .Returns(new Accumulator(1.0))
            .Returns(new Accumulator(3.0));
            var line10 = new ProgramLine(10, new List <IToken> {
                new Token("A"), _equalToken, _toToken, _colonToken
            });
            var line20 = new ProgramLine(20, new List <IToken> {
                new Token("A"), new Token("1")
            });

            _runEnvironment.CurrentLine = line10;

            forCmd.Execute();
            Assert.AreEqual(1.0, _variableRepository.GetOrCreateVariable("A", new short[] { }).GetValue().ValueAsDouble());
            Assert.AreEqual(1, _runEnvironment.ProgramStack.Count);
            var loopBackToken = _runEnvironment.CurrentLine.CurrentToken;

            // Execute next,
            line20.CurrentToken         = 0;
            _runEnvironment.CurrentLine = line20;
            nextCmd.Execute();

            // variable should be 2
            Assert.AreEqual(2.0, _variableRepository.GetOrCreateVariable("A", new short[] { }).GetValue().ValueAsDouble());

            // Should be back to just after for loop.
            Assert.AreEqual(10, _runEnvironment.CurrentLine.LineNumber.Value);
            Assert.AreEqual(loopBackToken, _runEnvironment.CurrentLine.CurrentToken);

            // Execute next, variable should be 3
            line20.CurrentToken         = 0;
            _runEnvironment.CurrentLine = line20;
            nextCmd.Execute();
            Assert.AreEqual(3.0, _variableRepository.GetOrCreateVariable("A", new short[] { }).GetValue().ValueAsDouble());
            Assert.AreEqual(10, _runEnvironment.CurrentLine.LineNumber.Value);
            Assert.AreEqual(loopBackToken, _runEnvironment.CurrentLine.CurrentToken);

            // Execute next
            line20.CurrentToken         = 0;
            _runEnvironment.CurrentLine = line20;
            nextCmd.Execute();

            // So we have exited the loop
            Assert.AreEqual(20, _runEnvironment.CurrentLine.LineNumber.Value);

            // Did we leave behind the token.
            var token = _runEnvironment.CurrentLine.NextToken();

            Assert.AreEqual("1", token.Text);

            // Variable should be 4.0
            Assert.AreEqual(4.0, _variableRepository.GetOrCreateVariable("A", new short[] { }).GetValue().ValueAsDouble());
            Assert.AreEqual(0, _runEnvironment.ProgramStack.Count);
        }
예제 #10
0
        /// <summary>
        /// Gets a variable reference which can be used a LValue for assignments.
        /// </summary>
        /// <returns>Reference to a variable.</returns>
        public VariableReference GetLeftValue()
        {
            string name = GetVariableName();

            return(_variableRepository.GetOrCreateVariable(name, GetIndexes()));
        }
예제 #11
0
        public void InputParsesNumbersAndStrings()
        {
            SetupSut();
            var tokens = new List <IToken>
            {
                new Token("A"), _comma,
                new Token("B"), _dollar, _comma,
                new Token("C"), _dollar
            };

            _runEnvironment.CurrentLine = new ProgramLine(10, tokens);

            _teletype.Input.Enqueue("23,\"456,abc\",456 abc");
            _sut.Execute();
            Assert.AreEqual("?", _teletype.Output.Dequeue());
            Assert.AreEqual(23.0, _variableRepository.GetOrCreateVariable("A", new short[] { }).GetValue().ValueAsDouble());
            Assert.AreEqual("456,abc", _variableRepository.GetOrCreateVariable("B$", new short[] { }).GetValue().ValueAsString());
            Assert.AreEqual("456 abc", _variableRepository.GetOrCreateVariable("C$", new short[] { }).GetValue().ValueAsString());
        }
예제 #12
0
        public void EvaluatorGetsDoubleVariable()
        {
            _variableRepository.GetOrCreateVariable("B", new short[] { }).SetValue(new Accumulator(5.5));
            _runEnvironment.CurrentLine = _tokeniser.Tokenise("10 PRINT B");
            _runEnvironment.CurrentLine.NextToken();    // Eat the print
            var result = _expressionEvaluator.GetExpression();

            Assert.AreEqual(5.5, result.ValueAsDouble());
        }