o
    Nrf51                     @  s   d dl mZ d dlmZ d dlmZmZ dd Zdd ZG dd	 d	Z	G d
d dZ
e
dZe
dZG dd deZG dd dZG dd dZdd Zdd ZeedZdd Zdd ZdS )    )annotations)deque)istasksubsc                 C  s"   t | r| d S t| trtS | S )z#Return the top level node of a taskr   r   
isinstancelisttask r   U/var/www/html/software/conda/envs/catlas/lib/python3.10/site-packages/dask/rewrite.pyhead   s
   
r   c                 C  s&   t | r
| dd S t| tr| S dS )z&Get the arguments for the current task   Nr   r   r	   r   r   r   args   s
   
r   c                   @  sF   e Zd ZdZdddZdd Zdd Zd	d
 Zedd Z	dd Z
dS )	Traversera  Traverser interface for tasks.

    Class for storing the state while performing a preorder-traversal of a
    task.

    Parameters
    ----------
    term : task
        The task to be traversed

    Attributes
    ----------
    term
        The current element in the traversal
    current
        The head of the current element in the traversal. This is simply `head`
        applied to the attribute `term`.
    Nc                 C  s$   || _ |sttg| _d S || _d S N)termr   END_stack)selfr   stackr   r   r   __init__2   s   
zTraverser.__init__c                 c  s.    | j tur| j V  |   | j tusd S d S r   )currentr   nextr   r   r   r   __iter__9   s
   
zTraverser.__iter__c                 C  s   t | jt| jS )zCopy the traverser in its current state.

        This allows the traversal to be pushed onto a stack, for easy
        backtracking.)r   r   r   r   r   r   r   r   copy>   s   zTraverser.copyc                 C  sD   t | j}|s| j | _dS |d | _| jt|dd  dS )z3Proceed to the next term in the preorder traversal.r   r   N)r   r   r   popextendreversed)r   Zsubtermsr   r   r   r   F   s
   

zTraverser.nextc                 C  s
   t | jS r   )r   r   r   r   r   r   r   Q   s   
zTraverser.currentc                 C  s   | j  | _dS )z<Skip over all subterms of the current level in the traversalN)r   r   r   r   r   r   r   skipU   s   zTraverser.skipr   )__name__
__module____qualname____doc__r   r   r   r   propertyr   r    r   r   r   r   r      s    

r   c                   @  s    e Zd ZdZdd Zdd ZdS )Tokenz[A token object.

    Used to express certain objects in the traversal of a task or pattern.c                 C  s
   || _ d S r   name)r   r(   r   r   r   r   _      
zToken.__init__c                 C  s   | j S r   r'   r   r   r   r   __repr__b   s   zToken.__repr__N)r!   r"   r#   r$   r   r*   r   r   r   r   r&   Z   s    r&   ?endc                   @  s6   e Zd ZdZdZd
ddZedd Zedd	 ZdS )NodezA Discrimination Net node.r   Nc                 C  s(   |r|ni }|r
|ng }t | ||fS r   )tuple__new__)clsedgespatternsr   r   r   r/   r   s   zNode.__new__c                 C     | d S )z@A dictionary, where the keys are edges, and the values are nodesr   r   r   r   r   r   r1   w      z
Node.edgesc                 C  r3   )z8A list of all patterns that currently match at this noder   r   r   r   r   r   r2   |   r4   zNode.patterns)NN)	r!   r"   r#   r$   	__slots__r/   r%   r1   r2   r   r   r   r   r-   m   s    

r-   c                   @  s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )RewriteRulea  A rewrite rule.

    Expresses `lhs` -> `rhs`, for variables `vars`.

    Parameters
    ----------
    lhs : task
        The left-hand-side of the rewrite rule.
    rhs : task or function
        The right-hand-side of the rewrite rule. If it's a task, variables in
        `rhs` will be replaced by terms in the subject that match the variables
        in `lhs`. If it's a function, the function will be called with a dict
        of such matches.
    vars: tuple, optional
        Tuple of variables found in the lhs. Variables can be represented as
        any hashable object; a good convention is to use strings. If there are
        no variables, this can be omitted.

    Examples
    --------
    Here's a `RewriteRule` to replace all nested calls to `list`, so that
    `(list, (list, 'x'))` is replaced with `(list, 'x')`, where `'x'` is a
    variable.

    >>> import dask.rewrite as dr
    >>> lhs = (list, (list, 'x'))
    >>> rhs = (list, 'x')
    >>> variables = ('x',)
    >>> rule = dr.RewriteRule(lhs, rhs, variables)

    Here's a more complicated rule that uses a callable right-hand-side. A
    callable `rhs` takes in a dictionary mapping variables to their matching
    values. This rule replaces all occurrences of `(list, 'x')` with `'x'` if
    `'x'` is a list itself.

    >>> lhs = (list, 'x')
    >>> def repl_list(sd):
    ...     x = sd['x']
    ...     if isinstance(x, list):
    ...         return x
    ...     else:
    ...         return (list, x)
    >>> rule = dr.RewriteRule(lhs, repl_list, variables)
    r   c                   sf   t  ts	td|| _t|r|| _n| j| _|| _ fddt|D | _	tt
t| j	| _d S )Nz!vars must be a tuple of variablesc                   s   g | ]}| v r|qS r   r   .0tvarsr   r   
<listcomp>   s    z(RewriteRule.__init__.<locals>.<listcomp>)r   r.   	TypeErrorlhscallabler   _applyrhsr   _varlistsortedsetr;   )r   r>   rA   r;   r   r:   r   r      s   
zRewriteRule.__init__c                 C  s(   | j }| D ]
\}}t|||}q|S r   )rA   itemsr   )r   Zsub_dictr   keyvalr   r   r   r@      s   zRewriteRule._applyc                 C  s   d| j  d| j d| j dS )NzRewriteRule(z, ))r>   rA   r;   r   r   r   r   __str__   s   zRewriteRule.__str__c                 C  s   t | S r   )strr   r   r   r   r*      s   zRewriteRule.__repr__N)r   )r!   r"   r#   r$   r   r@   rI   r*   r   r   r   r   r6      s    
-r6   c                   @  s:   e Zd ZdZdd Zdd Zdd Zdd	 ZdddZdS )RuleSeta%  A set of rewrite rules.

    Forms a structure for fast rewriting over a set of rewrite rules. This
    allows for syntactic matching of terms to patterns for many patterns at
    the same time.

    Examples
    --------

    >>> import dask.rewrite as dr
    >>> def f(*args): pass
    >>> def g(*args): pass
    >>> def h(*args): pass
    >>> from operator import add

    >>> rs = dr.RuleSet(
    ...         dr.RewriteRule((add, 'x', 0), 'x', ('x',)),
    ...         dr.RewriteRule((f, (g, 'x'), 'y'),
    ...                        (h, 'x', 'y'),
    ...                        ('x', 'y')))

    >>> rs.rewrite((add, 2, 0))
    2

    >>> rs.rewrite((f, (g, 'a', 3)))    # doctest: +ELLIPSIS
    (<function h at ...>, 'a', 3)

    >>> dsk = {'a': (add, 2, 0),
    ...        'b': (f, (g, 'a', 3))}

    >>> from toolz import valmap
    >>> valmap(rs.rewrite, dsk)         # doctest: +ELLIPSIS
    {'a': 2, 'b': (<function h at ...>, 'a', 3)}

    Attributes
    ----------
    rules : list
        A list of `RewriteRule`s included in the `RuleSet`.
    c                 G  s&   t  | _g | _|D ]}| | q	dS )zCreate a `RuleSet` for a number of rules

        Parameters
        ----------
        rules
            One or more instances of RewriteRule
        N)r-   _netrulesadd)r   rM   pr   r   r   r      s
   zRuleSet.__init__c                 C  s   t |ts	td|j}| j}t| j}t|jD ] }|}||v r#t	}||j
v r.|j
| }qt |j
|< |j
| }q|j
| j| | j| dS )zeAdd a rule to the RuleSet.

        Parameters
        ----------
        rule : RewriteRule
        z$rule must be instance of RewriteRuleN)r   r6   r=   r;   rL   lenrM   r   r>   VARr1   r-   r2   append)r   ruler;   Z	curr_nodeindr9   Z	prev_noder   r   r   rN      s   


zRuleSet.addc                 c  sT    t |}t|| jD ]\}}|D ]}| j| }t||}|dur&||fV  qqdS )al  A generator that lazily finds matchings for term from the RuleSet.

        Parameters
        ----------
        term : task

        Yields
        ------
        Tuples of `(rule, subs)`, where `rule` is the rewrite rule being
        matched, and `subs` is a dictionary mapping the variables in the lhs
        of the rule to their matching values in the term.N)r   _matchrL   rM   _process_match)r   r   SmsymsirS   r   r   r   r   iter_matches  s   


zRuleSet.iter_matchesc                 C  s&   |  |D ]\}}||} |S |S )z7Apply the rewrite rules in RuleSet to top level of term)r[   r   )r   r   rS   sdr   r   r   _rewrite0  s   
zRuleSet._rewrite	bottom_upc                 C  s   t | | |S )ae  Apply the `RuleSet` to `task`.

        This applies the most specific matching rule in the RuleSet to the
        task, using the provided strategy.

        Parameters
        ----------
        term: a task
            The task to be rewritten
        strategy: str, optional
            The rewriting strategy to use. Options are "bottom_up" (default),
            or "top_level".

        Examples
        --------
        Suppose there was a function `add` that returned the sum of 2 numbers,
        and another function `double` that returned twice its input:

        >>> add = lambda x, y: x + y
        >>> double = lambda x: 2*x

        Now suppose `double` was *significantly* faster than `add`, so
        you'd like to replace all expressions `(add, x, x)` with `(double,
        x)`, where `x` is a variable. This can be expressed as a rewrite rule:

        >>> rule = RewriteRule((add, 'x', 'x'), (double, 'x'), ('x',))
        >>> rs = RuleSet(rule)

        This can then be applied to terms to perform the rewriting:

        >>> term = (add, (add, 2, 2), (add, 2, 2))
        >>> rs.rewrite(term)  # doctest: +SKIP
        (double, (double, 2))

        If we only wanted to apply this to the top level of the term, the
        `strategy` kwarg can be set to "top_level".

        >>> rs.rewrite(term)  # doctest: +SKIP
        (double, (add, 2, 2))
        )
strategies)r   r
   Zstrategyr   r   r   rewrite;  s   )zRuleSet.rewriteN)r^   )	r!   r"   r#   r$   r   rN   r[   r]   r`   r   r   r   r   rK      s    (rK   c                 C  s
   |  |S r   )r]   netr   r   r   r   
_top_levelg  r)   rc   c                   sX   t |rt|ft fddt|D  }nt|tr' fddt|D } |S )Nc                 3  s    | ]}t  |V  qd S r   
_bottom_upr7   rb   r   r   	<genexpr>m  s    z_bottom_up.<locals>.<genexpr>c                   s   g | ]}t  |qS r   rd   r7   rf   r   r   r<   o  s    z_bottom_up.<locals>.<listcomp>)r   r   r.   r   r   r   r]   ra   r   rf   r   re   k  s
   &

re   )Z	top_levelr^   c                 c  s    t  }d}d}	 | jtu r|j|fV  z |j| jd}|r3|s3||  ||f |}|   W qW n	 t	y=   Y nw |jt
d}|rVd}|| jf }|   |}qz| \} }}d}W n
 tyk   Y dS w q	)z;Structural matching of term S to discrimination net node N.Fr   TN)r   r   r   r2   r1   getrR   r   r   r=   rQ   r   r    r   	Exception)rW   Nr   Zrestore_state_flagmatchesnr   r   r   rU   v  s@   
rU   c                 C  s\   i }| j }t|t|kstdt||D ]\}}||v r'|| |kr' dS |||< q|S )a  Process a match to determine if it is correct, and to find the correct
    substitution that will convert the term into the pattern.

    Parameters
    ----------
    rule : RewriteRule
    syms : iterable
        Iterable of subterms that match a corresponding variable.

    Returns
    -------
    A dictionary of {vars : subterms} describing the substitution to make the
    pattern equivalent with the term. Returns `None` if the match is
    invalid.z/length of varlist doesn't match length of syms.N)rB   rP   RuntimeErrorzip)rS   rY   r   Zvarlistvsr   r   r   rV     s   
rV   N)
__future__r   collectionsr   Z	dask.corer   r   r   r   r   r&   rQ   r   r.   r-   r6   rK   rc   re   r_   rU   rV   r   r   r   r   <module>   s$    <H 
&