public void VirtualMachineExecutesCallFunctionCorrectlyForRecursive(int paramValue1, int paramValue2, long expected)
        {
            var functionDefinition1 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, paramValue1),
                new Instruction(IntegerConstantToStack, paramValue2),
                new Instruction(CallFunction, 1L),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var functionDefinition2 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(StackToVariable, 1L),
                new Instruction(StackToVariable, 0L),
                new Instruction(VariableToStack, 1L),
                new Instruction(IntegerConstantToStack, 0L),
                new Instruction(IntegerEqual),
                new Instruction(BranchTrue, 14L),
                new Instruction(VariableToStack, 0L),
                new Instruction(VariableToStack, 1L),
                new Instruction(IntegerConstantToStack, 1L),
                new Instruction(IntegerSubtract),
                new Instruction(CallFunction, 1L),
                new Instruction(VariableToStack, 0L),
                new Instruction(IntegerMultiply),
                new Instruction(Branch, 15L),
                new Instruction(IntegerConstantToStack, 1L),
                new Instruction(IntegerConstantToStack, 1L),     // this and next statement used as a NOP.
                new Instruction(IntegerMultiply),
            },
                new List <VmType> {
                VmType.Integer, VmType.Integer
            },
                new List <VmType> {
                VmType.Integer
            },
                2
                );

            var vm = new VirtualMachine(functionDefinition1, functionDefinition2);

            VmValue executionResult = vm.Execute()[0];

            long actual = ((VmInteger)executionResult).Val;

            Assert.Equal(expected, actual);
        }
        public void CallFunctionBehavesCorrectlyWithMultipleReturnValues(int paramValue1, int paramValue2, int paramValue3, int paramValue4, long expected)
        {
            var functionDefinition1 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, paramValue1),
                new Instruction(IntegerConstantToStack, paramValue2),
                new Instruction(IntegerConstantToStack, paramValue3),
                new Instruction(IntegerConstantToStack, paramValue4),
                new Instruction(CallFunction, 1L),
                new Instruction(IntegerSubtract),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var functionDefinition2 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerDivide),
                new Instruction(StackToVariable, 0L),
                new Instruction(IntegerDivide),
                new Instruction(VariableToStack, 0L),
            },
                new List <VmType> {
                VmType.Integer, VmType.Integer, VmType.Integer, VmType.Integer
            },
                new List <VmType> {
                VmType.Integer, VmType.Integer
            },
                1
                );

            var vm = new VirtualMachine(functionDefinition1, functionDefinition2);

            VmValue executionResult = vm.Execute()[0];

            long actual = ((VmInteger)executionResult).Val;

            Assert.Equal(expected, actual);
        }
        public void VirtualMachineExecutesCallFunctionCorrectlyWithItemsOnStack(int paramValue1, int paramValue2, long expected)
        {
            var functionDefinition1 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, 10),
                new Instruction(IntegerConstantToStack, 10),
                new Instruction(IntegerConstantToStack, paramValue1),
                new Instruction(IntegerConstantToStack, paramValue2),
                new Instruction(CallFunction, 1L),
                new Instruction(IntegerMultiply),
                new Instruction(IntegerMultiply),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var functionDefinition2 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerSubtract),
            },
                new List <VmType> {
                VmType.Integer, VmType.Integer
            },
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var vm = new VirtualMachine(functionDefinition1, functionDefinition2);

            VmValue executionResult = vm.Execute()[0];

            long actual = ((VmInteger)executionResult).Val;

            Assert.Equal(expected, actual);
        }
        public void VirtualMachineExecutesCallFunctionCorrectlyForOneParam(int paramValue, long expected)
        {
            var functionDefinition1 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, paramValue),
                new Instruction(CallFunction, 1L),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var functionDefinition2 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(StackToVariable, 0L),
                new Instruction(VariableToStack, 0L),
                new Instruction(VariableToStack, 0L),
                new Instruction(IntegerMultiply),
            },
                new List <VmType> {
                VmType.Integer
            },
                new List <VmType> {
                VmType.Integer
            },
                1
                );

            var vm = new VirtualMachine(functionDefinition1, functionDefinition2);

            VmValue executionResult = vm.Execute()[0];

            long actual = ((VmInteger)executionResult).Val;

            Assert.Equal(expected, actual);
        }
        public void VirtualMachineExecutesCorrectFunction(int?functionToExecute, long expected)
        {
            var functionDefinition1 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, 3L),
                new Instruction(IntegerConstantToStack, 3L),
                new Instruction(IntegerMultiply),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var functionDefinition2 = new FunctionDefinition(
                new List <Instruction>()
            {
                new Instruction(IntegerConstantToStack, 3L),
                new Instruction(IntegerConstantToStack, 3L),
                new Instruction(IntegerMultiply),
                new Instruction(IntegerConstantToStack, 3L),
                new Instruction(IntegerMultiply),
            },
                new List <VmType>(),
                new List <VmType> {
                VmType.Integer
            },
                0
                );

            var vm = new VirtualMachine(functionDefinition1, functionDefinition2);

            VmValue executionResult = vm.Execute(functionToExecute ?? 0)[0];

            long actual = ((VmInteger)executionResult).Val;

            Assert.Equal(expected, actual);
        }