o
    Xi                     @  sR  U d Z ddlmZ ddl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mZmZmZmZmZ ddlm  mZ ddlmZ edZG dd	 d	ee ZG d
d dejee ZG dd deZG dd deZG dd deej ZG dd deZ ee!e"eee! ee" ee f Z#G dd deZ$dUddZ%G dd dZ&e&dZ'e&edZ(G dd  d Z)dVd$d%Z*e'a+de,d&< ej-dWd(d)Z.G d*d+ d+Z/G d,d- d-Z0G d.d/ d/e/Z1G d0d1 d1e/Z2G d2d3 d3e/Z3e3 Z4G d4d5 d5e/Z5G d6d7 d7e/Z6G d8d9 d9e/Z7			dXdYdAdBZ8dZdEdFZ9d[dMdNZ:G dOdP dPZ;d\dSdTZ<dS )]zDThe Pattern IR: used to describe (source) patterns of rewrite rules.    )annotationsN)Mapping)AnyCallableIterableIteratorProtocolSequenceTypeVarUnion)irTc                   @  s   e Zd ZdZd	ddZdS )
Patternz_This is essentially a Predicate[T], that is, a Callable[[T], bool] bound to the name "matches".itemr   returnboolc                 C     d S N selfr   r   r   S/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/rewriter/_pattern_ir.pymatches    s    zPattern.matchesN)r   r   r   r   )__name__
__module____qualname____doc__r   r   r   r   r   r      s    r   c                   @  s0   e Zd ZdZejdddZejddd	Zd
S )StringPatternz(Abstract base class for string patterns.r   strr   r   c                 C  r   r   r   r   r   r   r   r   &      zStringPattern.matchesc                 C  r   r   r   r   r   r   r   __str__*   r   zStringPattern.__str__Nr   r   r   r   r   r   )r   r   r   r   abcabstractmethodr   r!   r   r   r   r   r   #   s    r   c                   @  s8   e Zd ZdZdddZdd	d
ZdddZdddZdS )StringConstantPatternz!Matches strings with given value.valuer   c                 C  
   || _ d S r   _valuer   r'   r   r   r   __init__2      
zStringConstantPattern.__init__r   r   r   c                 C  s
   || j kS r   r)   r   r   r   r   r   5   r-   zStringConstantPattern.matchesc                 C     | j S r   r)   r    r   r   r   r!   8      zStringConstantPattern.__str__c                 C  r.   r   r)   r    r   r   r   r'   ;   r/   zStringConstantPattern.valueN)r'   r   r"   r#   )r   r   r   r   r,   r   r!   r'   r   r   r   r   r&   /   s    


r&   c                   @  s.   e Zd ZdZdddZdd	d
ZdddZdS )PrefixPatternz$Matches strings with a given prefix.r'   r   r   Nonec                 C  r(   r   r)   r+   r   r   r   r,   B   r-   zPrefixPattern.__init__r   c                 C  s   | | jS r   )
startswithr*   r+   r   r   r   r   E      zPrefixPattern.matchesc                 C  s   | j  dS )N*r)   r    r   r   r   r!   H   r3   zPrefixPattern.__str__N)r'   r   r   r1   )r'   r   r   r   r#   )r   r   r   r   r,   r   r!   r   r   r   r   r0   ?   s
    

r0   c                   @  sP   e Zd ZdZddddd	ZedddZedddZdddZdddZ	dS )AttrPatternzLBase class for an attribute pattern. Matches any attribute value by default.Fcan_match_nonename
str | Noner7   r   c                C     || _ || _d S r   )_name_can_match_noner   r8   r7   r   r   r   r,   O   s   
zAttrPattern.__init__r   c                 C  r.   r   r;   r    r   r   r   r8   S      zAttrPattern.namec                 C  r.   )z:Indicates whether this pattern can match a None attribute.r<   r    r   r   r   r7   W      zAttrPattern.can_match_noneattrir.Attrc                 C  s   dS )NTr   r   rB   r   r   r   r   \      zAttrPattern.matchesr   c                 C      | j d ur| j S dtt|  S Nz
anonymous:r;   r   idr    r   r   r   r!   _       zAttrPattern.__str__Nr8   r9   r7   r   r   r9   r   r   rB   rC   r   r   r#   )
r   r   r   r   r,   propertyr8   r7   r   r!   r   r   r   r   r5   L   s    
r5   c                      s(   e Zd ZdZddd
 fdd	Z  ZS )AttrVarzERepresents a pattern variable used to match against attribute values.Fr6   r8   r9   r7   r   c                  s   t  j||d d S )Nr6   superr,   r=   	__class__r   r   r,   f      zAttrVar.__init__rK   )r   r   r   r   r,   __classcell__r   r   rS   r   rP   c   s    rP   c                      s6   e Zd ZdZd fddZdd
dZdddZ  ZS )AttrConstantPatternzMatches attributes with given value.

    Uses standard equality for matching. For list-valued attributes, the order of elements matters.
    If order is immaterial, we need to define a separate pattern for that.
    r'   SupportedAttrTypesc                   s   t  d  || _d S r   )rR   r,   r*   r+   rS   r   r   r,   |   s   
zAttrConstantPattern.__init__rB   rC   r   r   c                 C  s<   |j tjjtjjtjjhv rt|jt| jkS |j| jkS r   )	typer   AttributeTypeINTSFLOATSSTRINGStupler'   r*   rD   r   r   r   r      s   zAttrConstantPattern.matchesr   c                 C  
   t | jS r   r   r*   r    r   r   r   r!      r-   zAttrConstantPattern.__str__)r'   rX   rN   r#   )r   r   r   r   r,   r   r!   rV   r   r   rS   r   rW   u   s
    

rW   r'   /AttrPattern | ValuePattern | SupportedAttrTypesr   c                 C  s   t | tr| S t | tr| jdurtdt| j| jdS t | tt	t
fr)t| S t | trLtdd | D r;t| S tdd | D rHt| S tdtdt|  d	)
zhRepresents promotion of values allowed as keyword-arguments in a pattern-builder call to an AttrPattern.NzDPattern variables used in attributes must not have check_method set.r6   c                 s      | ]
}t |ttfV  qd S r   
isinstanceintfloat.0ir   r   r   	<genexpr>       z#_to_attr_pattern.<locals>.<genexpr>c                 s  s    | ]}t |tV  qd S r   )rd   r   rg   r   r   r   rj      s    z9Only lists of int/float/str can be used as an AttrPatternCannot convert z to AttrPattern)rd   r5   Varcheck_method
ValueErrorrP   r8   r7   re   rf   r   rW   r	   all	TypeErrorrY   )r'   r   r   r   _to_attr_pattern   s"   



rr   c                   @  sX   e Zd 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S )(OpsetPatternBuildera  Represents an opset pattern and a pattern builder.

    (i) It is used to create a NodePattern (via OpPatternBuilder).
    Example usage:
    ::

        z = op.Matmul(x, y)

    Here, `op` is an instance of OpsetPatternBuilder and `op.Matmul` is an instance
    of OpPatternBuilder, and  `op.Matmul(x, y)` is an instance of NodePattern.

    (ii) It contains a domain pattern matched against the actual opset domain used in the
    input model.
    FdomainStringPattern | strrecordr   r   r1   c                 C  s0   t |tr	t|}|| _|rg | _d S d | _d S r   )rd   r   r&   _domain_pattern_nodes)r   rt   rv   r   r   r   r,      s   


zOpsetPatternBuilder.__init__r   c                 C  r.   r   )rw   r    r   r   r   domain_pattern   r/   z"OpsetPatternBuilder.domain_patternop_namer   OpPatternBuilderc                 C  s
   t | |S r   )r{   )r   rz   r   r   r   __getattr__   r-   zOpsetPatternBuilder.__getattr__r8   c                 C  s   t | t|S )z?This method is used to match against submodule ops with prefix.)r{   r0   )r   r8   r   r   r   	submodule      zOpsetPatternBuilder.submodulec                 C  r_   r   )r   rw   r    r   r   r   r!      r-   zOpsetPatternBuilder.__str__nodeNodePatternc                 C  s   | j d ur| j | d S d S r   )rx   append)r   r   r   r   r   add_node   s   
zOpsetPatternBuilder.add_nodeSequence[NodePattern]c                 C  s   | j d u r	td| j S )NzNodes were not recorded.)rx   ro   r    r   r   r   nodes   s   
zOpsetPatternBuilder.nodesN)F)rt   ru   rv   r   r   r1   )r   r   )rz   r   r   r{   )r8   r   r   r{   r#   )r   r   r   r1   )r   r   )r   r   r   r   r,   ry   r|   r}   r!   r   r   r   r   r   r   rs      s    
	



rs    z	pkg.torchc                   @  s4   e Zd ZdZddd	Zd
d
dd
d
d
ddddZd
S )r{   a;  A utility class to build a NodePattern.

    It is used primarily to create a NodePattern.
    Example usage:
    ::

        z = op.Matmul(x, y)

    Here, `op` is an instance of OpsetPatternBuilder and `op.Matmul` is an instance
    of OpPatternBuilder, and  `op.Matmul(x, y)` is an instance of NodePattern.

    pattern_builderrs   rz   str | Pattern[str]r   r1   c                 C  r:   r   )r   rz   )r   r   rz   r   r   r   r,      s   
zOpPatternBuilder.__init__N   )_domain_version_outputs_allow_other_attributes_allow_other_inputs_checkr   r9   r   
int | Noner   int | list[str | None]r   bool | Noner   r   Callable | Nonec             
   O  s   |d urt d|d u r| j }	nt|trt|}	ntdt|tr/dd t|D }nt|t	r=t
dd |D sAt ddd |D }
d	d
 | D }t|	| j|
|||||d}| j| |j}t|dkrq|d S |S )NzzThe pattern builder does not support '_version' keyword argument. Version restrictions should be handled by rewrite rules.z_domain must be a string.c                 S  s   g | ]}d qS r   r   )rh   _r   r   r   
<listcomp>  s    z-OpPatternBuilder.__call__.<locals>.<listcomp>c                 s  s"    | ]}t |ttd fV  qd S r   )rd   r   rY   rh   xr   r   r   rj     s    
z,OpPatternBuilder.__call__.<locals>.<genexpr>z,_outputs must be an int or a list[str|None].c                 S     g | ]}t |qS r   _to_value_patternr   r   r   r   r         c                 S  s   i | ]	\}}|t |qS r   )rr   )rh   r8   r'   r   r   r   
<dictcomp>  s    z-OpPatternBuilder.__call__.<locals>.<dictcomp>allow_other_attributesallow_other_inputscheckr   r   )ro   r   ry   rd   r   r&   rq   re   ranger	   rp   itemsr   rz   r   outputslen)r   r   r   r   r   r   r   argskwargsopset_patterninputs
attributesnode_patternoutput_valuesr   r   r   __call__   s@   



zOpPatternBuilder.__call__)r   rs   rz   r   r   r1   )r   r9   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r,   r   r   r   r   r   r{      s    
r{   r   ,ValuePattern | int | float | Callable | NoneValuePattern | Nonec                 C  s   | du s	t | tr| S t | ttfrt| S t | tr,tdd | D r(t| S tdt| r6td| dS t	dt
|  d)a_  Promotes an input-value used to construct a NodePattern to a ValuePattern.

    Example usage:
    ::
        x = op.MatMul(a, b)
        z = op.Add(x, 0)

    In this example, `a, `b`, and `x` are ValuePatterns used to construct a NodePattern.
    `0` is a constant (int) value, and is automatically promoted to a ValuePattern.

    Note that this is a shorthand for creating a Constant pattern. The user can more
    explicitly write this as:
    ::
        z = op.Add(x, op.Constant(0))

    If a callable is provided, it will be converted to a ValuePattern with the callable as the check attribute.
    Nc                 s  rb   r   rc   rg   r   r   r   rj   ?  rk   z$_to_value_pattern.<locals>.<genexpr>z5Only lists of int/float can be used as a ValuePatternr   rl   z to ValuePattern)rd   ValuePatternre   rf   Constantr	   rp   ro   callablerq   rY   )r   r   r   r   r   &  s   
r   _pattern_builderbuilderc                 c  s    t }| a d V  |a d S r   )r   )r   prev_builderr   r   r   r   K  s
   r   c                   @  s   e Zd ZdZdddd<ddZd=ddZed>ddZed?ddZed@ddZ	dAddZ
dBddZdCd#d$ZdDd&d'Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 ZdDd:d;ZdS )Er   zBase class for all patterns that match against IR values.

    This is used primarily to provide operator overloadings for arithmetic
    operations, so that we can write patterns like `x + 1` and `1 + x`.
    NFr   r7   r8   r9   r   r   r7   r   r   r1   c                C  s   || _ || _|| _g | _d S r   )r;   r   r<   _usesr   r8   r   r7   r   r   r   r,   [  s   
zValuePattern.__init__node_mapdict[NodePattern, NodePattern]c                 C  s   ~t | j| jdS )Nr   )r   r;   r   r   r   r   r   r   cloned  s   zValuePattern.clonec                 C  r.   r   r>   r    r   r   r   r8   h  r?   zValuePattern.namec                 C  r.   r   r   r    r   r   r   rn   l  r?   zValuePattern.check_methodc                 C  r.   )z7Indicates whether this variable can match a None input.r@   r    r   r   r   r7   p  rA   zValuePattern.can_match_noneNodePattern | Nonec                 C  r   r   r   r    r   r   r   produceru  rE   zValuePattern.producer!Sequence[tuple[NodePattern, int]]c                 C  r.   r   )r   r    r   r   r   usesx  r/   zValuePattern.usesr   r   indexre   c                 C  s   | j ||f d S r   )r   r   )r   r   r   r   r   r   
append_use{  rU   zValuePattern.append_user   c                 C  s   d| j dS )NzValuePattern()r>   r    r   r   r   __repr__~  s   zValuePattern.__repr__c                 C     t | |S r   r   Addr   otherr   r   r   __add__  r3   zValuePattern.__add__c                 C     t || S r   r   r   r   r   r   __radd__  r3   zValuePattern.__radd__c                 C  r   r   r   Subr   r   r   r   __sub__  r3   zValuePattern.__sub__c                 C  r   r   r   r   r   r   r   __rsub__  r3   zValuePattern.__rsub__c                 C  r   r   r   Mulr   r   r   r   __mul__  r3   zValuePattern.__mul__c                 C  r   r   r   r   r   r   r   __rmul__  r3   zValuePattern.__rmul__c                 C  r   r   r   Divr   r   r   r   __truediv__  r3   zValuePattern.__truediv__c                 C  r   r   r   r   r   r   r   __rtruediv__  r3   zValuePattern.__rtruediv__c                 C  r   r   )r   Powr   r   r   r   __pow__  r3   zValuePattern.__pow__c                 C  rF   rG   rH   r    r   r   r   r!     rJ   zValuePattern.__str__r8   r9   r   r   r7   r   r   r1   )r   r   r   r   rL   r   r   rM   )r   r   )r   r   )r   r   r   re   r#   )r   r   r   r   r,   r   rO   r8   rn   r7   r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r   r   r   r   r   T  s2    
	



r   c                   @  sd   e Zd ZdZddd,ddZd-ddZd.ddZed-ddZed/ddZ	d0d$d%Z
d1d*d+ZdS )2r   a)  Represents a pattern that matches against a Node.

    This differs from a NodeOutputPattern in that it matches against a node (which
    may produce 1 or more outputs), whereas a NodeOutputPattern matches against
    a specific output of a node.

    Args:
        domain: pattern to match against the domain of the node.
        op: pattern or string constant to match against the op_type of the node.
        inputs: sequence of ValuePatterns (or constants) to match against the inputs of the node.
        attributes: dictionary of attribute patterns to match against the attributes of the node.
        outputs: specifies pattern-variable-name for outputs (or None)
        allow_other_attributes: specifies whether other attributes (not mentioned in `attributes`)
          are allowed in the node.
    Nr   rt   r   opr   r   +Sequence[int | float | ValuePattern | None]r   dict[str, AttrPattern]r   Sequence[str | None]r   r   r   r   r   c                  s   |d u rd}|d u rd}| _ t|trt|n| _dd |D  _| _| _| _| _	t|trDt|trDd}	|
 ||	f _nd  _ fddt|D  _t jD ]\}
}|d urf| |
 qXd S )NTFc                 S  r   r   r   r   r   r   r   r     r   z(NodePattern.__init__.<locals>.<listcomp>r   c                   s   g | ]
\}}t  ||qS r   )NodeOutputPattern)rh   ri   r8   r    r   r   r     s    )rt   rd   r   r&   r   r   r   r   r   r   r'   _op_identifier	enumerater   r   )r   rt   r   r   r   r   r   r   r   overloadr   r'   r   r    r   r,     s0   zNodePattern.__init__r   r   c                 C  s   d dd | jD }d dd | jD }d dd | j D }t| j}t| j}|r6| d| n|}|rA| d| n|}| d| d| d	S )
N, c                 s      | ]}t |V  qd S r   r   rh   vr   r   r   rj         z&NodePattern.__str__.<locals>.<genexpr>c                 s  r   r   r   r   r   r   r   rj     r   c                 s  s"    | ]\}}| d | V  qdS )=Nr   rh   kr   r   r   r   rj     s     .z = z (r   )joinr   r   r   r   r   r   rt   )r   r   r   r   r   rt   qualified_opinputs_and_attributesr   r   r   r!     s   

zNodePattern.__str__ir.OperatorIdentifier | Nonec                 C  r.   r   )r   r    r   r   r   op_identifier  r/   zNodePattern.op_identifierc                 C  r_   r   )r   r   r    r   r   r   op_type     
zNodePattern.op_typec                 C  r.   r   r   r    r   r   r   rn     r?   zNodePattern.check_methodr   ir.Nodematch_basics.MatchResultc              
   C  s&  | j |js|d| j  d|j d|S | j|js,|d| j d|j d|S | j D ]E\}}|j|}|du rO|jsN|d| d|  S n||sf|d| d| d| d|  S |j	durv|
|j	|sv|  S q1| js|jD ]}|| jvr|d| d	|  S q}|S )
zMatches the pattern represented by self against a node.

        This is purely a local node-level match, and does not consider the subgraph rooted at the node.
        We check the domain, op_type, and attributes of the node, but not the inputs.
        zOpType mismatch: expected z, got r   zDomain mismatch: expected Nz
Attribute z not found in node.z mismatch: expected z not expected in node.)r   r   r   failrt   r   r   getr7   r8   bindr   )r   r   r   r8   attr_pattern
attr_valuer   r   r   r     s:   



zNodePattern.matchesr   r   swapr   c              
     s|    fdd| j D }|rt|dksJ d|d |d g}dd | jD }t| j| j|| j|| j| j| j	d}| | < |S )	Nc                   s"   g | ]}|d ur|  nd qS r   r   r   r   r   r   r     s   " z%NodePattern.clone.<locals>.<listcomp>   z<Internal error: commutative swap applies only to binary ops.r   r   c                 S  s   g | ]}|j qS r   )r8   )rh   r'   r   r   r   r     s    r   )
r   r   r   r   rt   r   r   r   r   r   )r   r   r   r   r   copiedr   r   r   r     s&   
zNodePattern.clone)rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   )r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r,   r!   r   rO   r   rn   r   r   r   r   r   r   r     s    
+


&r   c                      sH   e Zd ZdZ	dd fddZdddZedddZdddZ  Z	S )r   zRepresents a pattern that matches against a specific output of a Node.

    This is the primary pattern used to match against computed values, that
    is values computed using a specific op.
    Nr   r   output_indexre   r8   r9   r   r1   c                   s   t  | || _|| _d S r   )rR   r,   	_producer_output_index)r   r   r  r8   rS   r   r   r,   4  s   
zNodeOutputPattern.__init__r   r   c                 C  s   || j  j| j S r   )r  r   r  r   r   r   r   r   ;  s   zNodeOutputPattern.clonec                 C  r.   r   )r  r    r   r   r   r  ?  r?   zNodeOutputPattern.output_indexc                 C  r.   r   )r  r    r   r   r   r   C  r/   zNodeOutputPattern.producerr   )r   r   r  re   r8   r9   r   r1   )r   r   r   r   r   re   r   r   )
r   r   r   r   r,   r   rO   r  r   rV   r   r   rS   r   r   -  s    
r   c                      s4   e Zd ZdZdddd fddZdddZ  ZS )rm   zRepresents a pattern-variable.NFr   r8   r9   r   r   r7   r   r   r1   c                  s   t  j|||d d S )Nr   rQ   r   rS   r   r   r,   J  s   zVar.__init__r   r   c                 C  s   t | j| j| jdS )zBClones the pattern-variable, preserving its name and check method.r   )rm   r8   rn   r7   r   r   r   r   r   O  s   z	Var.cloner   )r   r   r   rm   r   r   r   r   r,   r   rV   r   r   rS   r   rm   G  s
    rm   c                      s,   e Zd ZdZd
 fddZddd	Z  ZS )AnyValuez4Represents a pattern that matches against any value.r   r1   c                   s   t  d  d S r   rQ   r    rS   r   r   r,   W  s   zAnyValue.__init__r   r   c                 C  s   | S r   r   r   r   r   r   r   Z  r   zAnyValue.clone)r   r1   )r   r   r   r	  r  r   r   rS   r   r	  T  s    r	  c                      sJ   e Zd ZdZ		dd fddZdddZedddZdddZ  Z	S )r   zBRepresents a pattern that matches against a scalar constant value.h㈵>:0yE>r'   -int | float | Sequence[int] | Sequence[float]rel_tolrf   abs_tolr   r1   c                   s4   t  d  t|trt|n|| _|| _|| _d S r   )rR   r,   rd   r	   listr*   _rel_tol_abs_tol)r   r'   r  r  rS   r   r   r,   e  s   
zConstant.__init__r   r   c                 C  s   ~t | j| j| jS r   )r   r*   r  r  r   r   r   r   r   p  s   zConstant.clone%int | float | list[int] | list[float]c                 C  r.   r   r)   r    r   r   r   r'   t  r?   zConstant.valuer   c                 C  r_   r   r`   r    r   r   r   r!   x  r-   zConstant.__str__)r
  r  )r'   r  r  rf   r  rf   r   r1   )r   r   r   r   )r   r  r#   )
r   r   r   r   r,   r   rO   r'   r!   rV   r   r   rS   r   r   b  s    
r   c                      sJ   e Zd ZdZ		dd fd
dZedddZdddZdddZ  Z	S )OpIdDispatchOrz`Represents a (restricted) form of value pattern disjunction that enables deterministic matching.Nop_to_pattern8Mapping[ir.OperatorIdentifier, tuple[Any, ValuePattern]]r8   r9   tag_varr   r1   c                   s   t  | || _|| _dS )a  
        Initialize an OpIdDispatchOr pattern.

        Args:
            op_to_pattern: A dictionary mapping operator identifiers to tuples of tag values and patterns.
                The keys are operator identifiers, and the values are tuples containing a tag value
                and a pattern to match against.
            name: An optional variable name for the pattern. Defaults to None. If present,
                this name will be bound to the value matched by the pattern.
            tag_var: An optional variable name for the tag. Defaults to None. If present,
                it will be bound to a value indicating which alternative was matched.
        N)rR   r,   _op_to_pattern_tag_var)r   r  r8   r  rS   r   r   r,     s   
zOpIdDispatchOr.__init__c                 C  r.   z=Returns the tag variable associated with the OrValue pattern.r  r    r   r   r   r    rA   zOpIdDispatchOr.tag_varr   r   c                   s$   t  fdd| j D | j| jS )Nc                   s(   i | ]\}}||d  |d   fqS )r   r   r   r   r   r   r   r     s   ( z(OpIdDispatchOr.clone.<locals>.<dictcomp>)r  r  r   r8   r  r   r   r   r   r     s
   zOpIdDispatchOr.cloner'   ir.Valuetuple[Any, ValuePattern] | Nonec                 C  s8   |  }|dur| }|dur|| jv r| j| S dS )z=Returns the pattern that should be tried for the given value.N)r   r   r  )r   r'   r   rI   r   r   r   get_pattern  s   
zOpIdDispatchOr.get_pattern)NN)r  r  r8   r9   r  r9   r   r1   rL   )r   r   r   r  )r'   r  r   r  )
r   r   r   r   r,   rO   r  r   r  rV   r   r   rS   r   r  |  s    
r  c                      sB   e Zd ZdZ			dd fddZedddZdddZ  ZS )BacktrackingOrzMRepresents an unrestricted form of OR pattern implemented using backtracking.NvaluesSequence[ValuePattern]r8   r9   r  
tag_valuesSequence[Any] | Noner   r1   c                   sd   t  | |dur|du rtdt|t|krtdnttt|}|| _|| _|| _dS )a  
        Initialize a BacktrackingOr pattern.

        Args:
            values: A sequence of value patterns to match against.
            name: An optional variable name for the pattern. Defaults to None. If present,
                this name will be bound to the value matched by the pattern.
            tag_var: An optional variable name for the tag. Defaults to None. If present,
                it will be bound to a value (from tag_values) indicating which alternative was matched.
            tag_values: An optional sequence of values to bind to the tag_var. Defaults to None.
                If present, the length of tag_values must match the number of alternatives in values.
                In a successful match, tag-var will be bound to the i-th value in tag_values if the i-th
                alternative pattern matched. If omitted, the default value of (0, 1, 2, ...) will be used.
        N4tag_var must be specified if tag_values is provided.Ctag_values must have the same length as the number of alternatives.)	rR   r,   ro   r   r^   r   r  _tag_values_values)r   r  r8   r  r!  rS   r   r   r,     s   
zBacktrackingOr.__init__c                 C  r.   r  r  r    r   r   r   r    rA   zBacktrackingOr.tag_varr   r   c                   s$   t  fdd| jD | j| j| jS )Nc                      g | ]}|  qS r   r   r   r   r   r   r         z(BacktrackingOr.clone.<locals>.<listcomp>)r  r&  r8   r  r%  r   r   r   r   r     s   zBacktrackingOr.cloneNNN)
r  r   r8   r9   r  r9   r!  r"  r   r1   rL   )r   r   r   r  )	r   r   r   r   r,   rO   r  r   rV   r   r   rS   r   r    s    #r  r  r   r8   r9   r  r!  r"  c                   sv   durdu rt dttkrt dntttd fdd}| }|p:t r8ndS )	aO  
    Creates an OR pattern.

    Args:
        values: A sequence of value patterns to match against.
        name: An optional variable name for the pattern. Defaults to None. If present,
            this name will be bound to the value matched by the pattern.
        tag_var: An optional variable name for the tag. Defaults to None. If present,
            it will be bound to a value (from tag_values) indicating which alternative was matched.
        tag_values: An optional sequence of values to bind to the tag_var. Defaults to None.
            If present, the length of tag_values must match the number of alternatives in values.
            In a successful match, tag-var will be bound to the i-th value in tag_values if the i-th
            alternative pattern matched. If omitted, the default value of (0, 1, 2, ...) will be used.
    Nr#  r$  r   OpIdDispatchOr | Nonec                    sh   i } t D ]'\}}t|ts d S | }| }|d u s"|| v r% d S | |f| |< qt|  S r   )r   rd   r   r   r   r  )mappingri   alternativer   rI   r8   r!  r  r  r   r   make_op_id_or_pattern  s   
z&OrValue.<locals>.make_op_id_or_pattern)r   r*  )ro   r   r^   r   r  )r  r8   r  r!  r.  optimized_patternr   r-  r   OrValue  s   r0  r   list[NodePattern]c                   s(   g  d fdd|       S )	zFReturns all nodes used in a pattern, given the outputs of the pattern.value_patternsSequence[ValuePattern | None]r   r1   c                   s<   | D ]}t |tr| }| vr | |j qd S r   )rd   r   r   r   r   )r2  value_patternr   node_patternsvisitr   r   r7    s   


z _nodes_in_pattern.<locals>.visitN)r2  r3  r   r1   )reverse)r   r   r5  r   _nodes_in_pattern  s
   r9  r   backward_sliceset[NodePattern]backward_slice_valuesset[ValuePattern]r1   c                 C  sZ   | |v rdS | |  | jD ]}t|trt| || qt|ttfr*| | qdS )zAdds all nodes in the backward slice of given node to the set `backward_slice`.

    The backward slice of a node is the set of all nodes that are reachable from the node
    in a backward traversal from the given node.
    N)addr   rd   r   _add_backward_slicer   r  r  )r   r:  r<  r4  r   r   r   r?     s   





r?  c                   @  s   e Zd ZdZd+d	d
Zed,ddZd-ddZd.ddZd.ddZ	ed/ddZ
ed/ddZd0ddZd0ddZed1d d!Zed.d"d#Zd2d%d&Zd3d(d)Zd*S )4GraphPatternz<Represents a pattern that can be matched against a subgraph.r   r   r   r   r   r   r1   c           
      C  s   || _ || _t|dkrtd|| _t }t }t }t }|D ]6}t|ts2tdt	| dt|t
rK| }	|	|vrJ||	 t|	|| q!t|ttfrW|| q!||ks`tdt|| _d S )Nr   z*GraphPattern must have at least one outputzInvalid type z for graph pattern output.z3Returning uncovered choice-values is not supported.)_inputsr   r   ro   rx   setrd   r   rq   rY   r   r   r>  r?  r  r  NotImplementedErrorr  output_nodes)
r   r   r   r   rD  coveredchoice_values_returnedcovered_choice_valuesr4  	candidater   r   r   r,   9  s4   



zGraphPattern.__init__r   c                 C  s    t | jdkrtd| jd S )Nr   z.GraphPattern does not have unique output node.r   )r   rD  ro   r    r   r   r   output_node`  s   
zGraphPattern.output_noder   re   c                 C  s
   | j | S r   )rx   )r   r   r   r   r   r   f  r-   zGraphPattern.nodec                 C  r_   r   )r   rx   r    r   r   r   	num_nodesi  r-   zGraphPattern.num_nodesc                 C  s   |   S r   )rJ  r    r   r   r   __len__l  s   zGraphPattern.__len__c                 C  r.   r   )rA  r    r   r   r   r   o  r?   zGraphPattern.inputsc                 C  r.   r   )r   r    r   r   r   r   s  r?   zGraphPattern.outputsIterator[NodePattern]c                 C  r_   r   )iterrx   r    r   r   r   __iter__w  r-   zGraphPattern.__iter__c                 C  r_   r   )reversedrx   r    r   r   r   __reversed__z  r-   zGraphPattern.__reversed__r   c                 C  s   t | jdkS )Nr   )r   rD  r    r   r   r   has_single_output_node}  r~   z#GraphPattern.has_single_output_nodec                 C  r_   r   )r   r   r    r   r   r   num_outputs  r   zGraphPattern.num_outputsSequence[GraphPattern]c                   sD   ddd  fddj D }dfddfddtj| D S )Nr   r   r   Iterable[bool]c                 S  s&   |   dks|   dkrddgS dgS )N)r   r   r   )r   r   r   FT)r   )r   r   r   r   commute_node  s   z*GraphPattern.commute.<locals>.commute_nodec                      g | ]} |qS r   r   )rh   r   )rU  r   r   r     r   z(GraphPattern.commute.<locals>.<listcomp>	swap_listr@  c                   s^   t | sS i   fddjD } fddtj| D } fddjD }t|||S )Nc                   r'  r   r   r   r   r   r   r     r(  z<GraphPattern.commute.<locals>.copy_graph.<locals>.<listcomp>c                   s   g | ]
\}}|  |qS r   r   )rh   r   r   r   r   r   r     s    c                   r'  r   r   r   r   r   r   r     r(  )anyrA  ziprx   r   r@  )rW  
new_inputs	new_nodesnew_outputsr    r   r   
copy_graph  s   

z(GraphPattern.commute.<locals>.copy_graphc                   rV  r   r   )rh   rW  )r]  r   r   r     r   )r   r   r   rT  )rW  rT  r   r@  )rx   	itertoolsproduct)r   iteration_spacer   )rU  r]  r   r   commute  s   
zGraphPattern.commuter   c                 C  sZ   d dd | jD }d dd | jD }d dd | jD }d| d| d	| d
S )Nr   c                 s  r   r   r   r   r   r   r   rj     r   z'GraphPattern.__str__.<locals>.<genexpr>c                 s  r   r   r   r   r   r   r   rj     r   z
   c                 s  r   r   r   )rh   nr   r   r   rj     r   z	pattern (z) {
   z
   return z
})r   rA  r   rx   )r   r   r   r   r   r   r   r!     s   zGraphPattern.__str__N)r   r   r   r   r   r   r   r1   r  )r   re   r   r   r  )r   r   )r   rL  rM   )r   rS  r#   )r   r   r   r   r,   rO   rI  r   rJ  rK  r   r   rN  rP  rQ  rR  ra  r!   r   r   r   r   r@  6  s(    
'





r@  pattern_constructorr   c                 C  s   t | j}dd |D dd }tddd}t| | |g|R  }W d   n1 s.w   Y  t|tr;|g}t||| S )a  Convert a pattern-construction function to a GraphPattern.

    A pattern-construction function will return values as below:
    ::
        def pattern(op, x: Var, shape1: Var, shape2: Var):
            ...
            return outputs

    We create a pattern graph by creating pattern-variables for each parameter of the function,
    and calling the function. The returned values are normalized to a list of ValuePatterns,
    which represent the outputs of the pattern graph.

    Args:
        pattern_constructor: Callable

    Returns:
        GraphPattern: A representation of the pattern that can be matched against a subgraph.
    c                 S  r   r   )rm   r   r   r   r   r     r   z%_to_graph_pattern.<locals>.<listcomp>r   Nr   T)rv   )	inspect	signature
parametersrs   r   rd   r   r@  r   )rc  _pattern_varspattern_inputsr   pattern_outputsr   r   r   _to_graph_pattern  s   

rj  )r'   ra   r   r5   )r   r   r   r   )r   rs   r)  )
r  r   r8   r9   r  r9   r!  r"  r   r   )r   r   r   r1  )r   r   r:  r;  r<  r=  r   r1   )rc  r   r   r@  )=r   
__future__r   r$   
contextlibrd  r^  collections.abcr   typingr   r   r   r   r   r	   r
   r   onnxscript.rewriter._basicsrewriter_basics
onnxscriptr   r   r   ABCr   r   r&   r0   Attrr5   rP   re   rf   rX   rW   rr   rs   onnxoptorch_module_opr{   r   r   __annotations__contextmanagerr   r   r   r   rm   r	  	ANY_VALUEr   r  r  r0  r9  r?  r@  rj  r   r   r   r   <module>   sl   (

0
I"L /6
0
s