o
    ,wi                     @   s   d Z ddlZddlZddlmZmZmZmZ ddlm	Z
 ddlmZ e Zdeddfdd	Ze Zd
eee edef f ddfddZdedefddZdedefddZeddddgZdedejfddZdS )zHelper functions for writing Daglish traversals.

These are kept in a separate file so they can reference both the core Daglish
implementation and Fiddle Buildable's.
    N)AnyCallableTypeUnion)config)daglishvaluereturnc                 C   s   t t|  dS )z)Registers a certain type to be immutable.N)_IMMUTABLE_OBJECT_IDSaddidr    r   [/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/fiddle/_src/daglish_extensions.pyregister_immutable    s   r   	fn_or_cls.c                 C   s   t t|  d S N)'_FUNCTIONS_WITH_IMMUTABLE_RETURN_VALUESr   r   )r   r   r   r   -register_function_with_immutable_return_value*   s   r   c                 C   s2   t | pt| totdd | D pt| tv S )av  Returns true if value is immutable from the point view of Fiddle.

  This method differs from `is_internable` in that NamedTuples and other tuple
  subclasses are included here.

  Frozen dataclasses are not considered as immutable here. Because dataclasses
  are not traversable by default, and will be handled like a generic object.
  The motivation for this decision is partly to encourage users to
  create fdl.Config out of dataclasses rather than have dataclass instances
  in the fdl.Config.

  Args:
    value: A candidate value to check for immutability.

  Returns:
    A bool indicating whether `value` is immutable.
  c                 s       | ]}t |V  qd S r   )is_immutable.0er   r   r   	<genexpr>E       zis_immutable.<locals>.<genexpr>)r   is_internable
isinstancetupleallr   r
   r   r   r   r   r   1   s
   

r   c                 C   sP   t | p't| totdd | D p't| tv p't| tjo'tt	| t
v S )at  Returns true if value can be unshared and build an equivalent object.

  This is a slight generalization of is_immutable, for example we can have

  shared = fdl.Config(jax.nn.initializers.glorot_uniform, batch_axis=(0,))
  cfg.a.init = shared
  cfg.b.init = shared

  is_unshareable will return True for `shared`, indicating that we can replace
  the config with the following one,

  cfg2.a.init = fdl.Config(jax.nn.initializers.glorot_uniform, batch_axis=(0,))
  cfg2.b.init = fdl.Config(jax.nn.initializers.glorot_uniform, batch_axis=(0,))

  This differs in configuration API, because setting

  (cfg_or_cfg2).a.init.batch_axis = (1,)

  will set both initializers in cfg, but only the first initializer in cfg2.

  However, if we immediately call fdl.build(cfg), it is equivalent to
  fdl.build(cfg2), because the initializer is the same.

  For codegen, this will explictly classsify jax dtypes and initializers as
  immutable, so that they are not extracted as separate variables in generated
  code.

  Args:
    value: A candidate value to check for immutability.

  Returns:
    A bool indicating whether `value` is immutable.
  c                 s   r   r   )is_unshareabler   r   r   r   r   o   r   z!is_unshareable.<locals>.<genexpr>)r   r   r   r   r   r   r
   
config_lib	Buildableget_callabler   r   r   r   r   r    K   s   
#
r    z(?:{})|z\.(?P<attr_name>[\w_]+)z#\[(?P<key>\d+|'[^']+'|\"[^\"]+\")\]pathc                 C   s   g }d}|t | k rTt| |}|std| d| d| }|d r0|t|d  n|d rB|tt	
|d  ntd| |d}|t | k s
t|S )a  Parses a string path into a path with Attr and Key elements.

  Note that we can't distinguish between Index and Key or Attr and
  BuildableAttr. We might eventually remove that distinction from Daglish
  itself.

  Args:
    path: Path string. If appended to a symbol it should be a valid Python
      expression; in particular if the first element is an attribute, the path
      must start with ".attribute_name", not "attribute_name".

  Returns:
    Parsed Daglish path.
  r   zCould not parse z (starting at position )	attr_namekeyzUnexpected regex match )len
_PATH_PARTmatch
ValueError	groupdictappendr   AttrKeyastliteral_evalAssertionErrorendr   )r%   resultcurrent_idxr+   
match_dictr   r   r   
parse_path   s"   
r8   )__doc__r1   retypingr   r   r   r   fiddle._srcr   r!   r   setr
   r   r   r   boolr   r    compileformatjoinr*   strPathr8   r   r   r   r   <module>   s2   
-