m &UIc@sdZdkZdkZdkZdkZdklZdklZl Z l Z l Z dfdYZ dZ dfdYZd Zd Zd Zd Zd e fdYZdZdfdYZdZdZdfdYZdfdYZeiZdS(s/A flow graph representation for Python bytecodeN(smisc(s CO_OPTIMIZEDs CO_NEWLOCALSs CO_VARARGSsCO_VARKEYWORDSt FlowGraphcBstZdZdZddZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZRS(NcCs[t|_|_td|_ti|_|ii|i|ii|idS(Ntexit( tBlocktselftcurrenttentryRtmisctSettblockstadd(R((t-/data/zmath/lib/python2.4/compiler/pyassem.pyt__init__ s cCsg|ioP|io7dGt|iGHdG|iiGHdG|iiGHnt|GHn||_dS(Ntends nexts (Rt_debugRtreprtnextt get_childrentblock(RR((R t startBlocks  cCs>|djo|i}n|ii||i|dS(N(RtNoneRtnewBlockRtaddNextR(RR((R t nextBlocks  cCst}|ii||S(N(RtbRRR (RR((R R6s cCs|i|idS(N(RRR(R((R tstartExitBlock;sicCs d|_dS(Ni(RR (R((R t _enable_debug@scCs d|_dS(Ni(RR (R((R t_disable_debugCscGs|io dG|GHn|dddgjo|ii|int|djo,t|dto|ii|dn|ii |dS(Ns it RETURN_VALUEt YIELD_VALUEii( RR tinstRt addOutEdgeRtlent isinstanceRtemit(RR((R R!Fs  'cCsxL|iiD];}||ijoqn|ip|i|iqqWt|ih}|i |i ||i|i|jo|i |in|S(slReturn the blocks in reverse postorder i.e. each node appears before all of its successors N( RRtelementsRRRRt dfs_postorderRtordertreverset fixupOrdertappend(RRR$((R tgetBlocksInOrderOs  cCs$|i|||i||dS(s"Fixup bad order introduced by DFS.N(RtfixupOrderHonorNextRt default_nexttfixupOrderForward(RRR*((R R&dsc Csh}x(tt|D]}||||RR9R8R0((R R+sZ      '  cCs |iiS(N(RRR"(R((R t getBlocksscCs|iS(s/Return nodes appropriate for use with dominatorN(RR(R((R tgetRootscCs4g}x'|iD]}|i|iqW|S(N(R3RRARtextendtgetContainedGraphs(RRR3((R RDs  (t__name__t __module__R RRRRRR RRR!R(R&R)R+RARBRD(((R R s         ) .  cCsbg}||||iD]0}|i|oqn|t||}qW|i||S(s;Depth-first search of tree rooted at b, return in postorderN(R$RtseenRR:thas_keyR#R'(RRGR:R$((R R#s   RcBsztZdZddZdZdZdZdZdZd Z d Z dZ dZ dZ dZRS(NitcCsYg|_ti|_ti|_||_ti|_ g|_ tidt_dS(Ni( RR<RRtinEdgestoutEdgestlabelRt_counttbidR(RRL((R R s    cCs1|iod|i|ifSn d|iSdS(Nss (RRLRN(R((R t__repr__s cCs2tt|i}d|i|idi|fS(Nss (tmaptstrRR<RLRNtjoin(RR<((R t__str__scCsG|d}|d djo|ii|dn|ii|dS(NiitJUMPi(RtopRRKR R<R'(RRRU((R R!s cCs|iS(N(RR<(R((R tgetInstructionsscCs|ii|dS(N(RRJR R(RR((R t addInEdgescCs|ii|dS(N(RRKR R(RR((R RscCs@|ii|t|idjpttt|idS(Ni(RRR'RRR4RPRQ(RR((R RsRt RAISE_VARARGSRt JUMP_ABSOLUTER7t CONTINUE_LOOPcCsXy|id\}}Wnttfj o dSnX||ijo g|_ndS(sLRemove bogus edge for unconditional transfers Each block has a next edge that accounts for implicit control transfers, e.g. from a JUMP_IF_FALSE to the block that will be executed if the test is true. These edges must remain for the current assembler code to work. If they are removed, the dfs_postorder gets things in weird orders. However, they shouldn't be there for other purposes, e.g. conversion to SSA form. This method will remove the next edge when it follows an unconditional control transfer. iN(RR<RUtargt IndexErrort ValueErrort_uncond_transferR(RR[RU((R t pruneNext s  cCsP|io2|id|ijo|ii|idn|ii|iS(Ni(RRRKR?R"(R((R Rs!cCsfg}xY|iD]N}t|djoqn|d}t|do|i|iqqW|S(sReturn all graphs contained within this block. For example, a MAKE_FUNCTION block will contain a reference to the graph for the function body. itgraphN( t containedRR<RRRUthasattrR'R`(RRaRRU((R RD#s  (s RETURN_VALUERXs YIELD_VALUERYs JUMP_FORWARDRZ(RERFRMR RORSR!RVRWRRR^R_RRD(((R Rs         tRAWtFLATtCONVtDONEt PyFlowGraphcBsItZeiZfdddZdZdZdZdZ dZ dZ dd Z d Z d ZeiZx%eiD]ZeieieqWeiZx%eiD]ZeieieqWd Zd ZdZhZdZdZeZeZdZdZ e Z!e Z"e Z#e Z$e Z%e Z&e Z'e Z(e Z)e Z*dZ+e+Z,e+Z-dZ.e/ei0Z1dZ2xFe3i4D]5\Z5Z6e5d djoe5dZe6ee|iD]3}t|to|i}n|i|qWt|S(sReturn a tuple for the const slot of the code object Must convert references to code (MAKE_FUNCTION) to code objects recursively. N( R3RRtR2R RgRR'R(RR3R2((R R_s (>RERFRR RhRRRRRRRRRRRRRtdisR.R RRRRRRRRt_convert_STORE_FASTt_convert_DELETE_FASTRRt_convert_STORE_NAMEt_convert_DELETE_NAMEt_convert_IMPORT_NAMEt_convert_IMPORT_FROMt_convert_STORE_ATTRt_convert_LOAD_ATTRt_convert_DELETE_ATTRt_convert_LOAD_GLOBALt_convert_STORE_GLOBALt_convert_DELETE_GLOBALRt_convert_LOAD_DEREFt_convert_STORE_DEREFRRytcmp_opRRtlocalstitemsRitobjRRR-RtnumRR(((R Rg:sv         !                  cCs|d djodSndS(NiRTi(R(R((R tisJumplsR|cBs)tZdZdZdZdZRS(s:Helper for marking func defs with nested tuples in arglistcCs||_||_dS(N(tcountRRu(RRRu((R R rs cCsd|i|ifS(NsTupleArg(%s, %s)(RRRu(R((R ROuscCs d|iS(Ns.%d(RR(R((R R}ws(RERFt__doc__R ROR}(((R R|ps   cCsbt|}|oKxH|D]<}t|to&tti|i}||}qqWn|S(N( RRlRnR[R R|RtflattenRutnumNames(RlRRnR[((R Rmzs cCs*t|tijptt|dS(s/Convert an int argument into high and low bytesiN(RtvalttypestIntTypeR4tdivmod(R((R RsRcBs;tZdZdZdZdZdZdZRS(s(lnotab This class builds the lnotab, which is documented in compile.c. Here's a brief recap: For each SET_LINENO instruction after the first one, two bytes are added to lnotab. (In some cases, multiple two-byte entries are added.) The first byte is the distance in bytes between the instruction for the last SET_LINENO and the current SET_LINENO. The second byte is offset in line numbers. If either offset is greater than 255, multiple two-byte entries are added -- see compile.c for the delicate details. cCs:g|_d|_d|_d|_d|_g|_dS(Ni(RRt codeOffsetRtlastlinetlastoffR(R((R R s      cGsAx$|D]}|iit|qW|it||_dS(N(RlR[RRR'tchrRR(RRlR[((R RscCs|idjo||_||_n|i|i}||i}|djo|ii }x0|djo"|d|d|d8}q_Wx6|djo(|||d|d8}d}qW|djp |djo||||n||_|i|_ndS(Nii( RRtlinenoRRRtaddrtlineRR'tpush(RRRRR((R Rs(         cCsdi|iS(NRI(RRRR(R((R RscCsditt|iS(NRI(RRRPRRR(R((R Rs(RERFRR RRRR(((R Rs    tStackDepthTrackercBstZddZhdd<dd<dd<dd<d d <d d<d d <d d <dd<dd<dd <dd <dd<dd<dd <dd<dd<dd<dd<dd <dd<dd <dd<dd<dd<d d<d!d<d"d<d#d<d$d<d%d<d&d'<d(d'<d)d