Пример #1
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            IPExpr        subExpr = Visit(context.expr());
            PLanguageType oldType = subExpr.Type;
            PLanguageType 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 (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));
                    }
                }
                throw handler.IncomparableTypes(context, oldType, newType);
            }
            throw new ArgumentException(nameof(context));
        }
Пример #2
0
 public static void ValidatePayloadTypes(ITranslationErrorHandler handler, ParserRuleContext context,
                                         PLanguageType payloadType, IReadOnlyList <IPExpr> arguments)
 {
     if (arguments.Count == 0)
     {
         if (!payloadType.IsSameTypeAs(PrimitiveType.Null))
         {
             throw handler.TypeMismatch(context, PrimitiveType.Null, payloadType);
         }
     }
     else if (arguments.Count == 1)
     {
         CheckArgument(handler, context, payloadType, arguments[0]);
     }
     else if (payloadType.Canonicalize() is TupleType tuple)
     {
         foreach (Tuple <IPExpr, PLanguageType> pair in arguments.Zip(tuple.Types, Tuple.Create))
         {
             CheckArgument(handler, context, pair.Item2, pair.Item1);
         }
     }
     else
     {
         throw handler.IncorrectArgumentCount(context, arguments.Count, 1);
     }
 }
Пример #3
0
        public static void Validate(ITranslationErrorHandler handler, Machine machine)
        {
            State         startState            = FindStartState(machine, handler);
            PLanguageType startStatePayloadType = GetStatePayload(startState);

            Debug.Assert(startStatePayloadType.IsSameTypeAs(machine.PayloadType));
            ValidateTransitions(handler, machine);
        }
Пример #4
0
        public static void ValidateMachine(ITranslationErrorHandler handler, Machine machine)
        {
            State         startState            = FindStartState(machine, handler);
            PLanguageType startStatePayloadType = GetStatePayload(startState, handler);

            if (!startStatePayloadType.IsSameTypeAs(machine.PayloadType))
            {
                throw handler.InternalError(machine.SourceLocation,
                                            "machine payload type is not the same as start state's entry payload type");
            }

            foreach (Interface machineInterface in machine.Interfaces)
            {
                if (!machine.PayloadType.IsAssignableFrom(machineInterface.PayloadType))
                {
                    // TODO: add special "invalid machine interface" error
                    throw handler.TypeMismatch(machine.StartState.Entry?.SourceLocation ?? machine.SourceLocation,
                                               machine.PayloadType,
                                               machineInterface.PayloadType);
                }
            }
        }
Пример #5
0
        public override IPExpr VisitCastExpr(PParser.CastExprContext context)
        {
            IPExpr        subExpr = Visit(context.expr());
            PLanguageType oldType = subExpr.Type;
            PLanguageType 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"));
        }