//
// Return values:
// If the return value is an Array, then it is an array of
- // MethodInfos
+ // MethodBases
//
// If the return value is an MemberInfo, it is anything, but a Method
//
//
// This is so we can catch correctly attempts to invoke instance methods
// from a static body (scan for error 120 in ResolveSimpleName).
- //
- protected static Expression MemberLookup (RootContext rc, Type t, string name, bool same_type)
- {
- MemberTypes mt =
- // MemberTypes.Constructor |
- MemberTypes.Event |
- MemberTypes.Field |
- MemberTypes.Method |
- MemberTypes.NestedType |
- MemberTypes.Property;
-
- BindingFlags bf =
- BindingFlags.Public |
- BindingFlags.Static |
- BindingFlags.Instance;
-
+ //
+ public static Expression MemberLookup (RootContext rc, Type t, string name,
+ bool same_type, MemberTypes mt, BindingFlags bf)
+ {
if (same_type)
bf |= BindingFlags.NonPublic;
if (mi == null)
return null;
- if (mi.Length == 1 && !(mi [0] is MethodInfo))
+ if (mi.Length == 1 && !(mi [0] is MethodBase))
return Expression.ExprClassFromMemberInfo (mi [0]);
-
+
for (int i = 0; i < mi.Length; i++)
- if (!(mi [i] is MethodInfo)){
+ 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");
-
+
+ for (i = 0; i < mi.Length; i++){
+ Type tt = mi [i].GetType ();
+
+ Console.WriteLine (i + ": " + mi [i]);
+ while (tt != TypeManager.object_type){
+ Console.WriteLine (tt);
+ tt = tt.BaseType;
+ }
+ }
}
return new MethodGroupExpr (mi);
}
+
+ public const MemberTypes AllMemberTypes =
+ MemberTypes.Constructor |
+ MemberTypes.Event |
+ MemberTypes.Field |
+ MemberTypes.Method |
+ MemberTypes.NestedType |
+ MemberTypes.Property;
+
+ public const BindingFlags AllBindingsFlags =
+ BindingFlags.Public |
+ BindingFlags.Static |
+ BindingFlags.Instance;
+
+ public static Expression MemberLookup (RootContext rc, Type t, string name,
+ bool same_type)
+ {
+ return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
+ }
// <summary>
// Resolves the E in `E.I' side for a member_access
public class Binary : Expression {
public enum Operator {
Multiply, Divide, Modulo,
- Add, Substract,
+ Add, Subtract,
ShiftLeft, ShiftRight,
- LessThan, GreatherThan, LessOrEqual, GreatherOrEqual,
+ LessThan, GreaterThan, LessOrEqual, GreaterOrEqual,
Equal, NotEqual,
BitwiseAnd,
ExclusiveOr,
Operator oper;
Expression left, right;
+ MethodBase method;
+ ArrayList Arguments;
+
public Binary (Operator oper, Expression left, Expression right)
{
return "%";
case Operator.Add:
return "+";
- case Operator.Substract:
+ case Operator.Subtract:
return "-";
case Operator.ShiftLeft:
return "<<";
return ">>";
case Operator.LessThan:
return "<";
- case Operator.GreatherThan:
+ case Operator.GreaterThan:
return ">";
case Operator.LessOrEqual:
return "<=";
- case Operator.GreatherOrEqual:
+ case Operator.GreaterOrEqual:
return ">=";
case Operator.Equal:
return "==";
} else {
left = ForceConversion (left, TypeManager.int32_type);
right = ForceConversion (right, TypeManager.int32_type);
+ type = TypeManager.int32_type;
}
}
//
// Step 1: Perform Operator Overload location
//
-
+ Expression left_expr, right_expr;
+ string op = "Operator" + oper;
+
+ left_expr = MemberLookup (tc.RootContext, l, op, false);
+
+ if (!(left_expr is MethodGroupExpr)){
+ // FIXME: Find proper error
+ tc.RootContext.Report.Error (118, "Did find something that is not a method");
+ return null;
+ }
+
+ right_expr = MemberLookup (tc.RootContext, r, op, false);
+
+ if (!(right_expr is MethodGroupExpr)){
+ // FIXME: Find proper error
+ tc.RootContext.Report.Error (118, "Did find something that is not a method");
+ return null;
+ }
+
+ if (left_expr != null || right_expr != null) {
+ //
+ // Now we need to form the union of these two sets and
+ // then call OverloadResolve on that.
+ //
+ MethodGroupExpr left_set = null, right_set = null;
+ int length1 = 0, length2 = 0;
+
+ if (left_expr != null) {
+ left_set = (MethodGroupExpr) left_expr;
+ length1 = left_set.Methods.Length;
+ }
+
+ if (right_expr != null) {
+ right_set = (MethodGroupExpr) right_expr;
+ length2 = right_set.Methods.Length;
+ }
+
+ MemberInfo [] mi = new MemberInfo [length1 + length2];
+ if (left_set != null)
+ left_set.Methods.CopyTo (mi, 0);
+ if (right_set != null)
+ right_set.Methods.CopyTo (mi, length1);
+
+ MethodGroupExpr union = new MethodGroupExpr (mi);
+
+ Arguments = new ArrayList ();
+ Arguments.Add (new Argument (left, Argument.AType.Expression));
+ Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+ method = Invocation.OverloadResolve (union, Arguments);
+ if (method != null)
+ return this;
+
+ }
+
//
// Step 2: Default operations on CLI native types.
//
-
+
// Only perform numeric promotions on:
// +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
//
} else
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;
}
- } else
-
- if (left == null || right == null)
- return null;
+ }
+ if (oper == Operator.Equal ||
+ oper == Operator.NotEqual ||
+ oper == Operator.LessOrEqual ||
+ oper == Operator.LessThan ||
+ oper == Operator.GreaterOrEqual ||
+ oper == Operator.GreaterThan){
+ type = TypeManager.bool_type;
+ }
+
return this;
}
if (left == null || right == null)
return null;
-
+
return ResolveOperator (tc);
}
if (oper == Operator.Equal ||
oper == Operator.NotEqual ||
oper == Operator.LessThan ||
- oper == Operator.GreatherThan ||
+ oper == Operator.GreaterThan ||
oper == Operator.LessOrEqual ||
- oper == Operator.GreatherOrEqual){
+ oper == Operator.GreaterOrEqual){
return true;
} else
return false;
opcode = OpCodes.Blt;
break;
- case Operator.GreatherThan:
+ case Operator.GreaterThan:
if (close_target)
opcode = OpCodes.Bgt_S;
else
opcode = OpCodes.Ble;
break;
- case Operator.GreatherOrEqual:
+ case Operator.GreaterOrEqual:
if (close_target)
opcode = OpCodes.Bge_S;
else
Type l = left.Type;
Type r = right.Type;
OpCode opcode;
+
+ if (method != null) {
+
+ bool is_static = method.IsStatic;
+
+ // FIXME : I am just not able to get this right !!
+ // There's something wrong with this part which causes
+ // an InvalidProgramException if this code is emitted
+
+ //if (Arguments != null)
+ // Invocation.EmitArguments (ec, Arguments);
+
+ //if (is_static){
+ // if (method is MethodInfo)
+ // ig.Emit (OpCodes.Call, (MethodInfo) method);
+ // else
+ // ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+ //} else {
+ // if (method is MethodInfo)
+ // ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+ // else
+ // ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+ //}
+
+ //return;
+ }
left.Emit (ec);
right.Emit (ec);
opcode = OpCodes.Add;
break;
- case Operator.Substract:
+ case Operator.Subtract:
if (ec.CheckState){
if (l == TypeManager.int32_type || l == TypeManager.int64_type)
opcode = OpCodes.Sub_Ovf;
opcode = OpCodes.Clt;
break;
- case Operator.GreatherThan:
+ case Operator.GreaterThan:
opcode = OpCodes.Cgt;
break;
opcode = OpCodes.Ceq;
break;
- case Operator.GreatherOrEqual:
+ case Operator.GreaterOrEqual:
ec.ig.Emit (OpCodes.Clt);
ec.ig.Emit (OpCodes.Ldc_I4_1);
if (e != null){
if (e is TypeExpr)
return e;
+ else if (e is FieldExpr){
+ FieldExpr fe = (FieldExpr) e;
+
+ if (!fe.FieldInfo.IsStatic)
+ fe.Instance = new This ();
+ }
+
if ((tc.ModFlags & Modifiers.STATIC) != 0)
return MemberStaticCheck (r, e);
else
public VariableInfo VariableInfo {
get {
- return (VariableInfo) Block.GetVariableInfo (Name);
+ return Block.GetVariableInfo (Name);
}
}
public override Expression Resolve (TypeContainer tc)
{
+ VariableInfo vi = Block.GetVariableInfo (Name);
+
+ type = vi.VariableType;
return this;
}
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
+ Type [] types = Pars.GetParameterInfo (tc);
+
+ type = types [Idx];
+
return this;
}
public override void Emit (EmitContext ec)
{
+ if (Idx < 255)
+ ec.ig.Emit (OpCodes.Ldarg_S, Idx);
+ else
+ ec.ig.Emit (OpCodes.Ldarg, Idx);
}
}
public bool Resolve (TypeContainer tc)
{
expr = expr.Resolve (tc);
+
return expr != null;
}
public class Invocation : Expression {
public readonly ArrayList Arguments;
Expression expr;
- MethodInfo method = null;
+ MethodBase method = null;
+ static Hashtable method_parameter_cache;
+
+ static Invocation ()
+ {
+ method_parameter_cache = new Hashtable ();
+ }
+
//
// arguments is an ArrayList, but we do not want to typecast,
// as it might be null.
/// -1 represents a type mismatch.
/// -2 represents a ref/out mismatch.
/// </summary>
- static int Badness (Argument a, ParameterInfo pi)
+ static int Badness (Argument a, Type t)
{
- if (pi.ParameterType == a.Expr.Type)
+ if (a.Expr.Type == null){
+ throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+ }
+
+ if (t == a.Expr.Type)
return 0;
-
+
// FIXME: Implement implicit conversions here.
// FIXME: Implement better conversion here.
return -1;
}
+ // <summary>
+ // Returns the Parameters (a ParameterData interface) for the
+ // Method `mb'
+ // </summary>
+ static ParameterData GetParameterData (MethodBase mb)
+ {
+ object pd = method_parameter_cache [mb];
+
+ if (pd != null)
+ return (ParameterData) pd;
+
+ if (mb is MethodBuilder || mb is ConstructorBuilder){
+ MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
+
+ InternalParameters ip = mc.ParameterInfo;
+ method_parameter_cache [mb] = ip;
+
+ return (ParameterData) ip;
+ } else {
+ ParameterInfo [] pi = mb.GetParameters ();
+ ReflectionParameters rp = new ReflectionParameters (pi);
+ method_parameter_cache [mb] = rp;
+
+ return (ParameterData) rp;
+ }
+ }
+
// <summary>
// Find the Applicable Function Members (7.4.2.1)
+ //
+ // me: Method Group expression with the members to select.
+ // it might contain constructors or methods (or anything
+ // that maps to a method).
+ //
+ // Arguments: ArrayList containing resolved Argument objects.
+ //
+ // Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+ // that is the best match of me on Arguments.
+ //
// </summary>
- static MethodInfo OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
+ public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
{
ArrayList afm = new ArrayList ();
int best_match = 10000;
int best_match_idx = -1;
- MethodInfo method = null;
-
+ MethodBase method = null;
+ int argument_count;
+
+ if (Arguments == null)
+ argument_count = 0;
+ else
+ argument_count = Arguments.Count;
+
for (int i = me.Methods.Length; i > 0; ){
i--;
- ParameterInfo [] pi = me.Methods [i].GetParameters ();
+ MethodBase mb = me.Methods [i];
+ ParameterData pd;
+
+ pd = GetParameterData (mb);
+
+ // If this is the case, we have a method with no args - presumably
+ if (pd == null && argument_count == 0)
+ return me.Methods [0];
//
// Compute how good this is
//
- if (pi.Length == Arguments.Count){
+ if (pd.Count == argument_count){
int badness = 0;
- for (int j = Arguments.Count; j > 0;){
+ for (int j = argument_count; j > 0;){
int x;
j--;
-
+
Argument a = (Argument) Arguments [j];
- x = Badness (a, pi [j]);
-
+ x = Badness (a, pd.ParameterType (j));
+
if (x < 0){
- // FIXME: report nice error.
- } else
- badness += x;
+ badness = best_match;
+ continue;
+ }
+
+ badness += x;
}
-
+
if (badness < best_match){
best_match = badness;
method = me.Methods [i];
if (!(this.expr is MethodGroupExpr)){
tc.RootContext.Report.Error (118,
- "Denotes an " + this.expr.ExprClass + " while a method was expected");
+ "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
return null;
}
return null;
}
- Console.WriteLine ("Found a method! " + method);
+ if (method is MethodInfo)
+ type = ((MethodInfo)method).ReturnType;
return this;
}
- public override void Emit (EmitContext ec)
+ public static void EmitArguments (EmitContext ec, ArrayList Arguments)
{
- int top = Arguments.Count;
+ int top;
+
+ if (Arguments != null)
+ top = Arguments.Count;
+ else
+ top = 0;
for (int i = 0; i < top; i++){
Argument a = (Argument) Arguments [i];
a.Emit (ec);
}
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ bool is_static = method.IsStatic;
+
+ if (!is_static){
+ MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+
+ if (mg.InstanceExpression == null){
+ Console.WriteLine ("Internal compiler error. Should check in the method groups for static/instance");
+ }
+
+ mg.InstanceExpression.Emit (ec);
+ }
+
+ if (Arguments != null)
+ EmitArguments (ec, Arguments);
+
+ if (is_static){
+ if (method is MethodInfo)
+ ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
+ else
+ ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+ } else {
+ if (method is MethodInfo)
+ ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+ else
+ ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+ }
- ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
}
}
public readonly ArrayList Indices;
public readonly ArrayList Initializers;
+ MethodBase method = null;
public New (string requested_type, ArrayList arguments)
{
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
+ type = tc.LookupType (RequestedType, false);
+
+ if (type == null)
+ return null;
+
+ Expression ml;
+
+ ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+ MemberTypes.Constructor, AllBindingsFlags);
+
+ if (! (ml is MethodGroupExpr)){
+ //
+ // FIXME: Find proper error
+ //
+ tc.RootContext.Report.Error (118, "Did find something that is not a method");
+ return null;
+ }
+
+ if (Arguments != null){
+ for (int i = Arguments.Count; i > 0;){
+ --i;
+ Argument a = (Argument) Arguments [i];
+
+ if (!a.Resolve (tc))
+ return null;
+ }
+ }
+
+ method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
+
+ if (method == null) {
+ tc.RootContext.Report.Error (-6,
+ "New invocation: Can not find a constructor for this argument list");
+ return null;
+ }
+
return this;
}
public override void Emit (EmitContext ec)
{
+ Invocation.EmitArguments (ec, Arguments);
+ ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
}
}
+ //
+ // Represents the `this' construct
+ //
public class This : Expression {
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
+ eclass = ExprClass.Variable;
+ type = tc.TypeBuilder;
+
return this;
}
public override void Emit (EmitContext ec)
{
+ ec.ig.Emit (OpCodes.Ldarg_0);
}
}
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
+ type = tc.LookupType (QueriedType, false);
+
+ if (type == null)
+ return null;
+
+ eclass = ExprClass.Type;
return this;
}
public override void Emit (EmitContext ec)
{
+ // FIXME: Implement.
}
}
public class MemberAccess : Expression {
public readonly string Identifier;
Expression expr;
+ Expression member_lookup;
public MemberAccess (Expression expr, string id)
{
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
- return this;
+ Expression new_expression = expr.Resolve (tc);
+
+ if (new_expression == null)
+ return null;
+
+ Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
+
+ member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
+
+ if (member_lookup is MethodGroupExpr){
+ MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
+
+ //
+ // Bind the instance expression to it
+ //
+ // FIXME: This is a horrible way of detecting if it is
+ // an instance expression. Figure out how to fix this.
+ //
+
+ if (expr is LocalVariableReference ||
+ expr is ParameterReference ||
+ expr is FieldExpr)
+ mg.InstanceExpression = expr;
+
+ return member_lookup;
+ } else if (member_lookup is FieldExpr){
+ FieldExpr fe = (FieldExpr) member_lookup;
+
+ fe.Instance = expr;
+
+ return member_lookup;
+ } else
+ //
+ // FIXME: This should generate the proper node
+ // ie, for a Property Access, it should like call it
+ // and stuff.
+
+ return member_lookup;
}
public override void Emit (EmitContext ec)
}
// <summary>
- // Fully resolved expression that evaluates to a type
+ // MethodGroup Expression.
+ //
+ // This is a fully resolved expression that evaluates to a type
// </summary>
public class MethodGroupExpr : Expression {
- public readonly MethodInfo [] Methods;
+ public readonly MethodBase [] Methods;
+ Expression instance_expression = null;
public MethodGroupExpr (MemberInfo [] mi)
{
- Methods = new MethodInfo [mi.Length];
+ Methods = new MethodBase [mi.Length];
mi.CopyTo (Methods, 0);
eclass = ExprClass.MethodGroup;
}
+ //
+ // `A method group may have associated an instance expression'
+ //
+ public Expression InstanceExpression {
+ get {
+ return instance_expression;
+ }
+
+ set {
+ instance_expression = value;
+ }
+ }
+
override public Expression Resolve (TypeContainer tc)
{
return this;
// </summary>
public class FieldExpr : Expression {
public readonly FieldInfo FieldInfo;
-
+ public Expression Instance;
+
public FieldExpr (FieldInfo fi)
{
FieldInfo = fi;
eclass = ExprClass.Variable;
+ type = fi.FieldType;
}
override public Expression Resolve (TypeContainer tc)
{
- // We are born in resolved state.
+ if (!FieldInfo.IsStatic){
+ if (Instance == null){
+ throw new Exception ("non-static FieldExpr without instance var\n" +
+ "You have to assign the Instance variable\n" +
+ "Of the FieldExpr to set this\n");
+ }
+
+ Instance = Instance.Resolve (tc);
+ if (Instance == null)
+ return null;
+
+ }
return this;
}
override public void Emit (EmitContext ec)
{
- // FIXME: Assert that this should not be reached?
+ ILGenerator ig = ec.ig;
+
+ if (FieldInfo.IsStatic)
+ ig.Emit (OpCodes.Ldsfld, FieldInfo);
+ else {
+ Instance.Emit (ec);
+
+ ig.Emit (OpCodes.Ldfld, FieldInfo);
+ }
}
}
eclass = ExprClass.PropertyAccess;
IsStatic = false;
- MethodInfo [] acc = pi.GetAccessors ();
+ MethodBase [] acc = pi.GetAccessors ();
for (int i = 0; i < acc.Length; i++)
if (acc [i].IsStatic)
IsStatic = true;
+
+ type = pi.PropertyType;
}
override public Expression Resolve (TypeContainer tc)
public class CheckedExpr : Expression {
- public readonly Expression Expr;
+ public Expression Expr;
public CheckedExpr (Expression e)
{
public override Expression Resolve (TypeContainer tc)
{
- // FIXME : Implement !
+ Expr = Expr.Resolve (tc);
+
+ if (Expr == null)
+ return null;
+
+ eclass = Expr.ExprClass;
+ type = Expr.Type;
return this;
}
public override void Emit (EmitContext ec)
{
+ bool last_check = ec.CheckState;
+
+ ec.CheckState = true;
+
+ Expr.Emit (ec);
+
+ ec.CheckState = last_check;
}
}
public class UnCheckedExpr : Expression {
- public readonly Expression Expr;
+ public Expression Expr;
public UnCheckedExpr (Expression e)
{
public override Expression Resolve (TypeContainer tc)
{
- // FIXME : Implement !
+ Expr = Expr.Resolve (tc);
+
+ if (Expr == null)
+ return null;
+
+ eclass = Expr.ExprClass;
+ type = Expr.Type;
return this;
}
public override void Emit (EmitContext ec)
{
+ bool last_check = ec.CheckState;
+
+ ec.CheckState = false;
+
+ Expr.Emit (ec);
+
+ ec.CheckState = last_check;
}
}
-
- public class ElementAccess : Expression {
-
+
+ public class ElementAccess : Expression {
+
public readonly ArrayList Arguments;
public readonly Expression Expr;
-
+
public ElementAccess (Expression e, ArrayList e_list)
{
Expr = e;
// FIXME : Implement
return this;
}
-
+
public override void Emit (EmitContext ec)
{
// FIXME : Implement !
}
-
+
}
-
+
public class BaseAccess : Expression {
public enum BaseAccessType {