示例#1
0
 public ChooseExpr(ParserRuleContext sourceLocation, IPExpr subExpr, PLanguageType type)
 {
     Type           = type;
     SourceLocation = sourceLocation;
     SubExpr        = subExpr;
 }
示例#2
0
 protected override void WriteTypeRef(PLanguageType type)
 {
     WriteParts(type.OriginalRepresentation);
 }
示例#3
0
 public SeqAccessExpr(ParserRuleContext sourceLocation, IPExpr seqExpr, IPExpr indexExpr, PLanguageType type)
 {
     SourceLocation = sourceLocation;
     SeqExpr        = seqExpr;
     IndexExpr      = indexExpr;
     Type           = type;
 }
示例#4
0
 public TupleAccessExpr(ParserRuleContext sourceLocation, IPExpr subExpr, int fieldNo, PLanguageType type)
 {
     SourceLocation = sourceLocation;
     SubExpr        = subExpr;
     FieldNo        = fieldNo;
     Type           = type;
 }
示例#5
0
 public NamedTupleExpr(ParserRuleContext sourceLocation, IPExpr[] tupleFields, PLanguageType type)
 {
     SourceLocation = sourceLocation;
     TupleFields    = tupleFields;
     Type           = type;
 }
示例#6
0
 protected abstract void WriteTypeRef(PLanguageType type);
示例#7
0
 public DefaultExpr(ParserRuleContext sourceLocation, PLanguageType type)
 {
     SourceLocation = sourceLocation;
     Type           = type;
 }
示例#8
0
 public Exception TypeMismatch(ParserRuleContext location, PLanguageType actual, params PLanguageType[] expected)
 {
     return(IssueError(location,
                       $"got type: {actual.OriginalRepresentation}, expected: {string.Join("; ", expected.Select(t => t.OriginalRepresentation))}"));
 }
示例#9
0
        public override IPExpr VisitBinExpr(PParser.BinExprContext context)
        {
            IPExpr lhs = Visit(context.lhs);
            IPExpr rhs = Visit(context.rhs);
            string op  = context.op.Text;

            Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > 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) }
            };

            Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > 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) }
            };

            Dictionary <string, Func <IPExpr, IPExpr, IPExpr> > 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":
                PLanguageType 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 if (rhsType is SetType rhsSet)
                {
                    if (!rhsSet.ElementType.IsAssignableFrom(lhs.Type))
                    {
                        throw handler.TypeMismatch(context.lhs, lhs.Type, rhsSet.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)));
            }
        }
示例#10
0
 public Exception IllegalChooseSubExprType(PParser.ChooseExprContext context, PLanguageType subExprType)
 {
     return(IssueError(context, $"choose expects a parameter of type int (max value) or a collection type (seq, set, or map) got a parameter of type {subExprType}"));
 }
示例#11
0
        public Exception IllegalInterfaceCoerce(ParserRuleContext context, PLanguageType oldType, PLanguageType newType)
        {
            PEvent outlierEvent =
                newType.AllowedPermissions.Value.First(x => !oldType.AllowedPermissions.Value.Contains(x));

            return(IssueError(context,
                              $"illegal Coerce, {oldType.OriginalRepresentation} permissions is not a superset of {newType.OriginalRepresentation} (e.g., event {outlierEvent.Name})"));
        }
示例#12
0
 public Exception IncomparableTypes(ParserRuleContext location, PLanguageType lhsType, PLanguageType rhsType)
 {
     return(IssueError(location,
                       $"types {lhsType.OriginalRepresentation} and {rhsType.OriginalRepresentation} are incomparable"));
 }
示例#13
0
 public MapType(PLanguageType keyType, PLanguageType valueType) : base(TypeKind.Map)
 {
     KeyType   = keyType;
     ValueType = valueType;
 }
示例#14
0
 public ValuesExpr(ParserRuleContext sourceLocation, IPExpr expr, PLanguageType type)
 {
     SourceLocation = sourceLocation;
     Expr           = expr;
     Type           = type;
 }
示例#15
0
        public override IPStmt VisitGotoStmt(PParser.GotoStmtContext context)
        {
            if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null))
            {
                throw handler.ChangeStateInNonVoidFunction(context);
            }

            PParser.StateNameContext stateNameContext = context.stateName();
            string          stateName = stateNameContext.state.GetText();
            IStateContainer current   = machine;

            foreach (PParser.IdenContext token in stateNameContext._groups)
            {
                current = current?.GetGroup(token.GetText());
                if (current == null)
                {
                    throw handler.MissingDeclaration(token, "group", token.GetText());
                }
            }

            AST.States.State state = current?.GetState(stateName);
            if (state == null)
            {
                throw handler.MissingDeclaration(stateNameContext.state, "state", stateName);
            }

            PLanguageType expectedType =
                state.Entry?.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;

            IPExpr[] rvaluesList = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToArray();
            foreach (IPExpr arg in rvaluesList)
            {
                if (arg is LinearAccessRefExpr linearArg && linearArg.LinearType == LinearType.Swap)
                {
                    throw handler.InvalidSwap(linearArg, "swap not allowed on goto");
                }
            }

            IPExpr payload;

            if (rvaluesList.Length == 0)
            {
                payload = null;
            }
            else if (rvaluesList.Length == 1)
            {
                payload = rvaluesList[0];
            }
            else
            {
                payload = new UnnamedTupleExpr(context, rvaluesList);
            }

            PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null;

            if (!expectedType.IsAssignableFrom(payloadType))
            {
                throw handler.TypeMismatch(context, payloadType, expectedType);
            }

            method.CanChangeState = true;
            return(new GotoStmt(context, state, payload));
        }
示例#16
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            IPExpr        subExpr = Visit(context.expr());
            PLanguageType oldType = subExpr.Type;
            PLanguageType newType = TypeResolver.ResolveType(context.type(), table, handler);

            if (context.cast.Text.Equals("as"))
            {
                if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType))
                {
                    throw handler.IncomparableTypes(context, oldType, newType);
                }

                return(new CastExpr(context, subExpr, newType));
            }

            if (context.cast.Text.Equals("to"))
            {
                if (!(newType is PermissionType || newType.IsSameTypeAs(PrimitiveType.Int) ||
                      newType.IsSameTypeAs(PrimitiveType.Float)))
                {
                    throw handler.IllegalTypeInCoerceExpr(context);
                }

                if (oldType.IsSameTypeAs(PrimitiveType.Int))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Float))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Float))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum))
                {
                    // TODO: are enum-to-enum coersions allowed?
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }

                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Machine) || oldType is PermissionType)
                {
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }

                    if (newType is PermissionType)
                    {
                        if (oldType.IsSameTypeAs(PrimitiveType.Machine))
                        {
                            return(new CoerceExpr(context, subExpr, newType));
                        }

                        if (oldType is PermissionType)
                        {
                            if (newType.AllowedPermissions.Value.Any(x => !oldType.AllowedPermissions.Value.Contains(x))
                                )
                            {
                                throw handler.IllegalInterfaceCoerce(context, oldType, newType);
                            }

                            return(new CoerceExpr(context, subExpr, newType));
                        }
                    }
                }

                throw handler.IncomparableTypes(context, oldType, newType);
            }

            throw handler.InternalError(context, new ArgumentOutOfRangeException(nameof(context), "invalid cast"));
        }
示例#17
0
        public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context)
        {
            if (machine?.IsSpec == true)
            {
                throw handler.IllegalMonitorOperation(context, context.RECEIVE().Symbol, machine);
            }

            Dictionary <PEvent, Function> cases = new Dictionary <PEvent, Function>();

            foreach (PParser.RecvCaseContext caseContext in context.recvCase())
            {
                Function recvHandler =
                    new Function(caseContext.anonEventHandler())
                {
                    Scope          = table.MakeChildScope(),
                    Owner          = method.Owner,
                    ParentFunction = method,
                    Role           = FunctionRole.ReceiveHandler
                };

                if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param)
                {
                    Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param);
                    paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler);
                    recvHandler.Signature.Parameters.Add(paramVar);
                }

                FunctionBodyVisitor.PopulateMethod(handler, recvHandler);

                foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId())
                {
                    if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent))
                    {
                        throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText());
                    }

                    if (cases.ContainsKey(pEvent))
                    {
                        throw handler.DuplicateReceiveCase(eventIdContext, pEvent);
                    }

                    PLanguageType expectedType =
                        recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;
                    if (!expectedType.IsAssignableFrom(pEvent.PayloadType))
                    {
                        throw handler.TypeMismatch(caseContext.anonEventHandler(), expectedType,
                                                   pEvent.PayloadType);
                    }

                    if (recvHandler.CanChangeState == true)
                    {
                        if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null))
                        {
                            throw handler.ChangeStateInNonVoidFunction(context);
                        }

                        method.CanChangeState = true;
                    }

                    if (recvHandler.CanRaiseEvent == true)
                    {
                        if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null))
                        {
                            throw handler.RaiseEventInNonVoidFunction(context);
                        }

                        method.CanRaiseEvent = true;
                    }

                    foreach (var callee in recvHandler.Callees)
                    {
                        method.AddCallee(callee);
                    }

                    cases.Add(pEvent, recvHandler);
                }
            }

            method.CanReceive = true;
            return(new ReceiveStmt(context, cases));
        }
示例#18
0
        private string SimplifiedRep(PLanguageType type)
        {
            switch (type.Canonicalize())
            {
            case DataType _:
                return("B");

            case EnumType _:
                return("E");

            case ForeignType foreign:
                return(foreign.CanonicalRepresentation);

            case MapType mapType:
                return($"MK{SimplifiedRep(mapType.KeyType)}V{SimplifiedRep(mapType.ValueType)}");

            case PermissionType _:
                return("R");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Bool):
                return("b");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Int):
                return("i");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Float):
                return("f");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Event):
                return("e");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Machine):
                return("m");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.String):
                return("r");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Any):
                return("a");

            case PrimitiveType primitiveType when Equals(primitiveType, PrimitiveType.Null):
                return("n");

            case PrimitiveType _:
                throw new ArgumentException("unrecognized primitive type", nameof(type));

            case SequenceType sequenceType:
                return($"S{SimplifiedRep(sequenceType.ElementType)}");

            case SetType setType:
                return($"U{SimplifiedRep(setType.ElementType)}");

            case TupleType tupleType:
                return($"T{tupleType.Types.Count}{string.Join("", tupleType.Types.Select(SimplifiedRep))}");

            case TypeDefType _:
                throw new ArgumentException("typedefs should be impossible after canonicalization", nameof(type));
            }

            throw new ArgumentException("unrecognized type kind", nameof(type));
        }