public Exception BinOpTypeMismatch( PParser.BinExprContext location, PLanguageType lhsType, PLanguageType rhsType) { return(IssueError(location, location.op, $"expected either both float or both int; got {lhsType.OriginalRepresentation} and {rhsType.OriginalRepresentation}")); }
public override IPExpr VisitBinExpr(PParser.BinExprContext context) { var lhs = Visit(context.lhs); var rhs = Visit(context.rhs); var op = context.op.Text; var arithCtors = new Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > { { "*", (elhs, erhs) => new BinOpExpr(context, BinOpType.Mul, elhs, erhs) }, { "/", (elhs, erhs) => new BinOpExpr(context, BinOpType.Div, elhs, erhs) }, { "+", (elhs, erhs) => new BinOpExpr(context, BinOpType.Add, elhs, erhs) }, { "-", (elhs, erhs) => new BinOpExpr(context, BinOpType.Sub, elhs, erhs) }, { "<", (elhs, erhs) => new BinOpExpr(context, BinOpType.Lt, elhs, erhs) }, { "<=", (elhs, erhs) => new BinOpExpr(context, BinOpType.Le, elhs, erhs) }, { ">", (elhs, erhs) => new BinOpExpr(context, BinOpType.Gt, elhs, erhs) }, { ">=", (elhs, erhs) => new BinOpExpr(context, BinOpType.Ge, elhs, erhs) } }; var logicCtors = new Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > { { "&&", (elhs, erhs) => new BinOpExpr(context, BinOpType.And, elhs, erhs) }, { "||", (elhs, erhs) => new BinOpExpr(context, BinOpType.Or, elhs, erhs) } }; var compCtors = new Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > { { "==", (elhs, erhs) => new BinOpExpr(context, BinOpType.Eq, elhs, erhs) }, { "!=", (elhs, erhs) => new BinOpExpr(context, BinOpType.Neq, elhs, erhs) } }; switch (op) { case "+": case "*": case "/": case "-": case "<": case ">": case ">=": case "<=": if (!(PrimitiveType.Int.IsAssignableFrom(lhs.Type) && PrimitiveType.Int.IsAssignableFrom(rhs.Type) || PrimitiveType.Float.IsAssignableFrom(lhs.Type) && PrimitiveType.Float.IsAssignableFrom(rhs.Type))) { throw handler.BinOpTypeMismatch(context, lhs.Type, rhs.Type); } return(arithCtors[op](lhs, rhs)); case "in": var rhsType = rhs.Type.Canonicalize(); if (rhsType is MapType rhsMap) { if (!rhsMap.KeyType.IsAssignableFrom(lhs.Type)) { throw handler.TypeMismatch(context.lhs, lhs.Type, rhsMap.KeyType); } } else if (rhsType is SequenceType rhsSeq) { if (!rhsSeq.ElementType.IsAssignableFrom(lhs.Type)) { throw handler.TypeMismatch(context.lhs, lhs.Type, rhsSeq.ElementType); } } else { throw handler.TypeMismatch(rhs, TypeKind.Map, TypeKind.Sequence); } return(new ContainsExpr(context, lhs, rhs)); case "==": case "!=": if (!lhs.Type.IsAssignableFrom(rhs.Type) && !rhs.Type.IsAssignableFrom(lhs.Type)) { throw handler.IncomparableTypes(context, lhs.Type, rhs.Type); } return(compCtors[op](lhs, rhs)); case "&&": case "||": if (!PrimitiveType.Bool.IsAssignableFrom(lhs.Type)) { throw handler.TypeMismatch(context.lhs, lhs.Type, PrimitiveType.Bool); } if (!PrimitiveType.Bool.IsAssignableFrom(rhs.Type)) { throw handler.TypeMismatch(context.rhs, rhs.Type, PrimitiveType.Bool); } return(logicCtors[op](lhs, rhs)); default: throw handler.InternalError(context, new ArgumentException($"unknown binary operation {op}", nameof(context))); } }
public override object VisitBinExpr(PParser.BinExprContext context) { return(null); }