//
namespace CIR {
+ using System;
using System.Collections;
using System.Diagnostics;
- using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
// expression).
// </remarks>
- public abstract Expression Resolve (TypeContainer tc);
+ public abstract Expression DoResolve (TypeContainer tc);
+
+
+ //
+ // Currently Resolve wraps DoResolve to perform sanity
+ // checking and assertion checking on what we expect from Resolve
+ //
+
+ public Expression Resolve (TypeContainer tc)
+ {
+ Expression e = DoResolve (tc);
+
+ if (e != null){
+ if (e.ExprClass == ExprClass.Invalid)
+ throw new Exception ("Expression " + e +
+ " ExprClass is Invalid after resolve");
+
+ if (e.ExprClass != ExprClass.MethodGroup)
+ if (e.type == null)
+ throw new Exception ("Expression " + e +
+ " did not set its type after Resolve");
+ }
+ return e;
+ }
+
// <summary>
// Emits the code for the expression
// </summary>
type = null;
}
+ // <summary>
+ // Returns a literalized version of a literal FieldInfo
+ // </summary>
+ static Expression Literalize (FieldInfo fi)
+ {
+ Type t = fi.FieldType;
+ object v = fi.GetValue (fi);
+
+ if (t == TypeManager.int32_type)
+ return new IntLiteral ((int) v);
+ else if (t == TypeManager.uint32_type)
+ return new UIntLiteral ((uint) v);
+ else if (t == TypeManager.int64_type)
+ return new LongLiteral ((long) v);
+ else if (t == TypeManager.uint64_type)
+ return new ULongLiteral ((ulong) v);
+ else if (t == TypeManager.float_type)
+ return new FloatLiteral ((float) v);
+ else if (t == TypeManager.double_type)
+ return new DoubleLiteral ((double) v);
+ else if (t == TypeManager.string_type)
+ return new StringLiteral ((string) v);
+ else if (t == TypeManager.short_type)
+ return new IntLiteral ((int) ((short)v));
+ else if (t == TypeManager.ushort_type)
+ return new IntLiteral ((int) ((ushort)v));
+ else if (t == TypeManager.sbyte_type)
+ return new IntLiteral ((int) ((sbyte)v));
+ else if (t == TypeManager.byte_type)
+ return new IntLiteral ((int) ((byte)v));
+ else if (t == TypeManager.char_type)
+ return new IntLiteral ((int) ((char)v));
+ else
+ throw new Exception ("Unknown type for literal (" + v.GetType () +
+ "), details: " + fi);
+ }
+
//
// Returns a fully formed expression after a MemberLookup
//
- static Expression ExprClassFromMemberInfo (MemberInfo mi)
+ static Expression ExprClassFromMemberInfo (TypeContainer tc, MemberInfo mi)
{
if (mi is EventInfo){
return new EventExpr ((EventInfo) mi);
} else if (mi is FieldInfo){
- return new FieldExpr ((FieldInfo) mi);
+ FieldInfo fi = (FieldInfo) mi;
+
+ if (fi.IsLiteral){
+ Expression e = Literalize (fi);
+ e.Resolve (tc);
+
+ return e;
+ } else
+ return new FieldExpr (fi);
} else if (mi is PropertyInfo){
return new PropertyExpr ((PropertyInfo) mi);
} else if (mi is Type)
return null;
if (mi.Length == 1 && !(mi [0] is MethodBase))
- return Expression.ExprClassFromMemberInfo (mi [0]);
+ return Expression.ExprClassFromMemberInfo (tc, mi [0]);
for (int i = 0; i < mi.Length; i++)
if (!(mi [i] is MethodBase)){
string right = name.Substring (dot_pos + 1);
Type t;
- if ((t = tc.LookupType (left, false)) != null)
+ if ((t = tc.LookupType (left, false)) != null){
+ Expression e;
+
left_e = new TypeExpr (t);
- else {
+ e = new MemberAccess (left_e, right);
+ return e.Resolve (tc);
+ } else {
//
// FIXME: IMplement:
return new EmptyCast (expr, target_type);
if (expr_type.IsValueType)
return new BoxedCast (expr);
- } else if (expr_type.IsSubclassOf (target_type))
+ } else if (expr_type.IsSubclassOf (target_type)) {
return new EmptyCast (expr, target_type);
- else
- // FIXME: missing implicit reference conversions:
- //
+ } else {
// from any class-type S to any interface-type T.
+ if (expr_type.IsClass && target_type.IsInterface) {
+ Type [] interfaces = expr_type.FindInterfaces (Module.FilterTypeName,
+ target_type.FullName);
+ if (interfaces != null)
+ return new EmptyCast (expr, target_type);
+ }
+
// from any interface type S to interface-type T.
+ // FIXME : Is it right to use IsAssignableFrom ?
+ if (expr_type.IsInterface && target_type.IsInterface)
+ if (target_type.IsAssignableFrom (expr_type))
+ return new EmptyCast (expr, target_type);
+
+
// from an array-type S to an array-type of type T
+ if (expr_type.IsArray && target_type.IsArray) {
+
+ throw new Exception ("Implement array conversion");
+
+ }
+
// from an array-type to System.Array
+ if (expr_type.IsArray && target_type.IsAssignableFrom (expr_type))
+ return new EmptyCast (expr, target_type);
+
// from any delegate type to System.Delegate
+ if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
+ target_type == TypeManager.delegate_type)
+ if (target_type.IsAssignableFrom (expr_type))
+ return new EmptyCast (expr, target_type);
+
// from any array-type or delegate type into System.ICloneable.
+ if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
+ if (target_type == TypeManager.cloneable_interface)
+ throw new Exception ("Implement conversion to System.ICloneable");
+
// from the null type to any reference-type.
-
+ // FIXME : How do we do this ?
+
return null;
+ }
+
return null;
}
ArrayList args = new ArrayList ();
args.Add (new Argument (expr, Argument.AType.Expression));
-
+
Expression ne = new New (target.FullName, args,
- new Location ("FIXME", 1, 1));
+ new Location (-1));
return ne.Resolve (tc);
}
- static int level = 0;
-
- protected static Hashtable conversion_cache;
// <summary>
- // Converts implicitly the resolved expression `expr' into the
- // `target_type'. It returns a new expression that can be used
- // in a context that expects a `target_type'.
+ // Implicit Numeric Conversions.
+ //
+ // expr is the expression to convert, returns a new expression of type
+ // target_type or null if an implicit conversion is not possible.
+ //
// </summary>
- static public Expression ConvertImplicit (TypeContainer tc, Expression expr,
- Type target_type)
+ static public Expression ImplicitNumericConversion (TypeContainer tc, Expression expr,
+ Type target_type, Location l)
{
Type expr_type = expr.Type;
- Expression e = null;
- if (conversion_cache == null)
- conversion_cache = new Hashtable ();
-
- if (expr_type == target_type)
- e = expr;
+ //
+ // Attempt to do the implicit constant expression conversions
- if (e != null) {
- if (conversion_cache.Contains (expr_type + "=>" + target_type) == false)
- conversion_cache.Add (expr_type + "=>" + target_type, e);
- return e;
+ if (expr is IntLiteral){
+ Expression e;
+
+ e = TryImplicitIntConversion (target_type, (IntLiteral) expr);
+ if (e != null)
+ return e;
+ } else if (expr is LongLiteral){
+ //
+ // Try the implicit constant expression conversion
+ // from long to ulong, instead of a nice routine,
+ // we just inline it
+ //
+ if (((LongLiteral) expr).Value > 0)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
}
-
- //
- // Step 1: Built-in conversions.
- //
if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to short, int, long, float, double.
//
if (target_type == TypeManager.int32_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.short_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.byte_type){
//
// From byte to short, ushort, int, uint, long, ulong, float, double
(target_type == TypeManager.ushort_type) ||
(target_type == TypeManager.int32_type) ||
(target_type == TypeManager.uint32_type))
- e = new EmptyCast (expr, target_type);
+ return new EmptyCast (expr, target_type);
if (target_type == TypeManager.uint64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.short_type){
//
// From short to int, long, float, double
//
if (target_type == TypeManager.int32_type)
- e = new EmptyCast (expr, target_type);
+ return new EmptyCast (expr, target_type);
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.ushort_type){
//
// From ushort to int, uint, long, ulong, float, double
//
- if ((target_type == TypeManager.uint32_type) ||
- (target_type == TypeManager.uint64_type))
- e = new EmptyCast (expr, target_type);
-
+ if (target_type == TypeManager.uint32_type)
+ return new EmptyCast (expr, target_type);
+
+ if (target_type == TypeManager.uint64_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
if (target_type == TypeManager.int32_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.int32_type){
//
// From int to long, float, double
//
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.uint32_type){
//
// From uint to long, ulong, float, double
//
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
if (target_type == TypeManager.uint64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if ((expr_type == TypeManager.uint64_type) ||
(expr_type == TypeManager.int64_type)){
//
- // From long to float, double
+ // From long/ulong to float, double
//
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
+ return InternalTypeConstructor (tc, expr, target_type);
} else if (expr_type == TypeManager.char_type){
//
// From char to ushort, int, uint, long, ulong, float, double
if ((target_type == TypeManager.ushort_type) ||
(target_type == TypeManager.int32_type) ||
(target_type == TypeManager.uint32_type))
- e = new EmptyCast (expr, target_type);
+ return new EmptyCast (expr, target_type);
if (target_type == TypeManager.uint64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
if (target_type == TypeManager.int64_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.float_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (target_type == TypeManager.double_type)
- e = new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.decimal_type)
- e = InternalTypeConstructor (tc, expr, target_type);
- }
-
- if (e != null) {
- if (conversion_cache.Contains (expr_type + "=>" + target_type) == false)
- conversion_cache.Add (expr_type + "=>" + target_type, e);
- return e;
+ return InternalTypeConstructor (tc, expr, target_type);
+ } else if (expr_type == TypeManager.float_type){
+ //
+ // float to double
+ //
+ if (target_type == TypeManager.double_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
}
+
+ return null;
+ }
+
+ // <summary>
+ // User-defined implicit conversions
+ // </summary>
+ static public Expression ImplicitUserConversion (TypeContainer tc, Expression source,
+ Type target, Location l)
+ {
+ Expression mg1, mg2;
+ MethodBase method;
+ ArrayList arguments;
- e = ImplicitReferenceConversion (expr, target_type);
- if (e != null){
- if (conversion_cache.Contains (expr_type + "=>" + target_type) == false)
- conversion_cache.Add (expr_type + "=>" + target_type, e);
- return e;
+ mg1 = MemberLookup (tc, source.Type, "op_Implicit", false);
+ mg2 = MemberLookup (tc, target, "op_Implicit", false);
+
+ MethodGroupExpr union = Invocation.MakeUnionSet (mg1, mg2);
+
+ if (union != null) {
+ arguments = new ArrayList ();
+ arguments.Add (new Argument (source, Argument.AType.Expression));
+
+ method = Invocation.OverloadResolve (tc, union, arguments, l, true);
+
+ if (method != null) {
+ MethodInfo mi = (MethodInfo) method;
+
+ if (mi.ReturnType == target)
+ return new UserImplicitCast (mi, arguments);
+ }
}
+
+ // If we have a boolean type, we need to check for the True
+ // and False operators too.
+
+ if (target == TypeManager.bool_type) {
+
+ mg1 = MemberLookup (tc, source.Type, "op_True", false);
+ mg2 = MemberLookup (tc, target, "op_True", false);
+
+ union = Invocation.MakeUnionSet (mg1, mg2);
- if (level != 0)
- throw new Exception ("Lame loop detected");
+ if (union == null)
+ return null;
+
+ arguments = new ArrayList ();
+ arguments.Add (new Argument (source, Argument.AType.Expression));
+ method = Invocation.OverloadResolve (tc, union, arguments, l, true);
+ if (method != null) {
+ MethodInfo mi = (MethodInfo) method;
+
+ if (mi.ReturnType == target)
+ return new UserImplicitCast (mi, arguments);
+ }
+ }
- level++;
- e = UserImplicitCast.CanConvert (tc, expr, target_type);
- level--;
+ return null;
+ }
+
+ // <summary>
+ // Converts implicitly the resolved expression `expr' into the
+ // `target_type'. It returns a new expression that can be used
+ // in a context that expects a `target_type'.
+ // </summary>
+ static public Expression ConvertImplicit (TypeContainer tc, Expression expr,
+ Type target_type, Location l)
+ {
+ Type expr_type = expr.Type;
+ Expression e;
+
+ if (expr_type == target_type)
+ return expr;
- if (e != null) {
- if (conversion_cache.Contains (expr_type + "=>" + target_type) == false)
- conversion_cache.Add (expr_type + "=>" + target_type, e);
+ e = ImplicitNumericConversion (tc, expr, target_type, l);
+ if (e != null)
+ return e;
+
+ e = ImplicitReferenceConversion (expr, target_type);
+ if (e != null)
+ return e;
+
+ e = ImplicitUserConversion (tc, expr, target_type, l);
+ if (e != null)
return e;
+
+ if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
+ IntLiteral i = (IntLiteral) expr;
+
+ if (i.Value == 0)
+ return new EmptyCast (expr, target_type);
}
-
- //
- // Could not find an implicit cast.
- //
return null;
}
+
+ // <summary>
+ // Attempts to apply the `Standard Implicit
+ // Conversion' rules to the expression `expr' into
+ // the `target_type'. It returns a new expression
+ // that can be used in a context that expects a
+ // `target_type'.
+ //
+ // This is different from `ConvertImplicit' in that the
+ // user defined implicit conversions are excluded.
+ // </summary>
+ static public Expression ConvertImplicitStandard (TypeContainer tc, Expression expr,
+ Type target_type, Location l)
+ {
+ Type expr_type = expr.Type;
+ Expression e;
+
+ if (expr_type == target_type)
+ return expr;
+
+ e = ImplicitNumericConversion (tc, expr, target_type, l);
+ if (e != null)
+ return e;
+
+ e = ImplicitReferenceConversion (expr, target_type);
+ if (e != null)
+ return e;
+
+ if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
+ IntLiteral i = (IntLiteral) expr;
+
+ if (i.Value == 0)
+ return new EmptyCast (expr, target_type);
+ }
+ return null;
+ }
// <summary>
// Attemps to perform an implict constant conversion of the IntLiteral
// into a different data type using casts (See Implicit Constant
{
Expression e;
- e = ConvertImplicit (tc, target, type);
+ e = ConvertImplicit (tc, target, type, l);
if (e != null)
return e;
- //
- // Attempt to do the implicit constant expression conversions
-
- if (target is IntLiteral){
- e = TryImplicitIntConversion (type, (IntLiteral) target);
- if (e != null)
- return e;
- } else if (target is LongLiteral){
- //
- // Try the implicit constant expression conversion
- // from long to ulong, instead of a nice routine,
- // we just inline it
- //
- if (((LongLiteral) target).Value > 0)
- return target;
- }
-
string msg = "Can not convert implicitly from `"+
TypeManager.CSharpName (target.Type) + "' to `" +
TypeManager.CSharpName (type) + "'";
if (target_type == TypeManager.uint32_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.char_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
} else if (expr_type == TypeManager.byte_type){
if (target_type == TypeManager.uint32_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.char_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
} else if (expr_type == TypeManager.ushort_type){
if (target_type == TypeManager.uint32_type)
return new EmptyCast (expr, target_type);
if (target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
if (target_type == TypeManager.char_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
} else if (expr_type == TypeManager.uint32_type){
return null;
}
+
+ // <summary>
+ // Implements Explicit Reference conversions
+ // </summary>
+ static Expression ConvertReferenceExplicit (TypeContainer tc, Expression expr,
+ Type target_type)
+ {
+ Type expr_type = expr.Type;
+ bool target_is_value_type = target_type.IsValueType;
+
+ //
+ // From object to any reference type
+ //
+ if (expr_type == TypeManager.object_type && !target_is_value_type)
+ return new ClassCast (expr, expr_type);
+
+ return null;
+ }
// <summary>
// Performs an explicit conversion of the expression `expr' whose
static public Expression ConvertExplicit (TypeContainer tc, Expression expr,
Type target_type)
{
- Expression ne;
+ Expression ne = ConvertImplicit (tc, expr, target_type, Location.Null);
+
+ if (ne != null)
+ return ne;
- if (Invocation.ConversionExists (tc, expr.Type, target_type) == true) {
- ne = ConvertImplicit (tc, expr, target_type);
-
- if (ne != null)
- return ne;
- }
-
ne = ConvertNumericExplicit (tc, expr, target_type);
if (ne != null)
return ne;
+
+ ne = ConvertReferenceExplicit (tc, expr, target_type);
+ if (ne != null)
+ return ne;
-
- return expr;
+ return null;
}
static string ExprClassName (ExprClass c)
// <summary>
// Reports that we were expecting `expr' to be of class `expected'
// </summary>
- protected void report118 (TypeContainer tc, Expression expr, string expected)
+ protected void report118 (TypeContainer tc, Location l, Expression expr, string expected)
{
- Error (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
+ string kind = "Unknown";
+
+ if (expr != null)
+ kind = ExprClassName (expr.ExprClass);
+
+ Error (tc, 118, l, "Expression denotes a '" + kind +
"' where an " + expected + " was expected");
}
}
this.child = child;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// This should never be invoked, we are born in fully
// initialized state.
{
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// This should never be invoked, we are born in fully
// initialized state.
second_valid = false;
}
- public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
+ public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
+ : base (child, return_type)
+
+ {
+ this.op = op;
+ this.op2 = op2;
+ second_valid = true;
+ }
+
+ public override Expression DoResolve (TypeContainer tc)
+ {
+ // This should never be invoked, we are born in fully
+ // initialized state.
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ base.Emit (ec);
+ ec.ig.Emit (op);
+
+ if (second_valid)
+ ec.ig.Emit (op2);
+ }
+
+ }
+
+ // <summary>
+ // This kind of cast is used to encapsulate a child and cast it
+ // to the class requested
+ // </summary>
+ public class ClassCast : EmptyCast {
+ public ClassCast (Expression child, Type return_type)
: base (child, return_type)
{
- this.op = op;
- this.op2 = op2;
- second_valid = true;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// This should never be invoked, we are born in fully
// initialized state.
public override void Emit (EmitContext ec)
{
base.Emit (ec);
- ec.ig.Emit (op);
- if (second_valid)
- ec.ig.Emit (op2);
+ ec.ig.Emit (OpCodes.Castclass, type);
}
}
-
+
// <summary>
// Unary expressions.
// </summary>
if (expr.Type == target_type)
return expr;
- return ConvertImplicit (tc, expr, target_type);
+ return ConvertImplicit (tc, expr, target_type, new Location (-1));
}
void report23 (Report r, Type t)
op_name = "op_" + oper;
mg = MemberLookup (tc, expr_type, op_name, false);
+
+ if (mg == null && expr_type != TypeManager.object_type)
+ mg = MemberLookup (tc, expr_type.BaseType, op_name, false);
if (mg != null) {
Arguments = new ArrayList ();
Arguments.Add (new Argument (expr, Argument.AType.Expression));
- method = Invocation.OverloadResolve (tc, (MethodGroupExpr) mg, Arguments, location);
+ method = Invocation.OverloadResolve (tc, (MethodGroupExpr) mg,
+ Arguments, location);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
// It is also not clear if we should convert to Float
// or Double initially.
//
+ Location l = new Location (-1);
+
if (expr_type == TypeManager.uint32_type){
//
// FIXME: handle exception to this rule that
// bt written as a decimal interger literal
//
type = TypeManager.int64_type;
- expr = ConvertImplicit (tc, expr, type);
+ expr = ConvertImplicit (tc, expr, type, l);
return this;
}
return null;
}
- e = ConvertImplicit (tc, expr, TypeManager.int32_type);
+ e = ConvertImplicit (tc, expr, TypeManager.int32_type, l);
if (e != null){
expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (tc, expr, TypeManager.int64_type);
+ e = ConvertImplicit (tc, expr, TypeManager.int64_type, l);
if (e != null){
expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (tc, expr, TypeManager.double_type);
+ e = ConvertImplicit (tc, expr, TypeManager.double_type, l);
if (e != null){
expr = e;
type = e.Type;
//
throw new Exception ("Implement me");
} else {
- report118 (tc, expr, "variable, indexer or property access");
+ report118 (tc, location, expr,
+ "variable, indexer or property access");
}
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
expr = expr.Resolve (tc);
if (expr == null)
return null;
-
+
+ eclass = ExprClass.Value;
return ResolveOperator (tc);
}
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
probe_type = tc.LookupType (ProbeType, false);
public override void Emit (EmitContext ec)
{
+ ILGenerator ig = ec.ig;
+
expr.Emit (ec);
if (Oper == Operator.Is){
- ec.ig.Emit (OpCodes.Isinst, probe_type);
+ ig.Emit (OpCodes.Isinst, probe_type);
+ ig.Emit (OpCodes.Ldnull);
+ ig.Emit (OpCodes.Cgt_Un);
} else {
- throw new Exception ("Implement as");
+ ig.Emit (OpCodes.Isinst, probe_type);
}
}
}
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
expr = expr.Resolve (tc);
if (expr == null)
return null;
expr = ConvertExplicit (tc, expr, type);
-
+
return expr;
}
if (expr.Type == target_type)
return expr;
- return ConvertImplicit (tc, expr, target_type);
+ return ConvertImplicit (tc, expr, target_type, new Location (-1));
}
//
// conveted to type double.
//
if (r != TypeManager.double_type)
- right = ConvertImplicit (tc, right, TypeManager.double_type);
+ right = ConvertImplicit (tc, right, TypeManager.double_type, location);
if (l != TypeManager.double_type)
- left = ConvertImplicit (tc, left, TypeManager.double_type);
+ left = ConvertImplicit (tc, left, TypeManager.double_type, location);
type = TypeManager.double_type;
} else if (l == TypeManager.float_type || r == TypeManager.float_type){
// converd to type float.
//
if (r != TypeManager.double_type)
- right = ConvertImplicit (tc, right, TypeManager.float_type);
+ right = ConvertImplicit (tc, right, TypeManager.float_type, location);
if (l != TypeManager.double_type)
- left = ConvertImplicit (tc, left, TypeManager.float_type);
+ left = ConvertImplicit (tc, left, TypeManager.float_type, location);
type = TypeManager.float_type;
} else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
+ Expression e;
+ Type other;
//
// If either operand is of type ulong, the other operand is
// converted to type ulong. or an error ocurrs if the other
// operand is of type sbyte, short, int or long
//
- Type other = null;
- if (l == TypeManager.uint64_type)
- other = r;
- else if (r == TypeManager.uint64_type)
- other = l;
+ if (l == TypeManager.uint64_type){
+ if (r != TypeManager.uint64_type && right is IntLiteral){
+ e = TryImplicitIntConversion (l, (IntLiteral) right);
+ if (e != null)
+ right = e;
+ }
+ other = right.Type;
+ } else {
+ if (left is IntLiteral){
+ e = TryImplicitIntConversion (r, (IntLiteral) left);
+ if (e != null)
+ left = e;
+ }
+ other = left.Type;
+ }
if ((other == TypeManager.sbyte_type) ||
(other == TypeManager.short_type) ||
(other == TypeManager.int64_type)){
string oper = OperName ();
- Error (tc, 34, "Operator `" + OperName ()
+ Error (tc, 34, location, "Operator `" + OperName ()
+ "' is ambiguous on operands of type `"
+ TypeManager.CSharpName (l) + "' "
+ "and `" + TypeManager.CSharpName (r)
// to type long.
//
if (l != TypeManager.int64_type)
- left = ConvertImplicit (tc, left, TypeManager.int64_type);
+ left = ConvertImplicit (tc, left, TypeManager.int64_type, location);
if (r != TypeManager.int64_type)
- right = ConvertImplicit (tc, right, TypeManager.int64_type);
+ right = ConvertImplicit (tc, right, TypeManager.int64_type, location);
type = TypeManager.int64_type;
} else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
// operand is converd to type uint
//
left = ForceConversion (tc, left, TypeManager.uint32_type);
- right = ForceConversion (tc, left, TypeManager.uint32_type);
+ right = ForceConversion (tc, right, TypeManager.uint32_type);
type = TypeManager.uint32_type;
}
} else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
if (l != TypeManager.decimal_type)
- left = ConvertImplicit (tc, left, TypeManager.decimal_type);
+ left = ConvertImplicit (tc, left, TypeManager.decimal_type, location);
if (r != TypeManager.decimal_type)
- right = ConvertImplicit (tc, right, TypeManager.decimal_type);
+ right = ConvertImplicit (tc, right, TypeManager.decimal_type, location);
type = TypeManager.decimal_type;
} else {
}
right = e;
- if (((e = ConvertImplicit (tc, left, TypeManager.int32_type)) != null) ||
- ((e = ConvertImplicit (tc, left, TypeManager.uint32_type)) != null) ||
- ((e = ConvertImplicit (tc, left, TypeManager.int64_type)) != null) ||
- ((e = ConvertImplicit (tc, left, TypeManager.uint64_type)) != null)){
+ Location loc = location;
+
+ if (((e = ConvertImplicit (tc, left, TypeManager.int32_type, loc)) != null) ||
+ ((e = ConvertImplicit (tc, left, TypeManager.uint32_type, loc)) != null) ||
+ ((e = ConvertImplicit (tc, left, TypeManager.int64_type, loc)) != null) ||
+ ((e = ConvertImplicit (tc, left, TypeManager.uint64_type, loc)) != null)){
left = e;
+ type = e.Type;
return this;
}
string op = "op_" + oper;
left_expr = MemberLookup (tc, l, op, false);
+
+ if (left_expr == null && l != TypeManager.object_type)
+ left_expr = MemberLookup (tc, l.BaseType, op, false);
right_expr = MemberLookup (tc, r, op, false);
+ if (right_expr != null && r != TypeManager.object_type)
+ right_expr = MemberLookup (tc, r.BaseType, op, false);
+
MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
- Arguments = new ArrayList ();
- Arguments.Add (new Argument (left, Argument.AType.Expression));
- Arguments.Add (new Argument (right, Argument.AType.Expression));
-
if (union != null) {
+ Arguments = new ArrayList ();
+ Arguments.Add (new Argument (left, Argument.AType.Expression));
+ Arguments.Add (new Argument (right, Argument.AType.Expression));
+
method = Invocation.OverloadResolve (tc, union, Arguments, location);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
// Only perform numeric promotions on:
// +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
//
- if (oper == Operator.LeftShift || oper == Operator.RightShift){
- return CheckShiftArguments (tc);
- } else if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
-
- if (l != TypeManager.bool_type || r != TypeManager.bool_type)
- error19 (tc);
- } else if (oper == Operator.Addition){
+ if (oper == Operator.Addition){
//
// If any of the arguments is a string, cast to string
//
} else {
// string + object
method = TypeManager.string_concat_object_object;
- right = ConvertImplicit (tc, right, TypeManager.object_type);
+ right = ConvertImplicit (tc, right,
+ TypeManager.object_type, location);
}
type = TypeManager.string_type;
Arguments = new ArrayList ();
Arguments.Add (new Argument (left, Argument.AType.Expression));
Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+ return this;
+
} else if (r == TypeManager.string_type){
// object + string
method = TypeManager.string_concat_object_object;
Arguments.Add (new Argument (left, Argument.AType.Expression));
Arguments.Add (new Argument (right, Argument.AType.Expression));
- left = ConvertImplicit (tc, left, TypeManager.object_type);
+ left = ConvertImplicit (tc, left, TypeManager.object_type, location);
type = TypeManager.string_type;
+
+ return this;
}
//
// FIXME: is Delegate operator + (D x, D y) handled?
//
- } else
- DoNumericPromotions (tc, l, r);
+ }
+
+ if (oper == Operator.LeftShift || oper == Operator.RightShift)
+ return CheckShiftArguments (tc);
+
+ if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+ if (l != TypeManager.bool_type || r != TypeManager.bool_type)
+ error19 (tc);
+
+ type = TypeManager.bool_type;
+ return this;
+ }
+
+ //
+ // We are dealing with numbers
+ //
+
+ DoNumericPromotions (tc, l, r);
if (left == null || right == null)
return null;
-
if (oper == Operator.BitwiseAnd ||
oper == Operator.BitwiseOr ||
oper == Operator.ExclusiveOr){
error19 (tc);
return null;
}
+ type = l;
}
if (oper == Operator.Equality ||
return this;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
left = left.Resolve (tc);
right = right.Resolve (tc);
if (left == null || right == null)
return null;
+ if (left.Type == null)
+ throw new Exception (
+ "Resolve returned non null, but did not set the type! (" +
+ left + ")");
+ if (right.Type == null)
+ throw new Exception (
+ "Resolve returned non null, but did not set the type! (" +
+ right + ")");
+
+ eclass = ExprClass.Value;
+
return ResolveOperator (tc);
}
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
expr = expr.Resolve (tc);
// First, if an implicit conversion exists from trueExpr
// to falseExpr, then the result type is of type falseExpr.Type
//
- conv = ConvertImplicit (tc, trueExpr, falseExpr.Type);
+ conv = ConvertImplicit (tc, trueExpr, falseExpr.Type, l);
if (conv != null){
type = falseExpr.Type;
trueExpr = conv;
- } else if ((conv = ConvertImplicit (tc, falseExpr, trueExpr.Type)) != null){
+ } else if ((conv = ConvertImplicit (tc,falseExpr,trueExpr.Type,l)) != null){
type = trueExpr.Type;
falseExpr = conv;
} else {
// simple_names and qualified_identifiers are placed on
// the tree equally.
//
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
if (Name.IndexOf (".") != -1)
return ResolveMemberAccess (tc, Name);
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
VariableInfo vi = Block.GetVariableInfo (Name);
eclass = ExprClass.Variable;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
Type [] types = Pars.GetParameterInfo (tc);
}
}
- /// <summary>
- /// Computes whether Argument `a' and the Type t of the ParameterInfo `pi' are
- /// compatible, and if so, how good is the match (in terms of
- /// "better conversions" (7.4.2.3).
- ///
- /// 0 is the best possible match.
- /// -1 represents a type mismatch.
- /// -2 represents a ref/out mismatch.
- /// </summary>
- static int Badness (Argument a, Type t)
- {
- Expression argument_expr = a.Expr;
- Type argument_type = argument_expr.Type;
-
- if (argument_type == null){
- throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
- }
-
- if (t == argument_type)
- return 0;
-
- //
- // Now probe whether an implicit constant expression conversion
- // can be used.
- //
- // An implicit constant expression conversion permits the following
- // conversions:
- //
- // * A constant-expression of type `int' can be converted to type
- // sbyte, byute, short, ushort, uint, ulong provided the value of
- // of the expression is withing the range of the destination type.
- //
- // * A constant-expression of type long can be converted to type
- // ulong, provided the value of the constant expression is not negative
- //
- // FIXME: Note that this assumes that constant folding has
- // taken place. We dont do constant folding yet.
- //
-
- if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
- IntLiteral ei = (IntLiteral) argument_expr;
- int value = ei.Value;
-
- if (t == TypeManager.sbyte_type){
- if (value >= SByte.MinValue && value <= SByte.MaxValue)
- return 1;
- } else if (t == TypeManager.byte_type){
- if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
- return 1;
- } else if (t == TypeManager.short_type){
- if (value >= Int16.MinValue && value <= Int16.MaxValue)
- return 1;
- } else if (t == TypeManager.ushort_type){
- if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
- return 1;
- } else if (t == TypeManager.uint32_type){
- //
- // we can optimize this case: a positive int32
- // always fits on a uint32
- //
- if (value >= 0)
- return 1;
- } else if (t == TypeManager.uint64_type){
- //
- // we can optimize this case: a positive int32
- // always fits on a uint64
- //
- if (value >= 0)
- return 1;
- }
- } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
- LongLiteral ll = (LongLiteral) argument_expr;
-
- if (t == TypeManager.uint64_type)
- if (ll.Value > 0)
- return 1;
- }
-
- // FIXME: Implement user-defined implicit conversions here.
- // FIXME: Implement better conversion here.
-
- return -1;
- }
-
// <summary>
// Returns the Parameters (a ParameterData interface) for the
// Method `mb'
}
}
- public static bool ConversionExists (TypeContainer tc, Type from, Type to)
+ // <summary>
+ // Tells whether a user defined conversion from Type `from' to
+ // Type `to' exists.
+ //
+ // FIXME: we could implement a cache here.
+ // </summary>
+ static bool ConversionExists (TypeContainer tc, Type from, Type to)
{
- if (conversion_cache == null)
- return false;
+ // Locate user-defined implicit operators
- Expression e = (Expression) conversion_cache [from + "=>" + to];
+ Expression mg;
+
+ mg = MemberLookup (tc, to, "op_Implicit", false);
- if (e != null)
- return true;
-
+ if (mg != null) {
+ MethodGroupExpr me = (MethodGroupExpr) mg;
+
+ for (int i = me.Methods.Length; i > 0;) {
+ i--;
+ MethodBase mb = me.Methods [i];
+ ParameterData pd = GetParameterData (mb);
+
+ if (from == pd.ParameterType (0))
+ return true;
+ }
+ }
+
+ mg = MemberLookup (tc, from, "op_Implicit", false);
+
+ if (mg != null) {
+ MethodGroupExpr me = (MethodGroupExpr) mg;
+
+ for (int i = me.Methods.Length; i > 0;) {
+ i--;
+ MethodBase mb = me.Methods [i];
+ MethodInfo mi = (MethodInfo) mb;
+
+ if (mi.ReturnType == to)
+ return true;
+ }
+ }
+
return false;
}
// Returns : 1 if a->p is better
// 0 if a->q or neither is better
// </summary>
- static int BetterConversion (TypeContainer tc, Argument a, Type p, Type q)
+ static int BetterConversion (TypeContainer tc, Argument a, Type p, Type q, bool use_standard)
{
Type argument_type = a.Expr.Type;
// taken place. We dont do constant folding yet.
//
- if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
+ if (argument_expr is IntLiteral){
IntLiteral ei = (IntLiteral) argument_expr;
int value = ei.Value;
}
if (q == null) {
- if (ConversionExists (tc, argument_type, p) == true)
+
+ Expression tmp;
+
+ if (use_standard)
+ tmp = ConvertImplicitStandard (tc, argument_expr, p, Location.Null);
+ else
+ tmp = ConvertImplicit (tc, argument_expr, p, Location.Null);
+
+ if (tmp != null)
return 1;
else
return 0;
+
}
if (ConversionExists (tc, p, q) == true &&
ConversionExists (tc, q, p) == false)
return 1;
-
if (p == TypeManager.sbyte_type)
if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
// 0 if candidate ain't better
// 1 if candidate is better than the current best match
// </summary>
- static int BetterFunction (TypeContainer tc, ArrayList args, MethodBase candidate, MethodBase best)
+ static int BetterFunction (TypeContainer tc, ArrayList args,
+ MethodBase candidate, MethodBase best,
+ bool use_standard)
{
ParameterData candidate_pd = GetParameterData (candidate);
ParameterData best_pd;
Argument a = (Argument) args [j];
- x = BetterConversion (tc, a, candidate_pd.ParameterType (j), null);
+ x = BetterConversion (
+ tc, a, candidate_pd.ParameterType (j), null,
+ use_standard);
- if (x > 0)
- continue;
- else
+ if (x <= 0)
break;
}
Argument a = (Argument) args [j];
x = BetterConversion (tc, a, candidate_pd.ParameterType (j),
- best_pd.ParameterType (j));
+ best_pd.ParameterType (j), use_standard);
y = BetterConversion (tc, a, best_pd.ParameterType (j),
- candidate_pd.ParameterType (j));
+ candidate_pd.ParameterType (j), use_standard);
rating1 += x;
rating2 += y;
return null;
}
-
+
// <summary>
// Find the Applicable Function Members (7.4.2.1)
//
//
// Arguments: ArrayList containing resolved Argument objects.
//
+ // loc: The location if we want an error to be reported, or a Null
+ // location for "probing" purposes.
+ //
+ // inside_user_defined: controls whether OverloadResolve should use the
+ // ConvertImplicit or ConvertImplicitStandard during overload resolution.
+ //
// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
// that is the best match of me on Arguments.
//
// </summary>
public static MethodBase OverloadResolve (TypeContainer tc, MethodGroupExpr me,
- ArrayList Arguments, Location loc)
+ ArrayList Arguments, Location loc,
+ bool use_standard)
{
ArrayList afm = new ArrayList ();
int best_match_idx = -1;
MethodBase candidate = me.Methods [i];
int x;
- x = BetterFunction (tc, Arguments, candidate, method);
+ x = BetterFunction (tc, Arguments, candidate, method, use_standard);
if (x == 0)
continue;
j--;
Argument a = (Argument) Arguments [j];
Expression a_expr = a.Expr;
+ Type parameter_type = pd.ParameterType (j);
- Expression conv = ConvertImplicit (tc, a_expr, pd.ParameterType (j));
-
- if (conv == null) {
- Error (tc, 1502, loc,
- "The best overloaded match for method '" + FullMethodDesc (method) +
- "' has some invalid arguments");
- Error (tc, 1503, loc,
- "Argument " + (j+1) +
- " : Cannot convert from '" + TypeManager.CSharpName (a_expr.Type)
- + "' to '" + TypeManager.CSharpName (pd.ParameterType (j)) + "'");
- return null;
- }
+ if (a_expr.Type != parameter_type){
+ Expression conv;
- //
- // Update the argument with the implicit conversion
- //
- if (a_expr != conv)
- a.Expr = conv;
+ if (use_standard)
+ conv = ConvertImplicitStandard (tc, a_expr, parameter_type,
+ Location.Null);
+ else
+ conv = ConvertImplicit (tc, a_expr, parameter_type,
+ Location.Null);
+
+ if (conv == null){
+ if (!Location.IsNull (loc)) {
+ Error (tc, 1502, loc,
+ "The best overloaded match for method '" + FullMethodDesc (method) +
+ "' has some invalid arguments");
+ Error (tc, 1503, loc,
+ "Argument " + (j+1) +
+ ": Cannot convert from '" + TypeManager.CSharpName (a_expr.Type)
+ + "' to '" + TypeManager.CSharpName (pd.ParameterType (j)) + "'");
+ }
+ return null;
+ }
+ //
+ // Update the argument with the implicit conversion
+ //
+ if (a_expr != conv)
+ a.Expr = conv;
+ }
}
return method;
}
+ public static MethodBase OverloadResolve (TypeContainer tc, MethodGroupExpr me,
+ ArrayList Arguments, Location loc)
+ {
+ return OverloadResolve (tc, me, Arguments, loc, false);
+ }
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
//
// First, resolve the expression that is used to
return null;
if (!(this.expr is MethodGroupExpr)){
- report118 (tc, this.expr, "method group");
+ report118 (tc, Location, this.expr, "method group");
return null;
}
}
}
- method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments, Location);
+ method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments,
+ Location);
if (method == null){
Error (tc, -6, Location,
if (method is MethodInfo)
type = ((MethodInfo)method).ReturnType;
+ eclass = ExprClass.Value;
return this;
}
Location = loc;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
type = tc.LookupType (RequestedType, false);
//
// FIXME: Find proper error
//
- report118 (tc, ml, "method group");
+ report118 (tc, Location, ml, "method group");
return null;
}
}
}
- method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments, Location);
+ method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments,
+ Location);
if (method == null) {
Error (tc, -6, Location,
"New invocation: Can not find a constructor for this argument list");
return null;
}
-
+
+ eclass = ExprClass.Value;
return this;
}
// Represents the `this' construct
//
public class This : Expression, LValue {
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
eclass = ExprClass.Variable;
type = tc.TypeBuilder;
}
}
+ // <summary>
+ // Implements the typeof operator
+ // </summary>
public class TypeOf : Expression {
public readonly string QueriedType;
+ Type typearg;
public TypeOf (string queried_type)
{
QueriedType = queried_type;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
- type = tc.LookupType (QueriedType, false);
+ typearg = tc.LookupType (QueriedType, false);
- if (type == null)
+ if (typearg == null)
return null;
-
+
+ type = TypeManager.type_type;
eclass = ExprClass.Type;
return this;
}
public override void Emit (EmitContext ec)
{
- throw new Exception ("Implement me");
- // FIXME: Implement.
+ ec.ig.Emit (OpCodes.Ldtoken, typearg);
+ ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
}
}
this.QueriedType = queried_type;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// FIXME: Implement;
throw new Exception ("Unimplemented");
}
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
Expression new_expression = expr.Resolve (tc);
eclass = ExprClass.Namespace;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
return this;
}
eclass = ExprClass.Type;
}
- override public Expression Resolve (TypeContainer tc)
+ override public Expression DoResolve (TypeContainer tc)
{
return this;
}
}
}
- override public Expression Resolve (TypeContainer tc)
+ override public Expression DoResolve (TypeContainer tc)
{
return this;
}
type = fi.FieldType;
}
- override public Expression Resolve (TypeContainer tc)
+ override public Expression DoResolve (TypeContainer tc)
{
if (!FieldInfo.IsStatic){
if (Instance == null){
type = pi.PropertyType;
}
- override public Expression Resolve (TypeContainer tc)
+ override public Expression DoResolve (TypeContainer tc)
{
// We are born in resolved state.
return this;
eclass = ExprClass.EventAccess;
}
- override public Expression Resolve (TypeContainer tc)
+ override public Expression DoResolve (TypeContainer tc)
{
// We are born in resolved state.
return this;
Expr = e;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
Expr = Expr.Resolve (tc);
Expr = e;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
Expr = Expr.Resolve (tc);
Arguments = e_list;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// FIXME: Implement;
throw new Exception ("Unimplemented");
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
// FIXME: Implement;
throw new Exception ("Unimplemented");
eclass = ExprClass.Value;
}
- public override Expression Resolve (TypeContainer tc)
+ public override Expression DoResolve (TypeContainer tc)
{
//
// We are born in a fully resolved state
return this;
}
- public static Expression CanConvert (TypeContainer tc, Expression source, Type target)
- {
- Expression mg1, mg2;
- MethodBase method;
- ArrayList arguments;
-
- mg1 = MemberLookup (tc, source.Type, "op_Implicit", false);
- mg2 = MemberLookup (tc, target, "op_Implicit", false);
-
- MethodGroupExpr union = Invocation.MakeUnionSet (mg1, mg2);
-
- if (union != null) {
- arguments = new ArrayList ();
- arguments.Add (new Argument (source, Argument.AType.Expression));
-
- method = Invocation.OverloadResolve (tc, union, arguments,
- new Location ("FIXME", 1, 1));
-
- if (method != null) {
- MethodInfo mi = (MethodInfo) method;
-
- if (mi.ReturnType == target)
- return new UserImplicitCast (mi, arguments);
- }
- }
-
- // If we have a boolean type, we need to check for the True
- // and False operators too.
-
- if (target == TypeManager.bool_type) {
-
- mg1 = MemberLookup (tc, source.Type, "op_True", false);
- mg2 = MemberLookup (tc, target, "op_True", false);
-
- union = Invocation.MakeUnionSet (mg1, mg2);
-
- if (union == null)
- return null;
-
- arguments = new ArrayList ();
- arguments.Add (new Argument (source, Argument.AType.Expression));
-
- method = Invocation.OverloadResolve (tc, union, arguments,
- new Location ("FIXME", 1, 1));
- if (method != null) {
- MethodInfo mi = (MethodInfo) method;
-
- if (mi.ReturnType == target)
- return new UserImplicitCast (mi, arguments);
- }
- }
-
- return null;
- }
-
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- if (method != null) {
-
- // Note that operators are static anyway
+ // Note that operators are static anyway
- if (arguments != null)
- Invocation.EmitArguments (ec, method, arguments);
-
- if (method is MethodInfo)
- ig.Emit (OpCodes.Call, (MethodInfo) method);
- else
- ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
- return;
- }
-
- throw new Exception ("Implement me");
+ if (arguments != null)
+ Invocation.EmitArguments (ec, method, arguments);
+
+ if (method is MethodInfo)
+ ig.Emit (OpCodes.Call, (MethodInfo) method);
+ else
+ ig.Emit (OpCodes.Call, (ConstructorInfo) method);
}
}