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