Exemplo n.º 1
0
		public HoistedLocalVariable (AnonymousMethodStorey storey, LocalVariable local, string name)
			: base (storey, name, local.Type)
		{
		}
Exemplo n.º 2
0
		public HoistedThis (AnonymousMethodStorey storey, Field field)
			: base (storey, field)
		{
		}
Exemplo n.º 3
0
		protected HoistedVariable (AnonymousMethodStorey storey, Field field)
		{
			this.storey = storey;
			this.field = field;
		}
Exemplo n.º 4
0
		public HoistedParameter (AnonymousMethodStorey scope, ParameterReference par)
			: base (scope, par.Name, par.Type)
		{
			this.parameter = par;
		}
Exemplo n.º 5
0
		//
		// Returns a field which holds referenced storey instance
		//
		Field GetReferencedStoreyField (AnonymousMethodStorey storey)
		{
			if (used_parent_storeys == null)
				return null;

			foreach (StoreyFieldPair sf in used_parent_storeys) {
				if (sf.Storey == storey)
					return sf.Field;
			}

			return null;
		}
Exemplo n.º 6
0
		protected HoistedVariable (AnonymousMethodStorey storey, string name, TypeSpec type)
			: this (storey, storey.AddCapturedVariable (name, type))
		{
		}
Exemplo n.º 7
0
		public void AddParentStoreyReference (EmitContext ec, AnonymousMethodStorey storey)
		{
			CheckMembersDefined ();

			if (used_parent_storeys == null)
				used_parent_storeys = new List<StoreyFieldPair> ();
			else if (used_parent_storeys.Exists (i => i.Storey == storey))
				return;

			TypeExpr type_expr = storey.CreateStoreyTypeExpression (ec);
			Field f = AddCompilerGeneratedField ("<>f__ref$" + storey.ID, type_expr);
			used_parent_storeys.Add (new StoreyFieldPair (storey, f));
		}
Exemplo n.º 8
0
		public void SetNestedStoryParent (AnonymousMethodStorey parentStorey)
		{
			Parent = parentStorey;
			spec.IsGeneric = false;
			spec.DeclaringType = parentStorey.CurrentType;
			MemberName.TypeParameters = null;
		}
Exemplo n.º 9
0
		public void AddCapturedThisField (EmitContext ec, AnonymousMethodStorey parent)
		{
			TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
			Field f = AddCompilerGeneratedField ("$this", type_expr);
			hoisted_this = new HoistedThis (this, f);

			initialize_hoisted_this = true;
			hoisted_this_parent = parent;
		}
Exemplo n.º 10
0
			public ThisInitializer (HoistedThis hoisted_this, AnonymousMethodStorey parent)
			{
				this.hoisted_this = hoisted_this;
				this.parent = parent;
			}
Exemplo n.º 11
0
			public StoreyFieldPair (AnonymousMethodStorey storey, Field field)
			{
				this.Storey = storey;
				this.Field = field;
			}
Exemplo n.º 12
0
		//
		// Creates a host for the anonymous method
		//
		AnonymousMethodMethod DoCreateMethodHost (EmitContext ec)
		{
			//
			// Anonymous method body can be converted to
			//
			// 1, an instance method in current scope when only `this' is hoisted
			// 2, a static method in current scope when neither `this' nor any variable is hoisted
			// 3, an instance method in compiler generated storey when any hoisted variable exists
			//

			Modifiers modifiers;
			TypeDefinition parent = null;
			TypeParameters hoisted_tparams = null;
			ParametersCompiled method_parameters = parameters;

			var src_block = Block.Original.Explicit;
			if (src_block.HasCapturedVariable || src_block.HasCapturedThis) {
				parent = storey = FindBestMethodStorey ();

				if (storey == null) {
					var top_block = src_block.ParametersBlock.TopBlock;
					var sm = top_block.StateMachine;

					if (src_block.HasCapturedThis) {
						//
						// Remove hoisted 'this' request when simple instance method is
						// enough. No hoisted variables only 'this' and don't need to
						// propagate this to value type state machine.
						//
						StateMachine sm_parent;
						var pb = src_block.ParametersBlock;
						do {
							sm_parent = pb.StateMachine;
							pb = pb.Parent == null ? null : pb.Parent.ParametersBlock;
						} while (sm_parent == null && pb != null);

						if (sm_parent == null) {
							top_block.RemoveThisReferenceFromChildrenBlock (src_block);
						} else if (sm_parent.Kind == MemberKind.Struct) {
							//
							// Special case where parent class is used to emit instance method
							// because currect storey is of value type (async host) and we cannot
							// use ldftn on non-boxed instances either to share mutated state
							//
							parent = sm_parent.Parent.PartialContainer;
							hoisted_tparams = sm_parent.OriginalTypeParameters;
						} else if (sm is IteratorStorey) {
							//
							// For iterators we can host everything in one class
							//
							parent = storey = sm;
						}
					}
				}

				modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
			} else {
				if (ec.CurrentAnonymousMethod != null)
					parent = storey = ec.CurrentAnonymousMethod.Storey;

				modifiers = Modifiers.STATIC | Modifiers.PRIVATE;

				//
				// Convert generated method to closed delegate method where unused
				// this argument is generated during compilation which speeds up dispatch
				// by about 25%
				//
				// Unused as it breaks compatibility
				//
				// method_parameters = ParametersCompiled.Prefix (method_parameters,
				//	new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object);
			}

			if (storey == null && hoisted_tparams == null)
				hoisted_tparams = ec.CurrentTypeParameters;

			if (parent == null)
				parent = ec.CurrentTypeDefinition.Parent.PartialContainer;

			string name = CompilerGeneratedContainer.MakeName (parent != storey ? block_name : null,
				"m", null, parent.PartialContainer.CounterAnonymousMethods++);

			MemberName member_name;
			if (hoisted_tparams != null) {
				var type_params = new TypeParameters (hoisted_tparams.Count);
				for (int i = 0; i < hoisted_tparams.Count; ++i) {
				    type_params.Add (hoisted_tparams[i].CreateHoistedCopy (null));
				}

				member_name = new MemberName (name, type_params, Location);
			} else {
				member_name = new MemberName (name, Location);
			}

			return new AnonymousMethodMethod (parent,
				this, storey, new TypeExpression (ReturnType, Location), modifiers,
				member_name, method_parameters);
		}
Exemplo n.º 13
0
			public AnonymousMethodMethod (TypeDefinition parent, AnonymousExpression am, AnonymousMethodStorey storey,
							  TypeExpr return_type,
							  Modifiers mod, MemberName name,
							  ParametersCompiled parameters)
				: base (parent, return_type, mod | Modifiers.COMPILER_GENERATED,
						name, parameters, null)
			{
				this.AnonymousMethod = am;
				this.Storey = storey;

				Parent.PartialContainer.Members.Add (this);
				Block = new ToplevelBlock (am.block, parameters);
			}