ó
\K]c           @@ s  d  Z  d d l m Z m Z d d l m Z m Z d d l m Z m	 Z	 d d l
 m Z m Z m Z d d l m Z d „  Z d „  Z e d	 d
 ƒ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d S(   s&   
Implement transformation on Numba IR
i    (   t   absolute_importt   print_function(   t
   namedtuplet   defaultdict(   t   compute_cfg_from_blockst   find_top_level_loops(   t   irt   errorst   ir_utils(   t   compute_use_defsc         @ s‘   ‡ f d †  } d „  } ‡  f d †  } g  } x] t  ˆ ƒ D]O } | | ƒ r: | | ƒ r: | | ƒ r: ˆ j ƒ  | j k r: | j | ƒ q: q: W| S(   sE   
    Returns a list of loops that are candidate for loop lifting
    c         @ s`   t  ƒ  } xD |  j D]9 } t  d „  ˆ  j | ƒ Dƒ ƒ } | sB t S| | O} q Wt | ƒ d k S(   s)   all exits must point to the same locationc         s@ s   |  ] \ } } | Vq d  S(   N(    (   t   .0t   xt   _(    (    s/   lib/python2.7/site-packages/numba/transforms.pys	   <genexpr>   s    i   (   t   sett   exitst
   successorst   Falset   len(   t   loopt   outedgest   kt   succs(   t   cfg(    s/   lib/python2.7/site-packages/numba/transforms.pyt   same_exit_point   s    	c         S@ s   t  |  j ƒ d k S(   s   there is one entryi   (   R   t   entries(   R   (    (    s/   lib/python2.7/site-packages/numba/transforms.pyt	   one_entry    s    c         @ sŒ   t  |  j ƒ t  |  j ƒ Bt  |  j ƒ B} x\ t ˆ  j | ƒ D]H } x? | j D]4 } t | t j ƒ rL t | j	 t j
 ƒ r€ t SqL qL Wq< Wt S(   s!   cannot have yield inside the loop(   R   t   bodyR   R   t   mapt   __getitem__t
   isinstanceR   t   Assignt   valuet   YieldR   t   True(   R   t   insiderst   blkt   inst(   t   blocks(    s/   lib/python2.7/site-packages/numba/transforms.pyt   cannot_yield$   s    )(   R   t   entry_pointR   t   append(   R   R%   R   R   R&   t
   candidatesR   (    (   R%   R   s/   lib/python2.7/site-packages/numba/transforms.pyt    _extract_loop_lifting_candidates   s    	$c         C@ sã   | | } | | } i  } x | D] } |  | | | <q! Wt  ƒ  }	 t  ƒ  }
 t | ƒ } x! | j j ƒ  D] } |	 | O}	 qg Wx! | j j ƒ  D] } |
 | O}
 q‹ W|	 |
 B} t t  | ƒ | @ƒ } t t  | ƒ | @|
 @ƒ } | | f S(   s7   Find input and output variables to a block region.
    (   R   R	   t   usemapt   valuest   defmapt   sorted(   R%   t   livemapt   callfromt   returntot   body_block_idst   inputst   outputst
   loopblocksR   t	   used_varst   def_varst   defst   vst   used_or_defined(    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   find_region_inout_vars9   s     

		
t   loop_lift_infos%   loop,inputs,outputs,callfrom,returntoc         C@ sí   t  |  | ƒ } g  } xÑ | D]É } | j \ } t t | j ƒ ƒ } |  j | ƒ \ \ } }	 t | j ƒ t | j ƒ Bt | j ƒ B}
 t d | d | d | d | d |
 ƒ \ } } t	 d | d | d | d | d | ƒ } | j
 | ƒ q W| S(	   s8   
    Returns information on looplifting candidates.
    R%   R/   R0   R1   R2   R   R3   R4   (   R*   R   t   nextt   iterR   R   R   R   R;   t   _loop_lift_infoR(   (   R   R%   R/   t   loopst	   loopinfosR   R0   t   an_exitR1   R   t   local_block_idsR3   R4   t   lli(    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   _loop_lift_get_candidate_infosY   s"    )c         C@ sV   | j  } | j } t j d | d | ƒ } t j d | d |  d | d | d | ƒ | S(   sR   
    Transform calling block from top-level function to call the lifted loop.
    t   scopet   loct   newblockt   calleet
   label_nextR3   R4   (   RF   RG   R   t   BlockR   t   fill_block_with_call(   t
   liftedloopt   blockR3   R4   R1   RF   RG   R#   (    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   _loop_lift_modify_call_blocku   s    			c         C@ s¡   | |  j  } | j } | j } t | ƒ d } t j d t j d | d | ƒ d |  j d |  j  ƒ | | <t j	 d t j d | d | ƒ d |  j
 ƒ | |  j <d S(	   s?   
    Inplace transform loop blocks for use as lifted loop.
    i   RN   RF   RG   R3   RJ   R4   N(   R0   RF   RG   t   minR   t   fill_callee_prologueR   RK   R3   t   fill_callee_epilogueR4   R1   (   t   loopinfoR%   t   entry_blockRF   RG   t   firstblk(    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   _loop_lift_prepare_loop_func‡   s    					c      	   @ s
  d d l  m } | j } t | j ƒ t | j ƒ Bt | j ƒ B}	 t ‡  f d †  |	 Dƒ ƒ }
 t | |
 ƒ |  j	 d |
 d t
 | j ƒ d t | j ƒ d t ƒ } | | | | | | ƒ } t | ˆ  | j | j | j | j ƒ } x |	 D] } ˆ  | =qè W| ˆ  | j <| S(   su   
    Modify the block inplace to call to the lifted-loop.
    Returns a dictionary of blocks of the lifted-loop.
    i    (   t
   LiftedLoopc         3@ s%   |  ] } | ˆ  | j  ƒ  f Vq d  S(   N(   t   copy(   R
   R   (   R%   (    s/   lib/python2.7/site-packages/numba/transforms.pys	   <genexpr>§   s    R%   t	   arg_namest	   arg_countt   force_non_generator(   t   numba.dispatcherRW   R   R   R   R   R   t   dictRV   t   derivet   tupleR3   R   R!   RO   R0   R4   R1   (   t   func_irRS   R%   t	   typingctxt	   targetctxt   flagst   localsRW   R   t   loopblockkeysR5   t	   lifted_irRM   t	   callblockR   (    (   R%   s/   lib/python2.7/site-packages/numba/transforms.pyt   _loop_lift_modify_blocksœ   s$    	)	c      	   C@ s‘   |  j  j ƒ  } t | ƒ } t | | |  j j ƒ } g  } x9 | D]1 }	 t |  |	 | | | | | ƒ }
 | j |
 ƒ q@ W|  j d | ƒ } | | f S(   sš   
    Loop lifting transformation.

    Given a interpreter `func_ir` returns a 2 tuple of
    `(toplevel_interp, [loop0_interp, loop1_interp, ....])`
    R%   (	   R%   RX   R   RE   t   variable_lifetimeR/   Rh   R(   R^   (   R`   Ra   Rb   Rc   Rd   R%   R   RA   R@   RS   t   liftedt   main(    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   loop_lifting¿   s    	c         @ sˆ   t  ˆ  ƒ ‰ ˆ  j ƒ  ‰ ‡ f d †  ‰ ‡  f d †  ‰ ‡ ‡ f d †  } d „  ‰ ‡ ‡ ‡ f d †  } x | ƒ  D] } | | ƒ qp Wˆ S(   s5   
    Rewrite loops that have multiple backedges.
    c           @ s   t  ˆ  j ƒ  ƒ d S(   Ni   (   t   maxt   keys(    (   t	   newblocks(    s/   lib/python2.7/site-packages/numba/transforms.pyt   new_block_idÝ   s    c         @ sc   d } xV |  j  D]K } ˆ  | } | j j ƒ  } |  j | k r | d 7} | d k r[ t Sq q Wt S(   Ni    i   (   R   t
   terminatort   get_targetst   headerR!   R   (   R   t   countR   R#   t   edges(   R%   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   has_multiple_backedgesà   s    

c          3@ s5   x. ˆ  j  ƒ  j ƒ  D] }  ˆ |  ƒ r |  Vq q Wd  S(   N(   R@   R,   (   t   lp(   R   Rv   (    s/   lib/python2.7/site-packages/numba/transforms.pyt#   yield_loops_with_multiple_backedgesí   s    c      	   @ s­   ‡  ‡ f d †  } t  |  t j ƒ r^ t j d |  j d | |  j ƒ d | |  j ƒ d |  j ƒ St  |  t j ƒ r’ t j d | |  j ƒ d |  j ƒ S|  j	 ƒ  s¥ t
 ‚ |  Sd  S(   Nc         @ s   |  ˆ k r ˆ  S|  S(   N(    (   t   target(   t   dstt   src(    s/   lib/python2.7/site-packages/numba/transforms.pyt   replaceó   s    t   condt   truebrt   falsebrRG   Ry   (   R   R   t   BranchR}   R~   R   RG   t   JumpRy   Rr   t   AssertionError(   t   termR{   Rz   R|   (    (   Rz   R{   s/   lib/python2.7/site-packages/numba/transforms.pyt   replace_targetò   s    
"c         @ sÒ   |  j  } ˆ  ƒ  } xe |  j D]Z } ˆ | } | | j j ƒ  k r | j ƒ  } ˆ | j | | ƒ | j d <| ˆ | <q q Wˆ | } t j d | j d | j ƒ } | j	 t j
 d | d | j ƒ ƒ | ˆ | <d S(   sC   
        Add new tail block that gathers all the backedges
        iÿÿÿÿRF   RG   Ry   N(   Rs   R   Rq   Rr   RX   R   RK   RF   RG   R(   R   (   R   Rs   t   tailkeyt   blkkeyR#   t   newblkt   entryblkt   tailblk(   Rp   Ro   R„   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   rewrite_single_backedge  s    		

"(   R   RX   (   R%   Rx   RŠ   R   (    (   R%   R   Rv   Rp   Ro   R„   s/   lib/python2.7/site-packages/numba/transforms.pyt    canonicalize_cfg_single_backedgeÖ   s    	c         C@ s
   t  |  ƒ S(   sc   
    Rewrite the given blocks to canonicalize the CFG.
    Returns a new dictionary of blocks.
    (   R‹   (   R%   (    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   canonicalize_cfg  s    c      	   @ sS  d d l  m } t ‡  ‡ ‡ ‡ f d † } | j |  ƒ j ƒ  |  j sM t ‚ |  j } |  j j ƒ  } t	 | ƒ }	 | j
 }
 t |	 |
 | ƒ g  } x˜ |	 D] \ } } g  } x' t |
 | | ƒ D] } | j | ƒ q¼ Wt | | ƒ t |  | | ƒ \ } } | j |  | | | | | | ƒ } | j | ƒ q— W| s:|  } n |  j | ƒ } | | f S(   s§   With-lifting transformation

    Rewrite the IR to extract all withs.
    Only the top-level withs are extracted.
    Returns the (the_new_ir, the_lifted_with_ir)
    i    (   t   postprocc         @ st   d d l  m } m } ˆ  j ƒ  } | rU t | _ t | _ t | _ t | _	 | } n | } | |  ˆ ˆ | ˆ |  S(   Ni    (   t
   LiftedWitht   ObjModeLiftedWith(
   R\   RŽ   R   RX   R   t   enable_loopliftR!   t   enable_pyobjectt   force_pyobjectt   no_cpython_wrapper(   R`   t
   objectmodet   kwargsRŽ   R   t   myflagst   cls(   Rc   Rd   Rb   Ra   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   dispatcher_factory-  s    					(   t   numbaR   R   t   PostProcessort   runRi   R‚   R%   RX   t   find_setupwithsR   t   _legalize_withs_cfgt   _cfg_nodes_in_regionR(   t   _legalize_with_headt   _get_with_contextmanagert   mutate_with_bodyR^   (   R`   Ra   Rb   Rc   Rd   R   R˜   t   vltR%   t   withsR   t   sub_irst	   blk_startt   blk_endt   body_blockst   nodet   cmkindt   extrat   subt   new_ir(    (   Rc   Rd   Rb   Ra   s/   lib/python2.7/site-packages/numba/transforms.pyt   with_lifting$  s0    				c         @ sÍ   d ‰  ‡ f d †  ‰ ‡  ‡ ‡ ‡ ‡ f d †  } xz ˆ ˆ j  D]k } t | t j ƒ r> | j } | | ƒ \ } } t | d ƒ sŸ t j d d ˆ ˆ j ƒ‚ n  | | f Sq> Wt j d d ˆ ˆ j ƒ‚ d S(	   s7   Get the global object used for the context manager
    s   Illegal use of context-manager.c         @ s   ˆ  j  |  ƒ S(   s#   Get the definition given a variable(   t   get_definition(   t   var(   R`   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   get_var_dfnb  s    c         @ s  ˆ j  |  ƒ } t | t j ƒ r‹ | j d k r‹ g  | j D] } ˆ | ƒ ^ q: } ‡ f d †  | j Dƒ } i | d 6| d 6} | j }  n d } t	 j
 t	 j ˆ |  ƒ } | t j k r× t j d d ˆ ˆ j ƒ‚ n  | d k rþ t j ˆ  d | j ƒ‚ n  | | f S(   s–   Return the context-manager object and extra info.

        The extra contains the arguments if the context-manager is used
        as a call.
        t   callc         @ s%   i  |  ] \ } } ˆ  | ƒ | “ q S(    (    (   R
   R   t   v(   R°   (    s/   lib/python2.7/site-packages/numba/transforms.pys
   <dictcomp>p  s   	 t   argsR•   s*   Undefined variable used as context managerRG   N(   R®   R   R   t   Exprt   opR³   t   kwst   funct   NoneR   t   guardt   find_global_valuet	   UNDEFINEDR   t   CompilerErrorRG   (   t   var_reft   dfnR   R³   R¶   Rª   t   ctxobj(   t   _illegal_cm_msgR¥   R%   R`   R°   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   get_ctxmgr_objf  s    !"R¡   s"   Unsupported context manager in useRG   s   malformed with-context usageN(	   R   R   R   t	   EnterWitht   contextmanagert   hasattrR   R¼   RG   (   R`   R%   R¥   RÁ   t   stmtR½   R¿   Rª   (    (   RÀ   R¥   R%   R`   R°   s/   lib/python2.7/site-packages/numba/transforms.pyR    ]  s    	c         C@ sÔ   t  t ƒ } x' |  j D] } | t | ƒ c d 7<q W| j t j ƒ d k ri t j d d |  j	 ƒ‚ n  | j t j
 ƒ d k rœ t j d d |  j	 ƒ‚ n  | j t j d ƒ | rÐ t j d d |  j	 ƒ‚ n  d S(   sa   Given *blk*, the head block of the with-context, check that it doesn't
    do anything else.
    i   s0   with's head-block must have exactly 1 ENTER_WITHRG   s*   with's head-block must have exactly 1 JUMPs'   illegal statements in with's head-blockN(   R   t   intR   t   typet   popR   RÂ   R   R¼   RG   R   t   DelR¸   (   R#   t   countersRÅ   (    (    s/   lib/python2.7/site-packages/numba/transforms.pyRŸ   –  s     c   
      C@ s˜   t  ƒ  } | g } x | r“ | j ƒ  } t |  j | ƒ Œ  \ } } t  g  | D]$ } | | k rL | | k rL | ^ qL ƒ }	 | j |	 ƒ | |	 O} q W| S(   s;   Find the set of CFG nodes that are in the given region
    (   R   RÈ   t   zipR   t   extend(
   R   t   region_begint
   region_endt   region_nodest   stackt   tosR   R   R¨   t   nodes(    (    s/   lib/python2.7/site-packages/numba/transforms.pyRž   ²  s    			c   	      C@ sœ   | j  ƒ  } | j ƒ  } x} |  D]u \ } } | | j } | | | k rf d } t j | d | ƒ‚ n  | | | k r d } t j | d | ƒ‚ q q Wd S(   s+   Verify the CFG of the with-context(s).
    s.   Entry of with-context not dominating the exit.RG   s¬   Does not support with-context that contain branches (i.e. break/return/raise) that can leave the with-context. Details: exit of with-context not post-dominating the entry. N(   t
   dominatorst   post_dominatorsRG   R   R¼   (	   R£   R   R%   t   domst   postdomst   st   eRG   t   msg(    (    s/   lib/python2.7/site-packages/numba/transforms.pyR   Ã  s    c         @ s    d „  } ‡  f d †  } g  } x{ t  | |  ƒ ƒ D]g \ ‰  } | ˆ  | ƒ s1 | |  k rj t j d ƒ ‚ n  ˆ  |  k s‚ t d ƒ ‚ | j ˆ  | f ƒ q1 q1 W| S(   sQ   Find all top-level with.

    Returns a list of ranges for the with-regions.
    c         s@ sI   xB |  j  ƒ  D]4 } x+ | j t j ƒ D] } | j | j f Vq& Wq Wd  S(   N(   R,   t
   find_instsR   RÂ   t   begint   end(   R%   R#   t   ew(    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   find_rangesÞ  s    c         @ s7   x0 | D]( \ } } ˆ  | k r ˆ  | k  r t  Sq Wt S(   N(   R!   R   (   t   startt   known_rangest   at   b(   R×   (    s/   lib/python2.7/site-packages/numba/transforms.pyt   previously_occurredã  s    sH   unsupported controlflow due to return/raise statements inside with blocks   starting offset is not a label(   R.   R   R¼   R‚   R(   (   R%   RÞ   Rã   Rà   RØ   (    (   R×   s/   lib/python2.7/site-packages/numba/transforms.pyRœ   Ù  s    	N(   t   __doc__t
   __future__R    R   t   collectionsR   R   t   numba.analysisR   R   R™   R   R   R   R	   R*   R;   R?   RE   RO   RV   Rh   Rl   R‹   RŒ   R­   R    RŸ   Rž   R   Rœ   (    (    (    s/   lib/python2.7/site-packages/numba/transforms.pyt   <module>   s,   	+						#		F		9	9			