public static void AnalyzeMethods(ITranslationErrorHandler handler, IEnumerable <Function> allFunctions) { var checker = new LinearTypeChecker(handler); foreach (var function in allFunctions) { checker.CheckFunction(function); } checker.CheckInterproceduralCalls(); }
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); }