using System.Reflection.Emit;
using System.Collections;
- public class Const : MemberCore {
- public Expression ConstantType;
+ public class Const : FieldMember {
public Expression Expr;
- public Attributes OptAttributes;
- public FieldBuilder FieldBuilder;
EmitContext const_ec;
+ bool resolved = false;
object ConstantValue = null;
- Type type;
bool in_transit = false;
Modifiers.INTERNAL |
Modifiers.PRIVATE;
- public Const (Expression constant_type, string name, Expression expr, int mod_flags,
- Attributes attrs, Location loc)
- : base (name, loc)
+ public Const (TypeContainer parent, Expression constant_type, string name,
+ Expression expr, int mod_flags, Attributes attrs, Location loc)
+ : base (parent, constant_type, mod_flags, AllowedModifiers,
+ new MemberName (name), null, attrs, loc)
{
- ConstantType = constant_type;
- Name = name;
Expr = expr;
- ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
- OptAttributes = attrs;
+ ModFlags |= Modifiers.STATIC;
}
public FieldAttributes FieldAttr {
/// <summary>
/// Defines the constant in the @parent
/// </summary>
- public override bool Define (TypeContainer parent)
+ public override bool Define ()
{
- type = parent.ResolveType (ConstantType, false, Location);
-
- if (type == null)
+ if (!base.Define ())
return false;
- const_ec = new EmitContext (parent, Location, null, type, ModFlags);
+ const_ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
+
+ Type ttype = MemberType;
+ while (ttype.IsArray)
+ ttype = TypeManager.GetElementType (ttype);
- if (!TypeManager.IsBuiltinType (type) &&
- (!type.IsSubclassOf (TypeManager.enum_type))) {
+ if (!TypeManager.IsBuiltinType (ttype) &&
+ (!ttype.IsSubclassOf (TypeManager.enum_type))) {
Report.Error (
-3, Location,
"Constant type is not valid (only system types are allowed)");
return false;
}
- Type ptype = parent.TypeBuilder.BaseType;
-
- if (ptype != null) {
- MemberList list = TypeContainer.FindMembers (
- ptype, MemberTypes.Field, BindingFlags.Public,
- Type.FilterName, Name);
-
- if (list.Count == 0)
- if ((ModFlags & Modifiers.NEW) != 0)
- WarningNotHiding (parent);
-
- } else if ((ModFlags & Modifiers.NEW) != 0)
- WarningNotHiding (parent);
-
- FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, FieldAttr);
TypeManager.RegisterConstant (FieldBuilder, this);
return true;
}
+ //
+ // Changes the type of the constant expression `expr' to the Type `type'
+ // Returns null on failure.
+ //
+ public static Constant ChangeType (Location loc, Constant expr, Type type)
+ {
+ if (type == TypeManager.object_type)
+ return expr;
+
+ bool fail;
+
+ // from the null type to any reference-type.
+ if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type))
+ return NullLiteral.Null;
+
+ if (!Convert.ImplicitStandardConversionExists (expr, type)){
+ Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
+ return null;
+ }
+
+ object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail);
+ if (fail){
+ Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
+
+ //
+ // We should always catch the error before this is ever
+ // reached, by calling Convert.ImplicitStandardConversionExists
+ //
+ throw new Exception (
+ String.Format ("LookupConstantValue: This should never be reached {0} {1}", expr.Type, type));
+ }
+
+ Constant retval;
+ if (type == TypeManager.int32_type)
+ retval = new IntConstant ((int) constant_value);
+ else if (type == TypeManager.uint32_type)
+ retval = new UIntConstant ((uint) constant_value);
+ else if (type == TypeManager.int64_type)
+ retval = new LongConstant ((long) constant_value);
+ else if (type == TypeManager.uint64_type)
+ retval = new ULongConstant ((ulong) constant_value);
+ else if (type == TypeManager.float_type)
+ retval = new FloatConstant ((float) constant_value);
+ else if (type == TypeManager.double_type)
+ retval = new DoubleConstant ((double) constant_value);
+ else if (type == TypeManager.string_type)
+ retval = new StringConstant ((string) constant_value);
+ else if (type == TypeManager.short_type)
+ retval = new ShortConstant ((short) constant_value);
+ else if (type == TypeManager.ushort_type)
+ retval = new UShortConstant ((ushort) constant_value);
+ else if (type == TypeManager.sbyte_type)
+ retval = new SByteConstant ((sbyte) constant_value);
+ else if (type == TypeManager.byte_type)
+ retval = new ByteConstant ((byte) constant_value);
+ else if (type == TypeManager.char_type)
+ retval = new CharConstant ((char) constant_value);
+ else if (type == TypeManager.bool_type)
+ retval = new BoolConstant ((bool) constant_value);
+ else
+ throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
+
+ return retval;
+ }
+
/// <summary>
/// Looks up the value of a constant field. Defines it if it hasn't
/// already been. Similar to LookupEnumValue in spirit.
/// </summary>
- public object LookupConstantValue ()
+ public bool LookupConstantValue (out object value)
{
- if (ConstantValue != null)
- return ConstantValue;
+ if (resolved) {
+ value = ConstantValue;
+ return true;
+ }
if (in_transit) {
Report.Error (110, Location,
"The evaluation of the constant value for `" +
Name + "' involves a circular definition.");
- return null;
+ value = null;
+ return false;
}
in_transit = true;
int errors = Report.Errors;
+ //
+ // We might have cleared Expr ourselves in a recursive definition
+ //
+ if (Expr == null){
+ value = null;
+ return false;
+ }
+
Expr = Expr.Resolve (const_ec);
in_transit = false;
if (Expr == null) {
if (errors == Report.Errors)
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
- if (!(Expr is Constant)) {
+ Expression real_expr = Expr;
+
+ Constant ce = Expr as Constant;
+ if (ce == null){
UnCheckedExpr un_expr = Expr as UnCheckedExpr;
CheckedExpr ch_expr = Expr as CheckedExpr;
+ EmptyCast ec_expr = Expr as EmptyCast;
if ((un_expr != null) && (un_expr.Expr is Constant))
Expr = un_expr.Expr;
else if ((ch_expr != null) && (ch_expr.Expr is Constant))
Expr = ch_expr.Expr;
- else {
+ else if ((ec_expr != null) && (ec_expr.Child is Constant))
+ Expr = ec_expr.Child;
+ else if (Expr is ArrayCreation){
+ Report.Error (133, Location, "Arrays can not be constant");
+ } else {
if (errors == Report.Errors)
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
- }
-
- ConstantValue = ((Constant) Expr).GetValue ();
- if (type != Expr.Type) {
- bool fail;
+ ce = Expr as Constant;
+ }
- // from the null type to any reference-type.
- if (Expr is NullLiteral && !type.IsValueType &&
- !TypeManager.IsEnumType (type)){
- return NullLiteral.Null;
- }
-
- ConstantValue = TypeManager.ChangeType (ConstantValue, type, out fail);
- if (fail){
- Convert.Error_CannotImplicitConversion (Location, Expr.Type, type);
- return null;
+ if (MemberType != real_expr.Type) {
+ ce = ChangeType (Location, ce, MemberType);
+ if (ce == null){
+ value = null;
+ return false;
}
-
- if (type == TypeManager.int32_type)
- Expr = new IntConstant ((int) ConstantValue);
- else if (type == TypeManager.uint32_type)
- Expr = new UIntConstant ((uint) ConstantValue);
- else if (type == TypeManager.int64_type)
- Expr = new LongConstant ((long) ConstantValue);
- else if (type == TypeManager.uint64_type)
- Expr = new ULongConstant ((ulong) ConstantValue);
- else if (type == TypeManager.float_type)
- Expr = new FloatConstant ((float) ConstantValue);
- else if (type == TypeManager.double_type)
- Expr = new DoubleConstant ((double) ConstantValue);
- else if (type == TypeManager.string_type)
- Expr = new StringConstant ((string) ConstantValue);
- else if (type == TypeManager.short_type)
- Expr = new ShortConstant ((short) ConstantValue);
- else if (type == TypeManager.ushort_type)
- Expr = new UShortConstant ((ushort) ConstantValue);
- else if (type == TypeManager.sbyte_type)
- Expr = new SByteConstant ((sbyte) ConstantValue);
- else if (type == TypeManager.byte_type)
- Expr = new ByteConstant ((byte) ConstantValue);
- else if (type == TypeManager.char_type)
- Expr = new CharConstant ((char) ConstantValue);
- else if (type == TypeManager.bool_type)
- Expr = new BoolConstant ((bool) ConstantValue);
+ Expr = ce;
}
+ ConstantValue = ce.GetValue ();
- if (type.IsEnum){
+ if (MemberType.IsEnum){
//
// This sadly does not work for our user-defined enumerations types ;-(
//
try {
ConstantValue = System.Enum.ToObject (
- type, ConstantValue);
+ MemberType, ConstantValue);
} catch (ArgumentException){
Report.Error (
-16, Location,
FieldBuilder.SetConstant (ConstantValue);
if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
- return null;
+ throw new Exception ("Cannot register const value");
- return ConstantValue;
+ value = ConstantValue;
+ resolved = true;
+ return true;
}
/// <summary>
/// Emits the field value by evaluating the expression
/// </summary>
- public void EmitConstant (TypeContainer parent)
+ public override void Emit ()
{
- LookupConstantValue ();
-
- return;
+ object value;
+ LookupConstantValue (out value);
+
+ if (OptAttributes != null) {
+ OptAttributes.Emit (const_ec, this);
+ }
+
+ base.Emit ();
}
}
}