예제 #1
0
 public override void EmitSet(CodeGen cg)
 {
     if (instance.Type.IsAssignableFrom(type))
     {
         cg.Emit(OpCodes.Castclass, instance.Type);
     }
     instance.EmitSet(cg);
 }
예제 #2
0
        public override void EmitSet(CodeGen cg)
        {
            Slot val = cg.GetLocalTmp(Type);

            val.EmitSet(cg);
            EmitSet(cg, val);
            cg.FreeLocalTmp(val);
        }
예제 #3
0
        /// <summary>
        /// Generates a static entry point for stand-alone EXEs.  We just new up our module dstructure
        /// and then call into Ops to get running.
        /// </summary>
        internal static CodeGen GenerateModuleEntryPoint(TypeGen tg, CodeGen init, string moduleName, IList <string> referencedAssemblies)
        {
            CodeGen main = tg.DefineMethod(MethodAttributes.Static | MethodAttributes.Public, "Main", typeof(int), Type.EmptyTypes, new string[] { });

            main.SetCustomAttribute(new CustomAttributeBuilder(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new object[0]));

            //  Create instance of the module
            Slot instance = main.GetLocalTmp(tg.myType);

            main.EmitNew(tg.DefaultConstructor);
            instance.EmitSet(main);

            // Emit instance for the ExecuteCompiled call
            instance.EmitGet(main);

            // Emit the delegate to the init method
            main.EmitDelegate(init, typeof(InitializeModule), instance);
            main.EmitString(moduleName);

            // emit the references assemblies
            if (referencedAssemblies != null)
            {
                for (int i = 0; i < referencedAssemblies.Count; i++)
                {
                    if (referencedAssemblies[i].ToLower().EndsWith("\\ironpython.dll"))
                    {
                        referencedAssemblies.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        if (referencedAssemblies[i].IndexOf(Path.DirectorySeparatorChar) != -1)
                        {
                            referencedAssemblies[i] = referencedAssemblies[i].Substring(referencedAssemblies[i].LastIndexOf(Path.DirectorySeparatorChar) + 1);
                        }

                        if (referencedAssemblies[i].ToLower().EndsWith(".dll"))
                        {
                            referencedAssemblies[i] = referencedAssemblies[i].Substring(0, referencedAssemblies[i].Length - 4);
                        }
                    }
                }
                main.EmitStringArray(referencedAssemblies);
            }
            else
            {
                main.Emit(OpCodes.Ldnull);
            }

            // Call ExecuteCompiled
            main.EmitCall(typeof(IronPython.Hosting.PythonEngine),
                          "ExecuteCompiled",
                          new Type[] { typeof(CustomFieldIdDict), typeof(InitializeModule), typeof(string), typeof(string[]) });

            main.EmitReturn();
            return(main);
        }
예제 #4
0
 public override void EmitSet(CodeGen cg, Slot val)
 {
     val.EmitGet(cg);
     cg.EmitCastToObject(Type);
     val = cg.GetLocalTmp(typeof(object));
     val.EmitSet(cg);
     instance.EmitGet(cg);
     cg.EmitInt(index);
     val.EmitGet(cg);
     cg.Emit(OpCodes.Stelem_Ref);
 }
예제 #5
0
        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();
        }
예제 #6
0
        // This override assumes that the IL stack already holds the value to be assigned from.
        public virtual void EmitSet(CodeGen cg)
        {
            // localTmpVal = <top of IL stack>
            Slot localTmpVal = cg.GetLocalTmp(typeof(object));

            localTmpVal.EmitSet(cg);

            // <slot> = localTmpVal
            EmitSet(cg, localTmpVal);

            cg.FreeLocalTmp(localTmpVal);
        }
예제 #7
0
        public override void EmitSet(CodeGen cg)
        {
            Slot val = cg.GetLocalTmp(Type);

            val.EmitSet(cg);

            base.EmitGet(cg);
            val.EmitGet(cg);
            cg.EmitCall(typeof(BuiltinWrapper), "set_CurrentValue");

            cg.FreeLocalTmp(val);
        }
예제 #8
0
        //!!! code review
        protected void FinishCompare(CodeGen cg)
        {
            BinaryExpr bright = (BinaryExpr)right;

            Slot valTmp = cg.GetLocalTmp(typeof(object));
            Slot retTmp = cg.GetLocalTmp(typeof(object));

            bright.left.Emit(cg);
            cg.Emit(OpCodes.Dup);
            valTmp.EmitSet(cg);

            cg.EmitCall(op.target.Method);
            cg.Emit(OpCodes.Dup);
            retTmp.EmitSet(cg);
            cg.EmitTestTrue();

            Label end = cg.DefineLabel();

            cg.Emit(OpCodes.Brfalse, end);

            valTmp.EmitGet(cg);

            if (IsComparision(bright.right))
            {
                bright.FinishCompare(cg);
            }
            else
            {
                bright.right.Emit(cg);
                cg.EmitCall(bright.op.target.Method);
            }

            retTmp.EmitSet(cg);
            cg.MarkLabel(end);
            retTmp.EmitGet(cg);
        }
예제 #9
0
        public override void Emit(CodeGen cg)
        {
            cg.EmitPosition(start, end);

            cg.EmitModuleInstance();
            cg.EmitString(root.MakeString());
            if (names == Star)
            {
                cg.EmitCall(typeof(Ops), "ImportStar"); //!!! this is tricky
            }
            else
            {
                Slot fromObj = cg.GetLocalTmp(typeof(object));
                cg.EmitStringArray(Name.ToStrings(names));

                if (asNames != null)
                {
                    cg.EmitStringArray(Name.ToStrings(asNames));
                    cg.EmitCall(typeof(Ops), "ImportFromAs");
                }
                else
                {
                    cg.EmitCall(typeof(Ops), "ImportFrom");
                }

                fromObj.EmitSet(cg);

                for (int i = 0; i < names.Length; i++)
                {
                    cg.EmitCallerContext();
                    fromObj.EmitGet(cg);
                    cg.EmitString(names[i].GetString());
                    cg.EmitCall(typeof(Ops), "ImportOneFrom");

                    Name asName;
                    if (i < asNames.Length && asNames[i] != null)
                    {
                        asName = asNames[i];
                    }
                    else
                    {
                        asName = names[i];
                    }

                    cg.EmitSet(asName);
                }
            }
        }
예제 #10
0
        private void MakeRawKeysMethod()
        {
            Slot    rawKeysCache = tg.AddStaticField(typeof(SymbolId[]), "ExtraKeysCache");
            CodeGen init         = tg.GetOrMakeInitializer();

            SymbolId[] nameArray = new SymbolId[names.Slots.Count];

            init.EmitSymbolIdArray(new List <Name>(names.Slots.Keys));

            rawKeysCache.EmitSet(init);

            CodeGen cg = tg.DefineMethodOverride(typeof(CustomFieldIdDict).GetMethod("GetExtraKeys"));

            rawKeysCache.EmitGet(cg);
            cg.EmitReturn();
            cg.Finish();
        }
예제 #11
0
        public void EmitIndirectedSymbol(CodeGen cg, SymbolId id)
        {
            Slot value;

            if (!indirectSymbolIds.TryGetValue(id, out value))
            {
                // create field, emit fix-up...

                value = AddStaticField(typeof(int), "symbol_" + SymbolTable.IdToString(id));
                CodeGen init     = GetOrMakeInitializer();
                Slot    localTmp = init.GetLocalTmp(typeof(SymbolId));
                init.EmitString((string)SymbolTable.IdToString(id));
                init.EmitCall(typeof(SymbolTable), "StringToId");
                localTmp.EmitSet(init);
                localTmp.EmitGetAddr(init);
                init.EmitFieldGet(typeof(SymbolId), "Id");
                value.EmitSet(init);

                cg.FreeLocalTmp(localTmp);
                indirectSymbolIds[id] = value;
            }

            value.EmitGet(cg);
        }
예제 #12
0
        public override void EmitSet(CodeGen cg)
        {
            // Disallow "[] = l", "[], a = l, l", "[[]] = [l]", etc
            if (items.Length == 0)
            {
                cg.Context.AddError("can't assign to " + EmptySequenceString, this);
                return;
            }

            // int leftCount = items.Length;
            Slot leftCount = cg.GetLocalTmp(typeof(int));

            cg.EmitInt(items.Length);
            leftCount.EmitSet(cg);

            // object[] values = new object[leftCount];
            Slot values = cg.GetLocalTmp(typeof(object[]));

            leftCount.EmitGet(cg);
            cg.Emit(OpCodes.Newarr, typeof(object));
            values.EmitSet(cg);

            // ie = Ops.GetEnumerator(<value on stack>)
            Slot ie = cg.GetLocalTmp(typeof(IEnumerator));

            cg.EmitCall(typeof(Ops), "GetEnumerator");
            ie.EmitSet(cg);

            // int rightCount = Ops.GetEnumeratorValues(ie, ref values);
            Slot rightCount = cg.GetLocalTmp(typeof(int));

            ie.EmitGet(cg);
            values.EmitGetAddr(cg);
            cg.EmitCall(typeof(Ops), "GetEnumeratorValues");
            rightCount.EmitSet(cg);

            // if (leftCount != rightCount)
            //      throw Ops.ValueErrorForUnpackMismatch(leftCount, rightCount);
            Label equalSizes = cg.DefineLabel();

            leftCount.EmitGet(cg);
            rightCount.EmitGet(cg);
            cg.Emit(OpCodes.Ceq);
            cg.Emit(OpCodes.Brtrue_S, equalSizes);

            leftCount.EmitGet(cg);
            rightCount.EmitGet(cg);
            cg.EmitCall(typeof(Ops).GetMethod("ValueErrorForUnpackMismatch"));
            cg.Emit(OpCodes.Throw);

            cg.MarkLabel(equalSizes);

            // for (int i = 0; i < leftCount; i++)
            //     items[i].Assign(values[i], env);

            int i = 0;

            foreach (Expr expr in items)
            {
                values.EmitGet(cg);
                cg.EmitInt(i++);
                cg.Emit(OpCodes.Ldelem_Ref);
                expr.EmitSet(cg);
            }

            cg.FreeLocalTmp(leftCount);
            cg.FreeLocalTmp(rightCount);
            cg.FreeLocalTmp(values);
            cg.FreeLocalTmp(ie);
        }
예제 #13
0
        public override void Emit(CodeGen cg)
        {
            Slot list = cg.GetLocalTmp(typeof(List));

            cg.EmitCall(typeof(Ops), "MakeList", Type.EmptyTypes);
            list.EmitSet(cg);

            // first loop: how many For; initialize labels/slots
            int iFors = 0;

            foreach (ListCompIter iter in iters)
            {
                if (iter is ListCompFor)
                {
                    iFors++;
                }
            }

            Label[] continueTargets = new Label[iFors];
            Slot[]  enumerators     = new Slot[iFors];
            int     jIters          = iters.Length;

            Label[] exitTargets = new Label[jIters];

            for (int i = 0; i < iFors; i++)
            {
                continueTargets[i] = cg.DefineLabel();
                enumerators[i]     = cg.GetLocalTmp(typeof(IEnumerator));
            }
            for (int i = 0; i < jIters; i++)
            {
                exitTargets[i] = cg.DefineLabel();
            }

            // second loop: before emiting item
            iFors = jIters = 0;
            foreach (ListCompIter iter in iters)
            {
                if (iter is ListCompFor)
                {
                    ListCompFor cfor = iter as ListCompFor;
                    cfor.list.Emit(cg);
                    cg.EmitCall(typeof(Ops), "GetEnumerator");
                    enumerators[iFors].EmitSet(cg);

                    cg.MarkLabel(continueTargets[iFors]);

                    enumerators[iFors].EmitGet(cg);
                    cg.EmitCall(typeof(IEnumerator), "MoveNext", Type.EmptyTypes);
                    cg.Emit(OpCodes.Brfalse, exitTargets[jIters]);

                    enumerators[iFors].EmitGet(cg);
                    cg.EmitCall(typeof(IEnumerator).GetProperty("Current").GetGetMethod());

                    cfor.lhs.EmitSet(cg);
                    iFors++;
                }
                else if (iter is ListCompIf)
                {
                    ListCompIf cif = iter as ListCompIf;

                    cg.EmitTestTrue(cif.test);
                    cg.Emit(OpCodes.Brfalse, exitTargets[jIters]);
                }

                jIters++;
            }

            // append the item
            list.EmitGet(cg);
            this.item.Emit(cg);
            cg.EmitCall(typeof(List), "Append");

            // third loop: in reverse order
            iFors  = continueTargets.Length - 1;
            jIters = iters.Length - 1;
            while (jIters >= 0)
            {
                ListCompIter iter = iters[jIters];
                if (iter is ListCompFor)
                {
                    cg.Emit(OpCodes.Br, continueTargets[iFors]);
                    cg.FreeLocalTmp(enumerators[iFors]);
                    iFors--;
                }

                cg.MarkLabel(exitTargets[jIters]);
                jIters--;
            }

            list.EmitGet(cg);
            cg.FreeLocalTmp(list);
        }
예제 #14
0
        //!!! need to evaluate break/continue through a try block
        public override void Emit(CodeGen cg)
        {
            Slot choiceVar = null;

            cg.EmitPosition(start, header);

            if (yieldTargets.Count > 0)
            {
                Label startOfBlock = cg.DefineLabel();
                choiceVar = cg.GetLocalTmp(typeof(int));
                cg.EmitInt(-1);
                choiceVar.EmitSet(cg);
                cg.Emit(OpCodes.Br, startOfBlock);

                int index = 0;
                foreach (YieldTarget yt in yieldTargets)
                {
                    cg.MarkLabel(yt.topBranchTarget);
                    cg.EmitInt(index++);
                    choiceVar.EmitSet(cg);
                    cg.Emit(OpCodes.Br, startOfBlock);
                }

                cg.MarkLabel(startOfBlock);
            }

            Label afterCatch = new Label();
            Label afterElse  = cg.DefineLabel();

            cg.PushTryBlock();
            cg.BeginExceptionBlock();

            if (yieldTargets.Count > 0)
            {
                int index = 0;
                foreach (YieldTarget yt in yieldTargets)
                {
                    choiceVar.EmitGet(cg);
                    cg.EmitInt(index);
                    cg.Emit(OpCodes.Beq, yt.tryBranchTarget);
                    index++;
                }
                cg.FreeLocalTmp(choiceVar);
            }

            body.Emit(cg);
            if (yieldInExcept)
            {
                afterCatch = cg.DefineLabel();
                cg.Emit(OpCodes.Leave, afterCatch);
            }
            cg.BeginCatchBlock(typeof(Exception));
            // Extract state from the carrier exception
            cg.EmitCallerContext();
            cg.EmitCall(typeof(Ops), "ExtractException");
            Slot pyExc  = cg.GetLocalTmp(typeof(object));
            Slot tmpExc = cg.GetLocalTmp(typeof(object));

            pyExc.EmitSet(cg);
            if (yieldInExcept)
            {
                cg.EndExceptionBlock();
                cg.PopTargets();
            }

            foreach (TryStmtHandler handler in handlers)
            {
                cg.EmitPosition(handler.start, handler.header);
                Label next = cg.DefineLabel();
                if (handler.test != null)
                {
                    pyExc.EmitGet(cg);
                    handler.test.Emit(cg);
                    cg.EmitCall(typeof(Ops), "CheckException");
                    if (handler.target != null)
                    {
                        tmpExc.EmitSet(cg);
                        tmpExc.EmitGet(cg);
                    }
                    cg.EmitPythonNone();
                    cg.Emit(OpCodes.Ceq);
                    cg.Emit(OpCodes.Brtrue, next);
                }

                if (handler.target != null)
                {
                    tmpExc.EmitGet(cg);
                    handler.target.EmitSet(cg);
                }

                cg.PushExceptionBlock(Targets.TargetBlockType.Catch, null);

                handler.body.Emit(cg);
                cg.EmitCallerContext();
                cg.EmitCall(typeof(Ops), "ClearException");

                cg.PopTargets();

                if (yieldInExcept)
                {
                    cg.Emit(OpCodes.Br, afterElse);
                }
                else
                {
                    cg.Emit(OpCodes.Leave, afterElse);
                }
                cg.MarkLabel(next);
            }

            cg.FreeLocalTmp(tmpExc);
            if (yieldInExcept)
            {
                pyExc.EmitGet(cg);
                cg.Emit(OpCodes.Throw);
                cg.MarkLabel(afterCatch);
            }
            else
            {
                cg.Emit(OpCodes.Rethrow);
                cg.EndExceptionBlock();
                cg.PopTargets();
            }

            if (elseStmt != null)
            {
                elseStmt.Emit(cg);
            }
            cg.MarkLabel(afterElse);

            cg.FreeLocalTmp(pyExc);

            yieldTargets.Clear();
        }
예제 #15
0
 public override void EmitSet(CodeGen cg)
 {
     attribute.EmitSet(cg);
 }
예제 #16
0
        public override void Emit(CodeGen cg)
        {
            cg.EmitPosition(start, header);
            Slot  choiceVar = null;
            Slot  returnVar = null;
            Label endOfTry  = new Label();

            if (yieldTargets.Count > 0)
            {
                Label startOfBlock = cg.DefineLabel();
                choiceVar = cg.GetLocalTmp(typeof(int));
                returnVar = cg.GetLocalTmp(typeof(bool));
                cg.EmitInt(0);
                returnVar.EmitSet(cg);
                cg.EmitInt(-1);
                choiceVar.EmitSet(cg);
                cg.Emit(OpCodes.Br, startOfBlock);

                int index = 0;
                foreach (YieldTarget yt in yieldTargets)
                {
                    cg.MarkLabel(yt.topBranchTarget);
                    cg.EmitInt(index++);
                    choiceVar.EmitSet(cg);
                    cg.Emit(OpCodes.Br, startOfBlock);
                }

                cg.MarkLabel(startOfBlock);
            }

            cg.PushTryBlock();
            cg.BeginExceptionBlock();

            if (yieldTargets.Count > 0)
            {
                int index = 0;
                endOfTry = cg.DefineLabel();
                foreach (YieldTarget yt in yieldTargets)
                {
                    choiceVar.EmitGet(cg);
                    cg.EmitInt(index++);
                    cg.Emit(OpCodes.Beq, endOfTry);
                }
            }

            body.Emit(cg);

            if (yieldTargets.Count > 0)
            {
                cg.MarkLabel(endOfTry);
            }

            cg.PopTargets();
            cg.PushFinallyBlock(returnVar);
            cg.BeginFinallyBlock();

            if (yieldTargets.Count > 0)
            {
                int index = 0;
                foreach (YieldTarget yt in yieldTargets)
                {
                    choiceVar.EmitGet(cg);
                    cg.EmitInt(index++);
                    cg.Emit(OpCodes.Beq, yt.tryBranchTarget);
                }
            }

            finallyStmt.Emit(cg);

            cg.EndExceptionBlock();
            cg.PopTargets();

            if (yieldTargets.Count > 0)
            {
                Label noReturn = cg.DefineLabel();
                returnVar.EmitGet(cg);
                cg.Emit(OpCodes.Brfalse_S, noReturn);
                cg.Emit(OpCodes.Ldc_I4_1);
                cg.EmitReturn();
                cg.MarkLabel(noReturn);
            }

            yieldTargets.Clear();
        }
예제 #17
0
        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);
        }