예제 #1
0
            /// <summary>
            /// Creates a new nest with the given parent.
            /// </summary>
            /// <param name="parent">The parent nest.</param>
            /// <param name="gen">The generator used to generate code for this function.</param>
            /// <param name="storeParent">
            /// True to create a field that stores the parent instance; otherwise false.
            /// </param>
            /// <param name="captures">
            /// The local variables that have been captured by nested functions.
            /// </param>
            /// <param name="createType">True to create a nested type, otherwise false.</param>
            public NestInfo(NestInfo parent, ILGenerator gen, NameItem[] captures, bool createType,
                            bool storeParent)
            {
                FreeLocals = new Dictionary <Type, Stack <LocalBuilder> >();
                Members    = new HashSet <string>();
                _captures  = new HashSet <NameItem>(captures);
                Parent     = parent;
                Generator  = gen;
                Locals     = new Stack <Dictionary <string, IVarDefinition> >();
                Locals.Push(new Dictionary <string, IVarDefinition>());

                if (createType)
                {
                    // create the type and constructor.
                    TypeDef = parent.TypeDef.DefineNestedType(
                        "<>c__DisplayClass" + (_id++),
                        TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
                    var ctor = TypeDef.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard,
                                                         new Type[0]);
                    var cgen = ctor.GetILGenerator();

                    // base();
                    cgen.Emit(OpCodes.Ldarg_0);
                    cgen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));
                    cgen.Emit(OpCodes.Ret);

                    if (storeParent)
                    {
                        ParentInst = TypeDef.DefineField("CS$<>__locals", parent.TypeDef,
                                                         FieldAttributes.Public);
                    }
                    else
                    {
                        ParentInst = null;
                    }

                    // create the local definition
                    // ThisInst = new TypeDef();
                    ThisInst = gen.DeclareLocal(TypeDef);
                    gen.Emit(OpCodes.Newobj, ctor);
                    gen.Emit(OpCodes.Stloc, ThisInst);

                    if (storeParent)
                    {
                        // ThisInst.ParentInst = this;
                        gen.Emit(OpCodes.Ldloc, ThisInst);
                        gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Stfld, ParentInst);
                    }
                }
                else
                {
                    TypeDef    = null;
                    ThisInst   = null;
                    ParentInst = null;
                }
            }