示例#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));
        }
示例#2
0
        public override object VisitVarDecl(PParser.VarDeclContext context)
        {
            foreach (var varName in context.idenList()._names)
            {
                var variable = method.Scope.Put(varName.GetText(), varName, VariableRole.Local);
                variable.Type = TypeResolver.ResolveType(context.type(), method.Scope, handler);
                method.AddLocalVariable(variable);
            }

            return(null);
        }
示例#3
0
        public override IPExpr VisitKeywordExpr(PParser.KeywordExprContext context)
        {
            switch (context.fun.Text)
            {
            case "keys":
            {
                IPExpr expr = Visit(context.expr());
                if (!(expr.Type.Canonicalize() is MapType mapType))
                {
                    throw handler.TypeMismatch(expr, TypeKind.Map);
                }

                return(new KeysExpr(context, expr, new SequenceType(mapType.KeyType)));
            }

            case "values":
            {
                IPExpr expr = Visit(context.expr());
                if (!(expr.Type.Canonicalize() is MapType mapType))
                {
                    throw handler.TypeMismatch(expr, TypeKind.Map);
                }

                return(new ValuesExpr(context, expr, new SequenceType(mapType.ValueType)));
            }

            case "sizeof":
            {
                var expr = Visit(context.expr());
                if (!(expr.Type.Canonicalize() is SequenceType) &&
                    !(expr.Type.Canonicalize() is MapType) &&
                    !(expr.Type.Canonicalize() is SetType))
                {
                    throw handler.TypeMismatch(expr, TypeKind.Map, TypeKind.Sequence, TypeKind.Set);
                }
                return(new SizeofExpr(context, expr));
            }

            case "default":
            {
                PLanguageType type = TypeResolver.ResolveType(context.type(), table, handler);
                return(new DefaultExpr(context, type.Canonicalize()));
            }

            default:
            {
                throw handler.InternalError(context,
                                            new ArgumentException($"Unknown keyword expression {context.fun.Text}", nameof(context)));
            }
            }
        }
示例#4
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            var subExpr = Visit(context.expr());
            var oldType = subExpr.Type;
            var newType = TypeResolver.ResolveType(context.type(), table, handler);

            if (context.cast.Text.Equals("as"))
            {
                if (!newType.IsAssignableFrom(oldType) && !oldType.IsAssignableFrom(newType))
                {
                    throw handler.IncomparableTypes(context, oldType, newType);
                }
                return(new CastExpr(context, subExpr, newType));
            }

            if (context.cast.Text.Equals("to"))
            {
                if (!(newType is PermissionType || newType.IsSameTypeAs(PrimitiveType.Int) ||
                      newType.IsSameTypeAs(PrimitiveType.Float)))
                {
                    throw handler.IllegalTypeInCoerceExpr(context);
                }

                if (oldType.IsSameTypeAs(PrimitiveType.Int))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Float) || PLanguageType.TypeIsOfKind(newType, TypeKind.Enum))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Float))
                {
                    if (newType.IsSameTypeAs(PrimitiveType.Float))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (PLanguageType.TypeIsOfKind(oldType, TypeKind.Enum))
                {
                    // TODO: are enum-to-enum coersions allowed?
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }
                    if (newType.IsSameTypeAs(PrimitiveType.Int))
                    {
                        return(new CoerceExpr(context, subExpr, newType));
                    }
                }
                else if (oldType.IsSameTypeAs(PrimitiveType.Machine) || oldType is PermissionType)
                {
                    if (newType.IsSameTypeAs(oldType))
                    {
                        return(subExpr);
                    }

                    if (newType is PermissionType)
                    {
                        if (oldType.IsSameTypeAs(PrimitiveType.Machine))
                        {
                            return(new CoerceExpr(context, subExpr, newType));
                        }
                        if (oldType is PermissionType)
                        {
                            if (newType.AllowedPermissions.Value.Any(x => !oldType.AllowedPermissions.Value.Contains(x))
                                )
                            {
                                throw handler.IllegalInterfaceCoerce(context, oldType, newType);
                            }
                            return(new CoerceExpr(context, subExpr, newType));
                        }
                    }
                }

                throw handler.IncomparableTypes(context, oldType, newType);
            }

            throw handler.InternalError(context, new ArgumentOutOfRangeException(nameof(context), "invalid cast"));
        }
示例#5
0
 private PLanguageType ResolveType(PParser.TypeContext typeContext)
 {
     return(TypeResolver.ResolveType(typeContext, CurrentScope, Handler));
 }