public override IPStmt VisitPopStmt(PParser.PopStmtContext context) { method.CanChangeState = true; if (method.Role.HasFlag(FunctionRole.TransitionFunction)) { throw handler.ChangedStateMidTransition(context, method); } return(new PopStmt(context)); }
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); }
public override IPStmt VisitPopStmt(PParser.PopStmtContext context) { if (machine?.IsSpec == true) { throw handler.IllegalMonitorOperation(context, context.POP().Symbol, machine); } if (!method.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null)) { throw handler.PopInNonVoidFunction(context); } method.CanChangeState = true; if (method.Role.HasFlag(FunctionRole.TransitionFunction)) { throw handler.ChangedStateMidTransition(context, method); } return(new PopStmt(context)); }
public static Scope AnalyzeCompilationUnit(ITranslationErrorHandler handler, params PParser.ProgramContext[] programUnits) { // Step 1: Build the global scope of declarations var globalScope = BuildGlobalScope(handler, programUnits); // Step 2: Validate machine specifications foreach (var machine in globalScope.Machines) { MachineChecker.Validate(handler, machine); } // Step 3: Fill function bodies var allFunctions = globalScope.GetAllMethods().ToList(); foreach (var machineFunction in allFunctions) { FunctionBodyVisitor.PopulateMethod(handler, machineFunction); FunctionValidator.CheckAllPathsReturn(handler, machineFunction); } // Step 2: Validate no static handlers foreach (var machine in globalScope.Machines) { MachineChecker.ValidateNoStaticHandlers(handler, machine); } // Step 4: Propagate purity properties ApplyPropagations(allFunctions, CreatePropagation(fn => fn.CanRaiseEvent, (fn, value) => fn.CanRaiseEvent = value, true), CreatePropagation(fn => fn.CanReceive, (fn, value) => fn.CanReceive = value, true), CreatePropagation(fn => fn.CanChangeState, (fn, value) => fn.CanChangeState = value, true)); // Step 5: Verify capability restrictions foreach (var machineFunction in allFunctions) { // TODO: is this checked earlier? if (machineFunction.Owner?.IsSpec == true && machineFunction.IsNondeterministic == true) { throw handler.NonDeterministicFunctionInSpecMachine(machineFunction); } if ((machineFunction.CanChangeState == true || machineFunction.CanRaiseEvent == 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); // Step 7: Check control flow well-formedness ControlFlowChecker.AnalyzeMethods(handler, allFunctions); // Step 8: Infer the creates set for each machine. foreach (var machine in globalScope.Machines) { InferMachineCreates.Populate(machine, handler); } // Step 9: Fill the module expressions ModuleSystemDeclarations.PopulateAllModuleExprs(handler, globalScope); var moduleTypeChecker = new ModuleSystemTypeChecker(handler, globalScope); // Step 10: Check that all module expressions are well-formed foreach (var moduleExpr in AllModuleExprs(globalScope)) { moduleTypeChecker.CheckWellFormedness(moduleExpr); } // Step 11: Check the test and implementation declarations foreach (var impl in globalScope.Implementations) { moduleTypeChecker.CheckImplementationDecl(impl); } foreach (var test in globalScope.SafetyTests) { moduleTypeChecker.CheckSafetyTest(test); } foreach (var test in globalScope.RefinementTests) { moduleTypeChecker.CheckRefinementTest(test); } return(globalScope); }