X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdynamic.cs;h=3524196957edf6668ed624c335d98063ce988d06;hb=28ff6bbe2eaf70dae544032628c7181bc495bca8;hp=0bb990e44af0d9ba9614479f7b82965315b80161;hpb=c4e1412b7a0f540fc43015ac9988a94638a0c0f2;p=mono.git diff --git a/mcs/mcs/dynamic.cs b/mcs/mcs/dynamic.cs index 0bb990e44af..3524196957e 100644 --- a/mcs/mcs/dynamic.cs +++ b/mcs/mcs/dynamic.cs @@ -6,10 +6,11 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2009 Novell, Inc +// Copyright 2011 Xamarin Inc. // using System; -using System.Reflection.Emit; +using System.Linq; using SLE = System.Linq.Expressions; #if NET_4_0 @@ -45,19 +46,13 @@ namespace Mono.CSharp public DynamicTypeExpr (Location loc) { this.loc = loc; - - type = InternalType.Dynamic; - eclass = ExprClass.Type; } - public override bool CheckAccessLevel (IMemberContext ds) + public override TypeSpec ResolveAsType (IMemberContext ec) { - return true; - } - - protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec) - { - return this; + eclass = ExprClass.Type; + type = ec.Module.Compiler.BuiltinTypes.Dynamic; + return type; } } @@ -101,9 +96,14 @@ namespace Mono.CSharp throw new NotImplementedException (); } + public override bool ContainsEmitWithAwait () + { + throw new NotSupportedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { - throw new NotImplementedException (); + throw new NotSupportedException (); } protected override Expression DoResolve (ResolveContext ec) @@ -128,7 +128,7 @@ namespace Mono.CSharp throw new NotImplementedException (); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { throw new NotImplementedException (); } @@ -142,7 +142,22 @@ namespace Mono.CSharp public override SLE.Expression MakeExpression (BuilderContext ctx) { - return SLE.Expression.Convert (obj.Expression, type.GetMetaInfo ()); +#if STATIC + return base.MakeExpression (ctx); +#else + + #if NET_4_0 + if (type.IsStruct && !obj.Expression.Type.IsValueType) + return SLE.Expression.Unbox (obj.Expression, type.GetMetaInfo ()); + + 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 ()); +#endif } } @@ -169,7 +184,11 @@ namespace Mono.CSharp #if NET_4_0 public override SLE.Expression MakeExpression (BuilderContext ctx) { +#if STATIC + return base.MakeExpression (ctx); +#else return SLE.Expression.Block (expr.MakeExpression (ctx), SLE.Expression.Default (type.GetMetaInfo ())); +#endif } #endif } @@ -198,16 +217,6 @@ namespace Mono.CSharp // class DynamicExpressionStatement : ExpressionStatement { - class StaticDataClass : CompilerGeneratedClass - { - public StaticDataClass () - : base (new RootDeclSpace (new NamespaceEntry (null, null, null)), - new MemberName (CompilerGeneratedClass.MakeName (null, "c", "DynamicSites", 0)), - Modifiers.INTERNAL | Modifiers.STATIC) - { - } - } - // // Binder flag dynamic constant, the value is combination of // flags known at resolve stage and flags known only at emit @@ -223,22 +232,19 @@ namespace Mono.CSharp { this.flags = flags; this.statement = statement; + eclass = 0; } protected override Expression DoResolve (ResolveContext ec) { - Child = new IntConstant ((int) (flags | statement.flags), statement.loc).Resolve (ec); + Child = new IntConstant (ec.BuiltinTypes, (int) (flags | statement.flags), statement.loc); - type = TypeManager.binder_flags; + type = ec.Module.PredefinedTypes.BinderFlags.Resolve (); eclass = Child.eclass; return this; } } - static StaticDataClass global_site_container; - static int field_counter; - static int container_counter; - readonly Arguments arguments; protected IDynamicBinder binder; protected Expression binder_expr; @@ -246,6 +252,9 @@ namespace Mono.CSharp // Used by BinderFlags protected CSharpBinderFlags flags; + TypeSpec binder_type; + TypeParameters context_mvars; + public DynamicExpressionStatement (IDynamicBinder binder, Arguments args, Location loc) { this.binder = binder; @@ -259,28 +268,9 @@ namespace Mono.CSharp } } - static TypeContainer CreateSiteContainer () + public override bool ContainsEmitWithAwait () { - if (global_site_container == null) { - global_site_container = new StaticDataClass (); - RootContext.ToplevelTypes.AddCompilerGeneratedClass (global_site_container); - global_site_container.CreateType (); - global_site_container.DefineType (); - global_site_container.Define (); - } - - return global_site_container; - } - - static Field CreateSiteField (FullNamedExpression type) - { - TypeContainer site_container = CreateSiteContainer (); - Field f = new Field (site_container, type, Modifiers.PUBLIC | Modifiers.STATIC, - new MemberName ("Site" + field_counter++), null); - f.Define (); - - site_container.AddField (f); - return f; + return arguments.ContainsEmitWithAwait (); } public override Expression CreateExpressionTree (ResolveContext ec) @@ -289,42 +279,30 @@ namespace Mono.CSharp return null; } - protected override Expression DoResolve (ResolveContext ec) + protected override Expression DoResolve (ResolveContext rc) { - if (DoResolveCore (ec)) - binder_expr = binder.CreateCallSiteBinder (ec, arguments); + if (DoResolveCore (rc)) + binder_expr = binder.CreateCallSiteBinder (rc, arguments); return this; } protected bool DoResolveCore (ResolveContext rc) { - int errors = rc.Report.Errors; + if (rc.CurrentTypeParameters != null && rc.CurrentTypeParameters[0].IsMethodTypeParameter) + context_mvars = rc.CurrentTypeParameters; - if (TypeManager.binder_type == null) { - var t = TypeManager.CoreLookupType (rc.Compiler, - "Microsoft.CSharp.RuntimeBinder", "Binder", MemberKind.Class, true); - if (t != null) - TypeManager.binder_type = new TypeExpression (t, Location.Null); - } - - if (TypeManager.call_site_type == null) - TypeManager.call_site_type = TypeManager.CoreLookupType (rc.Compiler, - "System.Runtime.CompilerServices", "CallSite", MemberKind.Class, true); - - if (TypeManager.generic_call_site_type == null) - TypeManager.generic_call_site_type = TypeManager.CoreLookupType (rc.Compiler, - "System.Runtime.CompilerServices", "CallSite", 1, MemberKind.Class, true); + int errors = rc.Report.Errors; + var pt = rc.Module.PredefinedTypes; - if (TypeManager.binder_flags == null) { - TypeManager.binder_flags = TypeManager.CoreLookupType (rc.Compiler, - "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags", MemberKind.Enum, true); - } + binder_type = pt.Binder.Resolve (); + pt.CallSite.Resolve (); + pt.CallSiteGeneric.Resolve (); eclass = ExprClass.Value; if (type == null) - type = InternalType.Dynamic; + type = rc.BuiltinTypes.Dynamic; if (rc.Report.Errors == errors) return true; @@ -346,17 +324,184 @@ namespace Mono.CSharp protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { + // + // This method generates all internal infrastructure for a dynamic call. The + // reason why it's quite complicated is the mixture of dynamic and anonymous + // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous + // methods can generate temporary storey as well (AnonStorey). Handling MVAR + // type parameters rewrite is non-trivial in such case as there are various + // combinations possible therefore the mutator is not straightforward. Secondly + // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit + // correct Site field type and its access from EmitContext. + // + int dyn_args_count = arguments == null ? 0 : arguments.Count; - TypeExpr site_type = CreateSiteType (RootContext.ToplevelTypes.Compiler, arguments, dyn_args_count, isStatement); - FieldExpr site_field_expr = new FieldExpr (CreateSiteField (site_type), loc); + int default_args = isStatement ? 1 : 2; + var module = ec.Module; + + 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); SymbolWriter.OpenCompilerGeneratedBlock (ec); Arguments args = new Arguments (1); args.Add (new Argument (binder)); - StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (site_type, "Create"), args))); + StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args))); - BlockContext bc = new BlockContext (ec.MemberContext, null, TypeManager.void_type); if (s.Resolve (bc)) { Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc), loc), s, loc); init.Emit (ec); @@ -365,14 +510,19 @@ namespace Mono.CSharp args = new Arguments (1 + dyn_args_count); args.Add (new Argument (site_field_expr)); if (arguments != null) { + int arg_pos = 1; foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add (new Argument (a.Expr, a.ArgType)); - continue; + } else { + args.Add (a); } - args.Add (a); + if (inflate_using_mvar && a.Type != targs[arg_pos].Type) + a.Expr.Type = targs[arg_pos].Type; + + ++arg_pos; } } @@ -389,113 +539,77 @@ namespace Mono.CSharp new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "Microsoft", loc), "CSharp", loc), "RuntimeBinder", loc); } - public static MemberAccess GetBinder (string name, Location loc) + protected MemberAccess GetBinder (string name, Location loc) { - return new MemberAccess (TypeManager.binder_type, name, loc); + return new MemberAccess (new TypeExpression (binder_type, loc), name, loc); } + } - TypeExpr CreateSiteType (CompilerContext ctx, Arguments arguments, int dyn_args_count, bool is_statement) + // + // Dynamic member access compound assignment for events + // + class DynamicEventCompoundAssign : ExpressionStatement + { + class IsEvent : DynamicExpressionStatement, IDynamicBinder { - int default_args = is_statement ? 1 : 2; - - bool has_ref_out_argument = false; - FullNamedExpression[] targs = new FullNamedExpression[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]; - if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) - has_ref_out_argument = true; + string name; - targs [i + 1] = new TypeExpression (a.Type, loc); - } - - TypeExpr del_type = null; - if (!has_ref_out_argument) { - string d_name = is_statement ? "Action" : "Func"; - - TypeSpec t = TypeManager.CoreLookupType (ctx, "System", d_name, dyn_args_count + default_args, MemberKind.Delegate, false); - if (t != null) { - if (!is_statement) - targs [targs.Length - 1] = new TypeExpression (type, loc); - - del_type = new GenericTypeExpr (t, new TypeArguments (targs), loc); - } + public IsEvent (string name, Arguments args, Location loc) + : base (null, args, loc) + { + this.name = name; + binder = this; } - // - // Create custom delegate when no appropriate predefined one is found - // - if (del_type == null) { - TypeSpec rt = is_statement ? TypeManager.void_type : type; - Parameter[] p = new Parameter [dyn_args_count + 1]; - p[0] = new Parameter (targs [0], "p0", Parameter.Modifier.NONE, null, loc); + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + type = ec.BuiltinTypes.Bool; - 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); + Arguments binder_args = new Arguments (3); - TypeContainer parent = CreateSiteContainer (); - Delegate d = new Delegate (parent.NamespaceEntry, parent, new TypeExpression (rt, loc), - Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, - new MemberName ("Container" + container_counter++.ToString ("X")), - new ParametersCompiled (ctx, p), null); + binder_args.Add (new Argument (new BinderFlags (0, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); - d.CreateType (); - d.DefineType (); - d.Define (); - d.Emit (); - - parent.AddDelegate (d); - del_type = new TypeExpression (d.Definition, loc); + return new Invocation (GetBinder ("IsEvent", loc), binder_args); } - - TypeExpr site_type = new GenericTypeExpr (TypeManager.generic_call_site_type, new TypeArguments (del_type), loc); - return site_type; } - public static void Reset () - { - global_site_container = null; - field_counter = container_counter = 0; - } - } - - // - // Dynamic member access compound assignment for events - // - class DynamicEventCompoundAssign : DynamicExpressionStatement, IDynamicBinder - { - string name; - Statement condition; + Expression condition; + ExpressionStatement invoke, assign; public DynamicEventCompoundAssign (string name, Arguments args, ExpressionStatement assignment, ExpressionStatement invoke, Location loc) - : base (null, args, loc) { - this.name = name; - base.binder = this; - - // Used by += or -= only - type = TypeManager.bool_type; - - condition = new If ( - new Binary (Binary.Operator.Equality, this, new BoolLiteral (true, loc), loc), - new StatementExpression (invoke), new StatementExpression (assignment), - loc); + condition = new IsEvent (name, args, loc); + this.invoke = invoke; + this.assign = assignment; + this.loc = loc; } - public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + public override Expression CreateExpressionTree (ResolveContext ec) { - Arguments binder_args = new Arguments (3); + return condition.CreateExpressionTree (ec); + } - 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))); + protected override Expression DoResolve (ResolveContext rc) + { + type = rc.BuiltinTypes.Dynamic; + eclass = ExprClass.Value; + condition = condition.Resolve (rc); + return this; + } - return new Invocation (GetBinder ("IsEvent", loc), binder_args); + 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); } } @@ -516,8 +630,8 @@ namespace Mono.CSharp flags |= ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; binder_args.Add (new Argument (new BinderFlags (flags, this))); - binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); - binder_args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + binder_args.Add (new Argument (new TypeOf (type, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); return new Invocation (GetBinder ("Convert", loc), binder_args); } } @@ -536,7 +650,7 @@ namespace Mono.CSharp Arguments binder_args = new Arguments (3); binder_args.Add (new Argument (new BinderFlags (0, this))); - binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (GetBinder ("InvokeConstructor", loc), binder_args); @@ -545,26 +659,73 @@ namespace Mono.CSharp class DynamicIndexBinder : DynamicMemberAssignable { + bool can_be_mutator; + public DynamicIndexBinder (Arguments args, Location loc) : base (args, loc) { } + public DynamicIndexBinder (CSharpBinderFlags flags, Arguments args, Location loc) + : this (args, loc) + { + base.flags = flags; + } + + protected override Expression DoResolve (ResolveContext ec) + { + can_be_mutator = true; + return base.DoResolve (ec); + } + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) { Arguments binder_args = new Arguments (3); - binder_args.Add (new Argument (new BinderFlags (0, this))); - binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args); } + + protected override Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + // + // Indexer has arguments which complicates things as the setter and getter + // are called in two steps when unary mutator is used. We have to make a + // copy of all variable arguments to not duplicate any side effect. + // + // ++d[++arg, Foo ()] + // + + if (!can_be_mutator) + return base.CreateSetterArguments (rc, rhs); + + var setter_args = new Arguments (Arguments.Count + 1); + for (int i = 0; i < Arguments.Count; ++i) { + var expr = Arguments[i].Expr; + + if (expr is Constant || expr is VariableReference || expr is This) { + setter_args.Add (Arguments [i]); + continue; + } + + LocalVariable temp = LocalVariable.CreateCompilerGenerated (expr.Type, rc.CurrentBlock, loc); + expr = new SimpleAssign (temp.CreateReferenceExpression (rc, expr.Location), expr).Resolve (rc); + Arguments[i].Expr = temp.CreateReferenceExpression (rc, expr.Location).Resolve (rc); + setter_args.Add (Arguments [i].Clone (expr)); + } + + setter_args.Add (new Argument (rhs)); + return setter_args; + } } class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder { - ATypeNameExpression member; + readonly ATypeNameExpression member; public DynamicInvocation (ATypeNameExpression member, Arguments args, Location loc) : base (null, args, loc) @@ -605,14 +766,14 @@ namespace Mono.CSharp binder_args.Add (new Argument (new BinderFlags (call_flags, this))); if (is_member_access) - binder_args.Add (new Argument (new StringLiteral (member.Name, member.Location))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, member.Name, member.Location))); if (member != null && member.HasTypeArguments) { TypeArguments ta = member.TypeArguments; if (ta.Resolve (ec)) { var targs = new ArrayInitializer (ta.Count, loc); foreach (TypeSpec t in ta.Arguments) - targs.Add (new TypeOf (new TypeExpression (t, loc), loc)); + targs.Add (new TypeOf (t, loc)); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (targs, loc))); } @@ -620,7 +781,7 @@ namespace Mono.CSharp binder_args.Add (new Argument (new NullLiteral (loc))); } - binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); Expression real_args; if (args == null) { @@ -654,15 +815,22 @@ namespace Mono.CSharp this.name = name; } + public DynamicMemberBinder (string name, CSharpBinderFlags flags, Arguments args, Location loc) + : this (name, args, loc) + { + base.flags = flags; + } + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) { Arguments binder_args = new Arguments (4); - 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))); + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args); } } @@ -691,17 +859,23 @@ namespace Mono.CSharp protected abstract Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet); + protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + var setter_args = new Arguments (Arguments.Count + 1); + setter_args.AddRange (Arguments); + setter_args.Add (new Argument (rhs)); + return setter_args; + } + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) { - if (right_side == EmptyExpression.OutAccess.Instance) { + if (right_side == EmptyExpression.OutAccess) { right_side.DoResolveLValue (rc, this); return null; } if (DoResolveCore (rc)) { - setter_args = new Arguments (Arguments.Count + 1); - setter_args.AddRange (Arguments); - setter_args.Add (new Argument (right_side)); + setter_args = CreateSetterArguments (rc, right_side); setter = CreateCallSiteBinder (rc, setter_args, true); } @@ -734,7 +908,7 @@ namespace Mono.CSharp throw new NotImplementedException (); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { EmitCall (ec, setter, setter_args, !leave_copy); } @@ -744,15 +918,23 @@ namespace Mono.CSharp class DynamicUnaryConversion : DynamicExpressionStatement, IDynamicBinder { - string name; + readonly string name; public DynamicUnaryConversion (string name, Arguments args, Location loc) : base (null, args, loc) { this.name = name; base.binder = this; - if (name == "IsTrue" || name == "IsFalse") - type = TypeManager.bool_type; + } + + public static DynamicUnaryConversion CreateIsTrue (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsTrue", args, loc) { type = rc.BuiltinTypes.Bool }; + } + + public static DynamicUnaryConversion CreateIsFalse (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsFalse", args, loc) { type = rc.BuiltinTypes.Bool }; } public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) @@ -766,10 +948,29 @@ namespace Mono.CSharp binder_args.Add (new Argument (new BinderFlags (flags, this))); binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc))); - binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (GetBinder ("UnaryOperation", loc), binder_args); } } + + sealed class DynamicSiteClass : HoistedStoreyClass + { + public DynamicSiteClass (TypeContainer parent, MemberBase host, TypeParameters tparams) + : base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC) + { + parent.DynamicSitesCounter++; + } + + 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); + return f.Spec; + } + } }