public override IPStmt VisitStringAssignStmt(PParser.StringAssignStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); string baseString = context.StringLiteral().GetText(); baseString = baseString.Substring(1, baseString.Length - 2); // strip beginning / end double quote int numNecessaryArgs = TypeCheckingUtils.PrintStmtNumArgs(baseString); if (numNecessaryArgs == -1) { throw handler.InvalidStringAssignFormat(context, context.StringLiteral().Symbol); } List <IPExpr> args = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToList(); foreach (IPExpr arg in args) { if (arg is LinearAccessRefExpr) { throw handler.StringAssignStmtLinearArgument(arg.SourceLocation); } } if (args.Count != numNecessaryArgs) { throw handler.IncorrectArgumentCount(context, args.Count, numNecessaryArgs); } if (variable.Type != PrimitiveType.String) { throw handler.TypeMismatch(context, variable.Type, PrimitiveType.String); } return(new StringAssignStmt(context, variable, baseString, args)); }
public override IPStmt VisitSendStmt(PParser.SendStmtContext context) { IPExpr machineExpr = exprVisitor.Visit(context.machine); if (!PrimitiveType.Machine.IsAssignableFrom(machineExpr.Type)) { throw handler.TypeMismatch(context.machine, machineExpr.Type, PrimitiveType.Machine); } IPExpr evtExpr = exprVisitor.Visit(context.@event); if (IsDefinitelyNullEvent(evtExpr)) { throw handler.EmittedNullEvent(evtExpr); } if (!PrimitiveType.Event.IsAssignableFrom(evtExpr.Type)) { throw handler.TypeMismatch(context.@event, evtExpr.Type, PrimitiveType.Event); } IPExpr[] args = (context.rvalueList()?.rvalue().Select(rv => exprVisitor.Visit(rv)) ?? Enumerable.Empty <IPExpr>()).ToArray(); if (evtExpr is EventRefExpr eventRef) { TypeCheckingUtils.ValidatePayloadTypes(handler, context, eventRef.PEvent.PayloadType, args); } return(new SendStmt(context, machineExpr, evtExpr, args)); }
public override IPStmt VisitRaiseStmt(PParser.RaiseStmtContext context) { IPExpr evtExpr = exprVisitor.Visit(context.expr()); if (IsDefinitelyNullEvent(evtExpr)) { throw handler.EmittedNullEvent(evtExpr); } if (!PrimitiveType.Event.IsAssignableFrom(evtExpr.Type)) { throw handler.TypeMismatch(context.expr(), evtExpr.Type, PrimitiveType.Event); } method.CanCommunicate = true; method.CanChangeState = true; IPExpr[] args = (context.rvalueList()?.rvalue().Select(rv => exprVisitor.Visit(rv)) ?? Enumerable.Empty <IPExpr>()).ToArray(); if (evtExpr is EventRefExpr eventRef) { TypeCheckingUtils.ValidatePayloadTypes(handler, context, eventRef.PEvent.PayloadType, args); } return(new RaiseStmt(context, evtExpr, args)); }
public MapAccessExpr(ParserRuleContext sourceLocation, IPExpr mapExpr, IPExpr indexExpr, PLanguageType type) { SourceLocation = sourceLocation; MapExpr = mapExpr; IndexExpr = indexExpr; Type = type; }
private (IPExpr, List <IPStmt>) SimplifyLvalue(IPExpr expr) { // TODO: I am suspicious. Antlr4.Runtime.ParserRuleContext location = expr.SourceLocation; PLanguageType type = expr.Type; switch (expr) { case MapAccessExpr mapAccessExpr: (IPExpr mapExpr, List <IPStmt> mapExprDeps) = SimplifyLvalue(mapAccessExpr.MapExpr); (IExprTerm mapIndex, List <IPStmt> mapIndexDeps) = SimplifyExpression(mapAccessExpr.IndexExpr); return(new MapAccessExpr(location, mapExpr, mapIndex, type), mapExprDeps.Concat(mapIndexDeps).ToList()); case NamedTupleAccessExpr namedTupleAccessExpr: (IPExpr ntExpr, List <IPStmt> ntExprDeps) = SimplifyLvalue(namedTupleAccessExpr.SubExpr); return(new NamedTupleAccessExpr(location, ntExpr, namedTupleAccessExpr.Entry), ntExprDeps); case SeqAccessExpr seqAccessExpr: (IPExpr seqExpr, List <IPStmt> seqExprDeps) = SimplifyLvalue(seqAccessExpr.SeqExpr); (IExprTerm seqIndex, List <IPStmt> seqIndexDeps) = SimplifyExpression(seqAccessExpr.IndexExpr); return(new SeqAccessExpr(location, seqExpr, seqIndex, type), seqExprDeps.Concat(seqIndexDeps).ToList()); case TupleAccessExpr tupleAccessExpr: (IPExpr tupExpr, List <IPStmt> tupExprDeps) = SimplifyLvalue(tupleAccessExpr.SubExpr); return(new TupleAccessExpr(location, tupExpr, tupleAccessExpr.FieldNo, type), tupExprDeps); case VariableAccessExpr variableAccessExpr: return(variableAccessExpr, new List <IPStmt>()); default: throw new ArgumentOutOfRangeException(nameof(expr)); } }
public TupleAccessExpr(ParserRuleContext sourceLocation, IPExpr subExpr, int fieldNo, PLanguageType type) { SourceLocation = sourceLocation; SubExpr = subExpr; FieldNo = fieldNo; Type = type; }
public override IPStmt VisitSendStmt(PParser.SendStmtContext context) { if (machine?.IsSpec == true) { throw handler.IllegalMonitorOperation(context, context.SEND().Symbol, machine); } IPExpr machineExpr = exprVisitor.Visit(context.machine); if (!PrimitiveType.Machine.IsAssignableFrom(machineExpr.Type)) { throw handler.TypeMismatch(context.machine, machineExpr.Type, PrimitiveType.Machine); } IPExpr evtExpr = exprVisitor.Visit(context.@event); if (IsDefinitelyNullEvent(evtExpr)) { throw handler.EmittedNullEvent(evtExpr); } if (!PrimitiveType.Event.IsAssignableFrom(evtExpr.Type)) { throw handler.TypeMismatch(context.@event, evtExpr.Type, PrimitiveType.Event); } IPExpr[] args = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToArray(); if (evtExpr is EventRefExpr eventRef) { TypeCheckingUtils.ValidatePayloadTypes(handler, context, eventRef.Value.PayloadType, args); } return(new SendStmt(context, machineExpr, evtExpr, args)); }
public IfStmt(ParserRuleContext sourceLocation, IPExpr condition, IPStmt thenBranch, IPStmt elseBranch) { SourceLocation = sourceLocation; Condition = condition; ThenBranch = CompoundStmt.FromStatement(thenBranch); ElseBranch = elseBranch == null ? null : CompoundStmt.FromStatement(elseBranch); }
public InsertStmt(ParserRuleContext sourceLocation, IPExpr variable, IPExpr index, IPExpr value) { SourceLocation = sourceLocation; Variable = variable; Index = index; Value = value; }
public override IPStmt VisitRaiseStmt(PParser.RaiseStmtContext context) { if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.RaiseEventInNonVoidFunction(context); } IPExpr evtExpr = exprVisitor.Visit(context.expr()); if (IsDefinitelyNullEvent(evtExpr)) { throw handler.EmittedNullEvent(evtExpr); } if (!PrimitiveType.Event.IsAssignableFrom(evtExpr.Type)) { throw handler.TypeMismatch(context.expr(), evtExpr.Type, PrimitiveType.Event); } method.CanRaiseEvent = true; IPExpr[] args = TypeCheckingUtils.VisitRvalueList(context.rvalueList(), exprVisitor).ToArray(); if (evtExpr is EventRefExpr eventRef) { TypeCheckingUtils.ValidatePayloadTypes(handler, context, eventRef.Value.PayloadType, args); } return(new RaiseStmt(context, evtExpr, args)); }
public override IPStmt VisitAssertStmt(PParser.AssertStmtContext context) { IPExpr assertion = exprVisitor.Visit(context.assertion); if (!PrimitiveType.Bool.IsSameTypeAs(assertion.Type)) { throw handler.TypeMismatch(context.assertion, assertion.Type, PrimitiveType.Bool); } IPExpr message; if (context.message == null) { message = new StringExpr(context, "", new List <IPExpr>()); } else { message = exprVisitor.Visit(context.message); if (!message.Type.IsSameTypeAs(PrimitiveType.String)) { throw handler.TypeMismatch(context.message, message.Type, PrimitiveType.String); } } return(new AssertStmt(context, assertion, message)); }
public UnaryOpExpr(ParserRuleContext sourceLocation, UnaryOpType operation, IPExpr subExpr) { SourceLocation = sourceLocation; Operation = operation; SubExpr = subExpr; Type = subExpr.Type; }
public IfStmt(ParserRuleContext sourceLocation, IPExpr condition, IPStmt thenBranch, IPStmt elseBranch) { SourceLocation = sourceLocation; Condition = condition; ThenBranch = thenBranch; ElseBranch = elseBranch; }
public SetAccessExpr(ParserRuleContext sourceLocation, IPExpr setExpr, IPExpr indexExpr, PLanguageType type) { SourceLocation = sourceLocation; SetExpr = setExpr; IndexExpr = indexExpr; Type = type; }
public override IPStmt VisitRemoveStmt(PParser.RemoveStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr value = exprVisitor.Visit(context.expr()); if (PLanguageType.TypeIsOfKind(variable.Type, TypeKind.Sequence)) { if (!PrimitiveType.Int.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.expr(), value.Type, PrimitiveType.Int); } } else if (PLanguageType.TypeIsOfKind(variable.Type, TypeKind.Map)) { var map = (MapType)variable.Type.Canonicalize(); if (!map.KeyType.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.expr(), value.Type, map.KeyType); } } else { throw handler.TypeMismatch(variable, TypeKind.Sequence, TypeKind.Map); } return(new RemoveStmt(context, variable, value)); }
public StringAssignStmt(ParserRuleContext sourceLocation, IPExpr location, string baseString, List <IPExpr> args) { SourceLocation = sourceLocation; Location = location; BaseString = baseString; Args = args; }
public SendStmt(ParserRuleContext sourceLocation, IPExpr machineExpr, IPExpr evt, IReadOnlyList <IPExpr> arguments) { SourceLocation = sourceLocation; MachineExpr = machineExpr; Evt = evt; Arguments = arguments; }
public override IPStmt VisitPrintStmt(PParser.PrintStmtContext context) { IPExpr message = exprVisitor.Visit(context.message); if (!message.Type.IsSameTypeAs(PrimitiveType.String)) { throw handler.TypeMismatch(context.message, message.Type, PrimitiveType.String); } return(new PrintStmt(context, message)); }
public override IPStmt VisitReturnStmt(PParser.ReturnStmtContext context) { IPExpr returnValue = context.expr() == null ? null : exprVisitor.Visit(context.expr()); PLanguageType returnType = returnValue?.Type ?? PrimitiveType.Null; if (!method.Signature.ReturnType.IsAssignableFrom(returnType)) { throw handler.TypeMismatch(context, returnType, method.Signature.ReturnType); } return(new ReturnStmt(context, returnValue)); }
public override IPStmt VisitAssertStmt(PParser.AssertStmtContext context) { IPExpr assertion = exprVisitor.Visit(context.expr()); if (!PrimitiveType.Bool.IsSameTypeAs(assertion.Type)) { throw handler.TypeMismatch(context.expr(), assertion.Type, PrimitiveType.Bool); } string message = context.StringLiteral()?.GetText() ?? ""; return(new AssertStmt(context, assertion, message)); }
private (VariableAccessExpr, IPStmt) SaveInTemporary(IPExpr expr, PLanguageType tempType) { Antlr4.Runtime.ParserRuleContext location = expr.SourceLocation; Variable temp = function.Scope.Put($"$tmp{numTemp++}", location, VariableRole.Local | VariableRole.Temp); Debug.Assert(tempType.IsAssignableFrom(expr.Type)); temp.Type = tempType; function.AddLocalVariable(temp); AssignStmt stmt = new AssignStmt(location, new VariableAccessExpr(location, temp), expr); return(new VariableAccessExpr(location, temp), stmt); }
public override IPStmt VisitWhileStmt(PParser.WhileStmtContext context) { IPExpr condition = exprVisitor.Visit(context.expr()); if (condition.Type != PrimitiveType.Bool) { throw handler.TypeMismatch(context.expr(), condition.Type, PrimitiveType.Bool); } IPStmt body = Visit(context.statement()); return(new WhileStmt(context, condition, body)); }
public override IPStmt VisitIfStmt(PParser.IfStmtContext context) { IPExpr condition = exprVisitor.Visit(context.expr()); if (condition.Type != PrimitiveType.Bool) { throw handler.TypeMismatch(context.expr(), condition.Type, PrimitiveType.Bool); } IPStmt thenBody = Visit(context.thenBranch); IPStmt elseBody = context.elseBranch == null ? new NoStmt(context) : Visit(context.elseBranch); return(new IfStmt(context, condition, thenBody, elseBody)); }
public override IPStmt VisitInsertStmt(PParser.InsertStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr index = exprVisitor.Visit(context.expr()); IPExpr value = exprVisitor.Visit(context.rvalue()); // Check linear types var valueIsInvariant = false; if (value is ILinearRef linearRef) { valueIsInvariant = linearRef.LinearType.Equals(LinearType.Swap); } // Check subtyping PLanguageType keyType = index.Type; PLanguageType valueType = value.Type; PLanguageType expectedKeyType; PLanguageType expectedValueType; switch (variable.Type.Canonicalize()) { case SequenceType sequenceType: expectedKeyType = PrimitiveType.Int; expectedValueType = sequenceType.ElementType; break; case MapType mapType: expectedKeyType = mapType.KeyType; expectedValueType = mapType.ValueType; break; default: throw handler.TypeMismatch(variable, TypeKind.Sequence, TypeKind.Map); } if (!expectedKeyType.IsAssignableFrom(keyType)) { throw handler.TypeMismatch(context.rvalue(), keyType, expectedKeyType); } if (valueIsInvariant && !expectedValueType.IsSameTypeAs(valueType) || !valueIsInvariant && !expectedValueType.IsAssignableFrom(valueType)) { throw handler.TypeMismatch(context.rvalue(), valueType, expectedValueType); } return(new InsertStmt(context, variable, index, value)); }
public static void CheckArgument(ITranslationErrorHandler handler, ParserRuleContext context, PLanguageType argumentType, IPExpr arg) { if (arg is ILinearRef linearRef) { if (linearRef.LinearType.Equals(LinearType.Swap) && !arg.Type.IsSameTypeAs(argumentType)) { throw handler.TypeMismatch(context, arg.Type, argumentType); } } if (!argumentType.IsAssignableFrom(arg.Type)) { throw handler.TypeMismatch(context, arg.Type, argumentType); } }
public BinOpExpr(ParserRuleContext sourceLocation, BinOpType operation, IPExpr lhs, IPExpr rhs) { SourceLocation = sourceLocation; Operation = operation; Lhs = lhs; Rhs = rhs; if (IsArithmetic(operation)) { Debug.Assert(Lhs.Type.IsSameTypeAs(Rhs.Type)); Type = Lhs.Type; } else { Type = PrimitiveType.Bool; } }
public override IPStmt VisitAssignStmt(PParser.AssignStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr value = exprVisitor.Visit(context.rvalue()); // If we're doing a move/swap assignment if (value is ILinearRef linearRef) { Variable refVariable = linearRef.Variable; switch (linearRef.LinearType) { case LinearType.Move: // Moved values must be subtypes of their destinations if (!variable.Type.IsAssignableFrom(refVariable.Type)) { throw handler.TypeMismatch(context.rvalue(), refVariable.Type, variable.Type); } return(new MoveAssignStmt(context, variable, refVariable)); case LinearType.Swap: // Within a function, swaps must only be subtyped in either direction // the actual types are checked at runtime. This is to allow swapping // with the `any` type. if (!variable.Type.IsAssignableFrom(refVariable.Type) && !refVariable.Type.IsAssignableFrom(variable.Type)) { throw handler.TypeMismatch(context.rvalue(), refVariable.Type, variable.Type); } return(new SwapAssignStmt(context, variable, refVariable)); default: throw handler.InternalError(linearRef.SourceLocation, new ArgumentOutOfRangeException(nameof(context))); } } // If this is a value assignment, we just need subtyping if (!variable.Type.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.rvalue(), value.Type, variable.Type); } return(new AssignStmt(context, variable, value)); }
public override IPStmt VisitGotoStmt(PParser.GotoStmtContext 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()); } } State state = current?.GetState(stateName); if (state == null) { throw handler.MissingDeclaration(stateNameContext.state, "state", stateName); } IPExpr payload = null; PLanguageType expectedType = state.Entry.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; if (context.rvalueList()?.rvalue() is PParser.RvalueContext[] rvalues) { if (rvalues.Length == 1) { payload = exprVisitor.Visit(rvalues[0]); } else { IPExpr[] tupleFields = rvalues.Select(exprVisitor.Visit).ToArray(); payload = new UnnamedTupleExpr(context, tupleFields, new TupleType(tupleFields.Select(f => f.Type).ToList())); } } PLanguageType payloadType = payload?.Type ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(payloadType)) { throw handler.TypeMismatch(context, payloadType, expectedType); } return(new GotoStmt(context, state, payload)); }
public override IPStmt VisitAnnounceStmt(PParser.AnnounceStmtContext context) { IPExpr evtExpr = exprVisitor.Visit(context.expr()); if (IsDefinitelyNullEvent(evtExpr)) { throw handler.EmittedNullEvent(evtExpr); } if (!PrimitiveType.Event.IsAssignableFrom(evtExpr.Type)) { throw handler.TypeMismatch(context.expr(), evtExpr.Type, PrimitiveType.Event); } List <IPExpr> args = (context.rvalueList()?.rvalue().Select(rv => exprVisitor.Visit(rv)) ?? Enumerable.Empty <IPExpr>()).ToList(); return(new AnnounceStmt(context, evtExpr, args.Count == 0 ? null : args[0])); }
private (IExprTerm, List <IPStmt>) SimplifyRvalue(IPExpr expr) { // TODO: I am suspicious. Antlr4.Runtime.ParserRuleContext location = expr.SourceLocation; PLanguageType type = expr.Type; #pragma warning disable CCN0002 // Non exhaustive patterns in switch block switch (expr) { case NamedTupleAccessExpr _: case SeqAccessExpr _: case TupleAccessExpr _: case MapAccessExpr _: (IExprTerm dataTypeItem, List <IPStmt> dataTypeItemDeps) = SimplifyExpression(expr); (IExprTerm cloneddataTypeItem, IPStmt cloneddataTypeItemDeps) = SaveInTemporary(new CloneExpr(dataTypeItem)); return(cloneddataTypeItem, dataTypeItemDeps.Append(cloneddataTypeItemDeps).ToList()); default: return(SimplifyExpression(expr)); } #pragma warning restore CCN0002 // Non exhaustive patterns in switch block }