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 override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context) { // TODO: can receive statements have event variables as their cases? var cases = new Dictionary <PEvent, Function>(); foreach (PParser.RecvCaseContext caseContext in context.recvCase()) { var recvHandler = new Function(caseContext.anonEventHandler()) { Scope = table.MakeChildScope(), Owner = method.Owner, Role = FunctionRole.ReceiveHandler }; if (caseContext.anonEventHandler().funParam() is PParser.FunParamContext param) { Variable paramVar = recvHandler.Scope.Put(param.name.GetText(), param, VariableRole.Param); paramVar.Type = TypeResolver.ResolveType(param.type(), recvHandler.Scope, handler); recvHandler.Signature.Parameters.Add(paramVar); } FunctionBodyVisitor.PopulateMethod(handler, recvHandler); foreach (PParser.EventIdContext eventIdContext in caseContext.eventList().eventId()) { if (!table.Lookup(eventIdContext.GetText(), out PEvent pEvent)) { throw handler.MissingDeclaration(eventIdContext, "event", eventIdContext.GetText()); } if (cases.ContainsKey(pEvent)) { throw handler.IssueError(eventIdContext, $"duplicate case for event {pEvent.Name} in receive"); } PLanguageType expectedType = recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null; if (!expectedType.IsAssignableFrom(pEvent.PayloadType)) { throw handler.TypeMismatch(caseContext.anonEventHandler().funParam(), expectedType, pEvent.PayloadType); } cases.Add(pEvent, recvHandler); } } return(new ReceiveStmt(context, cases)); }
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); }