String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
}
- Constant retval;
- if (type == TypeManager.int32_type)
- retval = new IntConstant ((int) constant_value, loc);
- else if (type == TypeManager.uint32_type)
- retval = new UIntConstant ((uint) constant_value, loc);
- else if (type == TypeManager.int64_type)
- retval = new LongConstant ((long) constant_value, loc);
- else if (type == TypeManager.uint64_type)
- retval = new ULongConstant ((ulong) constant_value, loc);
- else if (type == TypeManager.float_type)
- retval = new FloatConstant ((float) constant_value, loc);
- else if (type == TypeManager.double_type)
- retval = new DoubleConstant ((double) constant_value, loc);
- else if (type == TypeManager.string_type)
- retval = new StringConstant ((string) constant_value, loc);
- else if (type == TypeManager.short_type)
- retval = new ShortConstant ((short) constant_value, loc);
- else if (type == TypeManager.ushort_type)
- retval = new UShortConstant ((ushort) constant_value, loc);
- else if (type == TypeManager.sbyte_type)
- retval = new SByteConstant ((sbyte) constant_value, loc);
- else if (type == TypeManager.byte_type)
- retval = new ByteConstant ((byte) constant_value, loc);
- else if (type == TypeManager.char_type)
- retval = new CharConstant ((char) constant_value, loc);
- else if (type == TypeManager.bool_type)
- retval = new BoolConstant ((bool) constant_value, loc);
- else if (type == TypeManager.decimal_type)
- retval = new DecimalConstant ((decimal) constant_value, loc);
- else
- throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
-
- return retval;
+ return CreateConstant (type, constant_value, loc);
+ }
+
+ /// Returns a constant instance based on Type
+ /// The returned value is already resolved.
+ public static Constant CreateConstant (Type t, object v, Location loc)
+ {
+ if (t == TypeManager.int32_type)
+ return new IntConstant ((int) v, loc);
+ if (t == TypeManager.string_type)
+ return new StringConstant ((string) v, loc);
+ if (t == TypeManager.uint32_type)
+ return new UIntConstant ((uint) v, loc);
+ if (t == TypeManager.int64_type)
+ return new LongConstant ((long) v, loc);
+ if (t == TypeManager.uint64_type)
+ return new ULongConstant ((ulong) v, loc);
+ if (t == TypeManager.float_type)
+ return new FloatConstant ((float) v, loc);
+ if (t == TypeManager.double_type)
+ return new DoubleConstant ((double) v, loc);
+ if (t == TypeManager.short_type)
+ return new ShortConstant ((short)v, loc);
+ if (t == TypeManager.ushort_type)
+ return new UShortConstant ((ushort)v, loc);
+ if (t == TypeManager.sbyte_type)
+ return new SByteConstant ((sbyte)v, loc);
+ if (t == TypeManager.byte_type)
+ return new ByteConstant ((byte)v, loc);
+ if (t == TypeManager.char_type)
+ return new CharConstant ((char)v, loc);
+ if (t == TypeManager.bool_type)
+ return new BoolConstant ((bool) v, loc);
+ if (t == TypeManager.decimal_type)
+ return new DecimalConstant ((decimal) v, loc);
+ if (TypeManager.IsEnumType (t)) {
+ Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+ if (real_type == t)
+ real_type = System.Enum.GetUnderlyingType (real_type);
+ return new EnumConstant (CreateConstant (real_type, v, loc), t);
+ }
+ if (v == null && !TypeManager.IsValueType (t))
+ return new EmptyConstantCast (new NullConstant (loc), t);
+
+ throw new Exception ("Unknown type for constant (" + t +
+ "), details: " + v);
}
protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
Reduce (true, target);
base.Error_ValueCannotBeConverted (loc, target, expl);
}
- catch
+ catch
{
Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
GetValue ().ToString (), TypeManager.CSharpName (target));
}
public class FloatConstant : Constant {
- public readonly float Value;
+ public float Value;
public FloatConstant (float v, Location loc):
base (loc)
}
public class DoubleConstant : Constant {
- public readonly double Value;
+ public double Value;
public DoubleConstant (double v, Location loc):
base (loc)
Error_OperatorCannotBeApplied (loc, OperName (Oper), t);
}
- /// <remarks>
- /// The result has been already resolved:
- ///
- /// FIXME: a minus constant -128 sbyte cant be turned into a
- /// constant byte.
- /// </remarks>
- static Expression TryReduceNegative (Constant expr)
- {
- Expression e = null;
-
- if (expr is IntConstant)
- e = new IntConstant (-((IntConstant) expr).Value, expr.Location);
- else if (expr is UIntConstant){
- uint value = ((UIntConstant) expr).Value;
-
- if (value < 2147483649)
- return new IntConstant (-(int)value, expr.Location);
- else
- e = new LongConstant (-value, expr.Location);
- }
- else if (expr is LongConstant)
- e = new LongConstant (-((LongConstant) expr).Value, expr.Location);
- else if (expr is ULongConstant){
- ulong value = ((ULongConstant) expr).Value;
-
- if (value < 9223372036854775809)
- return new LongConstant(-(long)value, expr.Location);
- }
- else if (expr is FloatConstant)
- e = new FloatConstant (-((FloatConstant) expr).Value, expr.Location);
- else if (expr is DoubleConstant)
- e = new DoubleConstant (-((DoubleConstant) expr).Value, expr.Location);
- else if (expr is DecimalConstant)
- e = new DecimalConstant (-((DecimalConstant) expr).Value, expr.Location);
- else if (expr is ShortConstant)
- e = new IntConstant (-((ShortConstant) expr).Value, expr.Location);
- else if (expr is UShortConstant)
- e = new IntConstant (-((UShortConstant) expr).Value, expr.Location);
- else if (expr is SByteConstant)
- e = new IntConstant (-((SByteConstant) expr).Value, expr.Location);
- else if (expr is ByteConstant)
- e = new IntConstant (-((ByteConstant) expr).Value, expr.Location);
- return e;
- }
-
// <summary>
// This routine will attempt to simplify the unary expression when the
- // argument is a constant. The result is returned in `result' and the
- // function returns true or false depending on whether a reduction
- // was performed or not
+ // argument is a constant.
// </summary>
- bool Reduce (EmitContext ec, Constant e, out Expression result)
+ Constant TryReduceConstant (EmitContext ec, Constant e)
{
Type expr_type = e.Type;
switch (Oper){
- case Operator.UnaryPlus:
- if (expr_type == TypeManager.bool_type){
- result = null;
- Error23 (expr_type);
- return false;
- }
-
- result = e;
- return true;
-
- case Operator.UnaryNegation:
- result = TryReduceNegative (e);
- return result != null;
-
- case Operator.LogicalNot:
- if (expr_type != TypeManager.bool_type) {
- result = null;
- Error23 (expr_type);
- return false;
- }
-
- BoolConstant b = (BoolConstant) e;
- result = new BoolConstant (!(b.Value), b.Location);
- return true;
+ case Operator.UnaryPlus:
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type)
+ return new IntConstant (((ByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.sbyte_type)
+ return new IntConstant (((SByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.short_type)
+ return new IntConstant (((ShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.ushort_type)
+ return new IntConstant (((UShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.char_type)
+ return new IntConstant (((CharConstant)e).Value, e.Location);
+
+ // Predefined operators
+ if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
+ expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
+ expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
+ expr_type == TypeManager.decimal_type)
+ {
+ return e;
+ }
+
+ return null;
- case Operator.OnesComplement:
- if (!((expr_type == TypeManager.int32_type) ||
- (expr_type == TypeManager.uint32_type) ||
- (expr_type == TypeManager.int64_type) ||
- (expr_type == TypeManager.uint64_type) ||
- (expr_type.IsSubclassOf (TypeManager.enum_type)))){
-
- result = null;
- if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
- result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
- result = result.Resolve (ec);
- } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
- result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
- result = result.Resolve (ec);
- } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
- result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
- result = result.Resolve (ec);
- } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
- result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
- result = result.Resolve (ec);
+ case Operator.UnaryNegation:
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type)
+ return new IntConstant (-((ByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.sbyte_type)
+ return new IntConstant (-((SByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.short_type)
+ return new IntConstant (-((ShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.ushort_type)
+ return new IntConstant (-((UShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.char_type)
+ return new IntConstant (-((CharConstant)e).Value, e.Location);
+
+ // Predefined operators
+ if (expr_type == TypeManager.int32_type) {
+ int value = ((IntConstant)e).Value;
+ if (value == int.MinValue) {
+ if (ec.ConstantCheckState) {
+ ConstantFold.Error_CompileTimeOverflow (loc);
+ return null;
+ }
+ return e;
+ }
+ return new IntConstant (-value, e.Location);
+ }
+ if (expr_type == TypeManager.int64_type) {
+ long value = ((LongConstant)e).Value;
+ if (value == long.MinValue) {
+ if (ec.ConstantCheckState) {
+ ConstantFold.Error_CompileTimeOverflow (loc);
+ return null;
+ }
+ return e;
+ }
+ return new LongConstant (-value, e.Location);
}
- if (result == null || !(result is Constant)){
- result = null;
- Error23 (expr_type);
- return false;
+ if (expr_type == TypeManager.uint32_type) {
+ UIntLiteral uil = e as UIntLiteral;
+ if (uil != null) {
+ if (uil.Value == 2147483648)
+ return new IntLiteral (int.MinValue, e.Location);
+ return new LongLiteral (-uil.Value, e.Location);
+ }
+ return new LongConstant (-((UIntConstant)e).Value, e.Location);
}
- expr_type = result.Type;
- e = (Constant) result;
- }
+ if (expr_type == TypeManager.uint64_type) {
+ ULongLiteral ull = e as ULongLiteral;
+ if (ull != null && ull.Value == 9223372036854775808)
+ return new LongLiteral (long.MinValue, e.Location);
+ return null;
+ }
- if (e is EnumConstant){
- EnumConstant enum_constant = (EnumConstant) e;
- Expression reduced;
-
- if (Reduce (ec, enum_constant.Child, out reduced)){
- result = new EnumConstant ((Constant) reduced, enum_constant.Type);
- return true;
- } else {
- result = null;
- return false;
+ if (expr_type == TypeManager.float_type) {
+ FloatLiteral fl = e as FloatLiteral;
+ // For better error reporting
+ if (fl != null) {
+ fl.Value = -fl.Value;
+ return fl;
+ }
+ return new FloatConstant (-((FloatConstant)e).Value, e.Location);
}
- }
+ if (expr_type == TypeManager.double_type) {
+ DoubleLiteral dl = e as DoubleLiteral;
+ // For better error reporting
+ if (dl != null) {
+ dl.Value = -dl.Value;
+ return dl;
+ }
- if (expr_type == TypeManager.int32_type){
- result = new IntConstant (~ ((IntConstant) e).Value, e.Location);
- } else if (expr_type == TypeManager.uint32_type){
- result = new UIntConstant (~ ((UIntConstant) e).Value, e.Location);
- } else if (expr_type == TypeManager.int64_type){
- result = new LongConstant (~ ((LongConstant) e).Value, e.Location);
- } else if (expr_type == TypeManager.uint64_type){
- result = new ULongConstant (~ ((ULongConstant) e).Value, e.Location);
- } else {
- result = null;
- Error23 (expr_type);
- return false;
- }
- return true;
+ return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
+ }
+ if (expr_type == TypeManager.decimal_type)
+ return new DecimalConstant (-((DecimalConstant)e).Value, e.Location);
- case Operator.AddressOf:
- result = this;
- return false;
+ return null;
+
+ case Operator.LogicalNot:
+ if (expr_type != TypeManager.bool_type)
+ return null;
+
+ BoolConstant b = (BoolConstant) e;
+ return new BoolConstant (!(b.Value), b.Location);
+
+ case Operator.OnesComplement:
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type)
+ return new IntConstant (~((ByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.sbyte_type)
+ return new IntConstant (~((SByteConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.short_type)
+ return new IntConstant (~((ShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.ushort_type)
+ return new IntConstant (~((UShortConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.char_type)
+ return new IntConstant (~((CharConstant)e).Value, e.Location);
+
+ // Predefined operators
+ if (expr_type == TypeManager.int32_type)
+ return new IntConstant (~((IntConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.uint32_type)
+ return new UIntConstant (~((UIntConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.int64_type)
+ return new LongConstant (~((LongConstant)e).Value, e.Location);
+ if (expr_type == TypeManager.uint64_type)
+ return new ULongConstant (~((UIntConstant)e).Value, e.Location);
+ if (e is EnumConstant) {
+ e = TryReduceConstant (ec, ((EnumConstant)e).Child);
+ if (e != null)
+ e = new EnumConstant (e, expr_type);
+ return e;
+ }
+ return null;
- case Operator.Indirection:
- result = this;
- return false;
+ case Operator.AddressOf:
+ return e;
+
+ case Operator.Indirection:
+ return e;
}
throw new Exception ("Can not constant fold: " + Oper.ToString());
}
//
// Attempt to use a constant folding operation.
- if (Expr is Constant){
- Expression result;
-
- if (Reduce (ec, (Constant) Expr, out result))
- return result;
+ Constant cexpr = Expr as Constant;
+ if (cexpr != null) {
+ cexpr = TryReduceConstant (ec, cexpr);
+ if (cexpr != null) {
+ return cexpr;
+ }
}
//
// Step 2: Perform Operator Overload location
//
Type expr_type = Expr.Type;
- Expression mg;
- string op_name;
-
- op_name = oper_names [(int) Oper];
+ string op_name = oper_names [(int) Oper];
- mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
-
+ Expression mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
Expression e = StaticCallExpr.MakeSimpleCall (
ec, (MethodGroupExpr) mg, Expr, loc);
return e;
}
- // Only perform numeric promotions on:
- // +, -
-
- if (expr_type == null)
- return null;
-
switch (Oper){
case Operator.LogicalNot:
if (expr_type != TypeManager.bool_type) {
return this;
case Operator.OnesComplement:
- if (!((expr_type == TypeManager.int32_type) ||
- (expr_type == TypeManager.uint32_type) ||
- (expr_type == TypeManager.int64_type) ||
- (expr_type == TypeManager.uint64_type) ||
- (expr_type.IsSubclassOf (TypeManager.enum_type)))){
- Expression e;
-
- e = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
- if (e != null)
- goto ok;
- e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc);
- if (e != null)
- goto ok;
- e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
- if (e != null)
- goto ok;
- e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc);
- if (e != null)
- goto ok;
- Error23 (expr_type);
- return null;
- ok:
- Expr = e;
- expr_type = e.Type;
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
+ expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
+ expr_type == TypeManager.char_type)
+ {
+ type = TypeManager.int32_type;
+ return new EmptyCast (this, type);
+ }
+
+ // Predefined operators
+ if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
+ expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
+ TypeManager.IsEnumType (expr_type))
+ {
+ type = expr_type;
+ return this;
}
- type = expr_type;
- return this;
+ type = TypeManager.int32_type;
+ Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
+ if (Expr != null)
+ return this;
+
+ Error23 (expr_type);
+ return null;
case Operator.AddressOf:
if (!ec.InUnsafe) {
return new Indirection (Expr, loc);
case Operator.UnaryPlus:
- //
- // A plus in front of something is just a no-op, so return the child.
- //
- return Expr;
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
+ expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
+ expr_type == TypeManager.char_type)
+ {
+ return new EmptyCast (Expr, TypeManager.int32_type);
+ }
- case Operator.UnaryNegation:
- //
- // Deals with -literals
- // int operator- (int x)
- // long operator- (long x)
- // float operator- (float f)
- // double operator- (double d)
- // decimal operator- (decimal d)
- //
- Expression expr = null;
+ // Predefined operators
+ if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
+ expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
+ expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
+ expr_type == TypeManager.decimal_type)
+ {
+ return Expr;
+ }
+
+ Expr = Convert.ImplicitUserConversion(ec, Expr, TypeManager.int32_type, loc);
+ if (Expr != null) {
+ // Because we can completely ignore unary +
+ return Expr;
+ }
+
+ Error23 (expr_type);
+ return null;
+ case Operator.UnaryNegation:
//
// transform - - expr into expr
//
- if (Expr is Unary){
- Unary unary = (Unary) Expr;
-
- if (unary.Oper == Operator.UnaryNegation)
- return unary.Expr;
+ Unary u = Expr as Unary;
+ if (u != null && u.Oper == Operator.UnaryNegation) {
+ return u.Expr;
+ }
+
+ // Unary numeric promotions
+ if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
+ expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
+ expr_type == TypeManager.char_type)
+ {
+ type = TypeManager.int32_type;
+ return new EmptyCast (this, type);
}
//
- // perform numeric promotions to int,
- // long, double.
- //
- //
- // The following is inneficient, because we call
- // ImplicitConversion too many times.
- //
- // It is also not clear if we should convert to Float
- // or Double initially.
+ // Predefined operators
//
- if (expr_type == TypeManager.uint32_type){
- //
- // FIXME: handle exception to this rule that
- // permits the int value -2147483648 (-2^31) to
- // bt wrote as a decimal interger literal
- //
+ if (expr_type == TypeManager.uint32_type) {
type = TypeManager.int64_type;
- Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
+ Expr = Convert.ImplicitNumericConversion (Expr, type);
return this;
}
- if (expr_type == TypeManager.uint64_type){
- //
- // FIXME: Handle exception of `long value'
- // -92233720368547758087 (-2^63) to be wrote as
- // decimal integer literal.
- //
- Error23 (expr_type);
- return null;
- }
-
- if (expr_type == TypeManager.float_type){
+ if (expr_type == TypeManager.int32_type || expr_type == TypeManager.int64_type ||
+ expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
+ expr_type == TypeManager.decimal_type)
+ {
type = expr_type;
return this;
}
-
- expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
- if (expr != null){
- Expr = expr;
- type = expr.Type;
- return this;
- }
- expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
- if (expr != null){
- Expr = expr;
- type = expr.Type;
- return this;
- }
+ //
+ // User conversion
- expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);
- if (expr != null){
- Expr = expr;
- type = expr.Type;
+ type = TypeManager.int32_type;
+ Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
+ if (Expr != null)
return this;
- }
-
+
Error23 (expr_type);
return null;
}