private void SolveOperation(Context context, OpCode opCode)
        {
            var right = context.Pop();
            var left  = context.Pop();

            context.Push(_expressionSolver.Solve(opCode, left, right));
        }
        public override ParseResult VisitBinaryOperationExp(MelonParser.BinaryOperationExpContext context)
        {
            var left         = Visit(context.Left);
            var right        = Visit(context.Right);
            var opCode       = _opCodeText[context.Operation.Text];
            var operatorName = MelonVisitor._opCodeText.FirstOrDefault(x => x.Value == opCode).Key;

            var leftType  = left.typeReference.Type;
            var rightType = right.typeReference.Type;

            var getOutComeType = _expressionSolver.GetTypeForOperation(opCode, leftType, rightType);

            if (getOutComeType == null && (left.typeReference.TypeId != 0 && right.typeReference.TypeId != 0))
            {
                throw new MelonException($"No such operation: '{leftType.Name}' {operatorName} '{rightType.Name}'.");
            }

            if (left is ParseResult leftResult && right is ParseResult rightResult)
            {
                if (leftResult.type == ParseResultTypes.Literal && rightResult.type == ParseResultTypes.Literal)
                {
                    // Remove left side instructions
                    var leftLiteralOp = _opCodeLiteralTypes[leftResult.value.GetType()];
                    parseContext.instructions.RemoveRange(parseContext.instructions.Count - _opCodeArgs[leftLiteralOp] - 1, _opCodeArgs[leftLiteralOp] + 1);
                    instructionline--;

                    // Remove right side instructions
                    var rightLiteralOp = _opCodeLiteralTypes[rightResult.value.GetType()];
                    parseContext.instructions.RemoveRange(parseContext.instructions.Count - _opCodeArgs[rightLiteralOp] - 1, _opCodeArgs[rightLiteralOp] + 1);
                    instructionline--;

                    // Emit instructions for result value
                    var result = _expressionSolver.Solve(_opCodeText[context.Operation.Text], leftResult.value, rightResult.value);

                    if (result is MelonErrorObject melonErrorObject)
                    {
                        throw new MelonException($"No such operation: '{leftType.Name}' {operatorName} '{rightType.Name}'.");
                    }

                    parseContext.instructions.AddRange(GetInstructionsForLiteralValue(result));
                    instructionline++;

                    return(new ParseResult {
                        type = ParseResultTypes.Literal,
                        value = result,
                        typeReference = new TypeReference(_engine, GetTypeReference(result))
                    });
                }
            }

            parseContext.instructions.AddRange(GetInstructionsForOperation(context.Operation.Text, out int lineIncrease));
            instructionline += lineIncrease;

            var typeReference = _engine.Types.FirstOrDefault(t => t.Value.GetType() == getOutComeType).Key;

            return(new ParseResult {
                typeReference = new TypeReference(_engine, typeReference)
            });
        }
        public void ExpressionSolverTest(decimal expectedRes, string expression)
        {
            var parser     = new ExpressionParser();
            var solver     = new ExpressionSolver();
            var parsedData = parser.Parse(expression);

            Assert.AreEqual(expectedRes, solver.Solve(parsedData));
        }