}
}
+ // <summary>
+ // Utility wrapper routine for Error, just to beautify the code
+ // </summary>
+ static protected void Error (TypeContainer tc, int error, string s)
+ {
+ tc.RootContext.Report.Error (error, s);
+ }
+
+ static protected void Error (TypeContainer tc, int error, Location l, string s)
+ {
+ tc.RootContext.Report.Error (error, l, s);
+ }
+
+ // <summary>
+ // Utility wrapper routine for Warning, just to beautify the code
+ // </summary>
+ static protected void Warning (TypeContainer tc, int warning, string s)
+ {
+ tc.RootContext.Report.Warning (warning, s);
+ }
+
// <summary>
// Performs semantic analysis on the Expression
// </summary>
// This is so we can catch correctly attempts to invoke instance methods
// from a static body (scan for error 120 in ResolveSimpleName).
//
- public static Expression MemberLookup (RootContext rc, Type t, string name,
- bool same_type, MemberTypes mt, BindingFlags bf)
+ public static Expression MemberLookup (TypeContainer tc, Type t, string name,
+ bool same_type, MemberTypes mt, BindingFlags bf)
{
if (same_type)
bf |= BindingFlags.NonPublic;
- MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
+ MemberInfo [] mi = tc.RootContext.TypeManager.FindMembers (
+ t, mt, bf, Type.FilterName, name);
if (mi == null)
return null;
for (int i = 0; i < mi.Length; i++)
if (!(mi [i] is MethodBase)){
- rc.Report.Error (-5, "Do not know how to reproduce this case: " +
- "Methods and non-Method with the same name, report this please");
+ Error (tc,
+ -5, "Do not know how to reproduce this case: " +
+ "Methods and non-Method with the same name, " +
+ "report this please");
for (i = 0; i < mi.Length; i++){
Type tt = mi [i].GetType ();
BindingFlags.Static |
BindingFlags.Instance;
- public static Expression MemberLookup (RootContext rc, Type t, string name,
+ public static Expression MemberLookup (TypeContainer tc, Type t, string name,
bool same_type)
{
- return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
+ return MemberLookup (tc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
}
-
- // <summary>
- // Resolves the E in `E.I' side for a member_access
- //
- // This is suboptimal and should be merged with ResolveMemberAccess
- // </summary>
- static Expression ResolvePrimary (TypeContainer tc, string name)
- {
- int dot_pos = name.LastIndexOf (".");
-
- if (tc.RootContext.IsNamespace (name))
- return new NamespaceExpr (name);
-
- if (dot_pos != -1){
- } else {
- Type t = tc.LookupType (name, false);
-
- if (t != null)
- return new TypeExpr (t);
- }
- return null;
- }
-
+ //
+ // I am in general unhappy with this implementation.
+ //
+ // I need to revise this.
+ //
static public Expression ResolveMemberAccess (TypeContainer tc, string name)
{
- Expression left_e;
+ Expression left_e = null;
int dot_pos = name.LastIndexOf (".");
string left = name.Substring (0, dot_pos);
string right = name.Substring (dot_pos + 1);
+ Type t;
- left_e = ResolvePrimary (tc, left);
- if (left_e == null)
+ if ((t = tc.LookupType (left, false)) != null)
+ left_e = new TypeExpr (t);
+ else {
+ //
+ // FIXME: IMplement:
+
+ // Handle here:
+ // T.P Static property access (P) on Type T.
+ // e.P instance property access on instance e for P.
+ // p
+ //
+ }
+
+ if (left_e == null){
+ Error (tc, 246, "Can not find type or namespace `"+left+"'");
return null;
+ }
switch (left_e.ExprClass){
case ExprClass.Type:
- return MemberLookup (tc.RootContext,
+ return MemberLookup (tc,
left_e.Type, right,
left_e.Type == tc.TypeBuilder);
case ExprClass.EventAccess:
case ExprClass.MethodGroup:
case ExprClass.Invalid:
- tc.RootContext.Report.Error (-1000,
- "Internal compiler error, should have " +
- "got these handled before");
- break;
+ throw new Exception ("Should have got the " + left_e.ExprClass +
+ " handled before");
}
return null;
static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
{
Type expr_type = expr.Type;
-
+
if (target_type == TypeManager.object_type) {
if (expr_type.IsClass)
return new EmptyCast (expr, target_type);
if (expr_type.IsValueType)
- return new BoxedCast (expr, target_type);
+ return new BoxedCast (expr);
} else if (expr_type.IsSubclassOf (target_type))
return new EmptyCast (expr, target_type);
else
return ne.Resolve (tc);
}
-
+
+ static int level = 0;
+
+ 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'.
// </summary>
- static public Expression ConvertImplicit (TypeContainer tc, Expression expr, Type target_type)
+ static public Expression ConvertImplicit (TypeContainer tc, Expression expr,
+ Type target_type)
{
Type expr_type = expr.Type;
+ Console.WriteLine ("ConvertImplicit " + expr_type + " => " + target_type);
+
if (expr_type == target_type)
return expr;
- //
- // Step 1: Perform implicit conversions as found on expr.Type
- //
+ if (level != 0) {
+ if (conversion_cache == null)
+ conversion_cache = new Hashtable ();
+
+ Expression conv = (Expression) conversion_cache [expr_type + "=>" + target_type];
- if (UserImplicitCast.CanConvert (tc, expr, target_type) == true) {
- Expression imp = new UserImplicitCast (expr, target_type);
- imp.Resolve (tc);
- return imp;
+ return conv;
}
//
- // Step 2: Built-in conversions.
+ // Step 1: Built-in conversions.
//
if (expr_type == TypeManager.sbyte_type){
//
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (target_type == TypeManager.decimal_type)
return InternalTypeConstructor (tc, expr, target_type);
- } else
- return ImplicitReferenceConversion (expr, target_type);
+ }
+ Expression e;
+ e = ImplicitReferenceConversion (expr, target_type);
+ if (e != null){
+ return e;
+ }
+
+ level++;
+ e = UserImplicitCast.CanConvert (tc, expr, target_type);
+ level--;
+
+ if (e != null) {
+ if (conversion_cache == null)
+ conversion_cache = new Hashtable ();
+
+ conversion_cache.Add (expr_type.ToString () + "=>" + target_type.ToString (), e);
+ return e;
+ }
//
// Could not find an implicit cast.
//
TypeManager.CSharpName (target.Type) + "' to `" +
TypeManager.CSharpName (type) + "'";
- tc.RootContext.Report.Error (29, l, msg);
+ Error (tc, 29, l, msg);
return null;
}
return expr;
}
- void report (TypeContainer tc, int error, string s)
- {
- tc.RootContext.Report.Error (error, s);
- }
-
static string ExprClassName (ExprClass c)
{
switch (c){
// </summary>
protected void report118 (TypeContainer tc, Expression expr, string expected)
{
- report (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
- "' where an " + expected + " was expected");
+ Error (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
+ "' where an " + expected + " was expected");
}
}
// </summary>
public class BoxedCast : EmptyCast {
- public BoxedCast (Expression expr, Type target_type)
- : base (expr, target_type)
+ public BoxedCast (Expression expr)
+ : base (expr, TypeManager.object_type)
{
}
else
op_name = "op_" + oper;
- mg = MemberLookup (tc.RootContext, expr_type, op_name, false);
+ mg = MemberLookup (tc, expr_type, op_name, false);
if (mg != null) {
Arguments = new ArrayList ();
}
}
- tc.RootContext.Report.Error (187, "No such operator '" + OperName () +
- "' defined for type '" +
- TypeManager.CSharpName (expr_type) + "'");
+ if (oper == Operator.AddressOf){
+ if (expr.ExprClass != ExprClass.Variable){
+ Error (tc, 211, "Cannot take the address of non-variables");
+ return null;
+ }
+ type = Type.GetType (expr.Type.ToString () + "*");
+ }
+
+ Error (tc, 187, "No such operator '" + OperName () + "' defined for type '" +
+ TypeManager.CSharpName (expr_type) + "'");
return null;
}
//
if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
oper == Operator.PostDecrement || oper == Operator.PostIncrement){
- ((LValue) expr).Store (ig);
+ ((LValue) expr).Store (ec);
}
return;
}
break;
case Operator.AddressOf:
- throw new Exception ("Not implemented yet");
+ ((LValue)expr).AddressOf (ec);
+ break;
case Operator.Indirection:
throw new Exception ("Not implemented yet");
else
ig.Emit (OpCodes.Add);
ig.Emit (OpCodes.Dup);
- ((LValue) expr).Store (ig);
+ ((LValue) expr).Store (ec);
} else {
throw new Exception ("Handle Indexers and Properties here");
}
ig.Emit (OpCodes.Sub);
else
ig.Emit (OpCodes.Add);
- ((LValue) expr).Store (ig);
+ ((LValue) expr).Store (ec);
} else {
throw new Exception ("Handle Indexers and Properties here");
}
public override Expression Resolve (TypeContainer tc)
{
+ expr = expr.Resolve (tc);
+ if (expr == null)
+ return null;
+
type = tc.LookupType (target_type, false);
eclass = ExprClass.Value;
(other == TypeManager.int64_type)){
string oper = OperName ();
- tc.RootContext.Report.Error (34, "Operator `" + OperName ()
- + "' is ambiguous on operands of type `"
- + TypeManager.CSharpName (l) + "' "
- + "and `" + TypeManager.CSharpName (r)
- + "'");
+ Error (tc, 34, "Operator `" + OperName ()
+ + "' is ambiguous on operands of type `"
+ + TypeManager.CSharpName (l) + "' "
+ + "and `" + TypeManager.CSharpName (r)
+ + "'");
}
type = TypeManager.uint64_type;
} else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
void error19 (TypeContainer tc)
{
- tc.RootContext.Report.Error (
- 19,
- "Operator " + OperName () + " cannot be applied to operands of type `" +
- TypeManager.CSharpName (left.Type) + "' and `" +
- TypeManager.CSharpName (right.Type) + "'");
+ Error (tc, 19,
+ "Operator " + OperName () + " cannot be applied to operands of type `" +
+ TypeManager.CSharpName (left.Type) + "' and `" +
+ TypeManager.CSharpName (right.Type) + "'");
}
string op = "op_" + oper;
- left_expr = MemberLookup (tc.RootContext, l, op, false);
+ left_expr = MemberLookup (tc, l, op, false);
- right_expr = MemberLookup (tc.RootContext, r, op, false);
+ right_expr = MemberLookup (tc, r, op, false);
MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
if (l != TypeManager.bool_type || r != TypeManager.bool_type)
error19 (tc);
- } else
+ } else if (oper == Operator.Addition){
+ //
+ // If any of the arguments is a string, cast to string
+ //
+ if (l == TypeManager.string_type){
+ if (r == TypeManager.string_type){
+ // string + string
+ method = TypeManager.string_concat_string_string;
+ } else {
+ // string + object
+ method = TypeManager.string_concat_object_object;
+ right = ConvertImplicit (tc, right, TypeManager.object_type);
+ }
+ type = TypeManager.string_type;
+
+ Arguments = new ArrayList ();
+ Arguments.Add (new Argument (left, Argument.AType.Expression));
+ Arguments.Add (new Argument (right, Argument.AType.Expression));
+ } else if (r == TypeManager.string_type){
+ // object + string
+ method = TypeManager.string_concat_object_object;
+ Arguments = new ArrayList ();
+ Arguments.Add (new Argument (left, Argument.AType.Expression));
+ Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+ left = ConvertImplicit (tc, left, TypeManager.object_type);
+ type = TypeManager.string_type;
+ }
+
+ //
+ // FIXME: is Delegate operator + (D x, D y) handled?
+ //
+ } else
DoNumericPromotions (tc, l, r);
if (left == null || right == null)
return null;
+
if (oper == Operator.BitwiseAnd ||
oper == Operator.BitwiseOr ||
oper == Operator.ExclusiveOr){
public class Conditional : Expression {
Expression expr, trueExpr, falseExpr;
+ Location l;
- public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
+ public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
{
this.expr = expr;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
+ this.l = l;
}
public Expression Expr {
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
- throw new Exception ("Unimplemented");
- // return this;
+ expr = expr.Resolve (tc);
+
+ if (expr.Type != TypeManager.bool_type)
+ expr = Expression.ConvertImplicitRequired (
+ tc, expr, TypeManager.bool_type, l);
+
+ trueExpr = trueExpr.Resolve (tc);
+ falseExpr = falseExpr.Resolve (tc);
+
+ if (expr == null || trueExpr == null || falseExpr == null)
+ return null;
+
+ if (trueExpr.Type == falseExpr.Type)
+ type = trueExpr.Type;
+ else {
+ Expression conv;
+
+ //
+ // 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);
+ if (conv != null){
+ type = falseExpr.Type;
+ trueExpr = conv;
+ } else if ((conv = ConvertImplicit (tc, falseExpr, trueExpr.Type)) != null){
+ type = trueExpr.Type;
+ falseExpr = conv;
+ } else {
+ Error (tc, 173, l, "The type of the conditional expression can " +
+ "not be computed because there is no implicit conversion" +
+ " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
+ " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
+ return null;
+ }
+ }
+
+ eclass = ExprClass.Value;
+ return this;
}
public override void Emit (EmitContext ec)
{
+ ILGenerator ig = ec.ig;
+ Label false_target = ig.DefineLabel ();
+ Label end_target = ig.DefineLabel ();
+
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Brfalse, false_target);
+ trueExpr.Emit (ec);
+ ig.Emit (OpCodes.Br, end_target);
+ ig.MarkLabel (false_target);
+ falseExpr.Emit (ec);
+ ig.MarkLabel (end_target);
}
}
Expression e;
Report r = tc.RootContext.Report;
- e = MemberLookup (tc.RootContext, tc.TypeBuilder, Name, true);
+ e = MemberLookup (tc, tc.TypeBuilder, Name, true);
if (e != null){
if (e is TypeExpr)
return e;
//
// FIXME: implement me.
- r.Error (103, Location, "The name `" + Name + "' does not exist in the class `" +
- tc.Name + "'");
+ Error (tc, 103, Location, "The name `" + Name + "' does not exist in the class `" +
+ tc.Name + "'");
return null;
}
// A simple interface that should be implemeneted by LValues
// </summary>
public interface LValue {
- void Store (ILGenerator ig);
+
+ // <summary>
+ // The Store method should store the contents of the top
+ // of the stack into the storage that is implemented by
+ // the particular implementation of LValue
+ // </summary>
+ void Store (EmitContext ec);
+
+ // <summary>
+ // The AddressOf method should generate code that loads
+ // the address of the LValue and leaves it on the stack
+ // </summary>
+ void AddressOf (EmitContext ec);
}
public class LocalVariableReference : Expression, LValue {
ILGenerator ig = ec.ig;
int idx = vi.Idx;
+ vi.Used = true;
+
switch (idx){
case 0:
ig.Emit (OpCodes.Ldloc_0);
break;
default:
- if (idx < 255)
- ig.Emit (OpCodes.Ldloc_S, idx);
+ if (idx <= 255)
+ ig.Emit (OpCodes.Ldloc_S, (byte) idx);
else
ig.Emit (OpCodes.Ldloc, idx);
break;
}
}
- public void Store (ILGenerator ig)
+ public void Store (EmitContext ec)
{
+ ILGenerator ig = ec.ig;
VariableInfo vi = VariableInfo;
int idx = vi.Idx;
-
+
+ vi.Assigned = true;
switch (idx){
case 0:
ig.Emit (OpCodes.Stloc_0);
break;
default:
- if (idx < 255)
- ig.Emit (OpCodes.Stloc_S, idx);
+ if (idx <= 255)
+ ig.Emit (OpCodes.Stloc_S, (byte) idx);
else
ig.Emit (OpCodes.Stloc, idx);
break;
}
}
+
+ public void AddressOf (EmitContext ec)
+ {
+ VariableInfo vi = VariableInfo;
+ int idx = vi.Idx;
+
+ vi.Used = true;
+ vi.Assigned = true;
+
+ if (idx <= 255)
+ ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
+ else
+ ec.ig.Emit (OpCodes.Ldloca, idx);
+ }
}
public class ParameterReference : Expression, LValue {
public override void Emit (EmitContext ec)
{
- if (Idx < 255)
- ec.ig.Emit (OpCodes.Ldarg_S, Idx);
+ if (Idx <= 255)
+ ec.ig.Emit (OpCodes.Ldarg_S, (byte) Idx);
else
ec.ig.Emit (OpCodes.Ldarg, Idx);
}
- public void Store (ILGenerator ig)
+ public void Store (EmitContext ec)
{
- if (Idx < 255)
- ig.Emit (OpCodes.Starg_S, Idx);
+ if (Idx <= 255)
+ ec.ig.Emit (OpCodes.Starg_S, (byte) Idx);
else
- ig.Emit (OpCodes.Starg, Idx);
+ ec.ig.Emit (OpCodes.Starg, Idx);
}
+
+ public void AddressOf (EmitContext ec)
+ {
+ if (Idx <= 255)
+ ec.ig.Emit (OpCodes.Ldarga_S, (byte) Idx);
+ else
+ ec.ig.Emit (OpCodes.Ldarga, Idx);
+ }
}
// <summary>
Expression mg;
- mg = MemberLookup (tc.RootContext, to, "op_Implicit", false);
+ mg = MemberLookup (tc, to, "op_Implicit", false);
if (mg != null) {
MethodGroupExpr me = (MethodGroupExpr) mg;
}
}
- mg = MemberLookup (tc.RootContext, from, "op_Implicit", false);
+ mg = MemberLookup (tc, from, "op_Implicit", false);
if (mg != null) {
MethodGroupExpr me = (MethodGroupExpr) mg;
if (argument_type == null)
throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
-
-
+
if (p == q)
return 0;
-
+
if (argument_type == p)
return 1;
}
}
- // User-defined Implicit conversions come here
-
- if (q != null)
- if (ConversionExists (tc, p, q) == true &&
- ConversionExists (tc, q, p) == false)
+ if (q == null) {
+
+ Expression tmp;
+
+ tmp = ConvertImplicit (tc, argument_expr, p);
+
+ if (tmp != null)
return 1;
-
+ else
+ return 0;
+
+ }
+
+ Expression p_tmp, q_tmp;
+
+ p_tmp = ConvertImplicit (tc, argument_expr, p);
+ q_tmp = ConvertImplicit (tc, argument_expr, q);
+
+ if (p_tmp != null && q_tmp == null)
+ return 1;
+
if (p == TypeManager.sbyte_type)
if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
- q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+ q == TypeManager.uint32_type || q == TypeManager.uint64_type)
return 1;
if (p == TypeManager.short_type)
i--;
MethodBase candidate = me.Methods [i];
int x;
-
+
x = BetterFunction (tc, Arguments, candidate, method);
if (x == 0)
method = me.Methods [best_match_idx];
}
}
-
- if (best_match_idx != -1)
- return method;
-
- // Now we see if we can at least find a method with the same number of arguments
- // and then try doing implicit conversion on the arguments
if (Arguments == null)
argument_count = 0;
else
argument_count = Arguments.Count;
-
- ParameterData pd = null;
- for (int i = me.Methods.Length; i > 0;) {
- i--;
- MethodBase mb = me.Methods [i];
- pd = GetParameterData (mb);
+ ParameterData pd;
+
+ // Now we see if we can at least find a method with the same number of arguments
+ // and then try doing implicit conversion on the arguments
+ if (best_match_idx == -1) {
+
+ for (int i = me.Methods.Length; i > 0;) {
+ i--;
+ MethodBase mb = me.Methods [i];
+ pd = GetParameterData (mb);
+
+ if (pd.Count == argument_count) {
+ best_match_idx = i;
+ method = me.Methods [best_match_idx];
+ break;
+ } else
+ continue;
+ }
- if (pd.Count == argument_count) {
- best_match_idx = i;
- method = me.Methods [best_match_idx];
- break;
- } else
- continue;
}
- if (best_match_idx == -1)
+ if (method == null)
return null;
// And now convert implicitly, each argument to the required type
Expression conv = ConvertImplicit (tc, a_expr, pd.ParameterType (j));
if (conv == null) {
- tc.RootContext.Report.Error (1502, loc,
+ Error (tc, 1502, loc,
"The best overloaded match for method '" + FullMethodDesc (method) +
"' has some invalid arguments");
- tc.RootContext.Report.Error (1503, loc,
+ Error (tc, 1503, loc,
"Argument " + (j+1) +
" : Cannot convert from '" + TypeManager.CSharpName (a_expr.Type)
+ "' to '" + TypeManager.CSharpName (pd.ParameterType (j)) + "'");
method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments, Location);
if (method == null){
- tc.RootContext.Report.Error (-6, Location,
+ Error (tc, -6, Location,
"Could not find any applicable function for this argument list");
return null;
}
Expression ml;
- ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+ ml = MemberLookup (tc, type, ".ctor", false,
MemberTypes.Constructor, AllBindingsFlags);
if (! (ml is MethodGroupExpr)){
method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments, Location);
if (method == null) {
- tc.RootContext.Report.Error (-6, Location,
- "New invocation: Can not find a constructor for this argument list");
+ Error (tc, -6, Location,
+ "New invocation: Can not find a constructor for this argument list");
return null;
}
ec.ig.Emit (OpCodes.Ldarg_0);
}
- public void Store (ILGenerator ig)
+ public void Store (EmitContext ec)
{
//
- // Assignment to the "this" variable
+ // Assignment to the "this" variable.
+ //
+ // FIXME: Apparently this is a bug that we
+ // must catch as `this' seems to be readonly ;-)
//
- ig.Emit (OpCodes.Starg, 0);
+ ec.ig.Emit (OpCodes.Starg, 0);
+ }
+
+ public void AddressOf (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
}
}
if (new_expression == null)
return null;
- member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
+ member_lookup = MemberLookup (tc, expr.Type, Identifier, false);
if (member_lookup is MethodGroupExpr){
MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
public override void Emit (EmitContext ec)
{
- throw new Exception ("Implement me");
+ throw new Exception ("Should not happen I think");
}
}
}
}
- public class BuiltinTypeAccess : Expression {
- public readonly string AccessBase;
- public readonly string Method;
-
- public BuiltinTypeAccess (string type, string method)
- {
- System.Console.WriteLine ("DUDE! This type should be fully resolved!");
- AccessBase = type;
- Method = method;
- }
-
- public override Expression Resolve (TypeContainer tc)
- {
- // FIXME: Implement;
- throw new Exception ("Unimplemented");
- // return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- throw new Exception ("Unimplemented");
- }
- }
-
-
// Fully resolved expression that evaluates to a Field
// </summary>
public class FieldExpr : Expression, LValue {
}
}
- public void Store (ILGenerator ig)
+ public void Store (EmitContext ec)
{
if (FieldInfo.IsStatic)
- ig.Emit (OpCodes.Stsfld, FieldInfo);
+ ec.ig.Emit (OpCodes.Stsfld, FieldInfo);
else
- ig.Emit (OpCodes.Stfld, FieldInfo);
+ ec.ig.Emit (OpCodes.Stfld, FieldInfo);
+ }
+
+ public void AddressOf (EmitContext ec)
+ {
+ if (FieldInfo.IsStatic)
+ ec.ig.Emit (OpCodes.Ldsflda, FieldInfo);
+ else {
+ Instance.Emit (ec);
+ ec.ig.Emit (OpCodes.Ldflda, FieldInfo);
+ }
}
}
}
// <summary>
- // Fully resolved expression that evaluates to a Property
+ // Fully resolved expression that evaluates to a Expression
// </summary>
public class EventExpr : Expression {
public readonly EventInfo EventInfo;
}
public class UserImplicitCast : Expression {
-
- Expression source;
- Type target;
MethodBase method;
ArrayList arguments;
- public UserImplicitCast (Expression source, Type target)
+ public UserImplicitCast (MethodInfo method, ArrayList arguments)
{
- this.source = source;
- this.target = target;
+ this.method = method;
+ this.arguments = arguments;
+ type = method.ReturnType;
+ eclass = ExprClass.Value;
}
public override Expression Resolve (TypeContainer tc)
{
- source = source.Resolve (tc);
-
- if (source == null)
- return null;
-
- Expression mg1, mg2;
- MethodGroupExpr union;
- MethodInfo mi;
-
- mg1 = MemberLookup (tc.RootContext, source.Type, "op_Implicit", false);
- mg2 = MemberLookup (tc.RootContext, target, "op_Implicit", false);
-
- union = Invocation.MakeUnionSet (mg1, mg2);
-
- arguments = new ArrayList ();
- arguments.Add (new Argument (source, Argument.AType.Expression));
-
- if (union != null) {
- method = Invocation.OverloadResolve (tc, union, arguments,
- new Location ("FIXME", 1, 1));
-
- if (method != null) {
- mi = (MethodInfo) method;
-
- if (mi.ReturnType == target) {
- type = mi.ReturnType;
- return this;
- }
- }
- }
-
- if (target == TypeManager.bool_type) {
-
- mg1 = MemberLookup (tc.RootContext, source.Type, "op_True", false);
- mg2 = MemberLookup (tc.RootContext, target, "op_True", false);
-
- union = Invocation.MakeUnionSet (mg1, mg2);
-
- if (union == null)
- return null;
-
- method = Invocation.OverloadResolve (tc, union, arguments,
- new Location ("FIXME", 1, 1));
-
- if (method != null) {
- mi = (MethodInfo) method;
-
- if (mi.ReturnType == target) {
- type = mi.ReturnType;
- return this;
- }
- }
- }
-
- return null;
+ //
+ // We are born in a fully resolved state
+ //
+ return this;
}
- public static bool CanConvert (TypeContainer tc, Expression source, Type target)
+ public static Expression CanConvert (TypeContainer tc, Expression source, Type target)
{
- source = source.Resolve (tc);
-
- if (source == null)
- return false;
-
Expression mg1, mg2;
MethodBase method;
ArrayList arguments;
- mg1 = MemberLookup (tc.RootContext, source.Type, "op_Implicit", false);
- mg2 = MemberLookup (tc.RootContext, target, "op_Implicit", false);
+ mg1 = MemberLookup (tc, source.Type, "op_Implicit", false);
+ mg2 = MemberLookup (tc, target, "op_Implicit", false);
MethodGroupExpr union = Invocation.MakeUnionSet (mg1, mg2);
- arguments = new ArrayList ();
- arguments.Add (new Argument (source, Argument.AType.Expression));
-
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));
+ new Location ("FIXME", 1, 1));
+
if (method != null) {
MethodInfo mi = (MethodInfo) method;
if (mi.ReturnType == target)
- return true;
+ return new UserImplicitCast (mi, arguments);
}
}
if (target == TypeManager.bool_type) {
- mg1 = MemberLookup (tc.RootContext, source.Type, "op_True", false);
- mg2 = MemberLookup (tc.RootContext, target, "op_True", false);
+ mg1 = MemberLookup (tc, source.Type, "op_True", false);
+ mg2 = MemberLookup (tc, target, "op_True", false);
union = Invocation.MakeUnionSet (mg1, mg2);
if (union == null)
- return false;
+ 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 true;
+ return new UserImplicitCast (mi, arguments);
}
}
- return false;
-
+ return null;
}
public override void Emit (EmitContext ec)