//
using System;
+using System.Linq;
using SLE = System.Linq.Expressions;
#if NET_4_0
#if NET_4_0
if (type.IsStruct && !obj.Expression.Type.IsValueType)
return SLE.Expression.Unbox (obj.Expression, type.GetMetaInfo ());
-#endif
if (obj.Expression.NodeType == SLE.ExpressionType.Parameter) {
if (((SLE.ParameterExpression) obj.Expression).IsByRef)
return obj.Expression;
}
+#endif
return SLE.Expression.Convert (obj.Expression, type.GetMetaInfo ());
}
}
}
- Field CreateSiteField (EmitContext ec, FullNamedExpression type)
+ FieldSpec CreateSiteField (EmitContext ec, FullNamedExpression type)
{
- var tc = ec.CurrentTypeDefinition.Parent.PartialContainer;
- TypeContainer site_container = tc.CreateDynamicSite ();
-
- int index = site_container.Fields == null ? 0 : site_container.Fields.Count;
- Field f = new Field (site_container, type, Modifiers.PUBLIC | Modifiers.STATIC,
- new MemberName ("Site" + index.ToString ("X"), loc), null);
- f.Define ();
-
- site_container.AddField (f);
- return f;
+ var site_container = ec.CreateDynamicSite ();
+ return site_container.CreateCallSiteField (type, loc);
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
int dyn_args_count = arguments == null ? 0 : arguments.Count;
TypeExpr site_type = CreateSiteType (ec, arguments, dyn_args_count, isStatement);
+
FieldExpr site_field_expr = new FieldExpr (CreateSiteField (ec, site_type), loc);
SymbolWriter.OpenCompilerGeneratedBlock (ec);
int default_args = is_statement ? 1 : 2;
bool has_ref_out_argument = false;
- FullNamedExpression[] targs = new FullNamedExpression[dyn_args_count + default_args];
+ var targs = new TypeExpression[dyn_args_count + default_args];
targs [0] = new TypeExpression (TypeManager.call_site_type, loc);
for (int i = 0; i < dyn_args_count; ++i) {
Argument a = arguments [i];
Parameter[] p = new Parameter [dyn_args_count + 1];
p[0] = new Parameter (targs [0], "p0", Parameter.Modifier.NONE, null, loc);
- 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);
-
- TypeContainer site = ec.CurrentTypeDefinition.Parent.PartialContainer.CreateDynamicSite ();
+ var site = ec.CreateDynamicSite ();
int index = site.Types == null ? 0 : site.Types.Count;
+ if (site.Mutator != null)
+ rt = site.Mutator.Mutate (rt);
+
+ for (int i = 1; i < dyn_args_count + 1; ++i) {
+ var t = targs[i];
+ if (site.Mutator != null)
+ t.Type = site.Mutator.Mutate (t.Type);
+
+ p[i] = new Parameter (t, "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc);
+ }
+
Delegate d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc),
Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED,
new MemberName ("Container" + index.ToString ("X")),
- new ParametersCompiled (null, p), null);
+ new ParametersCompiled (p), null);
d.CreateType ();
d.DefineType ();
d.Define ();
d.Emit ();
- site.AddDelegate (d);
- del_type = new TypeExpression (d.Definition, loc);
+ var inflated = site.AddDelegate (d);
+ del_type = new TypeExpression (inflated, loc);
}
TypeExpr site_type = new GenericTypeExpr (TypeManager.generic_call_site_type, new TypeArguments (del_type), loc);
//
// Dynamic member access compound assignment for events
//
- class DynamicEventCompoundAssign : DynamicExpressionStatement, IDynamicBinder
+ class DynamicEventCompoundAssign : ExpressionStatement
{
- string name;
- Statement condition;
-
- public DynamicEventCompoundAssign (string name, Arguments args, ExpressionStatement assignment, ExpressionStatement invoke, Location loc)
- : base (null, args, loc)
+ class IsEvent : DynamicExpressionStatement, IDynamicBinder
{
- this.name = name;
- base.binder = this;
+ string name;
- // Used by += or -= only
- type = TypeManager.bool_type;
+ public IsEvent (string name, Arguments args, Location loc)
+ : base (null, args, loc)
+ {
+ this.name = name;
+ binder = this;
+ }
- condition = new If (
- new Binary (Binary.Operator.Equality, this, new BoolLiteral (true, loc), loc),
- new StatementExpression (invoke), new StatementExpression (assignment),
- loc);
+ public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
+ {
+ type = TypeManager.bool_type;
+
+ Arguments binder_args = new Arguments (3);
+
+ binder_args.Add (new Argument (new BinderFlags (0, this)));
+ binder_args.Add (new Argument (new StringLiteral (name, loc)));
+ binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
+
+ return new Invocation (GetBinder ("IsEvent", loc), binder_args);
+ }
}
- public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
+ Expression condition;
+ ExpressionStatement invoke, assign;
+
+ public DynamicEventCompoundAssign (string name, Arguments args, ExpressionStatement assignment, ExpressionStatement invoke, Location loc)
{
- Arguments binder_args = new Arguments (3);
+ condition = new IsEvent (name, args, loc);
+ this.invoke = invoke;
+ this.assign = assignment;
+ this.loc = loc;
+ }
- binder_args.Add (new Argument (new BinderFlags (0, this)));
- binder_args.Add (new Argument (new StringLiteral (name, loc)));
- binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc)));
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ return condition.CreateExpressionTree (ec);
+ }
- return new Invocation (GetBinder ("IsEvent", loc), binder_args);
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ type = InternalType.Dynamic;
+ eclass = ExprClass.Value;
+ condition = condition.Resolve (rc);
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ var rc = new ResolveContext (ec.MemberContext);
+ var expr = new Conditional (new BooleanExpression (condition), invoke, assign, loc).Resolve (rc);
+ expr.Emit (ec);
}
public override void EmitStatement (EmitContext ec)
{
- condition.Emit (ec);
+ var stmt = new If (condition, new StatementExpression (invoke), new StatementExpression (assign), loc);
+ stmt.Emit (ec);
}
}
return new Invocation (GetBinder ("UnaryOperation", loc), binder_args);
}
}
+
+ public class DynamicSiteClass : HoistedStoreyClass
+ {
+ //
+ // Holds the type to access the site. It gets inflated
+ // by MVARs for generic call sites
+ //
+ TypeSpec instance_type;
+
+ public DynamicSiteClass (TypeContainer parent, MemberBase host, TypeParameter[] tparams)
+ : base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC)
+ {
+ if (tparams != null) {
+ mutator = new TypeParameterMutator (tparams, CurrentTypeParameters);
+ }
+
+ parent.DynamicSitesCounter++;
+ }
+
+ public override TypeSpec AddDelegate (Delegate d)
+ {
+ TypeSpec inflated;
+
+ base.AddDelegate (d);
+
+ // Inflated type instance has to be updated manually
+ if (instance_type is InflatedTypeSpec) {
+ var inflator = new TypeParameterInflator (instance_type, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes);
+ inflated = (TypeSpec) d.CurrentType.InflateMember (inflator);
+ instance_type.MemberCache.AddMember (inflated);
+
+ //inflator = new TypeParameterInflator (d.Parent.CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes);
+ //d.Parent.CurrentType.MemberCache.AddMember (d.CurrentType.InflateMember (inflator));
+ } else {
+ inflated = d.CurrentType;
+ }
+
+ return inflated;
+ }
+
+ public FieldSpec CreateCallSiteField (FullNamedExpression type, Location loc)
+ {
+ int index = fields == null ? 0 : fields.Count;
+ Field f = new HoistedField (this, type, Modifiers.PUBLIC | Modifiers.STATIC, "Site" + index.ToString ("X"), null, loc);
+ f.Define ();
+
+ AddField (f);
+
+ var fs = f.Spec;
+ if (mutator != null) {
+ //
+ // Inflate the field, no need to keep it in MemberCache as it's accessed only once
+ //
+ var inflator = new TypeParameterInflator (instance_type, spec.MemberDefinition.TypeParameters, instance_type.TypeArguments);
+ fs = (FieldSpec) fs.InflateMember (inflator);
+ }
+
+ return fs;
+ }
+
+ protected override bool DoResolveTypeParameters ()
+ {
+ instance_type = spec;
+ if (mutator != null)
+ instance_type = instance_type.MakeGenericType (mutator.MethodTypeParameters.Select (l => l.Type).ToArray ());
+
+ return true;
+ }
+ }
}