Exemple #1
0
        public override Expression DoResolve(ResolveContext ec)
        {
            method = new AnonymousMethodMethod(Storey,
                                               this, Storey, null, TypeManager.system_boolean_expr,
                                               Modifiers.PUBLIC, OriginalMethod.GetSignatureForError(),
                                               new MemberName("MoveNext", Location),
                                               ParametersCompiled.EmptyReadOnlyParameters);

            if (!Compatible(ec))
            {
                return(null);
            }

            IteratorHost.DefineIteratorMembers();

            eclass = ExprClass.Value;
            return(this);
        }
Exemple #2
0
		public override void Emit (EmitContext ec)
		{
			//
			// Use same anonymous method implementation for scenarios where same
			// code is used from multiple blocks, e.g. field initializers
			//
			if (method == null) {
				//
				// Delay an anonymous method definition to avoid emitting unused code
				// for unreachable blocks or expression trees
				//
				method = DoCreateMethodHost (ec);
				method.Define ();
			}

			bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
			if (is_static && am_cache == null) {
				//
				// Creates a field cache to store delegate instance if it's not generic
				//
				if (!method.MemberName.IsGeneric) {
					var parent = method.Parent.PartialContainer;
					int id = parent.AnonymousMethodsCounter++;
					var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type;

					am_cache = new Field (parent, new TypeExpression (cache_type, loc),
						Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
						new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null);
					am_cache.Define ();
					parent.AddField (am_cache);
				} else {
					// TODO: Implement caching of generated generic static methods
					//
					// Idea:
					//
					// Some extra class is needed to capture variable generic type
					// arguments. Maybe we could re-use anonymous types, with a unique
					// anonymous method id, but they are quite heavy.
					//
					// Consider : "() => typeof(T);"
					//
					// We need something like
					// static class Wrap<Tn, Tm, DelegateType> {
					//		public static DelegateType cache;
					// }
					//
					// We then specialize local variable to capture all generic parameters
					// and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
					//
				}
			}

			Label l_initialized = ec.DefineLabel ();

			if (am_cache != null) {
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
				ec.Emit (OpCodes.Brtrue_S, l_initialized);
			}

			//
			// Load method delegate implementation
			//

			if (is_static) {
				ec.EmitNull ();
			} else if (storey != null) {
				Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
				if (e != null) {
					e.Emit (ec);
				}
			} else {
				ec.EmitThis ();

				//
				// Special case for value type storey where this is not lifted but
				// droped off to parent class
				//
				for (var b = Block.Parent; b != null; b = b.Parent) {
					if (b.ParametersBlock.StateMachine != null) {
						ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
						break;
					}
				}
			}

			var delegate_method = method.Spec;
			if (storey != null && storey.MemberName.IsGeneric) {
				TypeSpec t = storey.Instance.Type;

				//
				// Mutate anonymous method instance type if we are in nested
				// hoisted generic anonymous method storey
				//
				if (ec.IsAnonymousStoreyMutateRequired) {
					t = storey.Mutator.Mutate (t);
				}

				ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
			} else {
				if (delegate_method.IsGeneric)
					delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters);

				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			var constructor_method = Delegate.GetConstructor (type);
			ec.Emit (OpCodes.Newobj, constructor_method);

			if (am_cache != null) {
				ec.Emit (OpCodes.Stsfld, am_cache.Spec);
				ec.MarkLabel (l_initialized);
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
			}
		}
Exemple #3
0
        protected override Expression DoResolve(ResolveContext ec)
        {
            method = new AnonymousMethodMethod (Storey,
                this, Storey, null, TypeManager.system_boolean_expr,
                Modifiers.PUBLIC, OriginalMethod.GetSignatureForError (),
                new MemberName ("MoveNext", Location),
                ParametersCompiled.EmptyReadOnlyParameters);

            if (Compatible (ec) == null)
                return null;

            eclass = ExprClass.Value;
            return this;
        }
		public override void Emit (EmitContext ec)
		{
			//
			// Use same anonymous method implementation for scenarios where same
			// code is used from multiple blocks, e.g. field initializers
			//
			if (method == null) {
				//
				// Delay an anonymous method definition to avoid emitting unused code
				// for unreachable blocks or expression trees
				//
				method = DoCreateMethodHost (ec);
				method.Define ();
			}

			bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
			if (is_static && am_cache == null) {
				//
				// Creates a field cache to store delegate instance if it's not generic
				//
				if (!method.MemberName.IsGeneric) {
					TypeContainer parent = method.Parent.PartialContainer;
					int id = parent.Fields == null ? 0 : parent.Fields.Count;
					am_cache = new Field (parent, new TypeExpression (type, loc),
						Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
						new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null);
					am_cache.Define ();
					parent.AddField (am_cache);
				} else {
					// TODO: Implement caching of generated generic static methods
					//
					// Idea:
					//
					// Some extra class is needed to capture variable generic type
					// arguments. Maybe we could re-use anonymous types, with a unique
					// anonymous method id, but they are quite heavy.
					//
					// Consider : "() => typeof(T);"
					//
					// We need something like
					// static class Wrap<Tn, Tm, DelegateType> {
					//		public static DelegateType cache;
					// }
					//
					// We then specialize local variable to capture all generic parameters
					// and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
					//
				}
			}

			ILGenerator ig = ec.ig;
			Label l_initialized = ig.DefineLabel ();

			if (am_cache != null) {
				ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder);
				ig.Emit (OpCodes.Brtrue_S, l_initialized);
			}

			//
			// Load method delegate implementation
			//

			if (is_static) {
				ig.Emit (OpCodes.Ldnull);
			} else if (storey != null) {
				Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
				if (e != null)
					e.Emit (ec);
			} else {
				ig.Emit (OpCodes.Ldarg_0);
			}

			MethodInfo delegate_method = method.MethodBuilder;
			if (storey != null && storey.MemberName.IsGeneric) {
				Type t = storey.Instance.Type;
				
				//
				// Mutate anonymous method instance type if we are in nested
				// hoisted generic anonymous method storey
				//
				if (ec.CurrentAnonymousMethod != null &&
					ec.CurrentAnonymousMethod.Storey != null &&
					ec.CurrentAnonymousMethod.Storey.IsGeneric) {
					t = storey.GetGenericStorey ().MutateType (t);
				}

#if GMCS_SOURCE
				delegate_method = TypeBuilder.GetMethod (t, delegate_method);
#else
				throw new NotSupportedException ();
#endif
			}

			ig.Emit (OpCodes.Ldftn, delegate_method);

			ConstructorInfo constructor_method = Delegate.GetConstructor (RootContext.ToplevelTypes.Compiler, ec.CurrentType, type);
#if MS_COMPATIBLE
            if (type.IsGenericType && type is TypeBuilder)
                constructor_method = TypeBuilder.GetConstructor (type, constructor_method);
#endif
			ig.Emit (OpCodes.Newobj, constructor_method);

			if (am_cache != null) {
				ig.Emit (OpCodes.Stsfld, am_cache.FieldBuilder);
				ig.MarkLabel (l_initialized);
				ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder);
			}
		}
Exemple #5
0
		public override Expression DoResolve (EmitContext ec)
		{
			method = new AnonymousMethodMethod (Storey,
				this, Storey, null, TypeManager.system_boolean_expr,
				Modifiers.PUBLIC, OriginalMethod.GetSignatureForError (),
				new MemberName ("MoveNext", Location),
				Parameters.EmptyReadOnlyParameters);

			if (!Compatible (ec))
				return null;

			IteratorHost.DefineIteratorMembers ();

			eclass = ExprClass.Value;
			type = ec.ReturnType;
			return this;
		}