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 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); }