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)); }