}
}
- /// <summary>
- /// Expression which resolves to a type.
- /// </summary>
- public interface ITypeExpression
- {
- /// <summary>
- /// Resolve the expression, but only lookup types.
- /// </summary>
- Expression DoResolveType (EmitContext ec);
- }
-
/// <remarks>
/// Base class for expressions
/// </remarks>
{
return DoResolve (ec);
}
-
+
+ //
+ // This is used if the expression should be resolved as a type.
+ // the default implementation fails. Use this method in
+ // those participants in the SimpleName chain system.
+ //
+ public virtual Expression ResolveAsTypeStep (EmitContext ec)
+ {
+ return null;
+ }
+
+ //
+ // This is used to resolve the expression as a type, a null
+ // value will be returned if the expression is not a type
+ // reference
+ //
+ public Expression ResolveAsTypeTerminal (EmitContext ec)
+ {
+ Expression e = ResolveAsTypeStep (ec);
+
+ if (e == null)
+ return null;
+ if (e is SimpleName)
+ return null;
+ return e;
+ }
+
/// <summary>
/// Resolves an expression and performs semantic analysis on it.
/// </summary>
/// </remarks>
public Expression Resolve (EmitContext ec, ResolveFlags flags)
{
- // Are we doing a types-only search ?
- if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) {
- ITypeExpression type_expr = this as ITypeExpression;
-
- if (type_expr == null)
- return null;
-
- return type_expr.DoResolveType (ec);
- }
+ if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
+ return ResolveAsTypeStep (ec);
bool old_do_flow_analysis = ec.DoFlowAnalysis;
if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
if ((e is TypeExpr) || (e is ComposedCast)) {
if ((flags & ResolveFlags.Type) == 0) {
- e.Error118 (flags);
+ e.Error_UnexpectedKind (flags);
return null;
}
switch (e.eclass) {
case ExprClass.Type:
if ((flags & ResolveFlags.VariableOrValue) == 0) {
- e.Error118 (flags);
+ e.Error_UnexpectedKind (flags);
return null;
}
break;
case ExprClass.EventAccess:
case ExprClass.IndexerAccess:
if ((flags & ResolveFlags.VariableOrValue) == 0) {
- e.Error118 (flags);
+ Console.WriteLine ("I got: {0} and {1}", e.GetType (), e);
+ Console.WriteLine ("I am {0} and {1}", this.GetType (), this);
+ FieldInfo fi = ((FieldExpr) e).FieldInfo;
+
+ Console.WriteLine ("{0} and {1}", fi.DeclaringType, fi.Name);
+ e.Error_UnexpectedKind (flags);
return null;
}
break;
int count = mi.Length;
- if (count > 1)
- return new MethodGroupExpr (mi, loc);
-
if (mi [0] is MethodBase)
return new MethodGroupExpr (mi, loc);
+ if (count > 1)
+ return null;
+
return ExprClassFromMemberInfo (ec, mi [0], loc);
}
// notice that it is possible to write "ValueType v = 1", the ValueType here
// is an abstract class, and not really a value type, so we apply the same rules.
//
- if (target_type == TypeManager.object_type || target_type == TypeManager.value_type) {
+ if (target_type == TypeManager.object_type) {
//
// A pointer type cannot be converted to object
//
return new BoxedCast (expr);
if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type)
return new EmptyCast (expr, target_type);
+ } else if (target_type == TypeManager.value_type) {
+ if (expr_type.IsValueType)
+ return new BoxedCast (expr);
+ if (expr is NullLiteral)
+ return new BoxedCast (expr);
} else if (expr_type.IsSubclassOf (target_type)) {
//
// Special case: enumeration to System.Enum.
return UserDefinedConversion (ec, source, target, loc, true);
}
+ /// <summary>
+ /// Returns an expression that can be used to invoke operator true
+ /// on the expression if it exists.
+ /// </summary>
+ static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
+ {
+ MethodBase method;
+ Expression operator_group;
+
+ operator_group = MethodLookup (ec, e.Type, "op_True", loc);
+ if (operator_group == null)
+ return null;
+
+ ArrayList arguments = new ArrayList ();
+ arguments.Add (new Argument (e, Argument.AType.Expression));
+ method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc);
+
+ if (method == null)
+ return null;
+
+ return new StaticCallExpr ((MethodInfo) method, arguments, loc);
+ }
+
+ /// <summary>
+ /// Resolves the expression `e' into a boolean expression: either through
+ /// an implicit conversion, or through an `operator true' invocation
+ /// </summary>
+ public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
+ {
+ e = e.Resolve (ec);
+ if (e == null)
+ return null;
+
+ Expression converted = e;
+ if (e.Type != TypeManager.bool_type)
+ converted = Expression.ConvertImplicit (ec, e, TypeManager.bool_type, new Location (-1));
+
+ //
+ // If no implicit conversion to bool exists, try using `operator true'
+ //
+ if (converted == null){
+ Expression operator_true = Expression.GetOperatorTrue (ec, e, loc);
+ if (operator_true == null){
+ Report.Error (
+ 31, loc, "Can not convert the expression to a boolean");
+ return null;
+ }
+ e = operator_true;
+ } else
+ e = converted;
+
+ return e;
+ }
+
/// <summary>
/// Computes the MethodGroup for the user-defined conversion
/// operators from source_type to target_type. `look_for_explicit'
Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
string op_name;
- //
- // FIXME : How does the False operator come into the picture ?
- // This doesn't look complete and very correct !
- //
- if (target_type == TypeManager.bool_type && !look_for_explicit)
- op_name = "op_True";
- else
- op_name = "op_Implicit";
+ op_name = "op_Implicit";
MethodGroupExpr union3;
-
+
mg1 = MethodLookup (ec, source_type, op_name, loc);
if (source_type.BaseType != null)
mg2 = MethodLookup (ec, source_type.BaseType, op_name, loc);
return null;
Type most_specific_source, most_specific_target;
-
#if BLAH
foreach (MethodBase m in union.Methods){
Console.WriteLine ("Name: " + m.Name);
/// <summary>
/// Reports that we were expecting `expr' to be of class `expected'
/// </summary>
- public void Error118 (string expected)
+ public void Error_UnexpectedKind (string expected)
{
string kind = "Unknown";
"' where a `" + expected + "' was expected");
}
- public void Error118 (ResolveFlags flags)
+ public void Error_UnexpectedKind (ResolveFlags flags)
{
ArrayList valid = new ArrayList (10);
return this;
}
+ public override string ToString ()
+ {
+ return String.Format ("ConvCast ({0}, {1})", mode, child);
+ }
+
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
/// The downside of this is that we might be hitting `LookupType' too many
/// times with this scheme.
/// </remarks>
- public class SimpleName : Expression, ITypeExpression {
+ public class SimpleName : Expression {
public readonly string Name;
//
return SimpleNameResolve (ec, null, true);
}
- public Expression DoResolveType (EmitContext ec)
+ public override Expression ResolveAsTypeStep (EmitContext ec)
{
DeclSpace ds = ec.DeclSpace;
Namespace ns = ds.Namespace;
e = MemberLookup (ec, ec.ContainerType, Name, loc);
if (e == null)
- return DoResolveType (ec);
+ return ResolveAsTypeStep (ec);
if (e is TypeExpr)
return e;
return e;
if (!me.IsStatic &&
- TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
+ TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) &&
+ !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType)) {
Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
"outer type `" + me.DeclaringType + "' via nested type `" +
me.InstanceExpression.Type + "'");
/// <summary>
/// Fully resolved expression that evaluates to a type
/// </summary>
- public class TypeExpr : Expression, ITypeExpression {
+ public class TypeExpr : Expression {
public TypeExpr (Type t, Location l)
{
Type = t;
loc = l;
}
- public virtual Expression DoResolveType (EmitContext ec)
+ public override Expression ResolveAsTypeStep (EmitContext ec)
{
return this;
}
this.name = name;
}
- public override Expression DoResolveType (EmitContext ec)
+ public override Expression ResolveAsTypeStep (EmitContext ec)
{
if (type == null)
type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
public override Expression DoResolve (EmitContext ec)
{
- return DoResolveType (ec);
+ return ResolveAsTypeStep (ec);
}
public override void Emit (EmitContext ec)
// InitOnly fields can only be assigned in constructors
//
- if (ec.IsConstructor)
- return this;
+ if (ec.IsConstructor){
+ if (ec.ContainerType == FieldInfo.DeclaringType)
+ return this;
+ }
Report_AssignToReadonly (true);
if (instance_expr.Type.IsValueType){
IMemoryLocation ml;
LocalTemporary tempo = null;
-
+
if (!(instance_expr is IMemoryLocation)){
tempo = new LocalTemporary (
ec, instance_expr.Type);
//
if (instance_expr is This)
((This)instance_expr).AddressOf (ec, AddressOp.LoadStore);
- else
+ else if (instance_expr.Type.IsValueType && instance_expr is IMemoryLocation){
+ IMemoryLocation ml = (IMemoryLocation) instance_expr;
+
+ ml.AddressOf (ec, AddressOp.LoadStore);
+ } else
instance_expr.Emit (ec);
ig.Emit (OpCodes.Ldflda, FieldInfo);
}