o
    Xi                     @  s  d dl mZ d dlZd dlZd dlmZmZmZmZm	Z	 d dl
Zd dlZd dlmZ d dlmZmZmZmZmZmZmZ d dlmZ d dlmZ edZd	d
 ZG dd deZdd Zd7ddZ dd Z!dd Z"i ej#dej$dej%dej&dej'dej(dej)dej*dej+dej,dej-d ej.d!ej/d"ej0d#ej1d$ej2dej3d%ej4d&ej5d'iZ6ere	ej7ej8f Z9eZ:e	e9e:f Z;e<Z=e<Z>d8d-d.Z?d9d3d4Z@G d5d6 d6ZAdS ):    )annotationsN)TYPE_CHECKINGAnyNoReturnSequenceUnion)
onnx_types)analysis	ast_utilsautocast	irbuilderparam_manipulation
sourceinfovalues)type_annotation)_schemas
onnxscriptc                 C  s
   |  dS )Nznot supported. )	constructr   r   R/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/_internal/converter.pynot_allowed'      
r   c                      s   e Zd Zd fddZ  ZS )TranslationErrorargsobjectreturnNonec                   s   t  j|  d S N)super__init__)selfr   	__class__r   r   r   ,   s   zTranslationError.__init__)r   r   r   r   )__name__
__module____qualname__r   __classcell__r   r   r!   r   r   +   s    r   c                 C  s   t |  d S r   )loggerwarningmsgr   r   r   warn0   s   r+   r   r   c                 C  s   t | r   r   r)   r   r   r   fail4      r-   c                 C  s   | rt |d S r   r,   condr*   r   r   r   fail_if8   s   r1   c                 C  s   | rt | d S d S r   )r+   r/   r   r   r   ignore=   s   r2   AddAndOrDivEqualGreaterGreaterOrEqualLessLessOrEqualMatMulModMulNotNotEqualPowSubNegvalueir.Valuetypeinfota.TypeAnnotationValuer   c                 C  sD   zt | }|j| _|j| _W n	 ty   Y nw || jd< dS )z)Sets the type information on an IR value.rF   N)ir
from_prototo_type_prototypeshapeAttributeErrormeta)rD   rF   type_and_shaper   r   r   set_type_infoz   s   rP   varnamestrsource_infosourceinfo.SourceInfoc                 C  s0   t j| d}|jd| |d urt|| |S )Nnamer   )rH   ValuerN   
setdefaultrP   )rQ   rF   rS   rD   r   r   r   
make_value   s
   
rY   c                   @  s4  e Zd ZdZ				ddd
dZdddZedddZedddZdddZ	dddZ
ddd Zdd"d#Zdd%d&Zdd'd(Zdd*d+Zdd.d/Zdd1d2Zdd4d5Zdd8d9Z	:ddd>d?ZdddBdCZddGdHZ		dddMdNZddPdQZ	ddd[d\Zdd]d^ZddbdcZddedfZddgdhZddkdlZddodpZ	dddudvZ ddxdyZ!dddzd{Z"dd}d~Z#dddZ$dddZ%dddZ&dddZ'dd Z(dd Z)dddZ*dddZ+dddZ,ddddZ-dddZ.dddZ/dddZ0dddZ1dddZ2dddZ3dddZ4dddZ5dddZ6dddZ7dS )	Convertera  Main class to translate python code into ONNX operators.

    Args:
        ir_builder: convert AST node into ONNX structures, if None,
            class :class:`onnxscript.irbuilder.IRBuilder` is used

    The class uses logger `onnxscript`. Logging can be enabled with the following code:

    ::

        import logging
        logging.basicConfig(level=logging.DEBUG)

    Or if you need to enable only the logger used by this module:

    ::

        import logging
        logger = logging.getLogger('onnxscript')
        logger.setLevel(logging.DEBUG)
        console = logging.StreamHandler()
        logger.addHandler(console)
    Nopsetvalues.Opset | Noneglobal_namesdict[str, Any] | Nonesource
str | Nonedefault_opsetc                 C  sX   || _ |d ur| | _|| _|| _g | _d | _d| _t | _	i g| _
d | _t | _d S )Nr   )r_   copyglobalsthis_moduledefault_opset__outer_current_fn_nextvarset
_used_vars_locals	_analyzer	_castable)r    r[   r]   r_   ra   r   r   r   r      s   
zConverter.__init__var_namerR   r   boolc                 C  s
   || j v S )zSReturns True if the variable with the given name represents a polymorphic constant.)rm   )r    rn   r   r   r   is_castable   s   
zConverter.is_castableanalysis.AstAnalyzerc                 C     | j d u r	td| j S )NzAnalyzer not initialized.)rl   RuntimeErrorr    r   r   r   analyzer   s   
zConverter.analyzervalues.Opsetc                 C  rr   )Nzedefault_opset must be specified in script for functions that do not contain any use of an ONNX opset.)re   rs   rt   r   r   r   ra      s
   
zConverter.default_opsetnodeast.ASTr   c                 C  sb   |j dkrd S | jd ur,|j | jj ks|j| jjkr*| |d| d| j d d S d S || _d S )N zTwo distincts opset were used (z != z).)domainre   versionr-   )r    r[   rw   r   r   r   _set_default_opset   s   


zConverter._set_default_opsetc                 C  s   t |tjr0t |jtjr0|jj}t |tjr0|j| jv r0| j|j }t |t	j
r0|jdkr0|S t|D ]}| |}|durD|  S q5dS )z9Find the (first) ONNX opset used in the function, if any.ry   N)
isinstanceastCallfunc	AttributerD   Nameidrc   r   Opsetrz   iter_child_nodes_find_onnx_opset)r    rw   
opset_exprr[   childresr   r   r   r      s   
zConverter._find_onnx_opsetc                 C  s&   g | _ d| _d| _t | _i g| _dS )z;Initialize self for translating a new (top-level) function.Nr   )rf   rg   rh   ri   rj   rk   rt   r   r   r   _init_function_translation   s
   z$Converter._init_function_translationrT   c                 C  s   t j|| j| jjdS )N)codefunction_name)r   
SourceInfor_   rg   rV   r    rw   r   r   r   
_source_of   s   zConverter._source_of	error_msgc                 C  s   |  ||S )zMConstructs an error _message containing source information about an ast node.)r   r*   r    rw   r   r   r   r   _message   s   zConverter._messagec                 C     t | || d S r   )r+   r   r   r   r   r   r+        zConverter.warnr   c                 C  r   r   )r-   r   r   r   r   r   r-     r   zConverter.failrV   parent_nodec                 C  sB   | j | j t|| _| ji  tdt| jt	| dS )zEnter a control-flow block (a loop body or if-then-else branch).
        The block is translated into a nested-scope in ONNX.
        z!Converter:_enter_scope:%d:node:%sN)
rf   appendrg   r   
IRFunctionrk   r'   debuglenrK   )r    rV   r   r   r   r   _enter_scope  s   zConverter._enter_scopeirbuilder.IRFunctionc                 C  s2   t dt| j | j}| j | _| j  |S )zDExit from a control-flow block (a loop body or if-then-else branch).zConverter:_exit_scope:%d)r'   r   r   rk   rg   rf   pop)r    graphr   r   r   _exit_scope  s
   
zConverter._exit_scopedict[str, LocalSymValue]c                 C  s
   | j d S )N)rk   rt   r   r   r   _current_scope!  r   zConverter._current_scopevalLocalSymValuec                 C  s   t d| || jd |< d S )NzConverter:_bind:%sr   )r'   r   rk   )r    rV   r   r   r   r   _bind$  s   zConverter._bindTinforaise_exceptionSymValuec                 C  sV   t | jD ]}||v r||   S q|| jv r| j| S |r)t|d| ddS )a  Maps a python variable name to the corresponding value used during translation.

        Typically, a python variable X will correspond to an ONNX value Y. But other special
        cases include: constant values or functions (mapped to Graph attributes), etc.
        zUnbound name: .N)reversedrk   rc   
ValueErrorr*   )r    rV   r   r   scoper   r   r   _lookup(  s   	

zConverter._lookuptmp	candidatec                 C  sD   |}|| j v r| d| j }| jd | _|| j v s| j | |S )N_   )rj   rh   add)r    r   rr   r   r   generate_unique_name:  s   

zConverter.generate_unique_namevalues.AttrRefsourceinfo.SourceInfo | Noneir.Attrc                 C  s   |j j}d }|tjju rd}n,|tjju rd}n#|tjju r!d}n|tjju r*d}nd|d}t|r8|	|n| tj
||d |j jdS )Nvalue_float	value_intvalue_string
value_intszUnsupported attribute type r   rD   ref_attr_name)rD   rK   rH   AttributeTypeFLOATINTSTRINGINTSr-   r*   AttrrV   )r    r   r   attrtypeattrnamer*   r   r   r   _to_onnx_attr_refC  s   zConverter._to_onnx_attr_refvalues.SymbolValue | PyValuetargetPreferredName | NonerE   c           	      C  s   t |tjrR| |pd}| ||}| |gt| jdg |g}|jrJ| |d }t	
dtjj}| j| | |gt| jd|g|gS | j| |S t |tjrbt |jt	jrb|jS | ||phd|S )Nr   Constant_as_booltoCast)r}   r   AttrRefr   r   emitOpra   as_boolrH   	AttrInt64r   BOOLdtyperm   r   emit1SymbolValuerD   rW   _emit_const)	r    r   r   r   result_nameattrresultresult_as_bool	cast_attrr   r   r   _to_onnx_varU  s,   zConverter._to_onnx_varpy_varc                 C  s   | j | ||||dS )N)r   r   )r   r   )r    r   r   r   r   r   _py_var_to_onnx_vary  s   zConverter._py_var_to_onnx_varoutputsSequence[str]calleevalues.Op | strinputsSequence[ir.Value | None]attrsSequence[ir.Attr] | NoneSequence[ir.Value] | ir.Valuec                 C  s   t |tjst| j|}|d u rg }dd |D }tj|jj|jj|j	|||d}t |tjs:t
dt| d|jd| | jd usHJ | j| t|dkrV|S |d S )	Nc                 S  s   g | ]}t j|d qS )rU   )rH   rW   ).0or   r   r   
<listcomp>      z"Converter.emit.<locals>.<listcomp>)rz   r{   op_typer   r   
attributeszUnexpected type z for callee.r   r   r   )r}   r   r   ra   rH   Noder[   rz   r{   rV   	TypeErrorrK   rN   rX   rg   append_noder   )r    r   r   r   r   output_valuesrw   r   r   r   r   |  s&   zConverter.emitc                 O  s4   | j |i |}t|tjstdt|d|S )Nz#Expected single ONNX IR Value, got r   )r   r}   rH   rW   r   rK   )r    r   kwargsr   r   r   r   r     s   zConverter.emit1pyvaluePyValuesuggested_namec              
   C  s$  |d u rIt |tr|dkrd| }n6dt| }n.t |trGt|dkrGt |d trG|d dkr<d|d  d}ndt|d  d}nd}| |}z	tj||d}W n tyv } z| 	|j
d|d	|  W Y d }~nd }~ww td
|}| j| | |gt| jdg |gS )Nr   int64_int64_mr   _1dconstrU   z!Failed to convert constant value z to ONNX tensor: rD   r   )r}   intabslistr   r   rH   tensor	Exceptionr-   ast_node
AttrTensorrm   r   r   r   r   ra   )r    r   r   r   ovarr   excr   r   r   r   r     s2   

zConverter._emit_constoriginal_varc                 C  s   |  |}| |gd|gS )z9Emits a copy statement, using the ONNX Identity operator.Identity)r   r   )r    r  r   new_varr   r   r   
_emit_copy  s   
zConverter._emit_copyc              
     sb   t |tjr |jS t |tjtjtjtjtjtj	tj
tjfr/t fddt|D S dS )Nc                 3  s    | ]}  |V  qd S r   )_is_constant_expr)r   crt   r   r   	<genexpr>  s    z.Converter._is_constant_expr.<locals>.<genexpr>F)r}   r~   UnaryOpr  operandr   BinOpComparer   ListLoadr   allr   r   r   rt   r   r    s    zConverter._is_constant_exprexprast.exprc                 C  sl   i }t t|ddd}zt|| j|W S  ty5 } zt| |dt| jdt|d|d}~ww )aF  Evaluates a sub-expression that is assumed to represent a constant value.
        The expression can refer only to global names (inherited from the scope
        where the script is evaluated) and cannot refer to local names defined
        within the script.) Further, these expressions are assumed to be constants.
        Thus, any subsequent mutation of any state/variables (used in computing
        this constant value) will potentially lead to unexpected behavior (such
        as divergence between eager-mode execution and evaluation of the ONNX
        function.)
        z<ast>eval)filenamemodez Missing names, globals contains z	, locals r   N)compiler~   
Expressionr  rc   	NameErrorr   r   )r    r  localscpler   r   r   _eval_constant_expr  s"   zConverter._eval_constant_expr
annotationta.TypeAnnotationValue | Nonec                 C  s(   |  |}t|s| |d d }|S )NzUnsupported type annotation.)r  tais_valid_typer+   )r    r  rF   r   r   r   _get_type_annotation  s   

zConverter._get_type_annotation	attr_name	attr_meta"_schemas.AttributeParameter | Noneir.Attr | Nonec              	   C  s  t |tjr| |j| |}t |tjr|j}t |t	j
rG|}t	j
||jd|jd}|durE|j|jkrE| |d|j d|j d |S t |tjrw|}|jD ]!\}}	| || |}
|
j|	jkrs| |d| d|jd qR|j}t |t	jr| |d	|j d
 n		 n	 n| |}|du r|r|jr| |d| d dS |r|jnd}|t	jjkrt	|}t	j|||}|S )a  Translate an attribute-value specification of the form `attr_name=<expr>`
        in a call to an op. expr is an AST. The following cases are supported:
        * Expr evaluates to a script-time constant (a python-value) that can be mapped
        into an ONNX attribute value, or
        * Expr evaluates to None, in which case None is returned, or
        * Expr must be an attribute-reference, that is a name representing an
        attribute-parameter of a containing function.
        Nr   zAttribute type 'z ' does not match expected type ''zOuter scope variable 'z' referenced by function 'z' modified.zCannot use ir.Value 'z' as an attribute.zAttribute 'z' is required.)r}   r~   r   r   r   r   r   r   rD   rH   r   rK   rV   r-   r   r   outer_scope_variablesr   rW   r  requiredr   TENSORr   convenienceconvert_attribute)r    r"  r  r#  r   r   attr_ref
irfunctionpyvarpreviouscurrent	attr_typer   r   r   _translate_attr  sT   


zConverter._translate_attrast.Exprc                 C  s*   t |jtjs| |d |jj| j_d S )Nz(Docstring expression must be a constant.)r}   rD   r~   r   r-   rg   
doc_stringr   r   r   r   _translate_docstringC  s   zConverter._translate_docstringc                 C  s2  t |tjr| |}nct |tjtjtjfr| |}nRt |tjr)| 	|}nFt |tj
r5| |}n:t |tjrA| |}n.t |tjrN| ||}n!| |ra| | ||| |}nt| |dt|dt |tjrw|S |\}}}|du rdn|}t |tsJ | |}| |g|||S )zExpression-translation generates "IR statements/nodes" that compute the value of
        the expression into a target-variable, and returns the variable that is
        assigned this value.
        zUnsupported expression type r   Nr   )r}   r~   r   _translate_call_exprr  BitAndBitOr_translate_binary_op_exprr
  _translate_unary_op_exprr  _translate_compare_exprr   _translate_name_expr	Subscript_translate_subscript_exprr  r   r  r   r   r   rK   rH   rW   rR   r   r   )r    rw   r   r   r   r   r   r   r   r   r   _translate_exprH  s0   


zConverter._translate_exprir.Value | Nonec                 C  s$   t |tjr|jdu rdS | |S )zTranslation of an expression where "None" is permitted (eg., for an optional argument).
        None is represented as a Constant in Python 3.9+.
        N)r}   r~   r   rD   r?  r   r   r   r   _translate_opt_exprg  s   
zConverter._translate_opt_exprast.Subscriptc           +   	     sT   |j}|j}|du r| d}|}t|}|ji  d,d- fddd.fd	d
dd	d,d/fddd0fdd}g }g }g }	t|D ]=\}
}t	|t
jrx|jdu rp|jdu rp|jdu sw||
|f qW|rt	|tr||
|f qW|	|
|f qW|s|s|	s|gd|gS |st|dkrg }g }g }g }g }|D ]B\}
}|}||
 tt|d|jt|d|jd}t
t
j|fi |t
j|d fi |t
jd1i |}||
|f qg }|D ]'\}
}|
}||}||d  ||d  || ||d  q t|dkr~tdd}| d}|gd ||g}| d!}|gd ||g}| d"}|gd ||g}| d#}|gd ||g}n|d }|d }|d }|d }|rƈ| d$} | gd%|||||g}!|d&}|	r| d'}"n|}"|"gd(|!|g}#n |	r҈| d$}"n|}"|||||g}$|"gd%|$}#n|}#|	| |	r|	d) \}%}&nd}%|	D ].\}
}' |'}(td|
})|
|%kr| d*|
 }*n|}*|*gd+|#|(g|)g}#q|#S )2a>  List of supported syntaxes is below.
        `A` is a tensor or an expression equivalent to a tensor.

        ::

            A[:, 1]
            A[:2, 0]
            A[:2, :1]
            A[2:0:-1]
            A[1:]
            A[:2]
            A[1:-1]
            A[1:2]
            A[-1]
            A[0]
            A[:0:-1]

        *i* is a tensor holding one integer.

        ::

            A[i]
            A[i+1:i+2]

        Fully supported for python 3.9+.

        ::

            A[i:i+j, k]

        Not supported:

        ::

            A[::-1]
        N_subscriptedrV   r`   r   rE   c                   s$   |  vr | g| | <  |  S r   )r   )rD   rV   )cached_int_constsr   r    r   r   const_1d  s   z5Converter._translate_subscript_expr.<locals>.const_1dc                     s    dS )Nr   r   r   )rE  r   r   one_1d  r.   z3Converter._translate_subscript_expr.<locals>.one_1dl    l         default_value
int | Nonetuple[ir.Value, int | None]c                   s   | du r|du rt d ||fS | r0| }t|tr' ||fS t dt| | }|j d}	|gt
jd| gg }|dfS )zCTranslate optional start/stop/step component of a Slice expression.Nz@Default start/stop not supported when step direction is unknown.z&Slice component type must be int, not 	_reshapedReshape)rs   r  r  r}   r   rK   r?  r   rV   r   r   r   ra   )node_argrG  cstrD   reshapedreshaped_value)rE  rF  r    r   r   translate_slice_component  s(   



zFConverter._translate_subscript_expr.<locals>.translate_slice_component
slice_expr	ast.Slice#tuple[ir.Value, ir.Value, ir.Value]c                   s   | j d\}}|du r| jd\}}| jd\}}n%|dkr2| jd\}}| j \}}n| j \}}| j\}}|||fS )z4Translate slice-expression of the form from:to:step.r   Nr   )steplowerupper)rQ  	step_namerT  
lower_namer   
upper_name)maxintminintrP  r   r   translate_slice  s   
z<Converter._translate_subscript_expr.<locals>.translate_slicer  r   lineno
col_offsetr]  r^  r      axis_startConcat_end_axis_step_slicedSlicesqueezed_axes	_squeezedSqueezer   _axis_Gatherr   )rV   r`   r   rE   r   rE   )rG  rH  r   rI  )rQ  rR  r   rS  )r   )r?  rD   rV   r   r
   normalize_subscript_exprr   slice	enumerater}   r~   rh  rU  rV  rT  r   r  r  r   r   r   dictgetattrr]  r^  r   rH   r   r   r   extend)+r    rw   r   varrn   indicesr\  sliced_indicesscalar_indicesnon_scalar_indicesra  eltstartsendsaxesstepsri  r  indexr   elementaxis_varr   axis_0_attr
start_namestart_valueend_name	end_value	axes_name
axes_value
steps_namesteps_valuesliced_namesliced_valuer   r   slice_inputs	last_axisr   
index_exprindex_value	axis_attrgatheredr   )rD  rE  r   rZ  r[  rF  r    rP  r   r>  o  s   '









z#Converter._translate_subscript_exprast.Call6tuple[values.Op, list[ir.Value | None], list[ir.Attr]]c                   s    |j}|j  r5dd |jD }tj |j|dd\}}fdd|D } fdd| D }nfdd|jD }fd	d|jD }t	 |}d
d |D }|||fS )zTranslates a call-expression.c                 S  s   i | ]}|j |jqS r   )argrD   r   xr   r   r   
<dictcomp>`      z2Converter._translate_call_expr.<locals>.<dictcomp>F)fill_defaultsc                      g | ]}  |qS r   rA  r  rt   r   r   r   d  r  z2Converter._translate_call_expr.<locals>.<listcomp>c              	     s$   g | ]\}} || |qS r   )r2  get)r   r  yop_signaturer    r   r   r   e  s   $ c                   r  r   r  r  rt   r   r   r   g  r  c                   s   g | ]
}  |j|jqS r   )r2  r  rD   r  rt   r   r   r   h  s    c                 S  s   g | ]}|d ur|qS r   r   )r   r   r   r   r   r   n  r   )
_translate_callee_exprr   r  keywordsr   (separate_input_attributes_from_argumentsr   itemsr   static_cast_inputs)r    rw   r   r   r   r   r   r  r   r6  W  s   


zConverter._translate_call_exprtuple[ir.Value, ir.Value]c                 C  s   |j }t| |||fS r   )r  r   r  )r    opleftrightr  r   r   r   _cast_like_binary_expressionq  s   z&Converter._cast_like_binary_expression	ast.BinOpc                 C  s   t |j}|tvrt| |d|dg }t|jtjr6| |j	r6| 
|j	}t|tr6tddg}t| jt| }| || |j| |j	\}}|||g|fS )NUnsupported operator r   fmodr   )rK   r  
primop_mapr   r   r}   r~   r=   r  r  r  floatrH   r   r   r   ra   r  r?  r  )r    rw   r  r   rM  r  r  r   r   r   r9  u  s   

z#Converter._translate_binary_op_exprc                 C  s   t |j}|tvrt| || d|d| |jrB|jj}|t	j
kr7t	j| |j|jd}| |S |t	jkrB| |jS t| }| |j}t| j||gg fS )Nr  r   r_  )rK   r  r  r   r   r*   r  r  rD   r~   USubr   r]  r^  r?  UAddr   r   ra   )r    rw   r  r   rM  opnamer  r   r   r   r:    s   



z"Converter._translate_unary_op_exprc           	      C  s   t |jdks	J t |jdksJ t|jd }|tvr)t| |d|dt| }| |j}| |jd }t	
| j|dkrE|nd}| |||\}}|dkrp|  }| |g|||g}t	
| jd}||gg fS |||gg fS )Nr   r   r  r   r@   r7   r?   )r   opscomparatorsrK   r  r   r   r?  r  r   r   ra   r  r   r   )	r    rw   r  r  r  r  r   	tmp_valuenot_opr   r   r   r;    s    z!Converter._translate_compare_exprast.Namec                 C  s   |  |j| |S r   )r   r   r   r   r   r   r   r<    r   zConverter._translate_name_exprast.Attributec                 C  s   t |tjr,| j|j| |dd}t |tjr|S | |d|j dt	| d dS t |tj
r:| |d dS | |d dS )	zReturn an OpsetFr   r&  z'' is not an instance of type Opset but r   zNested module unimplemented.zInvalid opset expression.N)r}   r~   r   r   r   r   r   r   r-   rK   r   )r    rw   r   r   r   r   _translate_opset_expr  s   $zConverter._translate_opset_expr	values.Opc                 C  s   t |tjr'| |j}| || |j}||v r t||jS t||jS t |tj	r\|j
}| j|| |dd}t |tjtjfrF|S |s\|| jvrUtd|d t| j|S | |d dS )zReturn an OpFr  zUnknown function name z. The ONNX graph may not work.zInvalid calleeN)r}   r~   r   r  rD   r|   r   r   r   r   r   r   r   r   OnnxFunctionra   r+   r-   )r    rw   moduler  r   foundr   r   r   r    s&   

z Converter._translate_callee_exprast.stmtc                 C  s   t |tjr| |S t |tjr| |S t |tjr-|dur%| |S t| |dt |tj	r8| 
|S t |tjtjfrF| |S t|rV|dkrT| |S dS t |tjra| |S t|rhdS t| |dt|d)zmStatement translation: A single Python statement is mapped into a
        sequence of IR statements.
        NzCReturn statements are not permitted inside control-flow statements.r   zUnsupported statement type ''.)r}   r~   Assign_translate_assign_stmt	AnnAssignReturn_translate_return_stmtr   r   If_translate_if_stmtForWhile_translate_loop_stmtr
   is_doc_stringr5  FunctionDef_translate_nested_function_defis_print_callrK   )r    rw   index_of_stmtr   r   r   _translate_stmt  s2   








zConverter._translate_stmtstmtast.Assign | ast.AnnAssignc                   s   d fdd}t tjrj}njg}t|dkr" d	 |d
 }j}t |tjrdt |tjsA |dt	|d t|j
t|j
krQ d t|j
|j
D ]	\}}||| qXd S ||| d S )Nlhsrx   rhsr   r   c              
     sJ  t | tjr:| }| j} || }t tjr!j}nd }|d ur,t	|| t
||}| | d S t | tjrt |tjsR|dt|d |\}}}d
fdd  fdd| jD }	|	|||}
t |
tjr||
g}
t| j|
D ]\}}|jt
|| qd S | d	t| d d S )Nz5RHS must be a Call expression for unpacking, found: 'r&  r  rx   c                   s0   t | tjs | dt| d  | jS )Nz*LHS must be a Name for unpacking, found: 'r&  )r}   r~   r   r-   rK   r   r   r  rt   r   r   generate_onnx_name  s   zLConverter._translate_assign_stmt.<locals>.assign.<locals>.generate_onnx_namec                      g | ]} |qS r   r   r  r  r   r   r         zDConverter._translate_assign_stmt.<locals>.assign.<locals>.<listcomp>z-Unsupported construct in LHS of assignment: ')r  rx   )r}   r~   r   r   r   r?  r  r!  r  rP   r   r   r   Tupler   r-   rK   r6  eltsr   rH   rW   zip)r  r  r   trF   ru  r   r   r   output_namesr   r  outputr    r  r  r   assign  s<   

z0Converter._translate_assign_stmt.<locals>.assignr   zMulti-assignment not supported.r   zLeft term must be a tuple not 'r  z?Expected same number of elements on lhs and rhs of assignments.)r  rx   r  rx   r   r   )r}   r~   r  targetsr   r   r-   rD   r  rK   r  r  )r    r  r  r  r  r  pr   r   r  r   r    s&   (z Converter._translate_assign_stmt
ast.Returnc                   sv   fdd}fdd j }|d usJ dt|tjr1|t|j  fddt|jD S |d  |d	d
S )Nc              	     s@    j d ur| t j krt d j d| dd S d S )NzzMismatch in number of return values and types. Keyword 'return' cannot be used in a subgraph (test, loop).  returntype is z, num_outputs=r   )
returntyper   SyntaxErrorr   )nr  r   r   check_num_outputs<  s   
z;Converter._translate_return_stmt.<locals>.check_num_outputsc                   s   d| }  | |} j|j | dd}t|tjr/t|jtj	r/|j
 r/ ||} jjD ]}|j|jkrF || d} nq3 jd urTt| j|   jj| |S )N
return_valFr  _copy)r?  r   rV   r   r}   r   r   rD   rH   rW   is_graph_inputr  rg   r   r  rP   r   )expisuffixpreferred_name
return_varr   prev_outputrt   r   r   retH  s   


z-Converter._translate_return_stmt.<locals>.retz4Return statement without return-value not supported.c                   s    g | ]\}} ||t |qS r   )rR   )r   r  r  )r  r   r   r   _  s     z4Converter._translate_return_stmt.<locals>.<listcomp>r   r   ry   )rD   r}   r~   r  r   r  rq  )r    r  r  r   r   )r  r    r  r   r  ;  s   z Converter._translate_return_stmtast.Ifc              
     s  j |}|du r|jD ]}| qd S |du r(|jD ]}| qd S j |}j |}|d ur=||}t|}	|j
d}|j}|jd| |}	td|	}
|jd| |}td|}fdd	  fd
d|D }|s|d ||jgkr|d|d |tjd|g|
|g}t|tjr|g}t||D ]\}}|t|| qd S )NTFr0   
thenGraph_then_branch
elseGraph_else_branchc                   s
     | S r   r   r  rt   r   r   rename}  r   z,Converter._translate_if_stmt.<locals>.renamec                   r  r   r   r  r  r   r   r     r  z0Converter._translate_if_stmt.<locals>.<listcomp>z6A subgraph for a test do not have any output variable.z$Input and output cannot be the same r   r  )ru   constant_if_conditionbodyr  orelseassigned_varslive_outintersectionr   r?  testr   r]  _translate_blockrH   	AttrGraphr-   rV   r   r   r   ra   r}   rW   r  r   r   )r    r  constant_condslive_def_setr  	live_defsr  r]  	thenGraphthenAttr	elseGraphelseAttrrenamed
if_outputsr  r  r   )r  r    r   r  c  sP   


zConverter._translate_if_stmt	loop_stmtast.For | ast.Whilec           $   
     s  t  tjrvt  jtjs d  jj} j}t |tjs$J dt |j	tjs6 d|j	d |j	jdkrB d |j
rLt|j
dkrR d |jrYJ d	|j
d
 d}tdtj }|}d }d }n>t  tjr j}	t |	tjs d d}d }t|	jtj }|	j}d }|	}n dt d j j}
j j}j }|d usJ d||
|B }t }t||B }d  |}t|tj  }j!"| #|t$%|  j!"| |D ]$}|}t|d  }j!"| #|t$%|  qd }d}t& jD ]o\}}t |tj'rt|jdkrt |jd
 tj(rt |jtjsp|dt|jd |t jd kr|d ) }|jj|vr d|jjdt|d ||jj j*}d}q>+| q>|d urЈ) }||vrˈ d| dt|d || j*},dgt$-j.||p|gg }j!j/0| |D ]!}1| }|j2j!j3vr4||}j!j/0| q5 }||g fdd|D  }t67d|j8g} }fddfdd|D } 9| d||}!t |!t6j:rP|!g}!t;||!D ]\}"}##|"t$%|#| qUd S ) Nz*For loop target must be a single variable.zLoop bound not a call.zUnsupported loop bound r   rangez9Unsupported loop bound, only function 'range' is allowed.r   z0Unsupported loop bound, it should be 'range(?)'.zUnsupported loop bound.r   
loop_boundcond_inzgUnexpected condition type {type(loop_stmt)!r} for a while loop, it should be 'while <condition_name>:'.infinite_loopzUnexpected loop type zlive_out cannot be None here.	loop_bodyr  zqInstruction break can be introduced with test but it must be if <condition>: break. However condition is of type z3Instruction break must be the last one of the loop.z"Unable to find condition variable z in known variables r?   cond_outc                   s   g | ]} | qS r   )r   r   )r   pv)r  r    r   r   r   )  s    z2Converter._translate_loop_stmt.<locals>.<listcomp>r  c                   s     | }|S r   r  )r  r   rt   r   r   r  /  s   
z.Converter._translate_loop_stmt.<locals>.renamec                   r  r   r   r  r  r   r   r   3  r  Loop)<r}   r~   r  r   r   r-   r   iterr   r   r   r   r  r?  rY   r   r   r   r   r  r  r<  rK   ru   exposed_usesr  r  r  r   ri   r   r   INT64rg   append_parameterr   r   r   rq  r  Breakr   rD   r  r   r   ra   r   r   r   rV   assigned_namesr  r   rH   r  r   r   rW   r  )$r    r  python_loop_var_namer  o_loop_boundonnx_cond_var
i_cond_var
cond_whileo_loop_conditionr  r  vars_def_in_loopr  loop_state_varsscan_outputsr   onnx_loop_var_nameonnx_loop_varr  onnx_var_name	parametercondition_nameoperator_namer  r  current_scoper  onnx_varr  r   r   r   onnx_output_namesloop_outputsr  loop_outputr   )r  r  r    r   r    s  


2





zConverter._translate_loop_stmtstmtsSequence[ast.stmt]r  ir.Graphc           
   	   C  s   |  |d |D ]}| | q|D ]d}||  v r;|  | }| ||}|j| jjvr3| ||}| jj	| qd}t
| jD ]}||v rN|| } nqB|du re| |d d| dt| j d | | |||}| jj	| q|  }	|	jS )z:Translation of a then/else statement-block to an ir.Graph.Nr   z	ir.Value zF is not assigned a value along a conditional branch, known variables: r   )r   r  r   r   rV   rg   r  r  r   r   r   rk   r-   r   r   r   )
r    r2  rV   r  r  
python_varpython_var_valuer  r   function_irr   r   r   r  ?  s:   zConverter._translate_blockfnast.FunctionDefc              	     sn     j     }j } fdd|D |_ jt|	  j
| dS )z'Translate a nested function definition.c              	     s"   g | ]}| | fqS r   )r   r   )r   ru  r8  r    r   r   r   q  s    z<Converter._translate_nested_function_def.<locals>.<listcomp>N)r   rV   _translate_function_def_commonr   ru   r'  r   r   r   r   rg   add_nested_function)r    r8  r7  outer_scope_varsr   r:  r   r  k  s   
z(Converter._translate_nested_function_defc                 C  s  |j }|js|js|js|jrt|j d t|j D ]\}}t|j t|j	 }|j	r<||kr<| 
|j	||  }nd}|jrH| |j}nd}|rzt|rzt|}t|j||d}	| j|	 t|}
| |jt|	|
| | qt|j|| |}| j| | j|j | |jt|| | q|jr| 
|j}t || _!d}| j!D ]}t"|s| |jd| d d}q|rd| _!| jS d| _!| jS )z5Translate a function signature (top-level or nested).z,: Unsupported feature in function signature.NFz-Unsupported type annotation for return value r   T)#r   vararg
kwonlyargskw_defaultskwargr+   rV   rq  r   defaultsr  r  r!  r  is_attr_typer   get_attr_typerH   r   r  rg   r  base_type_is_boolr   r   r   r   rY   rj   r   r   returnsget_return_typesr  r   )r    r8  r   r  r  arg_with_default_start_indexrG  rF   attribute_typer   r   onnx_parameterr   invalidr  r   r   r   $_translate_function_signature_commonx  sV   

 


z.Converter._translate_function_signature_commonc                 C  s@   t d|j | |}t|jD ]\}}| j||d q| jS )zFTranslate a function definition, including the signature and its body.z+Converter:_translate_function_def_common:%s)r  )r'   r   rV   rL  rq  r  r  rg   )r    r8  r   r  r  r   r   r   r;    s
   
z(Converter._translate_function_def_commonc                 C  s   t |tjrB|   | jd u r| |}|r| || | jj}t	
|j|| _t|| j| j| _| |}| j| d | _|S tdt|d)Nz%Unsupported top-level statement type r   )r}   r~   r  r   re   r   r|   rd   rz   r   r   rV   rg   r	   AstAnalyzerr   rc   rl   r;  add_function_defr   rK   )r    r  r[   rz   fn_irr   r   r   translate_function_def  s   


z Converter.translate_function_defc                 C  s"   | j j}t|j|| _| |S )z+Translate a (top-level) function signature.)rd   rz   r   r   rV   rg   rL  )r    r8  rz   r   r   r   translate_function_signature  s   
z&Converter.translate_function_signature)NNNN)r[   r\   r]   r^   r_   r`   ra   r\   )rn   rR   r   ro   )r   rq   )r   rv   )r[   rv   rw   rx   r   r   )rw   rx   r   r\   )r   r   )rw   rx   r   rT   )rw   rx   r   rR   r   rR   )rw   rx   r   rR   r   r   )rw   rx   r   rR   r   r   )rV   rR   r   rx   )r   r   )r   r   )rV   rR   r   r   r   r   )T)rV   rR   r   rT   r   ro   r   r   )r   )r   rR   r   rR   )r   r   r   r   r   r   )NN)r   r   r   r   r   r   r   rE   )r   rR   r   rT   r   rE   r   )
r   r   r   r   r   r   r   r   r   r   rn  )r   r   r   r   r   rT   r   rE   )r  rE   r   rR   r   rE   )rw   rx   r   r   )r  r  r   r   )r  r  r   r  )r"  rR   r  rx   r#  r$  r   r%  )rw   r3  r   r   )rw   rx   r   r   r   rE   )rw   r  r   r@  )rw   rB  r   r   r   rE   )rw   r  r   r  )r   r  )rw   r  )rw   r  r   rE   )rw   r  r   rv   )rw   rx   r   r  )rw   r  r   r   )r  r  r   r   )r  r  r   r   )r  r  r   r   )r  r  r   r   )r2  r3  rV   rR   r  r   r   r4  )r8  r9  r   r   )r8  r9  r   r   )r  r9  r   r   )8r#   r$   r%   __doc__r   rp   propertyru   ra   r|   r   r   r   r   r+   r-   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r!  r2  r5  r?  rA  r>  r6  r  r9  r:  r;  r<  r  r  r  r  r  r  r  r  r  rL  r;  rP  rQ  r   r   r   r   rZ      s    










	


	
$


"



I

 
i






B
(
2 
+
,

4
rZ   )r   r   )rD   rE   rF   rG   r   r   )rQ   rR   rF   rG   rS   rT   r   rE   )B
__future__r   r~   loggingtypingr   r   r   r   r   onnx_irrH   r   r   onnxscript._internalr	   r
   r   r   r   r   r   r   r  onnxscript.irr   	getLoggerr'   r   r   r   r+   r-   r1   r2   r3   r4   r7  r8  r6   EqGtGtELtLtEMatMultr=   Multr?   NotEqr5   rA   rB   r  r  r   r   r   r   r   rR   PreferredNameOnnxVarNamerP   rY   rZ   r   r   r   r   <module>   s   $	

	



