예제 #1
0
            /// <summary>
            /// Defines a new Local variable and returns the field that
            /// represents it.
            /// </summary>
            /// <param name="name">The Lua name of the variable.</param>
            /// <returns>The variable that represents the local.</returns>
            public VarDefinition DefineLocal(NameItem name)
            {
                if (captures.Contains(name))
                {
                    string mName = name.Name;
                    if (members.Contains(mName))
                    {
                        int i = 0;
                        while (members.Contains(mName + "_" + i))
                        {
                            i++;
                        }
                        mName += "_" + i;
                    }

                    members.Add(mName);
                    var field = TypeDef.DefineField(mName, typeof(ILuaValue), FieldAttributes.Public);
                    return(Locals.Peek()[name.Name] = new CapturedVarDef(Generator, ThisInst, field));
                }
                else
                {
                    var loc = Generator.DeclareLocal(typeof(ILuaValue));
                    return(Locals.Peek()[name.Name] = new LocalVarDef(Generator, loc));
                }
            }
예제 #2
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;
                }
            }