B
      ›\º5  ã               @   s    d Z ddlmZmZmZ ddlmZmZmZ ddl	m
Z
mZmZ ddlmZ G dd„ deƒZG d	d
„ d
eƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdS )z"
Support for lowering generators.
é    )Úprint_functionÚdivisionÚabsolute_import)ÚConstantÚTypeÚBuilderé   )ÚcgutilsÚtypesÚconfig)ÚFunctionDescriptorc               @   s,   e Zd ZdZdZedd„ ƒZedd„ ƒZdS )ÚGeneratorDescriptorz9
    The descriptor for a generator's next function.
    © c             C   sl   t |tjƒst‚|j}dg}|f}|jd }|jd }	| |j|j||	|j	|j
||j||j||d|jd}
|
S )a  
        Build a GeneratorDescriptor for the generator returned by the
        function described by *fndesc*, with type *gentype*.

        The generator inherits the env_name from the *fndesc*.
        All emitted functions for the generator shares the same Env.
        Úgenz.nextT)ÚargtypesÚmanglerZinlineÚenv_name)Ú
isinstancer
   Ú	GeneratorÚAssertionErrorÚ
yield_typeÚqualnameÚunique_nameZnativeÚmodnameÚdocZtypemapZ	calltypesZkwsr   )ÚclsÚfunc_irÚfndescÚgentyper   ÚrestypeÚargsr   r   r   Úselfr   r   ú/lib/python3.7/site-packages/numba/generators.pyÚfrom_generator_fndesc   s    	


z)GeneratorDescriptor.from_generator_fndescc             C   s
   d| j  S )zz
        The LLVM name of the generator's finalizer function
        (if <generator type>.has_finalizer is true).
        Z	finalize_)Zmangled_name)r!   r   r   r"   Úllvm_finalizer_name'   s    z'GeneratorDescriptor.llvm_finalizer_nameN)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__Úclassmethodr#   Úpropertyr$   r   r   r   r"   r      s   r   c               @   s`   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚBaseGeneratorLowerz5
    Base support class for lowering generators.
    c             C   sr   |j | _ |j| _|j| _|j| _|j| _|j| _|  ¡ | _t	 
|j| j| j| j j¡| _| j  | jj¡| _i | _d S )N)Úcontextr   ÚlibraryÚ	call_convr   Úgenerator_infoÚgeninfoÚget_generator_typer   r   r#   r   ÚgendescZget_data_packerr   Ú
arg_packerÚresume_blocks)r!   Úlowerr   r   r"   Ú__init__5   s    
zBaseGeneratorLower.__init__c             C   s   t  ||dd¡S )Nr   r   )r	   Úgep_inbounds)r!   ÚbuilderÚgenptrr   r   r"   Úget_args_ptrE   s    zBaseGeneratorLower.get_args_ptrc             C   s   t j||ddddS )Nr   zgen.resume_index)Úname)r	   r8   )r!   r9   r:   r   r   r"   Úget_resume_index_ptrH   s    z'BaseGeneratorLower.get_resume_index_ptrc             C   s   t j||ddddS )Nr   é   z	gen.state)r<   )r	   r8   )r!   r9   r:   r   r   r"   Úget_state_ptrL   s    z BaseGeneratorLower.get_state_ptrc             C   s  |  | j¡ |j}|j | j| j| jg¡ | ¡  | 	¡  | j 
| j¡}| j tjd¡}|jd }|jd }| d¡ | jjr®x.t| jj|jƒD ]\}}| jj |||¡ qW | j ||j¡}	t |¡}
t |||	|
g|¡}|  ||¡}| d¡ | j ||¡ | ¡  dS )z‰
        Lower the generator's initialization function (which will fill up
        the passed-by-reference generator structure).
        r   r   r>   z# low_init_func increfz# low_init_func before returnN) Úsetup_functionr   r9   r-   Zinsert_generatorr   r3   r.   Zextract_function_argumentsZ	pre_lowerZget_return_typeZget_constantr
   Zint32ÚelementsÚdebug_printÚ
enable_nrtÚzipr   ÚfnargsÚnrtÚincrefr4   Zas_datar   Únullr	   Zmake_anonymous_structÚbox_generator_structr/   Zreturn_valueZ
post_lower)r!   r6   r9   ZrettyÚresume_indexZargstyZstatestyZargtyZargvalZargsvalZ	statesvalÚ
gen_structZretvalr   r   r"   Úlower_init_funcP   s0    





z"BaseGeneratorLower.lower_init_funcc             C   s(  |  | j¡ | d | jj¡¡ | jjd | jks6t‚|j}|j	}| j
 |¡\}| j ||  ||¡|j¡ |  ||¡| _|  ||¡| _| d¡}| ¡ }| d¡}| |¡ | j
 |¡ | |¡ |j|j  }| jd< | | | j¡|¡}	x"| j ¡ D ]\}
}|	 |
|¡ qøW | |¡ | |¡ dS )z¥
        Lower the generator's next() function (which takes the
        passed-by-reference generator structure and returns the next
        yielded value).
        z# lower_next_func: {0}r   Zgenerator_prologueZstop_iterationN) r@   r3   rB   Úformatr   r   r   r   r9   Úfunctionr/   Zget_argumentsr4   Z	load_intor;   rE   r=   Úresume_index_ptrr?   Úgen_state_ptrÚappend_basic_blockZlower_function_bodyÚposition_at_endÚreturn_stop_iterationZblkmapZfirstblkr5   ÚswitchÚloadÚitemsZadd_caseÚbranch)r!   r6   r9   rN   r:   ZprologueZentry_block_tailZ
stop_blockZfirst_blockrT   ÚindexÚblockr   r   r"   Úlower_next_func   s0    





z"BaseGeneratorLower.lower_next_funcc             C   sr   t  t  ¡ | j | j¡g¡}|jj|| jj	d}| 
d¡}t|ƒ}| j | j¡}| |jd |¡}|  ||¡ dS )z2
        Lower the generator's finalizer.
        )r<   Úentryr   N)r   rN   Zvoidr-   Zget_value_typer   ÚmoduleZget_or_insert_functionr3   r$   rQ   r   Zbitcastr    Úlower_finalize_func_body)r!   r6   ZfntyrN   Zentry_blockr9   Zgenptrtyr:   r   r   r"   Úlower_finalize_func¯   s    

z&BaseGeneratorLower.lower_finalize_funcc             C   s4   t  | jjjd¡}|j || j¡ | j |j¡ dS )zY
        Emit a StopIteration at generator end and mark the generator exhausted.
        éÿÿÿÿN)	r   ÚintrO   ÚtypeÚpointeer9   Ústorer/   rS   )r!   r6   Úindexvalr   r   r"   Úreturn_from_generator¾   s    z(BaseGeneratorLower.return_from_generatorc             C   s0   d|f }|j  |¡}|j |¡ || j|< d S )Nzgenerator_resume%d)rN   rQ   r9   rR   r5   )r!   r6   rX   Z
block_namerY   r   r   r"   Úcreate_resumption_blockÆ   s    
z*BaseGeneratorLower.create_resumption_blockc             C   s   t jr| j |d |¡¡ d S )NzDEBUGJIT: {0})r   Z	DEBUG_JITr-   rB   rM   )r!   r9   Úmsgr   r   r"   rB   Ì   s    zBaseGeneratorLower.debug_printN)r%   r&   r'   r(   r7   r;   r=   r?   rL   rZ   r^   re   rf   rB   r   r   r   r"   r,   0   s   1.r,   c               @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚGeneratorLowerz9
    Support class for lowering nopython generators.
    c             C   s   | j jS )N)r   r   )r!   r   r   r"   r2   Õ   s    z!GeneratorLower.get_generator_typec             C   s   |S )Nr   )r!   r6   rK   r   r   r"   rI   Ø   s    z#GeneratorLower.box_generator_structc             C   sf   |   |d¡ | jjrN|  ||¡}x,| j ||¡D ]\}}| jj |||¡ q0W |   |d¡ | ¡  dS )zg
        Lower the body of the generator's finalizer: decref all live
        state variables.
        z# generator: finalizez# generator: finalize endN)	rB   r-   rC   r;   r4   rU   rF   ÚdecrefÚret_void)r!   r9   r:   Zargs_ptrÚtyÚvalr   r   r"   r]   Û   s    z'GeneratorLower.lower_finalize_func_bodyN)r%   r&   r'   r(   r2   rI   r]   r   r   r   r"   rh   Ð   s   rh   c               @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚPyGeneratorLowerz<
    Support class for lowering object mode generators.
    c             C   s8   t j| jjjt jt jf| jj t jft| jj	ƒ ddS )zx
        Compute the actual generator type (the generator function's return
        type is simply "pyobject").
        T)Zgen_funcr   Z	arg_typesÚstate_typesZhas_finalizer)
r
   r   r   Zfunc_idÚfuncZpyobjectZ	arg_countÚlenr1   Ú
state_vars)r!   r   r   r"   r2   ñ   s    z#PyGeneratorLower.get_generator_typec             C   s"   t  |j|¡}|j || j|j¡S )z>
        Box the raw *gen_struct* as a Python object.
        )r	   Zalloca_once_valuer9   ÚpyapiZfrom_native_generatorr   Zenvarg)r!   r6   rK   Zgen_ptrr   r   r"   rI   þ   s    z%PyGeneratorLower.box_generator_structc             C   s    |j  t | jjj¡| j¡ dS )zo
        NULL-initialize all generator state variables, to avoid spurious
        decref's on cleanup.
        N)r9   rc   r   rH   rP   ra   rb   )r!   r6   r   r   r"   Úinit_generator_state  s    z%PyGeneratorLower.init_generator_statec          	   C   sº   | j  |¡}|  ||¡}| |¡}| d|t |jd¡¡}t 	||¡b |  
||¡}xNtt| jjƒƒD ]:}t ||d|¡}	| jj| }
| j  ||
|	¡}| |¡ qfW W dQ R X | ¡  dS )zg
        Lower the body of the generator's finalizer: decref all live
        state variables.
        ú>r   N)r-   Zget_python_apir=   rU   Zicmp_signedr   r`   ra   r	   Zif_unlikelyr?   Úrangerp   r   rn   r8   Úunpack_valueri   rj   )r!   r9   r:   rr   rO   rJ   Zneed_cleanuprP   Ústate_indexÚ
state_slotrk   rl   r   r   r"   r]     s    
z)PyGeneratorLower.lower_finalize_func_bodyN)r%   r&   r'   r(   r2   rI   rs   r]   r   r   r   r"   rm   ì   s
   rm   c               @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú
LowerYieldz>
    Support class for lowering a particular yield point.
    c                sj   ˆ | _ ˆ j| _ˆ j| _ˆ j| _| jj| _| jj| _| jj| _|| _| jj| _|| _	‡ fdd„|D ƒ| _
d S )Nc                s   g | ]}ˆ j j |¡‘qS r   )r0   rq   rX   )Ú.0Úv)r6   r   r"   ú
<listcomp>:  s   z'LowerYield.__init__.<locals>.<listcomp>)r6   r-   r9   Úgenlowerr   rP   rO   ZypÚinstÚ	live_varsÚlive_var_indices)r!   r6   Zyield_pointr   r   )r6   r"   r7   .  s    




zLowerYield.__init__c             C   sº   | j  d¡ xvt| j| jƒD ]d\}}t | j| jd|¡}| j	j
| }| j  |¡}| jjrl| jj | j||¡ | j | j|||¡ qW t | jjj| jj¡}| j || j¡ | j  d¡ d S )Nz# generator suspendr   z# generator suspend end)r6   rB   rD   r€   r   r	   r8   r9   rP   r   rn   Zloadvarr-   rC   rF   rG   Z
pack_valuer   r`   rO   ra   rb   r~   rX   rc   )r!   rw   r<   rx   rk   rl   rd   r   r   r"   Úlower_yield_suspend=  s    
zLowerYield.lower_yield_suspendc             C   s¨   | j  | j| jj¡ | j d¡ xvt| j| jƒD ]d\}}t	 
| j| jd|¡}| jj| }| j | j||¡}| j ||¡ | jjr0| jj | j||¡ q0W | j d¡ d S )Nz# generator resumer   z# generator resume end)r}   rf   r6   r~   rX   rB   rD   r€   r   r	   r8   r9   rP   r   rn   r-   rv   ZstorevarrC   rF   ri   )r!   rw   r<   rx   rk   rl   r   r   r"   Úlower_yield_resumeP  s    zLowerYield.lower_yield_resumeN)r%   r&   r'   r(   r7   r   r‚   r   r   r   r"   ry   )  s   ry   N)r(   Z
__future__r   r   r   Zllvmlite.llvmpy.corer   r   r   Ú r	   r
   r   Zfuncdescr   r   Úobjectr,   rh   rm   ry   r   r   r   r"   Ú<module>   s   $ !=