o
    oh˔                     @   sR  d dl mZ d dlZedddgidZ	 erd dlmZmZmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZm Z m!Z! d d	l"m#Z#m$Z$m%Z%m&Z&m'Z' d d
l(m)Z)m*Z*m+Z+m,Z, d dl-m.Z. d dl/m0Z0 d dl(m1Z1m2Z2 d dl3Z3d dl4Z4G dd dZ5G dd de5Z6nG dd dZ6dd Z7dS )    )import_moduleNzclang.cindexfromlistcindex)import_kwargs)VariableIntegerFloatFunctionPrototypeFunctionDefinitionFunctionCallnoneReturn
Assignmentintcint8int16int64uint8uint16uint32uint64float32float64float80
aug_assignbool_While	CodeBlock)PreDecrementPostDecrementPreIncrementPostIncrement)AddModMulPowRel)And
as_BooleanNotOr)Symbol)sympify)falsetruec                   @   s    e Zd ZdZdd Zdd ZdS )
BaseParserzBase Class for the C parserc                 C   s   t j | _dS )z6Initializes the Base parser creating a Clang AST indexN)cinIndexcreateindexself r6   l/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/parsing/c/c_parser.py__init__?   s   zBaseParser.__init__c              	   C   sL   | j jD ]}tddddddd|j |jj|jj|jj|jf |d qd	S )
z%Diagostics function for the Clang ASTz%s %s (line %s, col %s) %sFATALERRORWARNINGNOTEIGNORED)            r   fileN)	tudiagnosticsprintseveritylocationrC   linecolumnspelling)r5   outdiagr6   r6   r7   rE   C   s$   zBaseParser.diagnosticsN)__name__
__module____qualname____doc__r8   rE   r6   r6   r6   r7   r/   <   s    r/   c                       s   e Zd ZdZ f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d Z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$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Z  Z S ):CCodeConverterzThe Code Convereter for Clang AST

        The converter object takes the C source code or file as input and
        converts them to SymPy Expressions.
        c                    s   t    g | _tjjtitjjtitjj	t
tjjttjjttjjttjjttjjttjjttjjtitjjttjjttjjtid| _dS )zInitializes the code converter)voidboolintfloatN) superr8   	_py_nodesr0   TypeKindVOIDr   BOOLr   SCHARr   SHORTr   INTr   LONGr   UCHARr   USHORTr   UINTr   ULONGr   FLOATr   DOUBLEr   
LONGDOUBLEr   _data_typesr4   	__class__r6   r7   r8   \   s(   
CCodeConverter.__init__c                 C   sj   t j|}| jj||tjjd| _| jj	
 D ]}|jtjjks(|jtjjkr1| j| | q| jS )a  Function to parse a file with C source code

            It takes the filename as an attribute and creates a Clang AST
            Translation Unit parsing the file.
            Then the transformation function is called on the translation unit,
            whose reults are collected into a list which is returned by the
            function.

            Parameters
            ==========

            filename : string
                Path to the C file to be parsed

            flags: list
                Arguments to be passed to Clang while parsing the C code

            Returns
            =======

            py_nodes: list
                A list of SymPy AST nodes

            argsoptions)ospathabspathr3   parser0   TranslationUnit PARSE_DETAILED_PROCESSING_RECORDrD   cursorget_childrenkind
CursorKindVAR_DECLFUNCTION_DECLrX   append	transform)r5   filenameflagsfilepathchildr6   r6   r7   rq   x   s   zCCodeConverter.parsec                 C   s   t jddd}|| |d | jj|j|tjj	d| _
|  | j
j D ]}|jtjjks8|jtjjkrA| j| | q(| jS )a  Function to parse a string with C source code

            It takes the source code as an attribute, stores it in a temporary
            file and creates a Clang AST Translation Unit parsing the file.
            Then the transformation function is called on the translation unit,
            whose reults are collected into a list which is returned by the
            function.

            Parameters
            ==========

            source : string
                A string containing the C source code to be parsed

            flags: list
                Arguments to be passed to Clang while parsing the C code

            Returns
            =======

            py_nodes: list
                A list of SymPy AST nodes

            zw+z.cpp)modesuffixr   rk   )tempfileNamedTemporaryFilewriteseekr3   rq   namer0   rr   rs   rD   closert   ru   rv   rw   rx   ry   rX   rz   r{   )r5   sourcer}   rC   r   r6   r6   r7   	parse_str   s   

zCCodeConverter.parse_strc                 C   sT   t | d|jj  d}|du r&td|jddd | D f tjd ||S )aF  Transformation Function for Clang AST nodes

            It determines the kind of node and calls the respective
            transformation function for that node.

            Raises
            ======

            NotImplementedError : if the transformation for the provided node
            is not implemented

            ztransform_%sNzIgnoring node of type %s (%s) c                 s       | ]}|j V  qd S NrK   .0tr6   r6   r7   	<genexpr>       
z+CCodeConverter.transform.<locals>.<genexpr>rB   )	getattrrv   r   lowerrF   join
get_tokenssysstderr)r5   nodehandlerr6   r6   r7   r{      s   
	zCCodeConverter.transformc                 C   s  |j j| jd v r| jd |j j }n*|j j| jd v r&| jd |j j }n|j j| jd v r9| jd |j j }ntdz| }t|}|jtjjksT|jtjj	krft|}|jtjjksT|jtjj	ksT| 
|}tjjtjjtjjtjjtjjtjjtjjg}|j|v rt|trt|}nxt|tr|j j| jd v r|dkrtdntd}n]|j j| jd v r|dkrtdntd	}nG|j j| jd v rt|}n9t|ttttfr|j j| jd v rt|}n!|j j| jd v rt|}n|j j| jd v rtt|}n|}t|jj||d
W S |jtjjkr't|jj|dW S tdd dd |! D  t"yJ   t|jj|d Y S w )a  Transformation Function for Variable Declaration

            Used to create nodes for variable declarations and assignments with
            values or function call for the respective nodes in the clang AST

            Returns
            =======

            A variable node as Declaration, with the initial value if given

            Raises
            ======

            NotImplementedError : if called for data types not currently
            implemented

            Notes
            =====

            The function currently supports following data types:

            Boolean:
                bool, _Bool

            Integer:
                8-bit: signed char and unsigned char
                16-bit: short, short int, signed short,
                    signed short int, unsigned short, unsigned short int
                32-bit: int, signed int, unsigned int
                64-bit: long, long int, signed long,
                    signed long int, unsigned long, unsigned long int

            Floating point:
                Single Precision: float
                Double Precision: double
                Extended Precision: long double

            rU   rV   rT   &Only bool, int and float are supportedFr   rA   g        g      ?typevalue)r   z=Given variable declaration "{}" is not possible to parse yet!r   c                 s   r   r   r   r   r6   r6   r7   r   H  r   z4CCodeConverter.transform_var_decl.<locals>.<genexpr>r   )#r   rv   rg   NotImplementedErrorru   nextr0   rw   NAMESPACE_REFTYPE_REFr{   INTEGER_LITERALFLOATING_LITERALUNEXPOSED_EXPRBINARY_OPERATOR
PAREN_EXPRUNARY_OPERATORCXX_BOOL_LITERAL_EXPR
isinstancestrr+   rT   r   r   r,   rU   rV   r   rK   as_Declaration	CALL_EXPRformatr   r   StopIteration)r5   r   r   childrenr   valsupported_rhsr   r6   r6   r7   transform_var_decl   s   '







z!CCodeConverter.transform_var_declc           	      C   s:  |j j| jd v r| jd |j j }n=|j j| jd v r&| jd |j j }n*|j j| jd v r9| jd |j j }n|j j| jd v rL| jd |j j }ntdg }g }| D ]+}| |}|jtjjkrl|	| qX|jtjj
kr~|D ]}|	| quqX|	| qX|g krt||j|d}|S t||j||d}|S )a  Transformation Function For Function Declaration

            Used to create nodes for function declarations and definitions for
            the respective nodes in the clang AST

            Returns
            =======

            function : Codegen AST node
                - FunctionPrototype node if function body is not present
                - FunctionDefinition node if the function body is present


            rU   rV   rT   rS   z,Only void, bool, int and float are supported)return_typer   
parameters)r   r   r   body)result_typerv   rg   r   ru   r{   r0   rw   	PARM_DECLrz   COMPOUND_STMTr	   rK   r
   )	r5   r   ret_typer   paramr   declr   functionr6   r6   r7   transform_function_declT  sD   
z&CCodeConverter.transform_function_declc                 C   s  |j j| jd v r| jd |j j }n*|j j| jd v r&| jd |j j }n|j j| jd v r9| jd |j j }ntdzi| }t|}|jtjjtjj	tjj
fv rft|}|jtjjtjj	tjj
fv sT| |}|j j| jd v ryt|}n"|j j| jd v rt|}n|j j| jd v rtt|}ntdt|jj||d}W n ty   t|jj|d}Y nw z| t| td ty   Y |S w )a  Transformation function for Parameter Declaration

            Used to create parameter nodes for the required functions for the
            respective nodes in the clang AST

            Returns
            =======

            param : Codegen AST Node
                Variable node with the value and type of the variable

            Raises
            ======

            ValueError if multiple children encountered in the parameter node

            rU   rV   rT   r   r   r   z+Can't handle multiple children on parameter)r   rv   rg   r   ru   r   r0   rw   r   r   TEMPLATE_REFr{   r   r   r,   rT   r   rK   r   r   
ValueError)r5   r   r   r   r   litr   r   r6   r6   r7   transform_parm_decl  sb   






z"CCodeConverter.transform_parm_declc                 C   s8   zt | j}W t|S  ty   |j}Y t|S w )a  Transformation function for integer literal

            Used to get the value and type of the given integer literal.

            Returns
            =======

            val : list
                List with two arguments type and Value
                type contains the type of the integer
                value contains the value stored in the variable

            Notes
            =====

            Only Base Integer type supported for now

            )r   r   rK   r   literalrU   r5   r   r   r6   r6   r7   transform_integer_literal  s   z(CCodeConverter.transform_integer_literalc              	   C   s<   zt | j}W t|S  ttfy   |j}Y t|S w )a  Transformation function for floating literal

            Used to get the value and type of the given floating literal.

            Returns
            =======

            val : list
                List with two arguments type and Value
                type contains the type of float
                value contains the value stored in the variable

            Notes
            =====

            Only Base Float type supported for now

            )r   r   rK   r   r   r   rV   r   r6   r6   r7   transform_floating_literal  s   z)CCodeConverter.transform_floating_literalc                 C   s   d S r   r6   r5   r   r6   r6   r7   transform_string_literal  s   
z'CCodeConverter.transform_string_literalc              	   C   s@   z	t | j}W n ttfy   |j}Y nw tt|d S )a  Transformation function for character literal

            Used to get the value of the given character literal.

            Returns
            =======

            val : int
                val contains the ascii value of the character literal

            Notes
            =====

            Only for cases where character is assigned to a integer value,
            since character literal is not in SymPy AST

            rA   )r   r   rK   r   r   r   ordr   r   r6   r6   r7   transform_character_literal  s   
z*CCodeConverter.transform_character_literalc              	   C   s@   z	t | j}W n ttfy   |j}Y nw |dkrdS dS )zTransformation function for boolean literal

            Used to get the value of the given boolean literal.

            Returns
            =======

            value : bool
                value contains the boolean value of the variable

            r.   TF)r   r   rK   r   r   r   r   r6   r6   r7   transform_cxx_bool_literal_expr+  s   
z.CCodeConverter.transform_cxx_bool_literal_exprc                 C   s   dS )z2Transformation function for unexposed declarationsNr6   r   r6   r6   r7   transform_unexposed_decl=     z'CCodeConverter.transform_unexposed_declc                 C   sV   z|  }| t|}W n
 ty   Y dS w zt| td ty*   Y |S w )a  Transformation function for unexposed expression

            Unexposed expressions are used to wrap float, double literals and
            expressions

            Returns
            =======

            expr : Codegen AST Node
                the result from the wrapped expression

            None : NoneType
                No childs are found for the node

            Raises
            ======

            ValueError if the expression contains multiple children

            Nz&Unexposed expression has > 1 children.ru   r{   r   r   r   )r5   r   r   exprr6   r6   r7   transform_unexposed_exprA  s   z'CCodeConverter.transform_unexposed_exprc                 C   s   |j S )z-Returns the name of the declaration referencer   r   r6   r6   r7   transform_decl_ref_exprf  s   z&CCodeConverter.transform_decl_ref_exprc                 C   s   g }|  }t|}|jtjjkrt|}|jtjjks|jtjjkr.t|}|jtjjks#| |}z3|D ]*}| |}|jtjjkrL|	t
| q6|jtjjkr[|	t| q6|	| q6t||W S  tys   t| Y S w )aJ  Transformation function for a call expression

            Used to create function call nodes for the function calls present
            in the C code

            Returns
            =======

            FunctionCall : Codegen AST Node
                FunctionCall node with parameters if any parameters are present

            )ru   r   rv   r0   rw   r   r   r{   r   rz   r   r   r   r   r   )r5   r   r   r   r   first_childargr6   r6   r7   transform_call_exprj  s,   

z"CCodeConverter.transform_call_exprc                 C   s   t t| jS )z.Returns the Return Node for a return statement)r   r   ru   rK   r   r6   r6   r7   transform_return_stmt  s   z$CCodeConverter.transform_return_stmtc                 C   s*   g }|  }|D ]
}|| | q|S )a  Transformation function for compond statemets

            Returns
            =======

            expr : list
                list of Nodes for the expressions present in the statement

            None : NoneType
                if the compound statement is empty

            )ru   rz   r{   )r5   r   r   r   r   r6   r6   r7   transform_compound_stmt  s
   z&CCodeConverter.transform_compound_stmtc                 C   sZ   z|  }| t|}W n	 ty   Y nw z| t| td ty,   Y |S w )a@  Transformation function for declaration statements

            These statements are used to wrap different kinds of declararions
            like variable or function declaration
            The function calls the transformer function for the child of the
            given node

            Returns
            =======

            statement : Codegen AST Node
                contains the node returned by the children node for the type of
                declaration

            Raises
            ======

            ValueError if multiple children present

            z,Don't know how to handle multiple statementsr   )r5   r   r   	statementr6   r6   r7   transform_decl_stmt  s   z"CCodeConverter.transform_decl_stmtc                 C   s   |  t| S )z{Transformation function for Parenthesized expressions

            Returns the result from its children nodes

            )r{   r   ru   r   r6   r6   r7   transform_paren_expr  s   z#CCodeConverter.transform_paren_exprc                 C   s
   |  |S )a  Transformation function for handling shorthand operators

            Returns
            =======

            augmented_assignment_expression: Codegen AST node
                    shorthand assignment expression represented as Codegen AST

            Raises
            ======

            NotImplementedError
                If the shorthand operator for bitwise operators
                (~=, ^=, &=, |=, <<=, >>=) is encountered

            )transform_binary_operatorr   r6   r6   r7   &transform_compound_assignment_operator  s   
z5CCodeConverter.transform_compound_assignment_operatorc                 C   sn  g d}t | }|d j|v r| t| }t|tra|d jdkr*t|S |d jdkr8t	t|dS |d jdkrEt
t|S |d jdkrRtt|S |d jdkr_tt|S dS |d jdkrj|S |d jdkrvt	|dS |d jdkrttt|S dS |d	 jd
v r| t| }|d	 jdkrtt|S |d	 jdkrtt|S dS td)a  Transformation function for handling unary operators

            Returns
            =======

            unary_expression: Codegen AST node
                    simplified unary expression represented as Codegen AST

            Raises
            ======

            NotImplementedError
                If dereferencing operator(*), address operator(&) or
                bitwise NOT operator(~) is encountered

            )+-++--!r   r   r   r   r   r   rA   )r   r   z`Dereferencing operator, Address operator and bitwise NOT operator have not been implemented yet!N)listr   rK   r{   r   ru   r   r   r+   r$   r    r   r)   r,   rT   r!   r   r   )r5   r   operators_listtokensr   r6   r6   r7   transform_unary_operator  s>   

z'CCodeConverter.transform_unary_operatorc           
      C   sX  t | }g d}g }g }|D ]}|jtjjkr|jdkr$|d q|jdkr^|rY|d dkrYt|dk r;t	d|
 }|
 }|
 }	|| |||	 |rY|d dks1|
  q|j|v r|r| |j| |d krt|dk r|t	d|
 }|
 }|
 }	|| |||	 |r| |j| |d ksr||j q|jdv rt	d|jd	v rt	d
t	d|j|jtjjkr||jdg q|jtjjkr||jdg q|jtjjkr|jdv r||jdg qt	d|j|r&t|dk rt	d|
 }|
 }|
 }	|| |||	 |s|d d S )a  Transformation function for handling binary operators

            Returns
            =======

            binary_expression: Codegen AST node
                    simplified binary expression represented as Codegen AST

            Raises
            ======

            NotImplementedError
                If a bitwise operator or
                unary operator(which is a child of any binary
                operator in Clang AST) is encountered

            )r   r   */%=>>=<<===!=&&||+=-=*=/=%=()r   r@   zCUnary operators as a part of binary operators is not supported yet!)&|^z<<z>>z.Bitwise operator has not been implemented yet!)z&=z|=z^=z<<=z>>=z8Shorthand bitwise operator has not been implemented yet!z&Given token {} is not implemented yet!
identifierr   )r.   r-   booleanr   )r   r   rv   r0   	TokenKindPUNCTUATIONrK   rz   lenr   popperform_operationpriority_ofr   
IDENTIFIERLITERALKEYWORD)
r5   r   r   r   combined_variables_stackoperators_stacktokenrhslhsoperatorr6   r6   r7   r     s   








z(CCodeConverter.transform_binary_operatorc                 C   s@   |dv rdS |dv rdS |dv rdS |dv rdS |d	v rd
S dS )z%To get the priority of given operator)r   r   r   r   r   r   rA   )r   r   r@   r   r   r   r   r   r   r?   )r   r   r>   )r   r   r      r   r6   )r5   opr6   r6   r7   r    s   zCCodeConverter.priority_ofc                 C   s   |  |}|  |}|dkrt||dgS |dkr!t|| dgS |dkr,t||dgS |dkr<t|t|tddgS |dkrGt||dgS |dv rSt|||dgS |d	krbtt|t|dgS |d
krqt	t|t|dgS |dkr~t
t||dgS |dv rtt||d |dgS dS )zPerforms operation supported by the SymPy core

            Returns
            =======

            combined_variable: list
                contains variable content and type of variable

            r   r   r   r   r   r   r   r  r   r   r   )r   r   r   r   r   r   N)get_expr_for_operandr"   r$   r%   r   r#   r&   r'   r(   r*   r   r   r   )r5   r  r  r  	lhs_value	rhs_valuer6   r6   r7   r    s.   


z CCodeConverter.perform_operationc                 C   s   |d dkrt |d S |d dkr(d|d v r tt|d S tt|d S |d dkr2|d S |d dkrB|d dkr@tS tS d	S )
zGives out SymPy Codegen AST node

            AST node returned is corresponding to
            combined variable passed.Combined variable contains
            variable content and type of variable

            rA   r   r   r   .r   r   r.   N)r+   r   rV   r   rU   r.   r-   )r5   combined_variabler6   r6   r7   r    s   z#CCodeConverter.get_expr_for_operandc                 C   s   t S )z'Handles Null Statement and returns None)r   r   r6   r6   r7   transform_null_stmt  r   z"CCodeConverter.transform_null_stmtc                 C   sJ   |  }| t|}| t|}t|trt| }nt|}t||S )a  Transformation function for handling while statement

            Returns
            =======

            while statement : Codegen AST Node
                contains the while statement node having condition and
                statement block

            )ru   r{   r   r   r   r   r   )r5   r   r   	condition
statementsstatement_blockr6   r6   r7   transform_while_stmt  s   


z#CCodeConverter.transform_while_stmt)!rN   rO   rP   rQ   r8   rq   r   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  __classcell__r6   r6   rh   r7   rR   U   s>    $'v8F%%#: !rR   c                   @   s   e Zd Zdd ZdS )rR   c                 O   s   t d)NzModule not Installed)ImportError)r5   rl   kwargsr6   r6   r7   r8     s   rj   N)rN   rO   rP   r8   r6   r6   r6   r7   rR     s    c                 C   s6   t  }tj| r|j| g d}|S |j| g d}|S )zFunction for converting a C source code

    The function reads the source code present in the given file and parses it
    to give out SymPy Expressions

    Returns
    =======

    src : list
        List of Python expression strings

    )r}   )rR   rn   ro   existsrq   r   )r   	convertersrcr6   r6   r7   parse_c  s   r!  )8sympy.externalr   rn   r0   sympy.codegen.astr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   sympy.codegen.cnodesr   r   r    r!   
sympy.corer"   r#   r$   r%   r&   sympy.logic.boolalgr'   r(   r)   r*   sympy.core.symbolr+   sympy.core.sympifyr,   r-   r.   r   r   r/   rR   r!  r6   r6   r6   r7   <module>   s2    &h       =