public ChooseExpr(ParserRuleContext sourceLocation, IPExpr subExpr, PLanguageType type) { Type = type; SourceLocation = sourceLocation; SubExpr = subExpr; }
protected override void WriteTypeRef(PLanguageType type) { WriteParts(type.OriginalRepresentation); }
public SeqAccessExpr(ParserRuleContext sourceLocation, IPExpr seqExpr, IPExpr indexExpr, PLanguageType type) { SourceLocation = sourceLocation; SeqExpr = seqExpr; IndexExpr = indexExpr; Type = type; }
public TupleAccessExpr(ParserRuleContext sourceLocation, IPExpr subExpr, int fieldNo, PLanguageType type) { SourceLocation = sourceLocation; SubExpr = subExpr; FieldNo = fieldNo; Type = type; }
public NamedTupleExpr(ParserRuleContext sourceLocation, IPExpr[] tupleFields, PLanguageType type) { SourceLocation = sourceLocation; TupleFields = tupleFields; Type = type; }
protected abstract void WriteTypeRef(PLanguageType type);
public DefaultExpr(ParserRuleContext sourceLocation, PLanguageType type) { SourceLocation = sourceLocation; Type = type; }
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))}")); }
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))); } }
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}")); }
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})")); }
public Exception IncomparableTypes(ParserRuleContext location, PLanguageType lhsType, PLanguageType rhsType) { return(IssueError(location, $"types {lhsType.OriginalRepresentation} and {rhsType.OriginalRepresentation} are incomparable")); }
public MapType(PLanguageType keyType, PLanguageType valueType) : base(TypeKind.Map) { KeyType = keyType; ValueType = valueType; }
public ValuesExpr(ParserRuleContext sourceLocation, IPExpr expr, PLanguageType type) { SourceLocation = sourceLocation; Expr = expr; Type = type; }
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)); }
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")); }
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)); }
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)); }