
    Ug                         d Z ddlZddlZddlZddlZddlZ G d dej                        Z G d dej                        Z	 G d de	      Z
d	 Zd
 Zd ZddZd Zd Zd Zy)zJ
Utilities for manipulating the Abstract Syntax Tree of Python constructs
    Nc                   4     e Zd ZdZ fdZd Zd Zd Z xZS )NameVisitorzQ
    NodeVisitor that builds a set of all of the named identifiers in an AST
    c                 B    t        |   |i | t               | _        y N)super__init__setnames)selfargskwargs	__class__s      1lib/python3.12/site-packages/datashader/macros.pyr   zNameVisitor.__init__   s    $)&)U
    c                 N    | j                   j                  |j                         y r   )r
   addidr   nodes     r   
visit_NamezNameVisitor.visit_Name   s    

twwr   c                     t        |d      r&| j                  j                  |j                         y t        |d      r&| j                  j                  |j                         y y )Nargr   )hasattrr
   r   r   r   r   s     r   	visit_argzNameVisitor.visit_arg   sC    4JJNN488$T4 JJNN477# !r   c           
      L   t        j                  d      }| j                  D cg c]  }|j                  |      s| }}|r)t	        |D cg c]  }t        |dd        c}      dz   }nd}t        |||z         D cg c]  }dt        |      z    c}S c c}w c c}w c c}w )aD  
        Returns a list of new names that are not already present in the AST.

        New names will have the form _N, for N a non-negative integer. If the
        AST has no existing identifiers of this form, then the returned names
        will start at 0 ('_0', '_1', '_2'). If the AST already has identifiers
        of this form, then the names returned will not include the existing
        identifiers.

        Parameters
        ----------
        num_names: int
            The number of new names to return

        Returns
        -------
        list of str
        z^_(\d+)$   Nr   _)recompiler
   matchmaxintrangestr)r   	num_namesprop_renmatching_namesstart_numbers         r   get_new_nameszNameVisitor.get_new_names   s    & **[)%)ZZDZ7==3C!ZDNCNqAabE
NCDqHLL lL9$<=?= "#c!f=? 	? EC?s   BBB?B!)	__name__
__module____qualname____doc__r   r   r   r*   __classcell__r   s   @r   r   r      s     $?r   r   c                   "     e Zd ZdZ fdZ xZS )ExpandVarargTransformerz
    Node transformer that replaces the starred use of a variable in an AST
    with a collection of unstarred named variables.
    c                 @    t        |   |i | || _        || _        y)a  
        Parameters
        ----------
        starred_name: str
            The name of the starred variable to replace
        expand_names: list of stf
            List of the new names that should be used to replace the starred
            variable

        N)r   r   starred_nameexpand_names)r   r4   r5   r   r   r   s        r   r   z ExpandVarargTransformer.__init__?   s'     	$)&)((r   )r+   r,   r-   r.   r   r/   r0   s   @r   r2   r2   :   s    ) )r   r2   c                       e Zd Zd Zy)ExpandVarargTransformerStarredc                     |j                   j                  | j                  k(  r9| j                  D cg c]#  }t	        j
                  ||j                        % c}S |S c c}w )N)r   ctx)valuer   r4   r5   astNamer9   )r   r   names      r   visit_Starredz,ExpandVarargTransformerStarred.visit_StarredQ   sY    ::==D---%%'% 9=CHH$((3%' ' K's   (AN)r+   r,   r-   r>    r   r   r7   r7   O   s    r   r7   c                     t        j                  t        j                  |             }t	        j
                  |      }|S )z2
    Get the AST representation of a function
    )textwrapdedentinspect	getsourcer;   parse)fn	fn_sourcefn_asts      r   function_to_astrI   Y   s4      1 1" 56I YYy!F
 Mr   c                 ,    ddl }|j                  |       S )z9Convert AST to source code string using the astor packager   N)astor	to_source)r;   rK   s     r   ast_to_sourcerM   j   s    ??3r   c                     t        | t        j                        sJ | j                  d   }t        |t        j                        sJ t        | d|j                  z  d      S )zO
    Compile function AST into a code object suitable for use in eval/exec
    r   z<%s>exec)mode)
isinstancer;   ModulebodyFunctionDefr   r=   )rH   	fndef_asts     r   compile_function_astrV   p   sQ     fcjj)))AIi11166INN2@@r   c                    t        | t        j                        sJ | j                  d   }t        |t        j                        sJ t        |       }t        j                         }|}t        |      D ]  }|j                  } |j                  }|j                  }~t        j                  |      }	|	j                  |       t        ||	       |	|j                     S )Nr   )rQ   r;   rR   rS   rT   rV   rC   currentframer#   f_backf_locals	f_globalscopyupdateevalr=   )
rH   
stacklevelrU   codecurrent_frame
eval_framer   eval_localseval_globalsscopes
             r   function_ast_to_functionrf   z   s    fcjj)))AIi111  'D ((*MJ:&&
  %%K''LIIl#E	LL 	u   r   c                 .    t        j                  |       S )N)r   )r;   r   r=   s    r   
_build_argri      s    77tr   c                 f   t        | t        j                        sJ t        j                  |       } | j
                  d   }t        |t        j                        sJ |j                  }|j                  }|st        d      |sJ t        |t              r|}n|j                  }t               }|j                  |        |j                  |      }t        } |||      j                  |       }	|	j
                  d   }
|
j                  j                  j!                  |D cg c]  }t#        |       c}       d|
j                  _        t               }|j                  |	       ||j$                  v rt        dj'                  |            g |_        t        j*                  |	       |	S c c}w )a  
    Given a function AST that use a variable length positional argument
    (e.g. *args), return a function that replaces the use of this argument
    with one or more fixed arguments.

    To be supported, a function must have a starred argument in the function
    signature, and it may only use this argument in starred form as the
    input to other functions.

    For example, suppose expand_number is 3 and fn_ast is an AST
    representing this function...

    def my_fn1(a, b, *args):
        print(a, b)
        other_fn(a, b, *args)

    Then this function will return the AST of a function equivalent to...

    def my_fn1(a, b, _0, _1, _2):
        print(a, b)
        other_fn(a, b, _0, _1, _2)

    If the input function uses `args` for anything other than passing it to
    other functions in starred form, an error will be raised.

    Parameters
    ----------
    fn_ast: ast.FunctionDef
    expand_number: int

    Returns
    -------
    ast.FunctionDef
    r   zmInput function AST does not have a variable length positional argument
(e.g. *args) in the function signaturerh   NzNThe variable length positional argument {n} is used in an unsupported context
)r'   )rQ   r;   rR   r\   deepcopyrS   rT   r   vararg
ValueErrorr$   r   r   visitr*   r7   extendri   r
   formatdecorator_listfix_missing_locations)rH   expand_numberrU   fn_args	fn_varargvararg_namebefore_name_visitorr5   expand_transformer
new_fn_astnew_fndef_astr=   after_name_visitors                r   expand_function_ast_varargsr|      s   F fcjj))) ]]6"F AIi111 nnG I  * + 	+ 9 )S!mm &-f%&44]CL 8#\eFm  OOA&M ""+78<4	<8 !%M %Z((... 
F[F 	
  "I j) ) 	9s   !F.c                 R     t         t              r dk  rt        d       fd}|S )aX  
    Decorator to expand the variable length (starred) argument in a function
    signature with a fixed number of arguments.

    Parameters
    ----------
    expand_number: int
        The number of fixed arguments that should replace the variable length
        argument

    Returns
    -------
    function
        Decorator Function
    r   z,expand_number must be a non-negative integerc                 L    t        |       }t        |      }t        |d      S )N   )r_   )rI   r|   rf   )rF   rH   fn_expanded_astrs   s      r   _expand_varargsz'expand_varargs.<locals>._expand_varargs  s&     $5fmL'AFFr   )rQ   r"   rm   )rs   r   s   ` r   expand_varargsr     s0      mS)]Q->GHHG r   )r   )r.   r   r\   rC   r;   rA   NodeVisitorr   NodeTransformerr2   r7   rI   rM   rV   rf   ri   r|   r   r?   r   r   <module>r      sq    
   
 ,?#// ,?^)c11 )*%< " A!:cLr   