public static void ValidatePayloadTypes(ITranslationErrorHandler handler, ParserRuleContext context, PLanguageType payloadType, IReadOnlyList <IPExpr> arguments) { if (arguments.Count == 0) { if (!payloadType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.TypeMismatch(context, PrimitiveType.Null, payloadType); } } else if (arguments.Count == 1) { CheckArgument(handler, context, payloadType, arguments[0]); } else if (payloadType.Canonicalize() is TupleType tuple) { foreach (Tuple <IPExpr, PLanguageType> pair in arguments.Zip(tuple.Types, Tuple.Create)) { CheckArgument(handler, context, pair.Item2, pair.Item1); } } else { throw handler.IncorrectArgumentCount(context, arguments.Count, 1); } }
private static State FindStartState(Machine machine, ITranslationErrorHandler handler) { bool foundStartState = false; foreach (State state in machine.AllStates()) { if (state == machine.StartState || state.IsStart) { if (!foundStartState) { foundStartState = true; } else { throw handler.TwoStartStates(machine, state); } } } Debug.Assert(!(foundStartState && machine.StartState == null), "machine has unregistered start state"); if (!foundStartState || machine.StartState == null) { throw handler.MissingStartState(machine); } return(machine.StartState); }
public static PLanguageType ResolveType( ParserRuleContext context, Scope scope, ITranslationErrorHandler handler) { return(context == null ? PrimitiveType.Null : new TypeVisitor(scope, handler).Visit(context)); }
private static State FindStartState(Machine machine, ITranslationErrorHandler handler) { var foundStartState = false; foreach (State state in machine.AllStates()) { if (state == machine.StartState || state.IsStart) { if (!foundStartState) { foundStartState = true; } else { throw handler.InternalError(state.SourceLocation, $"Two start states {state.Name} occurs twice in all states list"); } } } if (foundStartState && machine.StartState == null) { throw handler.InternalError(machine.SourceLocation, "machine has unregistered start state"); } if (!foundStartState || machine.StartState == null) { // Allow machines with no start state so long as there are no other states. throw handler.MissingStartState(machine); } return(machine.StartState); }
public ModuleExprVisitor( ITranslationErrorHandler handler, Scope globalScope) { this.handler = handler; this.globalScope = globalScope; }
public Scope(ITranslationErrorHandler handler, Scope parent) { this.handler = handler; parent?.children.Remove(this); Parent = parent; parent?.children.Add(this); }
private static PParser.ProgramContext Parse(ITranslationErrorHandler handler, FileInfo inputFile) { var fileStream = new AntlrFileStream(inputFile.FullName); var lexer = new PLexer(fileStream); var tokens = new CommonTokenStream(lexer); var parser = new PParser(tokens); parser.RemoveErrorListeners(); try { // Stage 1: use fast SLL parsing strategy parser.Interpreter.PredictionMode = PredictionMode.Sll; parser.ErrorHandler = new BailErrorStrategy(); return(parser.program()); } catch (Exception e) when(e is RecognitionException || e is OperationCanceledException) { // Stage 2: use slower LL(*) parsing strategy tokens.Reset(); parser.AddErrorListener(new PParserErrorListener(inputFile, handler)); parser.Interpreter.PredictionMode = PredictionMode.Ll; parser.ErrorHandler = new DefaultErrorStrategy(); return(parser.program()); } }
public static void PopulateMethod(ITranslationErrorHandler handler, Function fun) { Contract.Requires(fun.Body == null); var visitor = new FunctionBodyVisitor(handler, fun.Owner, fun); visitor.Visit(fun.SourceLocation); }
private static void ValidateEventPayloadToTransitionTarget(ITranslationErrorHandler handler, ParserRuleContext sourceLocation, PLanguageType eventPayloadType, Function targetFunction) { IReadOnlyList <PLanguageType> entrySignature = targetFunction.Signature.ParameterTypes.ToList(); if (entrySignature.Count == 0) { return; } if (entrySignature.Count == 1 && entrySignature[0].IsAssignableFrom(eventPayloadType)) { return; } if (entrySignature.Count == 1 && eventPayloadType.Canonicalize() is TupleType tuple && tuple.Types.Count == 1 && entrySignature[0].IsAssignableFrom(tuple.Types[0])) { return; } if (entrySignature.Count == 1) { throw handler.TypeMismatch(sourceLocation, eventPayloadType, entrySignature[0]); } PLanguageType entrySignatureType = new TupleType(entrySignature.ToArray()); if (!entrySignatureType.IsAssignableFrom(eventPayloadType)) { throw handler.TypeMismatch(sourceLocation, eventPayloadType, entrySignatureType); } }
public StatementVisitor(ITranslationErrorHandler handler, Machine machine, Function method) { this.handler = handler; this.machine = machine; this.method = method; table = method.Scope; exprVisitor = new ExprVisitor(method, handler); }
public static void Validate(ITranslationErrorHandler handler, Machine machine) { var startState = FindStartState(machine, handler); var startStatePayloadType = GetStatePayload(startState); Debug.Assert(startStatePayloadType.IsSameTypeAs(machine.PayloadType)); ValidateTransitions(handler, machine); }
public static void AnalyzeMethods(ITranslationErrorHandler handler, IEnumerable <Function> allFunctions) { ControlFlowChecker checker = new ControlFlowChecker(handler); foreach (Function function in allFunctions) { checker.CheckFunction(function); } }
private DeclarationVisitor( ITranslationErrorHandler handler, Scope topLevelScope, ParseTreeProperty <IPDecl> nodesToDeclarations) { Handler = handler; currentScope = new StackProperty <Scope>(topLevelScope); this.nodesToDeclarations = nodesToDeclarations; }
public static void PopulateDeclarations( ITranslationErrorHandler handler, Scope topLevelScope, PParser.ProgramContext context, ParseTreeProperty <IPDecl> nodesToDeclarations) { var visitor = new DeclarationVisitor(handler, topLevelScope, nodesToDeclarations); visitor.Visit(context); }
public static void AnalyzeMethods(ITranslationErrorHandler handler, IEnumerable <Function> allFunctions) { var checker = new LinearTypeChecker(handler); foreach (Function function in allFunctions) { checker.CheckFunction(function); } checker.CheckInterproceduralCalls(); }
public static void PopulateAllModuleExprs( ITranslationErrorHandler handler, Scope globalScope) { var modExprVisitor = new ModuleExprVisitor(handler, globalScope); // first do all the named modules foreach (var mod in globalScope.NamedModules) { var context = (PParser.NamedModuleDeclContext)mod.SourceLocation; mod.ModExpr = modExprVisitor.Visit(context.modExpr()); } // all the test declarations foreach (var test in globalScope.SafetyTests) { var context = (PParser.SafetyTestDeclContext)test.SourceLocation; test.ModExpr = modExprVisitor.Visit(context.modExpr()); } foreach (var test in globalScope.RefinementTests) { var context = (PParser.RefinementTestDeclContext)test.SourceLocation; test.LeftModExpr = modExprVisitor.Visit(context.modExpr()[0]); test.RightModExpr = modExprVisitor.Visit(context.modExpr()[1]); } if (globalScope.Implementations.Any()) { // all user defind implementations foreach (var impl in globalScope.Implementations) { var context = (PParser.ImplementationDeclContext)impl.SourceLocation; impl.ModExpr = modExprVisitor.Visit(context.modExpr()); } } else if (!globalScope.SafetyTests.Any()) { var defaultImplDecl = new Implementation(ParserRuleContext.EmptyContext, "DefaultImpl") { Main = "Main" }; // create bindings from each machine to itself var defaultBindings = new List <Tuple <Interface, Machine> >(); foreach (var machine in globalScope.Machines.Where(m => !m.IsSpec)) { globalScope.Get(machine.Name, out Interface @interface); defaultBindings.Add(new Tuple <Interface, Machine>(@interface, machine)); } defaultImplDecl.ModExpr = new BindModuleExpr(ParserRuleContext.EmptyContext, defaultBindings); globalScope.AddDefaultImpl(defaultImplDecl); } }
public static void PopulateMethod(ITranslationErrorHandler handler, Function fun) { if (fun.Body != null) { return; } var visitor = new FunctionBodyVisitor(handler, fun.Owner, fun); visitor.Visit(fun.SourceLocation); }
public static void Populate(Machine machine, ITranslationErrorHandler handler) { InterfaceSet interfaces = new InterfaceSet(); foreach (Function function in machine.Methods) { interfaces.AddInterfaces(InferCreates(function, handler)); } machine.Creates = interfaces; }
private static void ValidateTransitions(ITranslationErrorHandler handler, Machine machine) { foreach (var state in machine.AllStates()) { foreach (var pair in state.AllEventHandlers) { var handledEvent = pair.Key; switch (pair.Value) { case EventDoAction eventDoAction: if (eventDoAction.Target != null) { ValidateEventPayloadToTransitionTarget(handler, eventDoAction.SourceLocation, handledEvent.PayloadType, eventDoAction.Target); } break; case EventGotoState eventGotoState: if (eventGotoState.Target.Entry != null) { ValidateEventPayloadToTransitionTarget(handler, eventGotoState.SourceLocation, handledEvent.PayloadType, eventGotoState.Target.Entry); } if (eventGotoState.TransitionFunction != null) { ValidateEventPayloadToTransitionTarget(handler, eventGotoState.SourceLocation, handledEvent.PayloadType, eventGotoState.TransitionFunction); } break; case EventPushState eventPushState: if (eventPushState.Target.Entry != null) { ValidateEventPayloadToTransitionTarget(handler, eventPushState.SourceLocation, handledEvent.PayloadType, eventPushState.Target.Entry); } break; } } if (state.Exit?.Signature.Parameters.Count > 0) { throw handler.IncorrectArgumentCount(state.SourceLocation, state.Exit.Signature.Parameters.Count, 0); } } }
public static void CheckAllPathsReturn(ITranslationErrorHandler handler, Function function) { if (function.IsForeign) { return; } if (!SurelyReturns(function.Body) && !function.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.NotAllPathsReturn(function); } }
private Scope(ITranslationErrorHandler handler, Scope parent = null) { this.handler = handler; parent?.children.Remove(this); Parent = parent; parent?.children.Add(this); EventSet eventSetWithHalt = new EventSet(); eventSetWithHalt.AddEvent(new PEvent("halt", null)); UniversalEventSet = parent == null ? eventSetWithHalt : parent.UniversalEventSet; }
public static void ValidateNoStaticHandlers(ITranslationErrorHandler handler, Machine machine) { foreach (State state in machine.AllStates()) { bool illegalUsage = state.Entry != null && IsStaticOrForeign(state.Entry); if (illegalUsage) { throw handler.StaticFunctionNotAllowedAsHandler(state.SourceLocation, state.Entry.Name); } illegalUsage = state.Exit != null && IsStaticOrForeign(state.Exit); if (illegalUsage) { throw handler.StaticFunctionNotAllowedAsHandler(state.SourceLocation, state.Exit.Name); } foreach (KeyValuePair <PEvent, AST.IStateAction> pair in state.AllEventHandlers) { switch (pair.Value) { case EventDoAction eventDoAction: if (eventDoAction.Target != null && IsStaticOrForeign(eventDoAction.Target)) { throw handler.StaticFunctionNotAllowedAsHandler(eventDoAction.SourceLocation, eventDoAction.Target.Name); } break; case EventGotoState eventGotoState: if (eventGotoState.TransitionFunction != null && IsStaticOrForeign(eventGotoState.TransitionFunction)) { throw handler.StaticFunctionNotAllowedAsHandler(eventGotoState.SourceLocation, eventGotoState.TransitionFunction.Name); } break; case EventDefer _: case EventIgnore _: case EventPushState _: break; default: throw handler.InternalError(pair.Value.SourceLocation, new System.Exception("Unknown transition type parsed, report to the P team")); } } } }
private static PLanguageType GetStatePayload(State startState, ITranslationErrorHandler handler) { if (!(startState.Entry?.Signature.Parameters.Count > 0)) { return(PrimitiveType.Null); } if (startState.Entry.Signature.Parameters.Count != 1) { throw handler.InternalError(startState.OwningMachine.SourceLocation, "Allowed start state entry with multiple parameters"); } return(startState.Entry.Signature.Parameters[0].Type); }
private static void ValidateTransitions(ITranslationErrorHandler handler, Machine machine) { foreach (State state in machine.AllStates()) { foreach (KeyValuePair <PEvent, AST.IStateAction> pair in state.AllEventHandlers) { PEvent handledEvent = pair.Key; switch (pair.Value) { case EventDoAction eventDoAction: if (eventDoAction.Target != null) { ValidateEventPayloadToTransitionTarget(handler: handler, sourceLocation: eventDoAction.SourceLocation, eventPayloadType: handledEvent.PayloadType, targetFunction: eventDoAction.Target); } break; case EventGotoState eventGotoState: if (eventGotoState.Target.Entry != null) { ValidateEventPayloadToTransitionTarget(handler: handler, sourceLocation: eventGotoState.SourceLocation, eventPayloadType: handledEvent.PayloadType, targetFunction: eventGotoState.Target.Entry); } if (eventGotoState.TransitionFunction != null) { ValidateEventPayloadToTransitionTarget(handler: handler, sourceLocation: eventGotoState.SourceLocation, eventPayloadType: handledEvent.PayloadType, targetFunction: eventGotoState.TransitionFunction); } break; case EventPushState eventPushState: if (eventPushState.Target.Entry != null) { ValidateEventPayloadToTransitionTarget(handler: handler, sourceLocation: eventPushState.SourceLocation, eventPayloadType: handledEvent.PayloadType, targetFunction: eventPushState.Target.Entry); } break; case EventDefer _: case EventIgnore _: { break; } } } } }
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 static Scope AnalyzeCompilationUnit(ITranslationErrorHandler handler, params PParser.ProgramContext[] programUnits) { // Step 1: Build the global scope of declarations Scope globalScope = BuildGlobalScope(handler, programUnits); // Step 2: Validate machine specifications foreach (Machine machine in globalScope.Machines) { Validator.ValidateMachine(handler, machine); } // Step 3: Fill function bodies List <Function> allFunctions = AllFunctions(globalScope).ToList(); foreach (Function machineFunction in allFunctions) { FunctionBodyVisitor.PopulateMethod(handler, machineFunction); } // Step 4: Propagate purity properties ApplyPropagations(allFunctions, CreatePropagation(fn => fn.CanCommunicate, (fn, value) => fn.CanCommunicate = value, true), CreatePropagation(fn => fn.CanChangeState, (fn, value) => fn.CanChangeState = value, true)); // Step 5: Verify purity invariants foreach (Function machineFunction in allFunctions) { if (machineFunction.Owner?.IsSpec == true && machineFunction.IsNondeterministic == true) { throw handler.NonDeterministicFunctionInSpecMachine(machineFunction); } if (machineFunction.CanChangeState == true && (machineFunction.Role.HasFlag(FunctionRole.TransitionFunction) || machineFunction.Role.HasFlag(FunctionRole.ExitHandler))) { throw handler.ChangedStateMidTransition(machineFunction.SourceLocation, machineFunction); } } // Step 6: Check linear type ownership LinearTypeChecker.AnalyzeMethods(handler, allFunctions); return(globalScope); }
private static void ValidateHandlers(ITranslationErrorHandler handler, Machine machine) { foreach (var state in machine.AllStates()) { if (state.Entry?.Signature.Parameters.Count > 1) { throw handler.MoreThanOneParameterForHandlers(state.SourceLocation, state.Entry.Signature.Parameters.Count); } if (state.Exit?.Signature.Parameters.Count > 0) { throw handler.ExitFunctionCannotTakeParameters(state.SourceLocation, state.Exit.Signature.Parameters.Count); } foreach (KeyValuePair <PEvent, AST.IStateAction> pair in state.AllEventHandlers) { PEvent handledEvent = pair.Key; switch (pair.Value) { case EventDoAction eventDoAction: if (eventDoAction.Target != null && eventDoAction.Target.Signature.ParameterTypes.Count() > 1) { throw handler.MoreThanOneParameterForHandlers(eventDoAction.SourceLocation, eventDoAction.Target.Signature.ParameterTypes.Count()); } break; case EventGotoState eventGotoState: if (eventGotoState.TransitionFunction != null && eventGotoState.TransitionFunction.Signature.ParameterTypes.Count() > 1) { throw handler.MoreThanOneParameterForHandlers(eventGotoState.SourceLocation, eventGotoState.TransitionFunction.Signature.ParameterTypes.Count()); } break; case EventPushState _: case EventDefer _: case EventIgnore _: { break; } } } } }
public static void ValidateNoStaticHandlers(ITranslationErrorHandler handler, Machine machine) { foreach (var state in machine.AllStates()) { var illegalUsage = state.Entry != null && IsStaticOrForeign(state.Entry); if (illegalUsage) { throw handler.StaticFunctionNotAllowedAsHandler(state.SourceLocation, state.Entry.Name); } illegalUsage = state.Exit != null && IsStaticOrForeign(state.Exit); if (illegalUsage) { throw handler.StaticFunctionNotAllowedAsHandler(state.SourceLocation, state.Exit.Name); } foreach (var pair in state.AllEventHandlers) { switch (pair.Value) { case EventDoAction eventDoAction: if (eventDoAction.Target != null && IsStaticOrForeign(eventDoAction.Target)) { throw handler.StaticFunctionNotAllowedAsHandler(eventDoAction.SourceLocation, eventDoAction.Target.Name); } break; case EventGotoState eventGotoState: if (eventGotoState.TransitionFunction != null && IsStaticOrForeign(eventGotoState.TransitionFunction)) { throw handler.StaticFunctionNotAllowedAsHandler(eventGotoState.SourceLocation, eventGotoState.TransitionFunction.Name); } break; } } } }
public static void ValidateMachine(ITranslationErrorHandler handler, Machine machine) { State startState = FindStartState(machine, handler); PLanguageType startStatePayloadType = GetStatePayload(startState, handler); if (!startStatePayloadType.IsSameTypeAs(machine.PayloadType)) { throw handler.InternalError(machine.SourceLocation, "machine payload type is not the same as start state's entry payload type"); } foreach (Interface machineInterface in machine.Interfaces) { if (!machine.PayloadType.IsAssignableFrom(machineInterface.PayloadType)) { // TODO: add special "invalid machine interface" error throw handler.TypeMismatch(machine.StartState.Entry?.SourceLocation ?? machine.SourceLocation, machine.PayloadType, machineInterface.PayloadType); } } }
private static Scope BuildGlobalScope(ITranslationErrorHandler handler, PParser.ProgramContext[] programUnits) { var globalScope = new Scope(handler); var nodesToDeclarations = new ParseTreeProperty <IPDecl>(); // Add built-in events to the table. globalScope.Put("halt", (PParser.EventDeclContext)null); globalScope.Put("null", (PParser.EventDeclContext)null); // Step 1: Create mapping of names to declaration stubs foreach (PParser.ProgramContext programUnit in programUnits) { DeclarationStubVisitor.PopulateStubs(globalScope, programUnit, nodesToDeclarations); } // Step 2: Validate declarations and fill with types foreach (PParser.ProgramContext programUnit in programUnits) { DeclarationVisitor.PopulateDeclarations(handler, globalScope, programUnit, nodesToDeclarations); } return(globalScope); }