o
    pic                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlm  mZ	 d dl
mZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ dd	lmZ dd
lmZmZmZmZ g ZG dd dZd ddZd ddZdd Z dd Z!dd Z"dd Z#dd Z$dd Z%dd Z&dS )!    N)core)convert_dtype)switch_to_static_graph)PirTranslatedLayer)TranslatedLayer)layers   )logging_utils)func_to_source_codeparse_arg_and_kwargsparse_varargs_name	type_namec                   @   s   e Zd ZdZdddZdd Zdd Zed	d
 Zedd Z	dd Z
dd Zedd Zedd Zedd Zedd Zedd Zedd ZdS )FunctionSpecz8
    Wrapper class for a function for class method.
    Nc                 C   s   t |r|j| _t|j| _n|| _d | _|d u r"d | _d | _	n| 
|| _tj| j| _	t|\| _| _t|| _| jd urXtt|dd ttfrZ|  j|jj7  _d S d S d S )N__self__)inspectismethod__func___dygraph_functionweakrefrefr   _class_instance_input_spec_flat_input_spec_verify_input_specpaddleutilsflattenr   
_arg_names_default_kwargsr   Zvarargs_name
isinstancegetattrr   r   Z_input_args_names)selffunction
input_spec r$   i/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/paddle/jit/dy2static/function_spec.py__init__.   s$   


zFunctionSpec.__init__c                 C   s  t | jt |k r8d| jj dt | j d| j dt | d| d}|r4t|d r4|d7 }t|t|t|}t	t |t | jD ]6}| j| }||v r\|
||  ||= qF|| jvrttd	| jj d
| d| d| d	|
| j|  qFt||fS )a  
        Moves kwargs with default value into arguments list to keep `args` contain the same length
        value as function definition.

        For example:

            Given function definition: `def foo(x, a=1, b=2)`,
            when calling it by `foo(23)`, the args is `[23]`, kwargs is `{a=1, b=2}`.
            In this function, it will return args with `[23, 1, 2]`, kwargs with `{}`

        Args:
            args(tuple): tuple of input arguments value of decorated function.
            kwargs(dict): dict of input keyword arguments value of decorated function.

        Return:
            New arguments tuple containing default kwargs value.
        zThe decorated function `z` requires z arguments: , but received z with .r   zP
	Maybe the function has more than one decorator, we don't support this for now.`z()` requires `z,` arguments, but not found in input `args`: z and `kwargs`: )lenr   dygraph_function__name__r   isclassNotImplementedError
ValueErrorlistrangeappendr   tuple)r!   argskwargs	error_msgiarg_namer$   r$   r%   unified_args_and_kwargsF   s$   4

 z$FunctionSpec.unified_args_and_kwargsc                    s   g }g }| j dur6|rt| jj d| dt|t| j k r/tdt| dt| j  t|| j }n#t|| j}dd | D }tt	|
 |  fdd	t|D }t| j|}||fS )
a  
        Converts input arguments into InputSpec.

        1. If specific input_spec, use them to construct feed layers.
        2. If input_spec is None, consider all Tensor and Numpy.ndarray as feed layers

        Args:
            args(tuple): tuple of input arguments value of function containing default kwargs value.
            kwargs(dict): kwargs arguments received by **kwargs.

        Return:
            Same nest structure with args and kwargs by replacing value with InputSpec.
        Nz# got unexpected keyword arguments: z;. Cannot trace the function when `input_spec` is specified.zCRequires len(arguments) >= len(input_spec), but received len(args):z < len(InputSpec): c                 S   s   g | ]}d | qS )zkwargs.r$   ).0keyr$   r$   r%   
<listcomp>       z3FunctionSpec.args_to_input_spec.<locals>.<listcomp>c                    s   i | ]	\}}| | qS r$   r$   )r:   idxr;   Zkwargs_list_with_specr$   r%   
<dictcomp>   s    z3FunctionSpec.args_to_input_spec.<locals>.<dictcomp>)r   r/   r+   r,   r*   convert_to_input_spec$_replace_to_input_spec_with_new_namer   keysr0   values	enumeratereplace_spec_empty_name)r!   r4   r5   args_with_specZkwargs_with_specZkwarg_namesr$   r?   r%   args_to_input_specp   s4   

zFunctionSpec.args_to_input_specc                 C   s$  ddl m} tj|}g }g }t|g t|D ]Z\}}t|tj	j
rht|dd}	tj	jj|jp6d| |jt|jd}
|	|
_ddlm} t||rb||j|}tj|
|j|}|| n||
 n|}
||
 ||
 qW d   n1 sw   Y  tj||tj||fS )	  
        Constructs feed layer by inputs with InputSpec information for main program.

        Args:
            input_with_spec(tuple): input arguments by replacing argument with InputSpec.
            main_program(Program): main program for inserting feed layer.
        r   to_placementsstop_gradientFfeed_)nameshapedtypeDistributedInputSpecN)/paddle.distributed.auto_parallel.placement_typerK   r   r   r   	ir_staticZprogram_guardrE   r   static	InputSpecr    inputdatarN   rO   r   rP   rL   7paddle.distributed.auto_parallel.static.dist_input_specrR   dims_mappingZ_pir_opsZshard_tensormeshr2   pack_sequence_as)r!   input_with_specmain_programrK   flat_input_specZfunction_argsZprogram_inputsr7   var_specrL   Z
feed_valuerR   
placementsZdist_feed_valuer$   r$   r%   pir_to_static_inputs_with_spec   sD   	

 z+FunctionSpec.pir_to_static_inputs_with_specc              	   C   s   t j|}g }| }t|D ]e\}}t|t jjrnt|dd}|j	|j
p*d| |j|jdd|d}	ddlm}
 ddlm} t||
rmdd	lm} | }||	}|j|j_|j|j_|jd
 |jd || n|}	||	 qt j||S )rI   rL   FrM   T)rN   rO   rP   Zis_dataZneed_check_feedrL   r   rQ   )DistributedTensor)get_default_distributed_contextprocess_meshrZ   )r   r   r   Zglobal_blockrE   r   rU   rV   r    Z
create_varrN   rO   rP   rY   rR   Z3paddle.distributed.auto_parallel.static.dist_tensorrc   Z4paddle.distributed.auto_parallel.static.dist_contextrd   r[   	dist_attrre   rZ   Zmark_annotatedZadd_dist_tensor_for_programr2   r\   )r!   r]   r^   r_   inputsblockr7   r`   rL   Z
feed_layerrR   rc   rd   Zdefault_dist_ctxZdist_tensorr$   r$   r%   to_static_inputs_with_spec   s:   	




z'FunctionSpec.to_static_inputs_with_specc                 C   s*   t |ttfstdt| dt|S )zJ
        Verifies the `input_spec` and its element type is valid.
        zBThe type(input_spec) should be one of (tuple, list), but received r(   )r   r3   r0   	TypeErrorr   )r!   r#   r$   r$   r%   r     s
   zFunctionSpec._verify_input_specc                 C   s   d | jjd| j| jS )Nz function: {}({}), input_spec: {},)formatr+   r,   joinr   r   r!   r$   r$   r%   __repr__  s
   
zFunctionSpec.__repr__c                 C   s*   | j d u rd S |   d u rtd|   S )NzFThe instance of class has been deleted, please re-create the instance.)r   RuntimeErrorrn   r$   r$   r%   class_instance$  s   
zFunctionSpec.class_instancec                 C   s   | j d ur| j| j S | jS N)rq   r   __get__rn   r$   r$   r%   r+   .  s   
zFunctionSpec.dygraph_functionc                 C      | j S rr   )r   rn   r$   r$   r%   	args_name5     zFunctionSpec.args_namec                 C   rt   rr   )r   rn   r$   r$   r%   r#   9  rv   zFunctionSpec.input_specc                 C   rt   rr   )r   rn   r$   r$   r%   r_   =  rv   zFunctionSpec.flat_input_specc                 C   s
   t | jS rr   )r
   r+   rn   r$   r$   r%   codeA  s   
zFunctionSpec.coderr   )r,   
__module____qualname____doc__r&   r9   rH   r   rb   ri   r   ro   propertyrq   r+   ru   r#   r_   rw   r$   r$   r$   r%   r   )   s.    
*8
5
3
	



r   Tc                 C   j   t  }| dur3t| tjr*|r%|  }dd |D }t t||}|S | j}|S tdt	|  |S )z
    Returns parameters of decorated layers. If set `include_sublayer` True,
    the parameters created in sub layers will be added.
    Nc                 S      g | ]}|j qS r$   rN   )r:   pr$   r$   r%   r<   P      z"get_parameters.<locals>.<listcomp>:Type of `layer_instance` should be nn.Layer, but received )
collectionsOrderedDictr   r   Layer
parameterszip_parametersrj   r   )layer_instanceinclude_sublayerparamsnamesr$   r$   r%   get_parametersF  s   r   c                 C   r|   )z
    Returns Variable buffers of decorated layers. If set `include_sublayer` True,
    the Variable buffers created in sub layers will be added.
    Nc                 S   r}   r$   r~   )r:   bufferr$   r$   r%   r<   f  r   zget_buffers.<locals>.<listcomp>r   )
r   r   r   r   r   buffersr   _buffersrj   r   )r   r   r   r   r$   r$   r%   get_buffers\  s   r   c           	   	   C   s,  ddl m} ddlm} g }ttj| D ]v\}}t|t	j
r+tjj|}d|_n\t|tjjrJ|j}| r?||}ntjj|}||_n=t|tjjjtjjfr|j}| ry| j}|| j|}||j|j|j|||j d}ntj|j|j|j}||_|!| qtj"| |}|S )Nr   rJ   rQ   T)rP   rN   r[   ra   Zlocal_shape)#rS   rK   rY   rR   rE   r   r   r   r   npndarrayrU   rV   
from_numpyrL   r   eagerTensorZis_distZfrom_dtensorfrom_tensorbase	frameworkVariablepirValuerf   re   rZ   rO   rP   rN   Z_local_shaper2   r\   )	r4   rK   rR   rG   r>   	input_varrL   r[   ra   r$   r$   r%   _replace_value_with_input_specq  sJ   

	r   c                 C   sL  t | t |ks
J t tt |d }g }tt| |D ]\}\}}d}ttj|D ]n\}}	t|	tj	rBtj
j|	}
d|
_n1t|	tjjrW|	j}tj
j|	}
||
_nt|	tjjjrq|	j}tj
|	j|	j|	j}
||
_n|	}
t|	tj	tjjtjjjfrdt|| d| d| |
_|d7 }||
 q-qtj| |}|S )Nr   r   Tz_jst.r(   )r*   strrE   r   r   r   r   r   r   r   rU   rV   r   rL   r   r   r   r   r   r   r   rO   rP   rN   zfillr2   r\   )r4   	arg_namesZorder_digitrG   orderargZname_prefixindexr>   Zorigin_inputr   rL   r$   r$   r%   rB     sB   "rB   c                    s  d fdd	}t  ttfrag }| d t D ]\}}t| |}|| qtt krTt d D ]}t |tjj	t
jfrStdt| d q<|t d  |S t  tri }| d  D ]\}}	| v rt|	 | ||< qr|	||< qr|S t  tjjr	 tgd }
t |
tjjstd	 d
 j|
_t |
r j|
_|
S td  d|
 d |
S  S )aD  
    Replaces tensor in structured `inputs` by InputSpec in `input_spec`.

    Args:
        inputs(list|dict): nested structure list or dict.
        input_spec(list|dict): same nested structure list or dict as inputs.


    Return:
        Same structure with inputs by replacing the element with specified InputSpec.
    Fc                    sf   t | t |urtdt | dt |  d|r/t| t|k r1tdt dt  d S d S )Nztype(input) should be r'   r(   zBRequires len(inputs) >= len(input_spec), but received len(inputs):z < len(input_spec):)typerj   r*   r/   )rW   speccheck_lengthr#   rg   r$   r%   check_type_and_len  s   z1convert_to_input_spec.<locals>.check_type_and_lenTNzThe inputs contain `z` without specifying InputSpec, its shape and dtype will be treated immutable. Please specific InputSpec information in `@to_static` if you expect them as mutable inputs.r   z1Give input spec into a non-tensorable arguments `z`.z;input spec is not compatible with real inputs. input_spec: z , real_spec:  )F)r   r3   r0   rE   rA   r2   r*   r   r   r   r   r   r	   warnr   extenddictitemsr   rU   rV   r   rp   rN   spec_greaterrO   )rg   r#   r   r]   r7   r   Zout_specZ
rest_inputrN   rW   Z	real_specr$   r   r%   rA     sT   





rA   c                 C   sD   t |}| dt| }t|D ]\}}|| }t||||< q|S )ao  
    Adds default name according to argument name from decorated function
    if without specifying InputSpec.name

    The naming rule are as followed:
        1. If InputSpec.name is not None, do nothing.
        2. If each argument `x` corresponds to an InputSpec, using the argument name like `x`
        3. If the arguments `inputs` corresponds to a list(InputSpec), using name like `inputs_0`, `inputs_1`
        4. If the arguments `input_dic` corresponds to a dict(InputSpec), using key as name.

    For example:

        # case 1: foo(x, y)
        foo = to_static(foo, input_spec=[InputSpec([None, 10]), InputSpec([None])])
        print([in_var.name for in_var in foo.inputs])  # [x, y]

        # case 2: foo(inputs) where inputs is a list
        foo = to_static(foo, input_spec=[[InputSpec([None, 10]), InputSpec([None])]])
        print([in_var.name for in_var in foo.inputs])  # [inputs_0, inputs_1]

        # case 3: foo(inputs) where inputs is a dict
        foo = to_static(foo, input_spec=[{'x': InputSpec([None, 10]), 'y': InputSpec([None])}])
        print([in_var.name for in_var in foo.inputs])  # [x, y]
    N)r0   r*   rE   _replace_spec_name)ru   r]   Zcandidate_arg_namesr7   r8   r#   r$   r$   r%   rF     s   rF   c                 C   s   t |tjjr|jdu r| |_|S t |ttfr4g }t|D ]\}}|  d| }|t	|| q|S t |t
rMi }| D ]\}}t	||||< q?|S |S )zL
    Replaces InputSpec.name with given `name` while not specifying it.
    N_)r   r   rU   rV   rN   r0   r3   rE   r2   r   r   r   )rN   r#   Zprocessed_specsr7   r   new_namer;   r$   r$   r%   r   5  s    

r   c                    sb   dd t j| D }|dd t j|D 7 }di   fddfdd|D }t|S )a  
    Generator hash spec with args/kwargs InputSpec names.
    Consider the following InputSpecs with same shape/dtype except for name:
      1. [InputSpec([3,3], 'float32', 'x'), InputSpec([3,3], 'float32', 'x')]
      2. [InputSpec([3,3], 'float32', 'x'), InputSpec([3,3], 'float32', 'y')]
    Under @to_static, we should generate two different program not just one, because
    the former has one input ('x'), but the latter has two input ('x', 'y').
    c                 S       g | ]}t |tjjr|jqS r$   r   r   rU   rV   rN   r:   r   r$   r$   r%   r<   U      z$_hash_spec_names.<locals>.<listcomp>c                 S   r   r$   r   r   r$   r$   r%   r<   Z  r   r   c                    s    | vr | <  d7  |  S )Nr   r$   r~   )r7   name_idsr$   r%   to_idxa  s   z _hash_spec_names.<locals>.to_idxc                    s   g | ]} |qS r$   r$   )r:   rN   )r   r$   r%   r<   h  r=   )r   r   r   r3   )Z
args_specsZkwargs_specsZ
spec_namesvaluer$   )r7   r   r   r%   _hash_spec_namesL  s   	


r   c                 C   s   dd }|| j |j S )Nc                 S   sB   t | t |kr
dS t| |D ]\}}|dkr||kr dS qdS )NFT)r*   r   )Zfirst_shapeZsecond_shapeZfirst_nZsecond_nr$   r$   r%   _shape_greatern  s   z$spec_greater.<locals>._shape_greater)rO   )firstotherr   r$   r$   r%   r   m  s   r   )T)'r   r   r   numpyr   r   Zpaddle.pir.corer   r   rT   Zpaddle.baseZpaddle.base.data_feederr   Zpaddle.base.dygraph.baser   Zpaddle.jit.pir_translated_layerr   Zpaddle.jit.translated_layerr   Zpaddle.nn.layerr    r	   r   r
   r   r   r   __all__r   r   r   r   rB   rA   rF   r   r   r   r$   r$   r$   r%   <module>   s6     

0&K#!