internal void PrepareForEmit(CodeGen cg, CodeGen icg) { Debug.Assert(cg != null, "null codegen"); Debug.Assert(icg != null, "null init codegen"); CreateGlobalSlots(icg, cg); PromoteLocalsToEnvironment(); icg.ContextSlot = icg.EnvironmentSlot = CreateEnvironment(icg); CreateClosureSlots(icg); // Detect class locals that may be used uninitialized // and create global-backed slots for them FlowChecker.Check(this); CreateBackedSlots(icg); string doc = body.GetDocString(); if (doc != null) { icg.EmitString(doc); icg.EmitSet(Name.Make("__doc__")); } }
public FlowDefiner(FlowChecker fc) { this.fc = fc; }
public FlowDeleter(FlowChecker fc) { this.fc = fc; }
public static void Check(ScopeStatement scope) { FlowChecker fc = new FlowChecker(scope); scope.Walk(fc); }
public override void Emit(CodeGen cg) { cg.EmitPosition(start, header); SignatureInfo sigInfo = SignatureInfo.Get(this, cg); FlowChecker.Check(this); string mname = name.GetString() + "$f" + counter++; // create the new method & setup it's locals CodeGen impl = cg.DefineMethod(mname, typeof(object), sigInfo.ParamTypes, sigInfo.ParamNames); impl.Names = CodeGen.CreateLocalNamespace(impl); impl.Context = cg.Context; for (int arg = sigInfo.HasContext ? 1 : 0; arg < sigInfo.ParamNames.Length; arg++) { impl.Names.SetSlot(sigInfo.ParamNames[arg], impl.GetArgumentSlot(arg)); } // then generate the actual method EmitFunctionImplementation(cg, impl, sigInfo.HasContext); if (NeedsWrapperMethod()) { impl = MakeWrapperMethodN(cg, impl.MethodInfo, sigInfo.HasContext); } // Create instance of the Function? object Type funcType, targetType; using (impl) { GetFunctionType(out funcType, out targetType); cg.EmitModuleInstance(); cg.EmitString(name.GetString()); cg.EmitDelegate(impl, targetType, sigInfo.ContextSlot); } int first = sigInfo.HasContext ? 1 : 0; // Emit string array (minus the first environment argument) cg.EmitInt(sigInfo.ParamNames.Length - first); cg.Emit(OpCodes.Newarr, typeof(string)); for (int i = first; i < sigInfo.ParamNames.Length; i++) { cg.Emit(OpCodes.Dup); cg.EmitInt(i - first); cg.EmitStringOrNull(sigInfo.ParamNames[i].GetString()); cg.Emit(OpCodes.Stelem_Ref); } cg.EmitObjectArray(defaults); if (flags == FuncDefType.None) { cg.Emit(OpCodes.Newobj, funcType.GetConstructor( new Type[] { typeof(PythonModule), typeof(string), targetType, typeof(string[]), typeof(object[]) })); } else { cg.EmitInt((int)flags); cg.Emit(OpCodes.Newobj, funcType.GetConstructor( new Type[] { typeof(PythonModule), typeof(string), targetType, typeof(string[]), typeof(object[]), typeof(FuncDefType) })); } string doc = body.GetDocString(); if (doc != null) { cg.Emit(OpCodes.Dup); cg.EmitString(doc); cg.EmitCall(typeof(PythonFunction).GetProperty("Documentation").GetSetMethod()); } // update func_code w/ appropriate state. cg.Emit(OpCodes.Dup); cg.EmitCall(typeof(PythonFunction).GetProperty("FunctionCode").GetGetMethod()); cg.Emit(OpCodes.Castclass, typeof(FunctionCode)); cg.Emit(OpCodes.Dup); cg.EmitInt(this.start.line); cg.EmitCall(typeof(FunctionCode), "SetLineNumber"); cg.EmitString(this.filename); cg.EmitCall(typeof(FunctionCode), "SetFilename"); cg.EmitSet(name); if (decorators != null) { decorators.Emit(cg); cg.EmitSet(name); } }