o
    i"+                     @  s   d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZmZ ddlmZ ejG dd	 d	ZejG d
d dZdddZddddd ddZdS )!z<Utilities for parsing and generating stub files for TVM FFI.    )annotationsN)Path)Callable	GeneratorIterable   )constsc                   @  s`   e Zd ZU dZded< ded< ded< ded	< d
ed< dddZedddZedddZ	dS )	CodeBlockz/A block of code to be generated in a stub file.zC.STUB_BLOCK_KINDSkindzstr | tuple[str, ...]paramintlineno_startz
int | None
lineno_endz	list[str]linesreturnNonec                 C  s   | j dv sJ dS )z-Validate the code block after initialization.>   Nexportglobalobject__all__ty-mapimport-objectimport-sectionN)r
   )self r   T/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/tvm_ffi/stub/file_utils.py__post_init__)   s   zCodeBlock.__post_init__c                 C  s*   | j sdS | j d }t|t|d S )zECalculate the indentation level of the block based on the first line.r    )r   lenlstrip)r   
first_liner   r   r   indent6   s   
zCodeBlock.indentlineolinestrc                 C  s  | tjr|ttjd  }td|| | g dS | tjrQ|ttjd  }dd |dD }t|dk rF|dgdt|  7 }td	t|| | g dS | tj	sYJ |ttj	d  }| d
rd}|td
d  }d|v rt|d}nW|df}nR| drd}|tdd  }n@| drd}|tdd  }n.|dkrd}d}n%| drd}|tdd  }n|dkrd}d}n
t
d| d|  t||| dg dS )zFParse a line to create a CodeBlock if it contains a stub begin marker.Nr   r
   r   r   r   r   c                 S  s   g | ]}|  qS r   )strip).0pr   r   r   
<listcomp>L   s    z-CodeBlock.from_begin_line.<locals>.<listcomp>;    r   zglobal/r   @zobject/r   zty-map/r   zexport/r   r   zUnknown stub type `z
` at line )
startswithCSTUB_TY_MAPr   r&   r	   STUB_IMPORT_OBJECTsplittuple
STUB_BEGIN
ValueError)r"   r#   splitsstubr
   r   r   r   r   from_begin_line>   sh   




zCodeBlock.from_begin_lineNr   r   )r   r   )r"   r   r#   r$   r   r	   )
__name__
__module____qualname____doc____annotations__r   propertyr!   staticmethodr8   r   r   r   r   r	      s   
 
r	   c                   @  sN   e Zd ZU dZded< ded< ded< dddZeddddZdddZdS )FileInfoz)Information about a file being processed.r   pathztuple[str, ...]r   zlist[CodeBlock]code_blocksverbosebooldry_runr   c                 C  s   t dd | jD }| j|kr|rttj dtj  dS |r{tj| j|ddD ]Q}|	ds5|	dr6q)|	d	rM|	dsMttj
 | tj  q)|	d
rd|	dsdttj | tj  q)|	drvttj | tj  q)t| q)|| _|s| jjd| jd dd dS )zTUpdate the file's lines based on the current code blocks and optionally show a diff.c                 s  s     | ]}|j D ]}|V  qqd S N)r   )r'   blockr#   r   r   r   	<genexpr>   s    z"FileInfo.update.<locals>.<genexpr>z-----> UnchangedFr,   )linetermz---z+++-+?
utf-8encodingT)r3   rC   r   printr/   	TERM_CYAN
TERM_RESETdifflibunified_diffr.   TERM_RED
TERM_GREENTERM_YELLOWrB   
write_textjoin)r   rD   rF   	new_linesr#   r   r   r   update   s(   


zFileInfo.updateFfileinclude_emptyFileInfo | Nonec              
   C  s  |   sJ d|  |  } d}| jdd }t|ddD ]\}}| tjr. dS | tj	r8d}q|s?|s?dS ~g }d}t|dD ]\}}| }	|	tj
rr|durbtd	| t||	}||_|j| qI|	tjr|du rtd
tj d| ||_|j| || d}qI|	tjrt||	}
||
_|
j| ||
 ~
qI|	tjrt||	}||_|j| || ~qI|	tj	rtd| d|	 |du r|tdd|||gd qI|j| qI|durtdt| t||dS )z:Parse a file to extract code blocks based on stub markers.zExpected a file, but got: FrO   rP   r   )startNTz"Nested stub not permitted at line zUnmatched `z` found at line zUnknown stub type at line z: r,   r%   z"Unclosed stub block at end of file)rB   r   rC   )is_fileresolve	read_text
splitlines	enumerater&   r.   r/   STUB_SKIP_FILESTUB_PREFIXr4   r5   r	   r8   r   r   appendSTUB_ENDr   r0   r1   rA   r3   )r^   r_   
has_markerr   _r#   codescodelineno
clean_linety_codeimp_coder   r   r   	from_file   st   




zFileInfo.from_filer   c                 C  s0   t | j}|dusJ d| j |j| _dS )zCReload the code blocks from disk while preserving original `lines`.Nz File no longer exists or valid: )rA   rs   rB   rC   )r   sourcer   r   r   reload   s   zFileInfo.reloadN)rD   rE   rF   rE   r   rE   )F)r^   r   r_   rE   r   r`   r9   )	r:   r;   r<   r=   r>   r]   r@   rs   ru   r   r   r   r   rA   z   s   
 
CrA   paths
list[Path]r   list[FileInfo]c                   s   ddd d fdd	}t | }t|d
d d}g }|D ])}zt|}W n ty= } z
 | W Y d}~qd}~ww |durG|| q|S )zLCollect all files from the given paths and parse them into FileInfo objects.e	Exceptionr   r   c                 S  s(   t tj dt  tj ddd d S )Nz[Error]
r,   T)endflush)rR   r/   rW   	traceback
format_excrT   )ry   r   r   r   	_on_error   s
   
z collect_files.<locals>._on_errorGenerator[Path, None, None]c                  3  sh    D ].} |   r| V  qt| d dD ]\}}}|D ]}t|| }|j tjvr,q|V  qqqd S )NF)follow_symlinkson_error)rb   	path_walkr   suffixlowerr/   DEFAULT_SOURCE_EXTS)r(   root_dirsfilesr^   fr   rv   r   r   _walk_recursive   s   z&collect_files.<locals>._walk_recursivec                 S  s   t | S rG   )r$   )r   r   r   r   <lambda>   s    zcollect_files.<locals>.<lambda>)keyN)ry   rz   r   r   )r   r   )listsortedrA   rs   rz   ri   )rv   r   	filenamesr   r^   contentry   r   r   r   collect_files   s    


r   TFtop_downr   r   r(   r   r   rE   r   "Callable[[Exception], None] | Noner   +Iterable[tuple[Path, list[str], list[str]]]c                c  sh    |   sdS t| dr| j|||dE dH  dS tj| |||dD ]\}}}t|}|||fV  q"dS )z@Compat wrapper for Path.walk (3.12+) with a fallback for < 3.12.Nwalkr   )topdownonerrorfollowlinks)existshasattrr   osr   )r(   r   r   r   root_strdirnamesr   r   r   r   r   r   
  s&   
r   )rv   rw   r   rx   )
r(   r   r   rE   r   r   r   rE   r   r   )r=   
__future__r   dataclassesrU   r   r}   pathlibr   typingr   r   r   r,   r   r/   	dataclassr	   rA   r   r   r   r   r   r   <module>   s$   Z
k'