using System.Reflection.Emit;
using System.Collections;
- public class Const : MemberBase {
- public Expression ConstantType;
+ public class Const : FieldBase {
public Expression Expr;
- public FieldBuilder FieldBuilder;
EmitContext const_ec;
+ bool resolved = false;
object ConstantValue = null;
Type type;
Modifiers.INTERNAL |
Modifiers.PRIVATE;
- public Const (Expression constant_type, string name, Expression expr, int mod_flags,
- Attributes attrs, Location loc)
- : base (constant_type, mod_flags, AllowedModifiers, Modifiers.PRIVATE, name, attrs, loc)
+ public Const (Expression constant_type, string name, Expression expr,
+ int mod_flags, Attributes attrs, Location loc)
+ : base (constant_type, mod_flags, AllowedModifiers,
+ new MemberName (name), null, attrs, loc)
{
- ConstantType = constant_type;
- Name = name;
Expr = expr;
}
/// </summary>
public override bool Define (TypeContainer parent)
{
- type = parent.ResolveType (ConstantType, false, Location);
+ type = parent.ResolveType (Type, false, Location);
if (type == null)
return false;
const_ec = new EmitContext (parent, Location, null, type, ModFlags);
- if (!TypeManager.IsBuiltinType (type) &&
- (!type.IsSubclassOf (TypeManager.enum_type))) {
+ Type ttype = type;
+ while (ttype.IsArray)
+ ttype = TypeManager.GetElementType (ttype);
+
+ if (!TypeManager.IsBuiltinType (ttype) &&
+ (!ttype.IsSubclassOf (TypeManager.enum_type))) {
Report.Error (
-3, Location,
"Constant type is not valid (only system types are allowed)");
/// 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;
}
Constant ce = Expr as Constant;
Expr = un_expr.Expr;
else if ((ch_expr != null) && (ch_expr.Expr is Constant))
Expr = ch_expr.Expr;
- else {
+ else if (Expr is ArrayCreation) {
+ ArrayCreation ac = (ArrayCreation) Expr;
+
+ Expr = ac.TurnIntoConstant ();
+ if (Expr == null){
+ Report.Error (150, Location, "A constant value is expected");
+ value = null;
+ return false;
+ }
+ } else {
if (errors == Report.Errors)
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
}
if (type != ce.Type) {
ce = ChangeType (Location, ce, type);
- if (ce == null)
- return null;
+ if (ce == null){
+ value = null;
+ return false;
+ }
Expr = ce;
}
ConstantValue = ce.GetValue ();
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 (TypeContainer parent)
{
- LookupConstantValue ();
-
- return;
+ object value;
+ LookupConstantValue (out value);
+
+ if (OptAttributes != null) {
+ OptAttributes.Emit (const_ec, this);
+ }
+
+ base.Emit (parent);
}
}
}