コード例 #1
0
        public override void InjectYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point)
        {
            // Store the new value into current
            var fe = new FieldExpr(((IteratorStorey)storey).CurrentField, loc);

            fe.InstanceExpression = new CompilerGeneratedThis(storey.CurrentType, loc);
            fe.EmitAssign(ec, expr, false, false);

            base.InjectYield(ec, expr, resume_pc, unwind_protect, resume_point);

            EmitLeave(ec, unwind_protect);

            ec.MarkLabel(resume_point);
        }
コード例 #2
0
ファイル: async.cs プロジェクト: xiaotie/NRefactory
        public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter)
        {
            var critical = Module.PredefinedTypes.ICriticalNotifyCompletion;

            if (!critical.Define())
            {
                throw new NotImplementedException();
            }

            var temp_critical  = new LocalTemporary(critical.TypeSpec);
            var label_critical = ec.DefineLabel();
            var label_end      = ec.DefineLabel();

            //
            // Special path for dynamic awaiters
            //
            // var awaiter = this.$awaiter as ICriticalNotifyCompletion;
            // if (awaiter == null) {
            //    var completion = (INotifyCompletion) this.$awaiter;
            //    this.$builder.AwaitOnCompleted (ref completion, ref this);
            // } else {
            //    this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this);
            // }
            //
            awaiter.Emit(ec);
            ec.Emit(OpCodes.Isinst, critical.TypeSpec);
            temp_critical.Store(ec);
            temp_critical.Emit(ec);
            ec.Emit(OpCodes.Brtrue_S, label_critical);

            var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec);

            awaiter.Emit(ec);
            ec.Emit(OpCodes.Castclass, temp.Type);
            temp.Store(ec);
            EmitOnCompleted(ec, temp, false);
            temp.Release(ec);
            ec.Emit(OpCodes.Br_S, label_end);

            ec.MarkLabel(label_critical);

            EmitOnCompleted(ec, temp_critical, true);

            ec.MarkLabel(label_end);

            temp_critical.Release(ec);
        }
コード例 #3
0
        public static Expression AddFiled(string fieldAlias, string tableAlias, string schema, Lexem lexem, ExpressionParser parser)
        {
            if (fieldAlias == "*")
            {
                if (schema != null)
                {
                    parser.Collection.Error("Can not use schema in * expression", lexem);
                }
                AllColumnExpr a = new AllColumnExpr();
                a.Prefix = tableAlias;
                return(a);
            }
            FieldExpr res = new FieldExpr();

            res.FieldName  = fieldAlias;
            res.TableAlias = tableAlias;
            res.Schema     = schema;
            res.Lexem      = lexem;
            return(res);
        }
コード例 #4
0
ファイル: async.cs プロジェクト: xiaotie/NRefactory
        public Expression GetResultExpression(EmitContext ec)
        {
            var fe_awaiter = new FieldExpr(awaiter, loc);

            fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc);

            //
            // result = awaiter.GetResult ();
            //
            if (IsDynamic)
            {
                var rc = new ResolveContext(ec.MemberContext);
                return(new Invocation(new MemberAccess(fe_awaiter, "GetResult"), new Arguments(0)).Resolve(rc));
            }

            var mg_result = MethodGroupExpr.CreatePredefined(awaiter_definition.GetResult, fe_awaiter.Type, loc);

            mg_result.InstanceExpression = fe_awaiter;

            return(new GetResultInvocation(mg_result, new Arguments(0)));
        }
コード例 #5
0
ファイル: async.cs プロジェクト: xiaotie/NRefactory
 public void EmitAssign(EmitContext ec, FieldExpr field)
 {
     stmt.EmitPrologue(ec);
     field.InstanceExpression.Emit(ec);
     stmt.Emit(ec);
 }
コード例 #6
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
		//
		// Creates field access expression for hoisted variable
		//
		protected virtual FieldExpr GetFieldExpression (EmitContext ec)
		{
			if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) {
				if (cached_outer_access != null)
					return cached_outer_access;

				//
				// When setting top-level hoisted variable in generic storey
				// change storey generic types to method generic types (VAR -> MVAR)
				//
				if (storey.Instance.Type.IsGenericOrParentIsGeneric) {
					var fs = MemberCache.GetMember (storey.Instance.Type, field.Spec);
					cached_outer_access = new FieldExpr (fs, field.Location);
				} else {
					cached_outer_access = new FieldExpr (field, field.Location);
				}

				cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
				return cached_outer_access;
			}

			FieldExpr inner_access;
			if (cached_inner_access != null) {
				if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access))
					inner_access = null;
			} else {
				inner_access = null;
				cached_inner_access = new Dictionary<AnonymousExpression, FieldExpr> (4);
			}

			if (inner_access == null) {
				if (field.Parent.IsGenericOrParentIsGeneric) {
					var fs = MemberCache.GetMember (field.Parent.CurrentType, field.Spec);
					inner_access = new FieldExpr (fs, field.Location);
				} else {
					inner_access = new FieldExpr (field, field.Location);
				}

				inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
				cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access);
			}

			return inner_access;
		}
コード例 #7
0
        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;
            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.Containers == null ? 0 : site.Containers.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, new TypeExpression(rt, loc),
                                 Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED,
                                 new MemberName("Container" + index.ToString("X")),
                                 new ParametersCompiled(p), null);

                d.CreateContainer();
                d.DefineContainer();
                d.Define();

                site.AddTypeContainer(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.AnonymousMethodsCounter > 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);

            Arguments args = new Arguments(1);

            args.Add(new Argument(binder));
            StatementExpression s = new StatementExpression(new SimpleAssign(site_field_expr, new Invocation(new MemberAccess(instanceAccessExprType, "Create"), args)));

            using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) {
                if (s.Resolve(bc))
                {
                    Statement init = new If(new Binary(Binary.Operator.Equality, site_field_expr, new NullLiteral(loc)), s, loc);
                    init.Emit(ec);
                }

                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));
                        }
                        else
                        {
                            args.Add(a);
                        }

                        if (inflate_using_mvar && a.Type != targs[arg_pos].Type)
                        {
                            a.Expr.Type = targs[arg_pos].Type;
                        }

                        ++arg_pos;
                    }
                }

                Expression target = new DelegateInvocation(new MemberAccess(site_field_expr, "Target", loc).Resolve(bc), args, loc).Resolve(bc);
                if (target != null)
                {
                    target.Emit(ec);
                }
            }
        }
コード例 #8
0
		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;
			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.Containers == null ? 0 : site.Containers.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, new TypeExpression (rt, loc),
					Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED,
					new MemberName ("Container" + index.ToString ("X")),
					new ParametersCompiled (p), null);

				d.CreateContainer ();
				d.DefineContainer ();
				d.Define ();

				site.AddTypeContainer (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.AnonymousMethodsCounter > 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);

			Arguments args = new Arguments (1);
			args.Add (new Argument (binder));
			StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args)));

			using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
				if (s.Resolve (bc)) {
					Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc)), s, loc);
					init.Emit (ec);
				}

				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));
						} else {
							args.Add (a);
						}

						if (inflate_using_mvar && a.Type != targs[arg_pos].Type)
							a.Expr.Type = targs[arg_pos].Type;

						++arg_pos;
					}
				}

				Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc);
				if (target != null)
					target.Emit (ec);
			}
		}
コード例 #9
0
ファイル: property.cs プロジェクト: furesoft/NRefactory
		void CreateAutomaticProperty ()
		{
			// Create backing field
			BackingField = new BackingFieldDeclaration (this, Initializer == null && Set == null);
			if (!BackingField.Define ())
				return;

			if (Initializer != null) {
				BackingField.Initializer = Initializer;
				Parent.RegisterFieldForInitialization (BackingField, new FieldInitializer (BackingField, Initializer, Location));
				BackingField.ModFlags |= Modifiers.READONLY;
			}

			Parent.PartialContainer.Members.Add (BackingField);

			FieldExpr fe = new FieldExpr (BackingField, Location);
			if ((BackingField.ModFlags & Modifiers.STATIC) == 0)
				fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);

			//
			// Create get block but we careful with location to
			// emit only single sequence point per accessor. This allow
			// to set a breakpoint on it even with no user code
			//
			Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
			Return r = new Return (fe, Get.Location);
			Get.Block.AddStatement (r);
			Get.ModFlags |= Modifiers.COMPILER_GENERATED;

			// Create set block
			if (Set != null) {
				Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
				Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
				Set.Block.AddStatement (new StatementExpression (a, Set.Location));
				Set.ModFlags |= Modifiers.COMPILER_GENERATED;
			}
		}
コード例 #10
0
ファイル: assign.cs プロジェクト: wskjava/SharpDevelop
 protected override Expression DoResolve(ResolveContext rc)
 {
     target = new FieldExpr(field, loc);
     source = rc.CurrentBlock.ParametersBlock.GetParameterInfo(parameter).CreateReferenceExpression(rc, loc);
     return(base.DoResolve(rc));
 }
コード例 #11
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
			protected override void DoEmit (EmitContext ec)
			{
				Expression source;

				if (parent == null)
					source = new CompilerGeneratedThis (ec.CurrentType, loc);
				else {
					source = new FieldExpr (parent.HoistedThis.Field, Location.Null) {
						InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null)
					};
				}

				hoisted_this.EmitAssign (ec, source, false, false);
			}
コード例 #12
0
			void FabricateBodyStatement ()
			{
				//
				// Delegate obj1 = backing_field
				// do {
				//   Delegate obj2 = obj1;
				//   obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
				// } while ((object)obj1 != (object)obj2)
				//

				var field_info = ((EventField) method).backing_field;
				FieldExpr f_expr = new FieldExpr (field_info, Location);
				if (!IsStatic)
					f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);

				var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
				var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);

				block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));

				var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
					new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
					new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location)));

				var body = new ExplicitBlock (block, Location, Location);
				block.AddStatement (new Do (body, cond, Location, Location));

				body.AddStatement (new StatementExpression (
					new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));

				var args_oper = new Arguments (2);
				args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
				args_oper.Add (new Argument (block.GetParameterReference (0, Location)));

				var op_method = GetOperation (Location);

				var args = new Arguments (3);
				args.Add (new Argument (f_expr, Argument.AType.Ref));
				args.Add (new Argument (new Cast (
					new TypeExpression (field_info.MemberType, Location),
					new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
					Location)));
				args.Add (new Argument (new LocalVariableReference (obj1, Location)));

				var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
				if (cas == null)
					return;

				body.AddStatement (new StatementExpression (new SimpleAssign (
					new LocalVariableReference (obj1, Location),
					new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
			}
コード例 #13
0
ファイル: async.cs プロジェクト: xiaotie/NRefactory
        public void EmitPrologue(EmitContext ec)
        {
            awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type);

            var fe_awaiter = new FieldExpr(awaiter, loc);

            fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc);

            Label skip_continuation = ec.DefineLabel();

            using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) {
                //
                // awaiter = expr.GetAwaiter ();
                //
                fe_awaiter.EmitAssign(ec, expr, false, false);

                Expression completed_expr;
                if (IsDynamic)
                {
                    var rc = new ResolveContext(ec.MemberContext);

                    Arguments dargs = new Arguments(1);
                    dargs.Add(new Argument(fe_awaiter));
                    completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc);

                    dargs = new Arguments(1);
                    dargs.Add(new Argument(completed_expr));
                    completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc);
                }
                else
                {
                    var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc);
                    pe.InstanceExpression = fe_awaiter;
                    completed_expr        = pe;
                }

                completed_expr.EmitBranchable(ec, skip_continuation, true);
            }

            base.DoEmit(ec);

            //
            // The stack has to be empty before calling await continuation. We handle this
            // by lifting values which would be left on stack into class fields. The process
            // is quite complicated and quite hard to test because any expression can possibly
            // leave a value on the stack.
            //
            // Following assert fails when some of expression called before is missing EmitToField
            // or parent expression fails to find await in children expressions
            //
            ec.AssertEmptyStack();

            var storey = (AsyncTaskStorey)machine_initializer.Storey;

            if (IsDynamic)
            {
                storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter);
            }
            else
            {
                storey.EmitAwaitOnCompleted(ec, fe_awaiter);
            }

            // Return ok
            machine_initializer.EmitLeave(ec, unwind_protect);

            ec.MarkLabel(resume_point);
            ec.MarkLabel(skip_continuation);
        }
コード例 #14
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
		//
		// Creates storey instance expression regardless of currect IP
		//
		public Expression GetStoreyInstanceExpression (EmitContext ec)
		{
			AnonymousExpression am = ec.CurrentAnonymousMethod;

			//
			// Access from original block -> storey
			//
			if (am == null)
				return Instance;

			//
			// Access from anonymous method implemented as a static -> storey
			//
			if (am.Storey == null)
				return Instance;

			Field f = am.Storey.GetReferencedStoreyField (this);
			if (f == null) {
				if (am.Storey == this) {
					//
					// Access from inside of same storey (S -> S)
					//
					return new CompilerGeneratedThis (CurrentType, Location);
				}

				//
				// External field access
				//
				return Instance;
			}

			//
			// Storey was cached to local field
			//
			FieldExpr f_ind = new FieldExpr (f, Location);
			f_ind.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
			return f_ind;
		}
コード例 #15
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
		protected virtual void EmitHoistedParameters (EmitContext ec, List<HoistedParameter> hoisted)
		{
			foreach (HoistedParameter hp in hoisted) {
				if (hp == null)
					continue;

				//
				// Parameters could be proxied via local fields for value type storey
				//
				if (hoisted_local_params != null) {
					var local_param = hoisted_local_params.Find (l => l.Parameter.Parameter == hp.Parameter.Parameter);
					var source = new FieldExpr (local_param.Field, Location);
					source.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
					hp.EmitAssign (ec, source, false, false);
					continue;
				}

				hp.EmitHoistingAssignment (ec);
			}
		}
コード例 #16
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
		void EmitHoistedFieldsInitialization (ResolveContext rc, EmitContext ec)
		{
			//
			// Initialize all storey reference fields by using local or hoisted variables
			//
			if (used_parent_storeys != null) {
				foreach (StoreyFieldPair sf in used_parent_storeys) {
					//
					// Get instance expression of storey field
					//
					Expression instace_expr = GetStoreyInstanceExpression (ec);
					var fs = sf.Field.Spec;
					if (TypeManager.IsGenericType (instace_expr.Type))
						fs = MemberCache.GetMember (instace_expr.Type, fs);

					FieldExpr f_set_expr = new FieldExpr (fs, Location);
					f_set_expr.InstanceExpression = instace_expr;

					// TODO: CompilerAssign expression
					SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec));
					if (a.Resolve (rc) != null)
						a.EmitStatement (ec);
				}
			}

			//
			// Initialize hoisted `this' only once, everywhere else will be
			// referenced indirectly
			//
			if (initialize_hoisted_this) {
				rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent));
			}

			//
			// Setting currect anonymous method to null blocks any further variable hoisting
			//
			AnonymousExpression ae = ec.CurrentAnonymousMethod;
			ec.CurrentAnonymousMethod = null;

			if (hoisted_params != null) {
				EmitHoistedParameters (ec, hoisted_params);
			}

			ec.CurrentAnonymousMethod = ae;
		}
コード例 #17
0
ファイル: anonymous.cs プロジェクト: furesoft/NRefactory
		//
		// Initializes all hoisted variables
		//
		public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block)
		{
			// There can be only one instance variable for each storey type
			if (Instance != null)
				throw new InternalErrorException ();

			//
			// Create an instance of this storey
			//
			ResolveContext rc = new ResolveContext (ec.MemberContext);
			rc.CurrentBlock = block;

			var storey_type_expr = CreateStoreyTypeExpression (ec);
			var source = new New (storey_type_expr, null, Location).Resolve (rc);

			//
			// When the current context is async (or iterator) lift local storey
			// instantiation to the currect storey
			//
			if (ec.CurrentAnonymousMethod is StateMachineInitializer && (block.HasYield || block.HasAwait)) {
				//
				// Unfortunately, normal capture mechanism could not be used because we are
				// too late in the pipeline and standart assign cannot be used either due to
				// recursive nature of GetStoreyInstanceExpression
				//
				var field = ec.CurrentAnonymousMethod.Storey.AddCompilerGeneratedField (
					LocalVariable.GetCompilerGeneratedName (block), storey_type_expr, true);

				field.Define ();
				field.Emit ();

				var fexpr = new FieldExpr (field, Location);
				fexpr.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location);
				fexpr.EmitAssign (ec, source, false, false);
				Instance = fexpr;
			} else {
				var local = TemporaryVariableReference.Create (source.Type, block, Location);
				if (source.Type.IsStruct) {
					local.LocalInfo.CreateBuilder (ec);
				} else {
					local.EmitAssign (ec, source);
				}

				Instance = local;
			}

			EmitHoistedFieldsInitialization (rc, ec);

			// TODO: Implement properly
			//SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
		}
コード例 #18
0
		void CreateAutomaticProperty ()
		{
			// Create backing field
			Field field = new BackingField (this);
			if (!field.Define ())
				return;

			Parent.PartialContainer.Members.Add (field);

			FieldExpr fe = new FieldExpr (field, Location);
			if ((field.ModFlags & Modifiers.STATIC) == 0)
				fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);

			//
			// Create get block but we careful with location to
			// emit only single sequence point per accessor. This allow
			// to set a breakpoint on it even with no user code
			//
			Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
			Return r = new Return (fe, Get.Location);
			Get.Block.AddStatement (r);

			// Create set block
			Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
			Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
			Set.Block.AddStatement (new StatementExpression (a, Set.Location));
		}
コード例 #19
0
ファイル: assign.cs プロジェクト: furesoft/NRefactory
		protected override Expression DoResolve (ResolveContext rc)
		{
			target = new FieldExpr (field, loc);
			source = rc.CurrentBlock.ParametersBlock.GetParameterInfo (parameter).CreateReferenceExpression (rc, loc);
			return base.DoResolve (rc);
		}