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(IModuleEnvironment), typeof(SymbolId[]), typeof(SymbolId[]) });
                ef = new FieldEnvironmentFactory(envType);
            } else {
                cg.EmitInt(size);
                envType = typeof(FunctionEnvironmentNDictionary);
                ctor = envType.GetConstructor(new Type[] { typeof(int), typeof(FunctionEnvironmentDictionary), typeof(IModuleEnvironment), typeof(SymbolId[]), typeof(SymbolId[]) });
                ef = new IndexEnvironmentFactory(size);
            }

            // *** END GENERATED CODE ***

            #endregion

            return envType;
        }
 private void CreateGeneratorTemps(EnvironmentFactory ef, CodeGen cg)
 {
     for (int i = 0; i < TempsCount; i++) {
         cg.Names.AddTempSlot(ef.MakeEnvironmentReference(SymbolTable.StringToId("temp$" + i)).CreateSlot(cg.EnvironmentSlot));
     }
 }
        internal Slot CreateEnvironment(CodeGen cg)
        {
            // Get the environment size
            int size = CalculateEnvironmentSize();

            // 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
            EmitEnvironmentIDs(cg);
            EmitOuterLocalIDs(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<SymbolId, EnvironmentReference>();

            foreach (KeyValuePair<SymbolId, Binding> kv in names) {
                if (!kv.Value.IsEnvironment) continue;
                SymbolId 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);
                }

                // 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;
        }