+ bool has_ref_out_argument = false;
+ var targs = new TypeExpression[dyn_args_count + default_args];
+ targs[0] = new TypeExpression (module.PredefinedTypes.CallSite.TypeSpec, loc);
+
+ TypeExpression[] targs_for_instance = null;
+ TypeParameterMutator mutator;
+
+ var site_container = ec.CreateDynamicSite ();
+
+ if (context_mvars != null) {
+ TypeParameters tparam;
+ TypeContainer sc = site_container;
+ do {
+ tparam = sc.CurrentTypeParameters;
+ sc = sc.Parent;
+ } while (tparam == null);
+
+ mutator = new TypeParameterMutator (context_mvars, tparam);
+
+ if (!ec.IsAnonymousStoreyMutateRequired) {
+ targs_for_instance = new TypeExpression[targs.Length];
+ targs_for_instance[0] = targs[0];
+ }
+ } else {
+ mutator = null;
+ }
+
+ for (int i = 0; i < dyn_args_count; ++i) {
+ Argument a = arguments[i];
+ if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref)
+ has_ref_out_argument = true;
+
+ var t = a.Type;
+
+ // Convert any internal type like dynamic or null to object
+ if (t.Kind == MemberKind.InternalCompilerType)
+ t = ec.BuiltinTypes.Object;
+
+ if (targs_for_instance != null)
+ targs_for_instance[i + 1] = new TypeExpression (t, loc);
+
+ if (mutator != null)
+ t = t.Mutate (mutator);
+
+ targs[i + 1] = new TypeExpression (t, loc);
+ }
+
+ TypeExpr del_type = null;
+ TypeExpr del_type_instance_access = null;
+ if (!has_ref_out_argument) {
+ string d_name = isStatement ? "Action" : "Func";
+
+ TypeExpr te = null;
+ Namespace type_ns = module.GlobalRootNamespace.GetNamespace ("System", true);
+ if (type_ns != null) {
+ te = type_ns.LookupType (module, d_name, dyn_args_count + default_args, LookupMode.Normal, loc);
+ }
+
+ if (te != null) {
+ if (!isStatement) {
+ var t = type;
+ if (t.Kind == MemberKind.InternalCompilerType)
+ t = ec.BuiltinTypes.Object;
+
+ if (targs_for_instance != null)
+ targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression (t, loc);
+
+ if (mutator != null)
+ t = t.Mutate (mutator);
+
+ targs[targs.Length - 1] = new TypeExpression (t, loc);
+ }
+
+ del_type = new GenericTypeExpr (te.Type, new TypeArguments (targs), loc);
+ if (targs_for_instance != null)
+ del_type_instance_access = new GenericTypeExpr (te.Type, new TypeArguments (targs_for_instance), loc);
+ else
+ del_type_instance_access = del_type;
+ }
+ }
+
+ //
+ // Create custom delegate when no appropriate predefined delegate has been found
+ //
+ Delegate d;
+ if (del_type == null) {
+ TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type;
+ Parameter[] p = new Parameter[dyn_args_count + 1];
+ p[0] = new Parameter (targs[0], "p0", Parameter.Modifier.NONE, null, loc);
+
+ var site = ec.CreateDynamicSite ();
+ int index = site.Types == null ? 0 : site.Types.Count;
+
+ if (mutator != null)
+ rt = mutator.Mutate (rt);
+
+ for (int i = 1; i < dyn_args_count + 1; ++i) {
+ p[i] = new Parameter (targs[i], "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc);
+ }
+
+ d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc),
+ Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED,
+ new MemberName ("Container" + index.ToString ("X")),
+ new ParametersCompiled (p), null);
+
+ d.CreateType ();
+ d.DefineType ();
+ d.Define ();
+ d.Emit ();
+
+ site.AddDelegate (d);
+ del_type = new TypeExpression (d.CurrentType, loc);
+ if (targs_for_instance != null) {
+ del_type_instance_access = null;
+ } else {
+ del_type_instance_access = del_type;
+ }
+ } else {
+ d = null;
+ }
+
+ var site_type_decl = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc);
+ var field = site_container.CreateCallSiteField (site_type_decl, loc);
+ if (field == null)
+ return;
+
+ if (del_type_instance_access == null) {
+ var dt = d.CurrentType.DeclaringType.MakeGenericType (module, context_mvars.Types);
+ del_type_instance_access = new TypeExpression (MemberCache.GetMember (dt, d.CurrentType), loc);
+ }
+
+ var instanceAccessExprType = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec,
+ new TypeArguments (del_type_instance_access), loc);
+
+ if (instanceAccessExprType.ResolveAsType (ec.MemberContext) == null)
+ return;
+
+ bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired;
+
+ TypeSpec gt;
+ if (inflate_using_mvar || context_mvars == null) {
+ gt = site_container.CurrentType;
+ } else {
+ gt = site_container.CurrentType.MakeGenericType (module, context_mvars.Types);
+ }
+
+ // When site container already exists the inflated version has to be
+ // updated manually to contain newly created field
+ if (gt is InflatedTypeSpec && site_container.Fields.Count > 1) {
+ var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes;
+ var inflator = new TypeParameterInflator (module, gt, tparams, gt.TypeArguments);
+ gt.MemberCache.AddMember (field.InflateMember (inflator));
+ }
+
+ FieldExpr site_field_expr = new FieldExpr (MemberCache.GetMember (gt, field), loc);
+
+ BlockContext bc = new BlockContext (ec.MemberContext, null, ec.BuiltinTypes.Void);