Exemplo n.º 1
0
        public override IPStmt VisitReceiveStmt(PParser.ReceiveStmtContext context)
        {
            if (machine?.IsSpec == true)
            {
                throw handler.IllegalMonitorOperation(context, context.RECEIVE().Symbol, machine);
            }

            Dictionary <PEvent, Function> cases = new Dictionary <PEvent, Function>();

            foreach (PParser.RecvCaseContext caseContext in context.recvCase())
            {
                Function recvHandler =
                    new Function(caseContext.anonEventHandler())
                {
                    Scope          = table.MakeChildScope(),
                    Owner          = method.Owner,
                    ParentFunction = method,
                    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.DuplicateReceiveCase(eventIdContext, pEvent);
                    }

                    PLanguageType expectedType =
                        recvHandler.Signature.ParameterTypes.ElementAtOrDefault(0) ?? PrimitiveType.Null;
                    if (!expectedType.IsAssignableFrom(pEvent.PayloadType))
                    {
                        throw handler.TypeMismatch(caseContext.anonEventHandler(), expectedType,
                                                   pEvent.PayloadType);
                    }

                    cases.Add(pEvent, recvHandler);
                }
            }

            method.CanReceive = true;
            return(new ReceiveStmt(context, cases));
        }