Example #1
0
        internal static Type ToSysType(ExprTypeKind kind)
        {
            switch (kind)
            {
            case ExprTypeKind.BL:
                return(typeof(BL));

            case ExprTypeKind.I4:
                return(typeof(I4));

            case ExprTypeKind.I8:
                return(typeof(I8));

            case ExprTypeKind.R4:
                return(typeof(R4));

            case ExprTypeKind.R8:
                return(typeof(R8));

            case ExprTypeKind.TX:
                return(typeof(TX));

            default:
                return(null);
            }
        }
Example #2
0
        public void Convert(ExprTypeKind kind)
        {
            Contracts.Assert(HasType);

            if (kind == ExprType)
            {
                return;
            }

            Contracts.Assert(SrcKind == ExprType);
            switch (kind)
            {
            case ExprTypeKind.I8:
                Contracts.Assert(ExprType == ExprTypeKind.I4);
                if (ExprValue != null)
                {
                    Contracts.Assert(ExprValue is I4);
                    ExprValue = (I8)(I4)ExprValue;
                }
                break;

            case ExprTypeKind.R4:
                Contracts.Assert(ExprType == ExprTypeKind.I4);
                if (ExprValue != null)
                {
                    Contracts.Assert(ExprValue is I4);
                    ExprValue = (R4)(I4)ExprValue;
                }
                break;

            case ExprTypeKind.R8:
                Contracts.Assert(ExprType == ExprTypeKind.I4 || ExprType == ExprTypeKind.I8 ||
                                 ExprType == ExprTypeKind.R4);
                if (ExprValue != null)
                {
                    if (ExprType == ExprTypeKind.I4)
                    {
                        Contracts.Assert(ExprValue is I4);
                        ExprValue = (R8)(I4)ExprValue;
                    }
                    else if (ExprType == ExprTypeKind.I8)
                    {
                        Contracts.Assert(ExprValue is I8);
                        ExprValue = (R8)(I8)ExprValue;
                    }
                    else
                    {
                        Contracts.Assert(ExprValue is R4);
                        ExprValue = (R8)(R4)ExprValue;
                    }
                }
                break;
            }

            // Set the new type.
            ExprType = kind;
        }
Example #3
0
 public void SetType(ExprTypeKind kind)
 {
     Contracts.Assert(kind != 0);
     Contracts.Assert(ExprValue == null);
     Contracts.Assert(ExprType == 0 || ExprType == kind);
     Contracts.Assert(SrcKind == ExprType);
     ExprType = kind;
     SrcKind  = kind;
 }
Example #4
0
 public void SetType(ExprTypeKind kind, object value)
 {
     Contracts.Assert(kind != 0);
     Contracts.Assert(value == null || value.GetType() == ToSysType(kind));
     Contracts.Assert(ExprValue == null);
     Contracts.Assert(ExprType == 0 || ExprType == kind);
     Contracts.Assert(SrcKind == ExprType);
     ExprType  = kind;
     SrcKind   = kind;
     ExprValue = value;
 }
Example #5
0
        public ParamNode(Token tok, string name, int index, DataViewType type)
            : base(tok)
        {
            Contracts.AssertNonEmpty(name);
            Contracts.Assert(index >= 0);
            Contracts.AssertValueOrNull(type);
            Name  = name;
            Index = index;
            Type  = type;

            if (type == null)
            {
                ExprType = ExprTypeKind.Error;
            }
            else if (type is TextDataViewType)
            {
                ExprType = ExprTypeKind.TX;
            }
            else if (type is BooleanDataViewType)
            {
                ExprType = ExprTypeKind.BL;
            }
            else if (type == NumberDataViewType.Int32)
            {
                ExprType = ExprTypeKind.I4;
            }
            else if (type == NumberDataViewType.Int64)
            {
                ExprType = ExprTypeKind.I8;
            }
            else if (type == NumberDataViewType.Single)
            {
                ExprType = ExprTypeKind.R4;
            }
            else if (type == NumberDataViewType.Double)
            {
                ExprType = ExprTypeKind.R8;
            }
        }
Example #6
0
        /// <summary>
        /// From:
        ///     pointer
        /// To:
        ///     pointer, integral
        /// </summary>
        public static Expr FromPointer(Expr expr, ExprType type, Env env)
        {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to   = type.Kind;

            if (from != ExprTypeKind.POINTER)
            {
                throw new InvalidOperationException("Expected a pointer.");
            }

            // if we are casting to another pointer, do a nop
            if (to == ExprTypeKind.POINTER)
            {
                if (expr.IsConstExpr)
                {
                    return(new ConstPtr(((ConstPtr)expr).Value, type, env));
                }
                return(new TypeCast(TypeCastType.NOP, expr, type, env));
            }

            // if we are casting to an integral
            if (type.IsIntegral)
            {
                // pointer -> ulong -> whatever integral
                if (expr.IsConstExpr)
                {
                    expr = new ConstULong(((ConstPtr)expr).Value, env);
                }
                else
                {
                    expr = new TypeCast(TypeCastType.NOP, expr, new ULongType(type.IsConst, type.IsVolatile), env);
                }
                return(MakeCast(expr, type, env));
            }

            throw new InvalidOperationException("Casting from a pointer to an unsupported Type.");
        }
Example #7
0
 private bool IsSimple(ExprTypeKind kind)
 {
     Contracts.Assert(ExprType != 0);
     return(ExprType == kind);
 }
Example #8
0
        /// <summary>
        /// From:
        ///     char, short, long
        /// To:
        ///     char, uchar, short, ushort, long, ulong, float double
        /// </summary>
        public static Expr SignedIntegralToArith(Expr expr, ExprType type)
        {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to   = type.Kind;

            Env env = expr.Env;

            switch (from)
            {
            case ExprTypeKind.CHAR:
                switch (to)
                {
                case ExprTypeKind.SHORT:
                case ExprTypeKind.USHORT:
                    return(new TypeCast(TypeCastType.INT8_TO_INT16, expr, type));

                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                    return(new TypeCast(TypeCastType.INT8_TO_INT32, expr, type));

                case ExprTypeKind.UCHAR:
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.FLOAT:
                    // char -> long -> float
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.DOUBLE:
                    // char -> long -> double
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT8_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.VOID:
                case ExprTypeKind.POINTER:
                case ExprTypeKind.FUNCTION:
                case ExprTypeKind.ARRAY:
                case ExprTypeKind.INCOMPLETE_ARRAY:
                case ExprTypeKind.STRUCT_OR_UNION:
                case ExprTypeKind.CHAR:
                default:
                    throw new InvalidProgramException($"Cannot cast from {from} to {to}");
                }

            case ExprTypeKind.SHORT:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                case ExprTypeKind.UCHAR:
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.USHORT:
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                    return(new TypeCast(TypeCastType.INT16_TO_INT32, expr, type));

                case ExprTypeKind.FLOAT:
                    // short -> long -> float
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.DOUBLE:
                    // short -> long -> double
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.INT16_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.VOID:
                case ExprTypeKind.SHORT:
                case ExprTypeKind.POINTER:
                case ExprTypeKind.FUNCTION:
                case ExprTypeKind.ARRAY:
                case ExprTypeKind.INCOMPLETE_ARRAY:
                case ExprTypeKind.STRUCT_OR_UNION:
                default:
                    throw new InvalidProgramException($"Cannot cast from {from} to {to}");
                }

            case ExprTypeKind.LONG:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstChar((SByte)((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.UCHAR:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstUChar((Byte)((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.SHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstShort((Int16)((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type));

                case ExprTypeKind.USHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstUShort((UInt16)((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type));

                case ExprTypeKind.ULONG:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt32)((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.FLOAT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstFloat(((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type));

                case ExprTypeKind.DOUBLE:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstDouble(((ConstLong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type));

                case ExprTypeKind.VOID:
                case ExprTypeKind.LONG:
                case ExprTypeKind.POINTER:
                case ExprTypeKind.FUNCTION:
                case ExprTypeKind.ARRAY:
                case ExprTypeKind.INCOMPLETE_ARRAY:
                case ExprTypeKind.STRUCT_OR_UNION:
                default:
                    throw new InvalidProgramException($"Cannot cast from {from} to {to}");
                }

            default:
                throw new InvalidProgramException();
            }
        }
Example #9
0
        /// <summary>
        /// From:
        ///     pointer, integral
        /// To:
        ///     pointer
        /// </summary>
        public static Expr ToPointer(Expr expr, ExprType type, Env env)
        {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to   = type.Kind;

            if (to != ExprTypeKind.POINTER)
            {
                throw new InvalidOperationException("Error: expected casting to pointer.");
            }

            if (from == ExprTypeKind.POINTER)
            {
                if (expr.IsConstExpr)
                {
                    return(new ConstPtr(((ConstPtr)expr).Value, type, env));
                }
                return(new TypeCast(TypeCastType.NOP, expr, type, env));
            }

            if (expr.Type.IsIntegral)
            {
                // if we are casting from an integral

                // whatever integral -> ulong
                switch (expr.Type.Kind)
                {
                case ExprTypeKind.CHAR:
                case ExprTypeKind.SHORT:
                case ExprTypeKind.LONG:
                    expr = SignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
                    break;

                case ExprTypeKind.UCHAR:
                case ExprTypeKind.USHORT:
                case ExprTypeKind.ULONG:
                    expr = UnsignedIntegralToArith(expr, new ULongType(type.IsConst, type.IsVolatile));
                    break;

                default:
                    break;
                }

                // ulong -> pointer
                if (expr.IsConstExpr)
                {
                    return(new ConstPtr(((ConstULong)expr).Value, type, env));
                }
                return(new TypeCast(TypeCastType.NOP, expr, type, env));
            }
            if (expr.Type is FunctionType)
            {
                if (!expr.Type.EqualType(((PointerType)type).RefType))
                {
                    throw new InvalidOperationException("Casting from an incompatible function.");
                }

                // TODO: only allow compatible Type?
                return(new TypeCast(TypeCastType.NOP, expr, type, env));
            }
            if (expr.Type is ArrayType)
            {
                // TODO: allow any pointer Type to cast to?
                return(new TypeCast(TypeCastType.NOP, expr, type, env));
            }

            throw new InvalidOperationException("Error: casting from an unsupported Type to pointer.");
        }
Example #10
0
        /// <summary>
        /// From:
        ///     float, double
        /// To:
        ///     char, uchar, short, ushort, long, ulong, float, double
        /// </summary>
        /// <remarks>
        /// According to MSDN "Conversions from Floating-Point Types",
        ///   float cannot convert to unsigned char.
        /// I don't know why, but I follow it.
        /// </remarks>
        public static Expr FloatToArith(Expr expr, ExprType type)
        {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to   = type.Kind;
            Env          env  = expr.Env;

            switch (from)
            {
            case ExprTypeKind.FLOAT:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((SByte)((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.SHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int16)((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.USHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt16)((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.LONG:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int32)((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type));

                case ExprTypeKind.ULONG:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt32)((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.FLOAT_TO_INT32, expr, type));

                case ExprTypeKind.DOUBLE:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstDouble(((ConstFloat)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.FLOAT_TO_DOUBLE, expr, type));

                default:
                    throw new InvalidProgramException();
                }

            case ExprTypeKind.DOUBLE:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                    // double -> float -> char
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((SByte)((ConstDouble)expr).Value, env));
                    }
                    return(FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new CharType(type.IsConst, type.IsVolatile)));

                case ExprTypeKind.SHORT:
                    // double -> float -> short
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int16)((ConstDouble)expr).Value, env));
                    }
                    return(FloatToArith(FloatToArith(expr, new FloatType(type.IsConst, type.IsVolatile)), new ShortType(type.IsConst, type.IsVolatile)));

                case ExprTypeKind.LONG:
                    // double -> float -> short
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int32)((ConstDouble)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type));

                case ExprTypeKind.ULONG:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt32)((ConstDouble)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, type));

                case ExprTypeKind.USHORT:
                    // double -> long -> ushort
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt16)((ConstDouble)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, new TypeCast(TypeCastType.DOUBLE_TO_INT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.FLOAT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstFloat((Single)((ConstDouble)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.DOUBLE_TO_FLOAT, expr, type));

                default:
                    throw new InvalidProgramException();
                }

            default:
                throw new InvalidProgramException();
            }
        }
Example #11
0
        /// <summary>
        /// From:
        ///     uchar, ushort, ulong
        /// To:
        ///     char, uchar, short, ushort, long, ulong, float, double
        /// </summary>
        /// <remarks>
        /// Aaccording to MSDN "Conversions from Unsigned Integral Types",
        ///   unsigned long converts directly to double.
        /// However, I just treat unsigned long as long.
        /// </remarks>
        public static Expr UnsignedIntegralToArith(Expr expr, ExprType type)
        {
            ExprTypeKind from = expr.Type.Kind;
            ExprTypeKind to   = type.Kind;

            Env env = expr.Env;

            switch (from)
            {
            case ExprTypeKind.UCHAR:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.SHORT:
                case ExprTypeKind.USHORT:
                    return(new TypeCast(TypeCastType.UINT8_TO_UINT16, expr, type));

                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                    return(new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, type));

                case ExprTypeKind.FLOAT:
                    // uchar -> ulong -> long -> float
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.DOUBLE:
                    // uchar -> ulong -> long -> double
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT8_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                default:
                    Debug.Assert(false);
                    return(null);
                }

            case ExprTypeKind.USHORT:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                case ExprTypeKind.UCHAR:
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.USHORT:
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.LONG:
                case ExprTypeKind.ULONG:
                    return(new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, type));

                case ExprTypeKind.FLOAT:
                    // ushort -> ulong -> long -> float
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                case ExprTypeKind.DOUBLE:
                    // ushort -> ulong -> long -> double
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, new TypeCast(TypeCastType.UINT16_TO_UINT32, expr, new LongType(type.IsConst, type.IsVolatile)), type));

                default:
                    Debug.Assert(false);
                    return(null);
                }

            case ExprTypeKind.ULONG:
                switch (to)
                {
                case ExprTypeKind.CHAR:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((SByte)((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.UCHAR:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((Byte)((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT8, expr, type));

                case ExprTypeKind.SHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int16)((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type));

                case ExprTypeKind.USHORT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstULong((UInt16)((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.PRESERVE_INT16, expr, type));

                case ExprTypeKind.LONG:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstLong((Int32)((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.NOP, expr, type));

                case ExprTypeKind.FLOAT:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstFloat(((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.INT32_TO_FLOAT, expr, type));

                case ExprTypeKind.DOUBLE:
                    if (expr.IsConstExpr)
                    {
                        return(new ConstDouble(((ConstULong)expr).Value, env));
                    }
                    return(new TypeCast(TypeCastType.INT32_TO_DOUBLE, expr, type));

                default:
                    Debug.Assert(false);
                    return(null);
                }

            default:
                Debug.Assert(false);
                return(null);
            }
        }