o
    qoi,                     @   s6  d Z ddlZddlZddlmZmZmZmZ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 ejZejZd
edee
j defddZejddG dd dZdejdeej fddZdedefddZejG dd dZ 	d$dede dededdf
d d!Z!dejdej"fd"d#Z#dS )%z<Library for generating code from a Config or Partial object.    N)AnyDictListSequenceTuple)daglish)configimport_manager)mini_ast)	namespace)special_value_codegenbase_varpathreturnc                 C   s   | d dd |D  S )a  Generates the LHS of an assignment, given a traversal path.

  Example: ["foo", 3, "bar"] -> "foo[3].bar".

  Args:
    base_var: Base variable name.
    path: Attribute path on `base_var` to assign to.

  Returns:
    Python code string for the LHS of an assignment.

  Raises:
    TypeError: If the first path element is not a string, or if any path element
      is not a string or an int.
   c                 s   s    | ]}|j V  qd S N)code).0x r   V/home/ubuntu/.local/lib/python3.10/site-packages/fiddle/_src/codegen/legacy_codegen.py	<genexpr>3   s    z"assignment_path.<locals>.<genexpr>)join)r   r   r   r   r   assignment_path"   s   r   T)frozenc                   @   s"   e Zd ZU dZeed< dd ZdS )_VarReferencez6Helper class whose repr() is just the provided string.namec                 C   s   | j S r   )r   )selfr   r   r   __repr__;   s   z_VarReference.__repr__N)__name__
__module____qualname____doc__str__annotations__r   r   r   r   r   r   6   s   
 r   	buildablec                    sF   t  i  dtjf fdd}tj||   fdd D S )zGFinds any sub-buildable nodes which are referenced by multiple parents.statec                    sD   t | tjrt|   d7  < |  t| < |j| ddD ]}qd S )N   Tignore_leaves)
isinstance
config_lib	Buildableidyield_map_child_values)valuer'   _children_by_idto_countr   r   traverseF   s   z(_get_shared_buildables.<locals>.traversec                    s    g | ]\}}|d kr | qS )r(   r   )r   
child_hashcount)r3   r   r   
<listcomp>O   s
    z*_get_shared_buildables.<locals>.<listcomp>)collectionsCounterr   StateBasicTraversalrunitems)r&   r5   r   r2   r   _get_shared_buildables?   s   
r?   r0   c                    s*   d dt jf fdd}t j||   S )z2Returns whether a value has any nested buildables.Fr'   c                    s4    pt | tj  s|| r||  d S d S d S r   )r+   r,   r-   is_traversableflattened_map_children)	sub_valuer'   resultr   r   r5   Z   s   z'_has_child_buildables.<locals>.traverse)r   r;   r<   r=   )r0   r5   r   rC   r   _has_child_buildablesV   s   rE   c                   @   s   e Zd ZU dZeed< eed< eje	dZ
eej ed< ejedZeeeejef f ed< dejfdd	Zd
edejdejddfddZdedeej dedejfddZdS )SharedBuildableManagerz4Helper class to manage shared configuration objects.r   r
   )default_factory	instancesinstances_and_names_by_idr&   c                 C   s   t || jv S r   )r.   rI   )r   r&   r   r   r   __contains__p   s   z#SharedBuildableManager.__contains__r   declr   Nc                 C   s"   | j | ||f| jt|< dS )zAdds a shared instance.

    Args:
      name: Variable name for code representing this instance.
      buildable: Actual Python Buildable object represented by the code being
        generated.
      decl: Code declaration for this instance.
    N)rH   appendrI   r.   )r   r   r&   rK   r   r   r   adds   s   
zSharedBuildableManager.addlhs_varlhs_path
attr_valuec                    sd   |rt |d tjrt S dd fdd	t||}t|t|}r0t|dS |S )a  Returns an assignment for a Python value.

    When this value references shared builder objects, then those objects are
    replaced with name references to the shared objects.

    Args:
      lhs_var: Variable name of the left-hand side assignment.
      lhs_path: Attribute path on `lhs_var` to assign to.
      attr_value: Python value representing the right-hand side of the
        expression.

    Returns:
      Codegen node representing the assignment.
    FNc                    sj   |pt j| }|  v rt jt|  d S t| tjr$dtdS |	| r.|
| S t|  jS )Nr(   TNotImplemented)r   r<   beginr   rI   r.   r+   r,   r-   r@   map_childrenr   transform_py_valuer
   )childr'   r   r5   used_not_implementedr   r   r5      s   

z/SharedBuildableManager.assign.<locals>.traversez0fdl.Config sub-nodes will replace NotImplementedr   )	r+   r   Indexr   Noopr   
AssignmentreprTrailingComment)r   rN   rO   rP   lhs
assignmentr   rW   r   assign   s   
zSharedBuildableManager.assign)r    r!   r"   r#   	Namespacer%   ImportManagerdataclassesfieldlistrH   r   r   CodegenNodedictrI   r   intr   r,   r-   r$   rJ   rM   r   r   PathElementr   r`   r   r   r   r   rF   d   s(   
 

rF   shared_shared_objectsshared_managerr
   variable_name_prefixc                    s@   dt jf fdd}t j|| j d}|| |  dS )a  Generates configuration for a shared object.

  The objects configured will be added to `shared_manager`.

  Args:
    shared_objects: List of shared objects, or any other nested structure
      compatible with daglish. Its dependencies can form a DAG, and any leaf
      nodes will be added first.
    shared_manager: Shared object manager.
    import_manager: Import manager.
    variable_name_prefix: Prefix for any variables introduced.
  r'   c           
         s   |j | ddD ]}qt| tjr]jjt| jd} t| } | j	}t
|| d| dg}| j D ]\}}t|g}	|||	| q<|| t
| dS dS )z%Generates code for a shared instance.Tr)   )prefix()N)r/   r+   r,   r-   r   get_new_nameget_callabler    rM   	__class__r   r[   __arguments__r>   r   BuildableAttrrL   r`   ImmediateAttrsBlock)
rV   r'   r1   r   relnamebuildable_subclass_strnodeskeyr0   r   r
   rl   rm   r   r   r5      s   z+_configure_shared_objects.<locals>.traverse)memoN)r   r;   MemoizedTraversalrI   copyinitial_state)rk   rl   r
   rm   r5   	traverserr   r{   r   _configure_shared_objects   s   r   c                    s   t  }t|t|dtt| d g dtjdtt f fdd  | g  	t
d t
 t
jgS )aD  Generates code, preferring nested dot-attribute assignment when possible.

  Example code output (abbreviated and with additional comments):

  # Shared instances are on top, since this format supports DAGs. However
  # choosing names is hard.
  shared_foo = fdl.Config(Foo)
  shared_foo.a = 1

  # Subsequent blocks set up a tree, doing attribute dot-assignment.
  root = fdl.Config(Baz)
  root.foo = shared_foo
  root.bar = fdl.Config(Bar)
  root.bar.foo2 = shared_foo

  Args:
    buildable: Config or Partial instance.

  Returns:
    Codegen node representing output code.
  r	   )rl   r
   rV   r   c                    s    t| } | j}ttd| d| dgg  dtjf fdd}tj	
||  t  D ]	\}}|| q>dS )z8Configures a tree node for the main configuration block.rootro   rp   r'   c                    s   |j s
||  dS g |j }t|j dkrt| snt| tjr/| vr/ | |f n
d||  |	| rKt| tjsM||  dS dS dS )z;Inner handler for traverse_with_path, assigning attributes.Nr(   r   )
current_pathrA   lenrE   r+   r,   r-   rL   r`   r@   )r0   r'   	full_path)deferredry   r   rl   r   r   handle_child_attr  s"   
zPcodegen_dot_syntax.<locals>.configure_main_tree_block.<locals>.handle_child_attrN)rM   r,   rr   rs   r   r[   r   r   r;   r<   r=   rL   rv   )rV   r   rw   rx   r   	sub_childsub_pathconfigure_main_tree_blockr
   main_tree_blocksrl   )r   ry   r   r   r   
  s   z5codegen_dot_syntax.<locals>.configure_main_tree_blockr   )ra   rb   rF   r   r?   r,   r-   r   r   rL   r   
ReturnStmtConfigBuildersorted_import_linesSharedThenResultAssignmentrH   )r&   r   r   r   r   codegen_dot_syntax   s&   "
(
r   )rj   )$r#   r9   rc   typingr   r   r   r   r   fiddler   fiddle._srcr   r,   fiddle._src.codegenr
   import_manager_libr   r   namespace_libr   ra   rb   r$   ri   r   	dataclassr   r-   r?   boolrE   rF   r   rf   r   r   r   r   r   <module>   sH   

Q
0