Example #1
0
        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);
        }
Example #2
0
        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));
        }
Example #3
0
        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);
        }