o
    Xi 2                     @  sl   d dl mZ d dlZd dlmZmZmZmZ d dlm	Z	m
Z
 dddZdddZdddZG dd dZdS )    )annotationsN)AnyOptionalSequenceSet)	ast_utils
sourceinfofor_stmtast.For	formattersourceinfo.Formatterreturnstrc                 C  s$   t | jtjst|| d| jjS )Nz*For loop target must be a single variable.)
isinstancetargetastName	TypeErrorid)r	   r    r   Q/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/_internal/analysis.py_get_loop_var   s   r   exprOptional[ast.expr]Set[str]c                 C  s   | du rt  S t| tjr| jhS t  }t| tjr2| j}| jD ]}t|jtjr0|	|jj q nt
| }|D ]}|t|B }q9|S )zMReturn set of all variables used, including function names, in an expression.N)setr   r   r   r   Callargskeywordsvalueadditer_child_nodes
_used_vars)r   resultchildrenkeywordcr   r   r   r"      s    

r"   lhsast.exprc                   s2   dd  t | tjr fdd| jD S  | hS )zGReturn set of assigned variables in the lhs of an assignment statement.c                 S  s   t | tjs
J d| jS )Nz"Only simple assignments supported.)r   r   r   r   )er   r   r   get_id(   s   z_lhs_vars.<locals>.get_idc                   s   h | ]} |qS r   r   .0xr*   r   r   	<setcomp>-   s    z_lhs_vars.<locals>.<setcomp>)r   r   Tupleelts)r'   r   r.   r   	_lhs_vars%   s   
r2   c                   @  sj   e Zd Z	d(d)d
dZd*ddZd*ddZd+ddZd,ddZd-ddZd.dd Z	d/d$d%Z
d0d&d'ZdS )1AstAnalyzerNfunast.FunctionDefr   r   globalsdict[str, Any] | Noner   Nonec                 C  s6   || _ i | _i | _i | _|r| || | | d S N)
_formatter_constant_if_condition_live_in	_live_out_compute_constant_if_conditionsdo_liveness_analysis)selfr4   r   r6   r   r   r   __init__2   s   zAstAnalyzer.__init__stmtast.stmtSet[str] | Nonec                 C     | j |S )zKGet the set of variables that are live at the entry of the given statement.)r<   getr@   rB   r   r   r   live_in@      zAstAnalyzer.live_inc                 C  rE   )zJGet the set of variables that are live at the exit of the given statement.)r=   rF   rG   r   r   r   live_outD   rI   zAstAnalyzer.live_outdict[str, Any]c                 C  sd   |  |j}t|D ]$}t|tjr/t|jtjr/|jj}||vr/||v r/t	|| | j
|< qdS )a:  Identify if-statements with constant conditions.

        If-statements of the form `if name:` where `name` is an outer-scope variable
        and name is not assigned to within the function body, are treated as constant
        conditions. The value of such conditions is determined from the outer-scope.
        N)assigned_varsbodyr   walkr   Iftestr   r   boolr;   )r@   r4   r6   rL   node
python_varr   r   r   r>   H   s   
z+AstAnalyzer._compute_constant_if_conditionsif_stmtast.IfOptional[bool]c                 C  s   | j |dS )a
  Return the constant value of the if-statement condition, if it is constant.

        Args:
            if_stmt: The if-statement-ast to analyze.

        Returns:
            The constant boolean value of the if-statement condition, or None if not constant.
        N)r;   rF   )r@   rT   r   r   r   constant_if_condition[   s   	z!AstAnalyzer.constant_if_conditionast.stmt | list[ast.stmt]r   c                   sJ  d fdd}t |tjrt|jd S t |tjrt|jS t |tjr(t S t |tj	rM 
|}|du rA||j||jB S |rH||jS ||jS t |tjr_||jt| jhB S t |tjrj||jS t |trs||S t |tjr|t S t |tjrt S t|rt S t|rt S  |d	t|d
}t|)zReturn the set of all variables that may be assigned to in an execution of input stmt
        or sequence of statements.
        blockSequence[ast.stmt]r   r   c                   s"   t  }| D ]	}| |B }q|S r9   )r   rL   )rY   r#   sr@   r   r   assigned_in_blockk   s   z4AstAnalyzer.assigned_vars.<locals>.assigned_in_blockr   NUnsupported statement type .)rY   rZ   r   r   )r   r   Assignr2   targets	AnnAssignr   Returnr   rO   rW   rM   orelseForr   r:   WhilelistBreakFunctionDefr   is_print_callis_doc_stringtype
ValueError)r@   rB   r]   constant_conderror_messager   r\   r   rL   f   s<   







zAstAnalyzer.assigned_varsc                   sT   d fdddfdd	 t |tjsJ t }t|jD ]}||}q d
S )z4Perform liveness analysis of the given function-ast.rB   rC   rJ   r   r   c                   s"   |j | <  | |}|j| < |S r9   )r=   r<   )rB   rJ   live)do_visitr@   r   r   visit   s   


z/AstAnalyzer.do_liveness_analysis.<locals>.visitc           
        s  dfdd}t | tjr|t| jd t| jB S t | tjr/|t| j	t| jB S t | tj
r:t| jS t | tjrl | }|d u r^|| j|}|| j|}||B t| jB S |rf|| j|S || j|S t | tjrt|  j}d }|}||kr|}|| j||h}||ks|S t | tjrt| j}	d }||	B }||kr|}|| j||	B }||ks|S t | tjr|S t| r|S t | tjr|S t| r|S t | d	t| d
)NrY   rZ   rJ   r   r   c                      t | D ]} ||}q|S r9   reversed)rY   rJ   r[   rr   r   r   
visitBlock      zFAstAnalyzer.do_liveness_analysis.<locals>.do_visit.<locals>.visitBlockr   r^   r_   rY   rZ   rJ   r   r   r   )r   r   r`   
differencer2   ra   r"   r   rb   r   rc   rO   rW   rM   rd   rP   re   r   r:   rf   rh   r   rk   ri   rj   rm   rl   )
rB   rJ   rw   rn   live1live2
p_loop_varprevcurr	cond_vars)r@   rr   r   r   rq      sZ   




z2AstAnalyzer.do_liveness_analysis.<locals>.do_visitNrB   rC   rJ   r   r   r   )r   r   ri   r   ru   rM   )r@   r4   rp   r[   r   )rq   r@   rr   r   r?      s   6z AstAnalyzer.do_liveness_analysisstmtsrZ   set[str]c                   s*   dfddd fd
d|t  S )az  Return the set of variables that are used before being defined by given block.
        In essence, this identifies the "inputs" to a given code-block.
        For example, consider the following code-block:
        ::

        x = x + 10
        y = 20
        z = x + y
        x = 30

        The exposed_uses of this code-block is { x }. The value of z is not used within
        the block. Even though the value of y is used within the block, it is assigned
        a value before it is used. However, in contrast, the incoming value of x is used
        (in the first statement). Hence x is included in the exposed_uses.
        rY   rZ   rJ   r   r   c                   rs   r9   rt   )rY   rJ   rB   rv   r   r   rw      rx   z,AstAnalyzer.exposed_uses.<locals>.visitBlockrB   rC   c           	        s  t | tjr|t| jd t| jB S t | tjr(|t| j	t| jB S t | tj
r3t| jS t | tjre | }|d u rW| j|}| j|}||B t| jB S |r_| j|S | j|S t| rl|S t| rs|S t | tjrt|  jh}||}| jt |}t| j}||B |B S t | tjr| jt }t| j}||B |B S t | tjr|S t | tjr| j|v r|| j | | B }|S t | dt| d)Nr   r^   r_   ) r   r   r`   rz   r2   ra   r"   r   rb   r   rc   rO   rW   rM   rd   rP   r   rj   rk   re   r   r:   r   iterrf   rh   ri   nameremoveouter_scope_variablesrm   rl   )	rB   rJ   rn   r{   r|   loop_var_setused_after_loopused_inside_loopused_in_loop_header)r@   rw   r   r   rr      sN   







z'AstAnalyzer.exposed_uses.<locals>.visitNry   r   )r   )r@   r   r   )r@   rr   rw   r   exposed_uses   s   0zAstAnalyzer.exposed_usesc                 C  s8   t |tjsJ | |j}dd |jjD }||S )zReturn the set of outer-scope variables used in a nested function.

        Args:
            fun: The function-ast to analyze.
            formatter: The formatter object.

        Returns:
            A set of variable names (strings).
        c                 S  s   g | ]}|j qS r   )argr+   r   r   r   
<listcomp>*  s    z5AstAnalyzer.outer_scope_variables.<locals>.<listcomp>)r   r   ri   r   rM   r   rz   )r@   r4   
used_vars_inputsr   r   r   r     s   

z!AstAnalyzer.outer_scope_variablesr9   )r4   r5   r   r   r6   r7   r   r8   )rB   rC   r   rD   )r4   r5   r6   rK   r   r8   )rT   rU   r   rV   )rB   rX   r   r   )r4   r5   r   r8   )r   rZ   r   r   )r4   r5   r   r   )__name__
__module____qualname__rA   rH   rJ   r>   rW   rL   r?   r   r   r   r   r   r   r3   1   s    





,
DHr3   )r	   r
   r   r   r   r   )r   r   r   r   )r'   r(   r   r   )
__future__r   r   typingr   r   r   r   onnxscript._internalr   r   r   r"   r2   r3   r   r   r   r   <module>   s   


