- // Attempt to do the implicit constant expression conversions
-
- if (target is IntLiteral){
- e = TryImplicitIntConversion (type, (IntLiteral) target);
- if (e != null)
- return e;
- } else if (target is LongLiteral){
- //
- // Try the implicit constant expression conversion
- // from long to ulong, instead of a nice routine,
- // we just inline it
- //
- if (((LongLiteral) target).Value > 0)
- return target;
- }
-
- string msg = "Can not convert implicitly from `"+
- TypeManager.CSharpName (target.Type) + "' to `" +
- TypeManager.CSharpName (type) + "'";
-
- Error (tc, 29, l, msg);
-
- return null;
- }
-
- // <summary>
- // Performs the explicit numeric conversions
- // </summary>
- static Expression ConvertNumericExplicit (TypeContainer tc, Expression expr,
- Type target_type)
- {
- Type expr_type = expr.Type;
-
- if (expr_type == TypeManager.sbyte_type){
- //
- // From sbyte to byte, ushort, uint, ulong, char
- //
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.byte_type){
- //
- // From byte to sbyte and char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.short_type){
- //
- // From short to sbyte, byte, ushort, uint, ulong, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.ushort_type){
- //
- // From ushort to sbyte, byte, short, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.int32_type){
- //
- // From int to sbyte, byte, short, ushort, uint, ulong, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.uint32_type)
- return new EmptyCast (expr, target_type);
- if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.uint32_type){
- //
- // From uint to sbyte, byte, short, ushort, int, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.int32_type)
- return new EmptyCast (expr, target_type);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.int64_type){
- //
- // From long to sbyte, byte, short, ushort, int, uint, ulong, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.int32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.uint64_type)
- return new EmptyCast (expr, target_type);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.uint64_type){
- //
- // From ulong to sbyte, byte, short, ushort, int, uint, long, char
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.int32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.int64_type)
- return new EmptyCast (expr, target_type);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- } else if (expr_type == TypeManager.char_type){
- //
- // From char to sbyte, byte, short
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- } else if (expr_type == TypeManager.float_type){
- //
- // From float to sbyte, byte, short,
- // ushort, int, uint, long, ulong, char
- // or decimal
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.int32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.int64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
- if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (tc, expr, target_type);
- } else if (expr_type == TypeManager.double_type){
- //
- // From double to byte, byte, short,
- // ushort, int, uint, long, ulong,
- // char, float or decimal
- //
- if (target_type == TypeManager.sbyte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
- if (target_type == TypeManager.byte_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
- if (target_type == TypeManager.short_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
- if (target_type == TypeManager.ushort_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.int32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
- if (target_type == TypeManager.uint32_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
- if (target_type == TypeManager.int64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
- if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (target_type == TypeManager.char_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
- if (target_type == TypeManager.float_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
- if (target_type == TypeManager.decimal_type)
- return InternalTypeConstructor (tc, expr, target_type);
- }
-
- // decimal is taken care of by the op_Explicit methods.
-
- return null;
- }
-
- // <summary>
- // Performs an explicit conversion of the expression `expr' whose
- // type is expr.Type to `target_type'.
- // </summary>
- static public Expression ConvertExplicit (TypeContainer tc, Expression expr,
- Type target_type)
- {
- Expression ne = ConvertImplicit (tc, expr, target_type);
-
- if (ne != null)
- return ne;
-
- ne = ConvertNumericExplicit (tc, expr, target_type);
- if (ne != null)
- return ne;
-
-
- return expr;
- }
-
- static string ExprClassName (ExprClass c)
- {
- switch (c){
- case ExprClass.Invalid:
- return "Invalid";
- case ExprClass.Value:
- return "value";
- case ExprClass.Variable:
- return "variable";
- case ExprClass.Namespace:
- return "namespace";
- case ExprClass.Type:
- return "type";
- case ExprClass.MethodGroup:
- return "method group";
- case ExprClass.PropertyAccess:
- return "property access";
- case ExprClass.EventAccess:
- return "event access";
- case ExprClass.IndexerAccess:
- return "indexer access";
- case ExprClass.Nothing:
- return "null";
- }
- throw new Exception ("Should not happen");
- }
-
- // <summary>
- // Reports that we were expecting `expr' to be of class `expected'
- // </summary>
- protected void report118 (TypeContainer tc, Expression expr, string expected)
- {
- Error (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
- "' where an " + expected + " was expected");
- }
- }
-
- // <summary>
- // This is just a base class for expressions that can
- // appear on statements (invocations, object creation,
- // assignments, post/pre increment and decrement). The idea
- // being that they would support an extra Emition interface that
- // does not leave a result on the stack.
- // </summary>
-
- public abstract class ExpressionStatement : Expression {
-
- // <summary>
- // Requests the expression to be emitted in a `statement'
- // context. This means that no new value is left on the
- // stack after invoking this method (constrasted with
- // Emit that will always leave a value on the stack).
- // </summary>
- public abstract void EmitStatement (EmitContext ec);
- }
-
- // <summary>
- // This kind of cast is used to encapsulate the child
- // whose type is child.Type into an expression that is
- // reported to return "return_type". This is used to encapsulate
- // expressions which have compatible types, but need to be dealt
- // at higher levels with.
- //
- // For example, a "byte" expression could be encapsulated in one
- // of these as an "unsigned int". The type for the expression
- // would be "unsigned int".
- //
- // </summary>
-
- public class EmptyCast : Expression {
- protected Expression child;
-
- public EmptyCast (Expression child, Type return_type)
- {
- ExprClass = child.ExprClass;
- type = return_type;
- this.child = child;
- }
-
- public override Expression Resolve (TypeContainer tc)
- {
- // This should never be invoked, we are born in fully
- // initialized state.
-