예제 #1
0
 private void CreateGeneratorTemps(EnvironmentFactory ef, CodeGen cg)
 {
     for (int i = 0; i < tempsCount; i++)
     {
         cg.Names.AddTempSlot(ef.MakeEnvironmentReference(Name.Make("temp$" + i)).CreateSlot(cg.EnvironmentSlot));
     }
 }
예제 #2
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" });

            PromoteLocalsToEnvironment();

            // 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();
        }
예제 #3
0
 public EnvironmentNamespace(EnvironmentFactory factory)
 {
     this.factory = factory;
 }
        private static Type GetEnvironmentType(int size, CodeGen cg, out ConstructorInfo ctor, out EnvironmentFactory ef)
        {
            Type envType;

            #region Generated partial factories

            // *** BEGIN GENERATED CODE ***

            if (size <= 32 && Options.OptimizeEnvironments)
            {
                if (size <= 2)
                {
                    envType = typeof(FunctionEnvironment2Dictionary);
                }
                else if (size <= 4)
                {
                    envType = typeof(FunctionEnvironment4Dictionary);
                }
                else if (size <= 8)
                {
                    envType = typeof(FunctionEnvironment8Dictionary);
                }
                else if (size <= 16)
                {
                    envType = typeof(FunctionEnvironment16Dictionary);
                }
                else
                {
                    envType = typeof(FunctionEnvironment32Dictionary);
                }
                ctor = envType.GetConstructor(new Type[] { typeof(FunctionEnvironmentDictionary), typeof(IFrameEnvironment), typeof(SymbolId[]) });
                ef   = new FieldEnvironmentFactory(envType);
            }
            else
            {
                cg.EmitInt(size);
                envType = typeof(FunctionEnvironmentNDictionary);
                ctor    = envType.GetConstructor(new Type[] { typeof(int), typeof(FunctionEnvironmentDictionary), typeof(IFrameEnvironment), typeof(SymbolId[]) });
                ef      = new IndexEnvironmentFactory(size);
            }

            // *** END GENERATED CODE ***

            #endregion

            return(envType);
        }
예제 #5
0
        protected Slot CreateEnvironment(CodeGen cg)
        {
            // Get the environment size
            int size = CalculateEnvironmentSize();

            // Create the array for the names
            Slot namesSlot = cg.GetLocalTmp(typeof(SymbolId[]));

            cg.EmitInt(size - tempsCount);
            cg.Emit(System.Reflection.Emit.OpCodes.Newarr, typeof(SymbolId));
            namesSlot.EmitSet(cg);

            // Find the right environment type
            ConstructorInfo    ctor;
            EnvironmentFactory esf;
            Type envType = GetEnvironmentType(size, cg, out ctor, out esf);

            // Emit the static link for the environment constructor
            cg.EmitStaticLinkOrNull();
            cg.EmitCallerContext();
            // Emit the names array for the environment constructor
            namesSlot.EmitGet(cg);
            cg.EmitNew(ctor);

            // Store the environment reference in the local
            Slot environmentSlot = cg.GetFrameSlot(envType);

            environmentSlot.EmitSet(cg);

            // Remember the environment factory for parent access
            environmentFactory = esf;

            // Create environment references
            environment = new Dictionary <Name, EnvironmentReference>();

            foreach (KeyValuePair <Name, Binding> kv in names)
            {
                if (!kv.Value.IsEnvironment)
                {
                    continue;
                }
                Name name = kv.Key;
                EnvironmentReference er = esf.MakeEnvironmentReference(name);
                Slot slot = er.CreateSlot(environmentSlot);
                Slot current;
                if (cg.Names.Slots.TryGetValue(name, out current))
                {
                    slot.EmitSet(cg, current);
                }
                else
                {
                    slot.EmitSetUninitialized(cg, name);
                }

                // Set the name into the array
                namesSlot.EmitGet(cg);
                cg.EmitInt(er.Index);
                cg.Emit(OpCodes.Ldelema, typeof(SymbolId));
                cg.EmitSymbolIdInt(name.GetString());
                cg.Emit(OpCodes.Call, typeof(SymbolId).GetConstructor(new Type[] { typeof(int) }));

                // The full slot goes to the codegen's namespace
                cg.Names.SetSlot(name, slot);
                // Environment reference goes to the environment
                environment[name] = er;
            }

            return(environmentSlot);
        }