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