String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
}
- 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);
+ 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;
}
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 float Value;
+ public readonly float Value;
public FloatConstant (float v, Location loc):
base (loc)
}
public class DoubleConstant : Constant {
- public double Value;
+ public readonly 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.
+ // 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
// </summary>
- Constant TryReduceConstant (EmitContext ec, Constant e)
+ bool Reduce (EmitContext ec, Constant e, out Expression result)
{
Type expr_type = e.Type;
switch (Oper){
- 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.UnaryPlus:
+ if (expr_type == TypeManager.bool_type){
+ result = null;
+ Error23 (expr_type);
+ return false;
+ }
- 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 (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);
- }
-
- 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;
+ 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.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);
}
- 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 (result == null || !(result is Constant)){
+ result = null;
+ Error23 (expr_type);
+ return false;
}
- if (expr_type == TypeManager.double_type) {
- DoubleLiteral dl = e as DoubleLiteral;
- // For better error reporting
- if (dl != null) {
- dl.Value = -dl.Value;
- return dl;
- }
- return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
- }
- if (expr_type == TypeManager.decimal_type)
- return new DecimalConstant (-((DecimalConstant)e).Value, e.Location);
+ expr_type = result.Type;
+ e = (Constant) result;
+ }
- return null;
-
- case Operator.LogicalNot:
- if (expr_type != TypeManager.bool_type)
- return null;
+ if (e is EnumConstant){
+ EnumConstant enum_constant = (EnumConstant) e;
+ Expression reduced;
- 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;
+ if (Reduce (ec, enum_constant.Child, out reduced)){
+ result = new EnumConstant ((Constant) reduced, enum_constant.Type);
+ return true;
+ } else {
+ result = null;
+ return false;
}
- return null;
+ }
- case Operator.AddressOf:
- return e;
+ 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;
- case Operator.Indirection:
- return e;
+ case Operator.AddressOf:
+ result = this;
+ return false;
+
+ case Operator.Indirection:
+ result = this;
+ return false;
}
throw new Exception ("Can not constant fold: " + Oper.ToString());
}
//
// Attempt to use a constant folding operation.
- Constant cexpr = Expr as Constant;
- if (cexpr != null) {
- cexpr = TryReduceConstant (ec, cexpr);
- if (cexpr != null) {
- return cexpr;
- }
+ if (Expr is Constant){
+ Expression result;
+
+ if (Reduce (ec, (Constant) Expr, out result))
+ return result;
}
//
// Step 2: Perform Operator Overload location
//
Type expr_type = Expr.Type;
- string op_name = oper_names [(int) Oper];
+ Expression mg;
+ string op_name;
+
+ op_name = oper_names [(int) Oper];
- Expression mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+ 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:
- // 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;
+ 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;
}
- type = TypeManager.int32_type;
- Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
- if (Expr != null)
- return this;
-
- Error23 (expr_type);
- return null;
+ type = expr_type;
+ return this;
case Operator.AddressOf:
if (!ec.InUnsafe) {
return new Indirection (Expr, loc);
case Operator.UnaryPlus:
- // 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);
- }
-
- // 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;
+ //
+ // A plus in front of something is just a no-op, so return the child.
+ //
+ return Expr;
case Operator.UnaryNegation:
//
- // transform - - expr into expr
+ // Deals with -literals
+ // int operator- (int x)
+ // long operator- (long x)
+ // float operator- (float f)
+ // double operator- (double d)
+ // decimal operator- (decimal d)
//
- Unary u = Expr as Unary;
- if (u != null && u.Oper == Operator.UnaryNegation) {
- return u.Expr;
- }
+ Expression expr = null;
- // 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);
+ //
+ // transform - - expr into expr
+ //
+ if (Expr is Unary){
+ Unary unary = (Unary) Expr;
+
+ if (unary.Oper == Operator.UnaryNegation)
+ return unary.Expr;
}
//
- // Predefined operators
+ // perform numeric promotions to int,
+ // long, double.
//
- if (expr_type == TypeManager.uint32_type) {
+ //
+ // 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.
+ //
+ 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
+ //
type = TypeManager.int64_type;
- Expr = Convert.ImplicitNumericConversion (Expr, type);
+ Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
return this;
}
- 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)
- {
+ 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){
type = expr_type;
return this;
}
+
+ expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
+ if (expr != null){
+ Expr = expr;
+ type = expr.Type;
+ return this;
+ }
- //
- // User conversion
-
- type = TypeManager.int32_type;
- Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
- if (Expr != null)
+ expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
+ if (expr != null){
+ Expr = expr;
+ type = expr.Type;
return this;
+ }
+ expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);
+ if (expr != null){
+ Expr = expr;
+ type = expr.Type;
+ return this;
+ }
+
Error23 (expr_type);
return null;
}