o
    XiM                     @  sT  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlmZm	Z	m
Z
mZmZmZmZmZ d dlZd dlZd dlZd dlmZ d dlmZmZmZ d dlmZ d dlmZ d dlmZ ed	Z ed
Z!d.d/ddZ"ej#j$j%j&e'ej#j$j%j(e)ej#j$j%j*e+ej#j$j%j,dej#j$j%j-dej#j$j%j.dej#j$j%j/dej#j$j%j0ee' ej#j$j%j1ee) ej#j$j%j2ee+ ej#j$j%j3dej#j$j%j4dej#j$j%j5dej#j$j%j6diZ7e8 Z9e:e;Z<G dd dZ=d0ddZ>d1ddZ?ej@G dd deZAG d d! d!eAZBejCd"d"d#G d$d% d%ZDG d&d' d'eBee!e f ZEG d(d) d)eBZFG d*d+ d+ZGG d,d- d-eGZHdS )2    )annotationsN)AnyCallableClassVarGenericOptionalProtocolSequenceTypeVar)	ParamSpec)	ast_utils	irbuilder
sourceinfo)	converter)_schemas)ONNXType_R_P versionintdomainstrreturnc                 C  sP   |dkrd}|| ft jjvrtdd t jj D S t jj|| f }t|dS )z=Selects a suitable ONNX ir_version for a given opset version.r   ai.onnxc                 s  s$    | ]\}}|d  dkr|V  qdS )r   r   N ).0kvr   r   O/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/_internal/values.py	<genexpr>,   s    z$select_ir_version.<locals>.<genexpr>
   )onnxhelperOP_SET_ID_VERSION_MAPmaxitems)r   r   required_min_versionr   r   r   select_ir_version'   s   

r(   c                      s   e Zd ZU dZded< ded< i Zded< d" fdd	Zd#d$ddZdd Zdd Z	dd Z
d%ddZd&ddZdd Zd'd d!Z  ZS )(Opseta  Represents an ONNX Opset, which consists of a domain name, a version.

    It also contains a set of operations. This represents an Opset defined
    in the ONNX schema registry and the operations are retrieved from the
    ONNX schema registry. It also stores function definitions created for
    ops in the corresponding Opset.

    Only a single instance of Opset is created for a given (domain, version) pair.
    r   r   r   r   z,ClassVar[dict[tuple[type, str, int], Opset]]cachec                   sJ   | ||f}| j |}|r|S t | }||_||_i |_|| j |< |S N)r*   getsuper__new__r   r   function_defs)clsr   r   keyexistinginstance	__class__r   r   r.   Y   s   

zOpset.__new__NOptional[str]Optional[int]c                 C     d S r+   r   )selfr   r   r   r   r   __init__e   s   zOpset.__init__c                 C  s   | j j d| jd| jdS )N(z, ))r5   __name__r   r   r9   r   r   r   __repr__i   s   zOpset.__repr__c                 C  s8   zt j|| j| j}t| ||W S  ty   Y d S w r+   )r"   defs
get_schemar   r   Op	Exception)r9   opnameschemar   r   r   __getitem__l   s   zOpset.__getitem__c                 C  s0   zt j|| j| j W dS  ty   Y dS w )NFT)r"   r@   rA   r   r   rC   )r9   rD   r   r   r   __contains__s   s   zOpset.__contains__r   c                 C     | j S r+   )r   r>   r   r   r   __str__{   s   zOpset.__str__attrrB   c              
   C  sN   zt j|| j| j}t| ||W S  ty& } z	td| d|d }~ww )Nz
Attribute z not found.)r"   r@   rA   r   r   rB   rC   AttributeError)r9   rJ   rE   excr   r   r   __getattr__~   s   zOpset.__getattr__c                 C  s   || j |j< d S r+   )r/   name)r9   funr   r   r   add_function_def      zOpset.add_function_def_onnx.defs.OpSchemac                 G  s4   t |}|r|d du r|  |r|d du s|S )zTrims 'None' values from the end of the inputs list. This is used to support
        omitting optional inputs when no more required inputs follow to prepare a valid call
        against the Op. Used by the static opset code generator.
        N)listpop)r9   rR   inputs
input_listr   r   r   _prepare_inputs   s
   zOpset._prepare_inputs)r   r   r   r   )NN)r   r6   r   r7   r   r   )rJ   r   r   rB   )rR   rS   )r=   
__module____qualname____doc____annotations__r*   r.   r:   r?   rF   rG   rI   rM   rP   rY   __classcell__r   r   r4   r   r)   J   s   
 


r)   
attr_protoonnx.AttributeProtor   c                 C  s   | j tjjkr	tS tj| S )z+Get the default value of an ONNX attribute.)typer"   AttributeProto	UNDEFINED_EmptyDefaultr#   get_attribute_value)r`   r   r   r   _get_attribute_value   s   rg   varir.Valuec                 C  s   | j dS )Ntypeinfo)metar,   )rh   r   r   r   	_typeinfo   s   rl   c                   @  s:   e Zd ZdZedddZedddZedd
dZdS )OpLikez2A protocol for objects that have an ONNX OpSchema.r   r   c                 C  r8   r+   r   r>   r   r   r   rN         zOpLike.namer)   c                 C  r8   r+   r   r>   r   r   r   opset   rn   zOpLike.opsetOptional[_schemas.OpSignature]c                 C  r8   r+   r   r>   r   r   r   op_signature   rn   zOpLike.op_signatureNrZ   r   r)   r   rp   )r=   r[   r\   r]   propertyrN   ro   rq   r   r   r   r   rm      s    rm   c                   @  sn   e Zd ZdZ	ddddZdd ZedddZedddZedddZ	ed ddZ
e
jd!ddZ
dS )"rB   a(  Represents an ONNX op instance (for example, the MatMul op from ONNX opset version 13).

    It belongs to a particular Opset and has a name.

    Attributes:
        opset: The Opset that this op belongs to.
        name: The name of the op.
        op_schema: The ONNX OpSchema for the op.
    Nro   r)   rN   r   	op_schemaOptional[onnx.defs.OpSchema]r   Nonec                 C  sf   || _ || _|  |d ur|| _n||  }d ur|j| _nd | _d | _| jd u r1td|| d S d S )NzRAn OpSchema was not provided for Op '%s' and there is not one found in opset '%s'.)_opset_name
_op_schemaru   
_signatureloggerdebug)r9   ro   rN   ru   opr   r   r   r:      s    

zOp.__init__c                 O  s\   ddl m} | }t|dr%| jd u rtd| j d|| j||S | | ||S )Nr   	evaluatorevalzOpSchema not found for op 'z'.)	onnxscript._internalr   defaulthasattrru   
ValueErrorrN   r   eval_op)r9   argskwargsr   default_evaluatorr   r   r   __call__   s   

zOp.__call__c                 C  rH   r+   )ry   r>   r   r   r   rN         zOp.namec                 C  rH   r+   )rx   r>   r   r   r   ro      r   zOp.opsetc                 C  rH   r+   )rz   r>   r   r   r   ru      r   zOp.op_schemarp   c                 C  s4   | j dur| j S | jdu rdS tj| j| _ | j S )!Returns the signature of this op.N)r{   ru   r   OpSignaturefrom_op_schemar>   r   r   r   rq      s   

zOp.op_signaturevalue_schemas.OpSignaturec                 C  
   || _ d S r+   r{   r9   r   r   r   r   rq         
r+   )ro   r)   rN   r   ru   rv   r   rw   rZ   rr   )r   rv   rs   r   r   )r=   r[   r\   r]   r:   r   rt   rN   ro   ru   rq   setterr   r   r   r   rB      s    rB   F)repreqc                   @  s*   e Zd ZU dZded< ded< ded< dS )	OnnxClosurezRRepresents a nested function used as a graph-valued attribute for an ONNX op call.irbuilder.IRFunctionfunction_irztypes.FrameTypeframer   functionN)r=   r[   r\   r]   r^   r   r   r   r   r      s
   
 r   c                      s|   e Zd ZdZd/ fddZed0ddZejd1ddZd2ddZd3ddZ	d4ddZ
d d! Z	"	"	"	"	"d5d6d-d.Z  ZS )7OnnxFunctiona  Represents an ONNX op for which a function-body has been defined in onnxscript.

    Attributes:
        opset: Opset the function belongs to.
        name: Name of the function.
        function: Python function.
        function_ir: Python code parsed as an :class:`irbuilder.IRFunction`.
        source: Source code used to generate the function.
        kwargs: Additional properties used to construct a ModelProto.
        op_schema: Generated ONNX OpSchema for this op.
    ro   Optional[Opset]pyfunr   irfunr   sourcer   r   dict[str, Any]c                   sx   |pt |jd}t ||j || _|| _|j| jjd< || _	|| _
tjj| j| jj| jd| _t| | d| _dS )au  Constructs an OnnxFunction.

        Args:
            opset: opset the function belongs to
            pyfun: python function
            irfun: python code parsed by class
                :class:`onnxscript.converter.Converter`
            source: source code used to generate the function
            kwargs: additional properties used to construct a ModelProto
           opset_versionr   rN   FN)r)   r   r-   r:   rN   r   r   r   rk   r   r   r   r   from_functionr{   	functoolsupdate_wrapper	traceable)r9   ro   r   r   r   r   r4   r   r   r:     s   
zOnnxFunction.__init__r   rp   c                 C  rH   r   r   r>   r   r   r   rq   :     zOnnxFunction.op_signaturer   r   c                 C  r   r+   r   r   r   r   r   rq   ?  r   r   _P.args	_P.kwargsr   c                 O  s   ddl m} | | ||S )z=Implements an eager-mode execution of an onnxscript function.r   r   )r   r   r   eval_function)r9   r   r   r   r   r   r   r   C  s   zOnnxFunction.__call__c                 C     | j j d| jdS Nr;   r<   )r5   r=   r   r>   r   r   r   r?   I     zOnnxFunction.__repr__onnx.FunctionProtoc                 C  s
   | j  S )z7Converts the function into :class:`onnx.FunctionProto`.)r   to_function_protor>   r   r   r   r   L  r   zOnnxFunction.to_function_protoc                 K  sD   | j jrtdd | j jD rtdi | j|}| jdi |S )z4Converts the function into :class:`onnx.ModelProto`.c                 s  s    | ]}|j d u V  qd S r+   )r   )r   rJ   r   r   r   r    R  s    

z.OnnxFunction.to_model_proto.<locals>.<genexpr>zBA function with required attributes cannot be exported as a model.Nr   )r   attrsanyr   r   _to_model_proto)r9   r   merged_kw_argsr   r   r   to_model_protoP  s   	zOnnxFunction.to_model_protoNio_typesOptional[ONNXType]input_typesOptional[Sequence[ONNXType]]output_typesvalue_infosdict[str, ONNXType] | Noner   
int | Noneonnx.ModelProtoc                 K  s  | j  }dd | D }| j j }	|	j }
|D ]&}|j}|dur1||
vr1|j	dd|
|< d|
vrAd|jv rA|jd |
d< qd|
vrS|durL|nt
j |
d< d|v r]|d}nt|
d }tj|	|d}|D ]	}||j| < qlt|}|jdd= |jd	d |
 D  |j}|r|jd
d | D  |dur|jD ]}|ds|j|  q|jD ]}|ds|j|  q|durt|j|D ]\}}|j|  q|durt|j|D ]\}}|j|  q| D ]
\}}t||| q|S )a  Converts this instance into a `onnx.ModelProto`.

        Args:
            io_types: When specified, all the inputs/outputs of the model
                are set to be of this type.
            input_types: When specified, all the inputs of the model
                are set to be of the corresponding type in this list.
            output_types: When specified, all the outputs of the model
                are set to be of the corresponding type in this list.
            value_infos: A dictionary mapping intermediate variable names to ONNX types.
                Used to set value_info for intermediate variables.
            opset_version: The standard opset version to use for the model if it
                cannot be inferred. Otherwise defaults to the current opset version.
            kwargs: Additional parameters given to function :func:`onnx.helper.make_model`.

        Returns:
            An instance of :class:`onnx.ModelProto`.
        c                 S  s   g | ]}|j qS r   )r   )r   funcr   r   r   
<listcomp>~  s    z0OnnxFunction._to_model_proto.<locals>.<listcomp>Nr   r   r   
ir_version)r   c                 S  s   g | ]\}}t j||d qS ))r   r   )r"   OperatorSetIdProto)r   r   r   r   r   r   r     s    c                 S  s"   g | ]\}}t j|| qS r   )r"   r#   make_value_infoto_type_proto)r   rN   rb   r   r   r   r     s    rb   ) r   get_called_functionsvaluesgraphcloneopset_importscopyr   rk   r,   r"   r@   onnx_opset_versionrV   r(   irModel	functions
identifierto_protoopset_importextendr&   
value_infoinputHasFieldrb   CopyFromr   outputzipsetattr)r9   r   r   r   r   r   r   sub_functionsir_functions
main_graphr   r   r   r   modelmodel_protor   r   r   rb   r   r   r   r   r   r   a  sh   






zOnnxFunction._to_model_proto)
ro   r   r   r   r   r   r   r   r   r   rs   r   )r   r   r   r   r   r   rZ   )r   r   )NNNNN)r   r   r   r   r   r   r   r   r   r   r   r   )r=   r[   r\   r]   r:   rt   rq   r   r   r?   r   r   r   r_   r   r   r4   r   r   	  s"    $


r   c                      s^   e Zd ZdZd fddZdd	 Zd
d ZedddZedddZ	e	j
dddZ	  ZS )TracedOnnxFunctionzqTracedOnnxFunction.

    Attributes:
        name: Name of the op. E.g. "aten::add".
        func: Function.
    ro   r)   r   r   c                   s>   t  ||j || _tjj| jd| jd| _t	
| | d S )N_tracedr   )r-   r:   r=   r   r   r   r   rN   r{   r   r   )r9   ro   r   r4   r   r   r:     s   
zTracedOnnxFunction.__init__c                 O  s   | j |i |S r+   )r   )r9   r   r   r   r   r   r     rQ   zTracedOnnxFunction.__call__c                 C  r   r   )r5   r=   r   r>   r   r   r   r?     r   zTracedOnnxFunction.__repr__r   r   c                 C  sZ   t | j\}}t| j}t| j}|j }||j	 t
j| j||d}||S )zgReturn the function_ir.

        This function IR contains only the signature of the function.
        )ro   global_namesr   )r   get_src_and_astr   inspect	getmodulegetclosurevars__dict__r   update	nonlocalsconverter_module	Converterrx   translate_function_signature)r9   srcfunc_astmoduleclosurer   r   r   r   r   r     s   

zTracedOnnxFunction.function_irrp   c                 C  rH   r   r   r>   r   r   r   rq     r   zTracedOnnxFunction.op_signaturer   r   c                 C  r   r+   r   r   r   r   r   rq     r   )ro   r)   r   r   )r   r   rs   r   )r=   r[   r\   r]   r:   r   r?   rt   r   rq   r   r_   r   r   r4   r   r     s    
r   c                   @  s   e Zd ZdZddd	Zd
S )SymbolValuea  Represents script-time value information about named variables used in a script.

    At translation-time, the (local) variables of a script, including its parameters,
    are bound to a SymbolValue.

    SymbolValues fall into the following categories:

    AttrRef: Function parameters of attribute-kind, also mapped to ONNX attributes

    Dynamic: values computed at runtime (of tensor type, for now) mapped to NodeArgs.
    Dynamic values include input-parameters of the script, as well intermediate
    values computed in the script.

    For example, consider the following script definition:
    ::

        @script()
        def ThresholdedRelu(X, alpha: float):
            zero = op.CastLike(0, X)
            return op.Where(X > alpha, X, zero)

    Here, `X` has a Dynamic value, `alpha` has an AttrRef value, and `zero`
    has a Dynamic value.

    Scripts may also contain references to global variables, but the translator
    does not associate a SymbolValue with them. The python value of global variables
    is used directly in the translation, and such global variables are intended
    to be used for limited purposes, namely:
    * To identify an opset
    * To represent constant-values, translated into ONNX constants.
    r   r   infosourceinfo.SourceInfor   rw   c                 C  s0   t |tjstdt|d|| _|| _dS )z
        Initializes SymbolValue.

        Arguments:
            value: The value bound to a python variable in a script.
            info: source-location information for error-messages/debugging
        z/info must be of type sourceinfo.SourceInfo not .N)
isinstancer   
SourceInfo	TypeErrorrb   r   r   )r9   r   r   r   r   r   r:     s   
zSymbolValue.__init__N)r   r   r   r   r   rw   )r=   r[   r\   r]   r:   r   r   r   r   r     s     r   c                      s   e Zd Zd fd	d
Z  ZS )AttrRefrJ   ir.Attras_boolboolr   r   r   rw   c                   s   t  || || _dS )a  Initializes AttrRef.

        Arguments:
            attr: An ir.Attr representing the attribute-parameter
            as_bool: Whether the attribute is to be interpreted as a bool type (represented as int in ONNX)
            info: for debugging use.
        N)r-   r:   r   )r9   rJ   r   r   r4   r   r   r:   .  s   
zAttrRef.__init__)rJ   r   r   r   r   r   r   rw   )r=   r[   r\   r:   r_   r   r   r4   r   r   -  s    r   )r   )r   r   r   r   r   r   )r`   ra   r   r   )rh   ri   r   r   )I
__future__r   dataclassesr   r   loggingtypestypingr   r   r   r   r   r   r	   r
   r"   	onnx.defsonnx_irr   typing_extensionsr   r   r   r   r   r   r   onnxscript.irr   onnxscript.onnx_typesr   r   r   r(   r@   OpSchemaAttrTypeFLOATfloatINTr   STRINGr   TENSORGRAPHSPARSE_TENSOR
TYPE_PROTOFLOATSINTSSTRINGSTENSORSGRAPHSSPARSE_TENSORSTYPE_PROTOS_ATTRIBUTE_TYPE_TO_PYTHON_TYPEobjectre   	getLoggerr=   r|   r)   rg   rl   runtime_checkablerm   rB   	dataclassr   r   r   r   r   r   r   r   r   <module>   sb   (

M
J A5/