Beispiel #1
0
 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}"));
 }
Beispiel #2
0
        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)));
            }
        }
Beispiel #3
0
 public override object VisitBinExpr(PParser.BinExprContext context)
 {
     return(null);
 }