public override void ExitBinaryExpression([NotNull] PigeonParser.BinaryExpressionContext context) { var left = Types.Get(context.expr(0)); var right = Types.Get(context.expr(1)); if (!BinaryOperator.TryGetResType(context.op.Text, left, right, out var type)) { errorBag.ReportInvalidTypeBinaryOperator(context.op.GetTextSpan(), context.op.Text, left, right); } Types.Put(context, type); }
public override object VisitBinaryExpression([NotNull] PigeonParser.BinaryExpressionContext context) { var left = Visit(context.expr(0)); var right = Visit(context.expr(1)); var resType = analyser.Types.Get(context); var areBothInt = analyser.Types.Get(context.expr(0)) == PigeonType.Int && analyser.Types.Get(context.expr(1)) == PigeonType.Int; switch (context.op.Text) { case "==": return(left.Equals(right)); case "!=": return(!left.Equals(right)); case "&&": return((bool)left && (bool)right); case "||": return((bool)left || (bool)right); case "<": if (areBothInt) { return((int)left < (int)right); } return(Convert.ToSingle(left) < Convert.ToSingle(right)); case ">": if (areBothInt) { return((int)left > (int)right); } return(Convert.ToSingle(left) > Convert.ToSingle(right)); case "<=": if (areBothInt) { return((int)left <= (int)right); } return(Convert.ToSingle(left) <= Convert.ToSingle(right)); case ">=": if (areBothInt) { return((int)left >= (int)right); } return(Convert.ToSingle(left) >= Convert.ToSingle(right)); case "+": if (resType == PigeonType.Int) { return((int)left + (int)right); } else if (resType == PigeonType.Float) { return(Convert.ToSingle(left) + Convert.ToSingle(right)); } else { return(left.ToString() + right.ToString()); } case "-": if (resType == PigeonType.Int) { return((int)left - (int)right); } return(Convert.ToSingle(left) - Convert.ToSingle(right)); case "*": if (resType == PigeonType.Int) { return((int)left * (int)right); } return(Convert.ToSingle(left) * Convert.ToSingle(right)); case "/": if (resType == PigeonType.Int) { return((int)left / (int)right); } return(Convert.ToSingle(left) / Convert.ToSingle(right)); case "%": return((int)left % (int)right); default: throw new InternalErrorException($"Unsupported binary operator {context.op.Text}"); } }