Esempio n. 1
0
        private void EmitGeneratorBody(CodeGen cg, CodeGen ocg)
        {
            // Create the GenerateNext function
            CodeGen ncg = cg.DefineMethod(name.GetString() + "$g" + counter++, typeof(bool),
                new Type[] { typeof(Generator), typeof(object).MakeByRefType() },
                new String[] { "$gen", "$ret" });
            ncg.Context = cg.Context;

            PromoteLocalsToEnvironment();
            ncg.FuncOrClassName = name.ToString();
            ncg.EmitSetTraceBackUpdateStatus(false);

            // Namespace without er factory - all locals must exist ahead of time
            ncg.Names = new Namespace(null);
            Slot generator = ncg.GetArgumentSlot(0);
            ncg.StaticLinkSlot = new FieldSlot(generator, typeof(Generator).GetField("staticLink"));
            if (HasEnvironment) {
                cg.EnvironmentSlot = CreateEnvironment(cg);
                EnvironmentFactory ef = this.environmentFactory;
                Slot envSlotCast = new CastSlot(
                    new FieldSlot(generator, typeof(Generator).GetField("environment")),
                    ef.EnvironmentType
                    );
                Slot envSlot = ncg.GetLocalTmp(ef.EnvironmentType);
                // setup the environment and static link slots
                ncg.EnvironmentSlot = envSlot;
                ncg.ContextSlot = envSlot;
                // pull the environment into typed local variable
                envSlot.EmitSet(ncg, envSlotCast);
                InheritEnvironment(ncg);
                CreateGeneratorTemps(ef, ncg);
            } else {
                ncg.ContextSlot = ncg.StaticLinkSlot;
            }
            ncg.ModuleSlot = new PropertySlot(ncg.ContextSlot, typeof(ICallerContext).GetProperty("Module"));

            CreateClosureSlots(ncg);
            CreateGlobalSlots(ncg, ocg);

            // Emit the generator body using the typed er
            EmitGenerator(ncg);

            // Initialize the generator
            EmitTupleParams(cg);

            // Create instance of the generator
            cg.EmitStaticLinkOrNull();
            cg.EmitEnvironmentOrNull();
            cg.EmitDelegate(ncg, typeof(Generator.NextTarget), null);
            cg.EmitNew(typeof(Generator), new Type[] { typeof(FunctionEnvironmentDictionary), typeof(FunctionEnvironmentDictionary), typeof(Generator.NextTarget) });
            cg.EmitReturn();
        }
        private void CreateClosureSlots(Slot staticLink, Namespace nspace)
        {
            foreach (KeyValuePair<SymbolId, Binding> kv in names) {
                if (!kv.Value.IsFree) continue;

                // Find the slot
                Slot instance = staticLink;
                ScopeStatement current = parent;

                for (; ; ) {
                    instance = new CastSlot(instance, current.environmentFactory.EnvironmentType);
                    Debug.Assert(current != null, "cannot resolve closure", kv.Key.GetString());
                    if (current.environment != null) {
                        EnvironmentReference er;

                        // Is the slot in this environment?
                        if (current.TryGetEnvironmentReference(kv.Key, out er)) {
                            nspace.SetSlot(kv.Key, er.CreateSlot(instance));
                            break;
                        }
                    }
                    instance = EnvironmentFactory.MakeParentSlot(instance);
                    current = current.parent;
                }
            }
        }