예제 #1
0
        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__"));
            }
        }
예제 #2
0
 public FlowDefiner(FlowChecker fc)
 {
     this.fc = fc;
 }
예제 #3
0
 public FlowDeleter(FlowChecker fc)
 {
     this.fc = fc;
 }
예제 #4
0
        public static void Check(ScopeStatement scope)
        {
            FlowChecker fc = new FlowChecker(scope);

            scope.Walk(fc);
        }
예제 #5
0
        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);
            }
        }