+ if (method is MethodInfo)
+ type = ((MethodInfo)method).ReturnType;
+
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ // <summary>
+ // Emits the list of arguments as an array
+ // </summary>
+ static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
+ {
+ ILGenerator ig = ec.ig;
+ int count = arguments.Count - idx;
+ Argument a = (Argument) arguments [idx];
+ Type t = a.expr.Type;
+ string array_type = t.FullName + "[]";
+ LocalBuilder array;
+
+ array = ig.DeclareLocal (Type.GetType (array_type));
+ IntLiteral.EmitInt (ig, count);
+ ig.Emit (OpCodes.Newarr, t);
+ ig.Emit (OpCodes.Stloc, array);
+
+ int top = arguments.Count;
+ for (int j = idx; j < top; j++){
+ a = (Argument) arguments [j];
+
+ ig.Emit (OpCodes.Ldloc, array);
+ IntLiteral.EmitInt (ig, j - idx);
+ a.Emit (ec);
+
+ ArrayAccess.EmitStoreOpcode (ig, t);
+ }
+ ig.Emit (OpCodes.Ldloc, array);
+ }
+
+ // <summary>
+ // Emits a list of resolved Arguments that are in the arguments
+ // ArrayList.
+ //
+ // The MethodBase argument might be null if the
+ // emission of the arguments is known not to contain
+ // a `params' field (for example in constructors or other routines
+ // that keep their arguments in this structure
+ // </summary>
+
+ public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
+ {
+ ParameterData pd = null;
+ int top;
+
+ if (arguments != null)
+ top = arguments.Count;
+ else
+ top = 0;
+
+ if (mb != null)
+ pd = GetParameterData (mb);
+
+ for (int i = 0; i < top; i++){
+ Argument a = (Argument) arguments [i];
+
+ if (pd != null){
+ if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
+ EmitParams (ec, i, arguments);
+ return;
+ }
+ }
+
+ a.Emit (ec);
+ }
+ }
+
+ public static void EmitCall (EmitContext ec,
+ bool is_static, Expression instance_expr,
+ MethodBase method, ArrayList Arguments)
+ {
+ ILGenerator ig = ec.ig;
+ bool struct_call = false;
+
+ if (!is_static){
+ //
+ // If this is ourselves, push "this"
+ //
+ if (instance_expr == null){
+ ig.Emit (OpCodes.Ldarg_0);
+ } else {
+ //
+ // Push the instance expression
+ //
+ if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
+
+ struct_call = true;
+
+ //
+ // If the expression implements IMemoryLocation, then
+ // we can optimize and use AddressOf on the
+ // return.
+ //
+ // If not we have to use some temporary storage for
+ // it.
+ if (instance_expr is IMemoryLocation)
+ ((IMemoryLocation) instance_expr).AddressOf (ec);
+ else {
+ Type t = instance_expr.Type;
+
+ instance_expr.Emit (ec);
+ LocalBuilder temp = ig.DeclareLocal (t);
+ ig.Emit (OpCodes.Stloc, temp);
+ ig.Emit (OpCodes.Ldloca, temp);
+ }
+ } else
+ instance_expr.Emit (ec);
+ }
+ }
+
+ if (Arguments != null)
+ EmitArguments (ec, method, Arguments);
+
+ if (is_static || struct_call){
+ 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);
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+ EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ Emit (ec);
+
+ //
+ // Pop the return value if there is one
+ //
+ if (method is MethodInfo){
+ if (((MethodInfo)method).ReturnType != TypeManager.void_type)
+ ec.ig.Emit (OpCodes.Pop);
+ }
+ }
+ }
+
+ public class New : ExpressionStatement {
+ public readonly ArrayList Arguments;
+ public readonly string RequestedType;
+
+ Location loc;
+ MethodBase method = null;
+
+ //
+ // If set, the new expression is for a value_target, and
+ // we will not leave anything on the stack.
+ //
+ Expression value_target;
+
+ public New (string requested_type, ArrayList arguments, Location l)
+ {
+ RequestedType = requested_type;
+ Arguments = arguments;
+ loc = l;
+ }
+
+ public Expression ValueTypeVariable {
+ get {
+ return value_target;
+ }
+
+ set {
+ value_target = value;
+ }
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ type = ec.TypeContainer.LookupType (RequestedType, false);
+
+ if (type == null)
+ return null;
+
+ bool IsDelegate = TypeManager.IsDelegateType (type);
+
+ if (IsDelegate)
+ return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+
+ Expression ml;
+
+ ml = MemberLookup (ec, type, ".ctor", false,
+ MemberTypes.Constructor, AllBindingsFlags, loc);
+
+ bool is_struct = false;
+ is_struct = type.IsSubclassOf (TypeManager.value_type);
+
+ if (! (ml is MethodGroupExpr)){
+ if (!is_struct){
+ report118 (loc, ml, "method group");
+ return null;
+ }
+ }
+
+ if (ml != null) {
+ if (Arguments != null){
+ for (int i = Arguments.Count; i > 0;){
+ --i;
+ Argument a = (Argument) Arguments [i];
+
+ if (!a.Resolve (ec, loc))
+ return null;
+ }
+ }
+
+ method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
+ Arguments, loc);
+ }
+
+ if (method == null && !is_struct) {
+ Error (-6, loc,
+ "New invocation: Can not find a constructor for " +
+ "this argument list");
+ return null;
+ }
+
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ //
+ // This DoEmit can be invoked in two contexts:
+ // * As a mechanism that will leave a value on the stack (new object)
+ // * As one that wont (init struct)
+ //
+ // You can control whether a value is required on the stack by passing
+ // need_value_on_stack. The code *might* leave a value on the stack
+ // so it must be popped manually
+ //
+ // Returns whether a value is left on the stack
+ //
+ bool DoEmit (EmitContext ec, bool need_value_on_stack)
+ {
+ if (method == null){
+ IMemoryLocation ml = (IMemoryLocation) value_target;
+
+ ml.AddressOf (ec);
+ } else {
+ Invocation.EmitArguments (ec, method, Arguments);
+ ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+ return true;
+ }
+
+ //
+ // It must be a value type, sanity check
+ //
+ if (value_target != null){
+ ec.ig.Emit (OpCodes.Initobj, type);
+
+ if (need_value_on_stack){
+ value_target.Emit (ec);
+ return true;
+ }
+ return false;
+ }
+
+ throw new Exception ("No method and no value type");
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ DoEmit (ec, true);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ if (DoEmit (ec, false))
+ ec.ig.Emit (OpCodes.Pop);
+ }
+ }
+
+ // <summary>
+ // Represents an array creation expression.
+ // </summary>
+ //
+ // <remarks>
+ // There are two possible scenarios here: one is an array creation
+ // expression that specifies the dimensions and optionally the
+ // initialization data
+ // </remarks>
+ public class ArrayCreation : ExpressionStatement {
+
+ string RequestedType;
+ string Rank;
+ ArrayList Initializers;
+ Location loc;
+ ArrayList Arguments;
+
+ MethodBase method = null;
+ Type array_element_type;
+ bool IsOneDimensional = false;
+
+ bool IsBuiltinType = false;
+
+ int dimensions = 0;
+
+ public ArrayCreation (string requested_type, ArrayList exprs,
+ string rank, ArrayList initializers, Location l)
+ {
+ RequestedType = requested_type;
+ Rank = rank;
+ Initializers = initializers;
+ loc = l;
+
+ Arguments = new ArrayList ();
+
+ foreach (Expression e in exprs)
+ Arguments.Add (new Argument (e, Argument.AType.Expression));
+
+ }
+
+ public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
+ {
+ RequestedType = requested_type;
+ Initializers = initializers;
+ loc = l;
+
+ Rank = rank.Substring (0, rank.LastIndexOf ("["));
+
+ string tmp = rank.Substring (rank.LastIndexOf ("["));
+
+ dimensions = tmp.Length - 1;
+ }
+
+ public static string FormArrayType (string base_type, int idx_count, string rank)
+ {
+ StringBuilder sb = new StringBuilder (base_type);
+
+ sb.Append (rank);
+
+ sb.Append ("[");
+ for (int i = 1; i < idx_count; i++)
+ sb.Append (",");
+ sb.Append ("]");
+
+ return sb.ToString ();
+ }
+
+ public static string FormElementType (string base_type, int idx_count, string rank)
+ {
+ StringBuilder sb = new StringBuilder (base_type);
+
+ sb.Append ("[");
+ for (int i = 1; i < idx_count; i++)
+ sb.Append (",");
+ sb.Append ("]");
+
+ sb.Append (rank);