o
    @axX                     @   s   d Z ddlmZ ddlmZ ddlmZ dZG dd deZ	G dd	 d	eZ
G d
d de
ZG dd de
ZG dd deZG dd deZG dd deZG dd de
ZG dd deZG dd deZG dd deZG dd deZG dd deZG d d! d!eZG d"d# d#eZG d$d% d%eZG d&d' d'eZG d(d) d)eZG d*d+ d+eZG d,d- d-eZG d.d/ d/eZG d0d1 d1eZG d2d3 d3eZG d4d5 d5eZ G d6d7 d7eZ!G d8d9 d9eZ"G d:d; d;eZ#G d<d= d=e#Z$G d>d? d?e#Z%G d@dA dAeZ&G dBdC dCeZ'dDS )Ez
Generator for C/C++.
    )dedent)pythran_ward)signatures_to_stringz$Copyright (C) 2008 Andreas Kloecknerc                   @   s   e Zd ZdddZdS )NopTc                 c   s    dV  d S N  )selfwith_semicolonr   r   0/usr/lib/python3/dist-packages/pythran/cxxgen.pygenerate'   s   
zNop.generateNT__name__
__module____qualname__r   r   r   r   r   r   %   s    r   c                   @   s&   e Zd Zd	ddZdd Zdd ZdS )

DeclaratorTc                 c   sp    |   \}}t|}|d d D ]}|V  q|rdnd}|d u r,d|d |f V  d S d|d ||f V  d S )N;r   z%s%sz%s %s%s)get_decl_pairlist)r	   r
   tp_linestp_decllineZscr   r   r   r   ,   s   zDeclarator.generatec                 C   s   dS )aH  Return a tuple ``(type_lines, rhs)``.

        *type_lines* is a non-empty list of lines (most often just a
        single one) describing the type of this declarator. *rhs* is the right-
        hand side that actually contains the function/array/constness notation
        making up the bulk of the declarator syntax.
        Nr   r	   r   r   r   r   7   s    zDeclarator.get_decl_pairc                 C   s.   |   \}}d|}|du r|S d||f S )z'Return the declarator as a single line. Nz%s %s)r   join)r	   r   r   r   r   r   inline@   s
   
zDeclarator.inlineNr   )r   r   r   r   r   r   r   r   r   r   r   +   s    
	r   c                   @   s    e Zd ZdZdd Zdd ZdS )Valuez@A simple declarator: *typename* and *name* are given as strings.c                 C      || _ || _d S Ntypenamename)r	   r"   r#   r   r   r   __init__M      
zValue.__init__c                 C   s   | j g| jfS r    r!   r   r   r   r   r   Q   s   zValue.get_decl_pairNr   r   r   __doc__r$   r   r   r   r   r   r   J   s    r   c                   @   s(   e Zd Zdd Zedd Zdd ZdS )NestedDeclaratorc                 C   
   || _ d S r    )subdeclr	   r*   r   r   r   r$   V      
zNestedDeclarator.__init__c                 C   s   | j jS r    )r*   r#   r   r   r   r   r#   Y   s   zNestedDeclarator.namec                 C   s
   | j  S r    r*   r   r   r   r   r   r   ]   r,   zNestedDeclarator.get_decl_pairN)r   r   r   r$   propertyr#   r   r   r   r   r   r(   U   s
    
r(   c                   @      e Zd ZdddZdd ZdS )DeclSpecifierr   c                 C   s   t | | || _|| _d S r    )r(   r$   specsep)r	   r*   r1   r2   r   r   r   r$   b   s   
zDeclSpecifier.__init__c                    s&    fdd} j  \}}|||fS )Nc                 3   sN    t | }zd j jt|f V  W n	 ty   Y nw |D ]}|V  qd S )Nz%s%s%s)iterr1   r2   nextStopIteration)Zsub_ititr   r   r   r   add_spech   s   z-DeclSpecifier.get_decl_pair.<locals>.add_specr-   )r	   r7   sub_tpsub_declr   r   r   r   g   s   
zDeclSpecifier.get_decl_pairN)r   r   r   r   r$   r   r   r   r   r   r0   a       
r0   c                   @      e Zd Zdd ZdS )Typedefc                 C   s   t | |d d S )NZtypedef)r0   r$   r+   r   r   r   r$   w   s   zTypedef.__init__Nr   r   r   r$   r   r   r   r   r=   v       r=   c                   @      e Zd Zdd Zdd ZdS )FunctionDeclarationc                 G   s"   t | | d| _|| _|| _d S )NT)r(   r$   r   	arg_decls
attributes)r	   r*   rB   rC   r   r   r   r$   |   s   
zFunctionDeclaration.__init__c                 C   sJ   | j  \}}| jrdg| }|d|ddd | jD d| jf fS )Nr   z	%s(%s) %s, c                 s   s    | ]}|  V  qd S r    )r   ).0Zadr   r   r   	<genexpr>       z4FunctionDeclaration.get_decl_pair.<locals>.<genexpr>r   )r*   r   r   r   rB   rC   )r	   r8   r9   r   r   r   r      s   

z!FunctionDeclaration.get_decl_pairNr:   r   r   r   r   rA   {   s    rA   c                   @   s"   e Zd ZdZdddZdd ZdS )Structa  
    A structure declarator.

    Attributes
    ----------
    tpname : str
        Name of the structure. (None for unnamed struct)
    fields : [Declarator]
        Content of the structure.
    inherit : str
        Parent class of current structure.
    Nc                 C   s   || _ || _|| _dS )z&Initialize the structure declarator.  N)tpnamefieldsinherit)r	   rI   rJ   rK   r   r   r   r$      s   
zStruct.__init__c                    s    fdd}| dfS )z See Declarator.get_decl_pair.c                  3   sl    d}  j dur|  j 7 }  jdur| d j 7 } | V  dV   jD ]}| D ]}d| V  q(q"dV  dS )z2 Iterator generating lines for struct definition. zstruct Nz : {  z} )rI   rK   rJ   r   )Zdeclff_liner   r   r   get_tp   s   




z$Struct.get_decl_pair.<locals>.get_tpr   r   )r	   rP   r   r   r   r      s   
zStruct.get_decl_pairr    r&   r   r   r   r   rH      s    
rH   c                       s&   e Zd Z fddZdddZ  ZS )Templatec                       t t| | || _d S r    )superrQ   r$   template_spec)r	   rT   r*   	__class__r   r   r$         
zTemplate.__init__Fc                 c   sJ    dd | j V  | j|D ]}|V  qt| jttfs#dV  d S d S )Nztemplate <%s>rD   r   )r   rT   r*   r   
isinstancerQ   rA   )r	   r
   ir   r   r   r      s   
zTemplate.generate)F)r   r   r   r$   r   __classcell__r   r   rU   r   rQ      s    rQ   c                   @      e Zd ZdddZdd ZdS )ExceptHandlerNc                 C      || _ || _|| _d S r    )r#   bodyalias)r	   r#   r^   r_   r   r   r   r$         
zExceptHandler.__init__c                 c   sD    | j d u r
dV  nd| j | jpdf V  | j D ]}|V  qd S )Nz
catch(...)z%catch (pythonic::types::%s const& %s)r   )r#   r_   r^   r   r	   r   r   r   r   r      s   
zExceptHandler.generater    r   r   r   r$   r   r   r   r   r   r\      r;   r\   c                   @   r@   )	TryExceptc                 C   r   r    )try_except_)r	   rd   re   r   r   r   r$      r%   zTryExcept.__init__c                 c   sF    dV  | j  D ]}|V  q	| jD ]}| D ]}d| V  qqd S )NtryrM   )rd   r   re   )r	   r   Z	exceptionr   r   r   r      s   
zTryExcept.generateNrb   r   r   r   r   rc          rc   c                   @   r[   )IfNc                 C   r]   r    )	conditionthen_else_)r	   ri   rj   rk   r   r   r   r$      r`   zIf.__init__c                 c   sR    d| j  V  | j D ]}|V  q| jd ur%dV  | j D ]}|V  qd S d S )Nzif (%s)else)ri   rj   r   rk   ra   r   r   r   r      s   
zIf.generater    rb   r   r   r   r   rh      r;   rh   c                   @   r@   )Loopc                 C   r)   r    r^   r	   r^   r   r   r   r$      r,   zLoop.__init__c                 c   s&    |   V  | j D ]}|V  qd S r    )
intro_liner^   r   ra   r   r   r   r      s
   
zLoop.generateNrb   r   r   r   r   rm          rm   c                       $   e Zd Z fddZdd Z  ZS )Whilec                    rR   r    )rS   rs   r$   ri   )r	   ri   r^   rU   r   r   r$      rW   zWhile.__init__c                 C   s
   d| j  S )Nz
while (%s))ri   r   r   r   r   rp     r,   zWhile.intro_liner   r   r   r$   rp   rZ   r   r   rU   r   rs      s    rs   c                       rr   )Forc                    s&   t t| | || _|| _|| _d S r    )rS   ru   r$   startri   update)r	   rv   ri   rw   r^   rU   r   r   r$     s   
zFor.__init__c                 C   s   d| j | j| jf S )Nzfor (%s; %s; %s))rv   ri   rw   r   r   r   r   rp     s   zFor.intro_linert   r   r   rU   r   ru     s    ru   c                       rr   )AutoForc                    s    t t| | || _|| _d S r    )rS   rx   r$   targetr3   )r	   ry   Ziter_r^   rU   r   r   r$     s   
zAutoFor.__init__c                 C   s*   | j dkrd| j | jS d| j | jS )N_z$for (PYTHRAN_UNUSED auto&& {0}: {1})zfor (auto&& {0}: {1}))ry   formatr3   r   r   r   r   rp     s   
zAutoFor.intro_linert   r   r   rU   r   rx     s    rx   c                   @   r@   )Definec                 C   r   r    symbolvalue)r	   r~   r   r   r   r   r$   !  r%   zDefine.__init__c                 c       d| j | jf V  d S )Nz#define %s %sr}   r   r   r   r   r   %     zDefine.generateNrb   r   r   r   r   r|      rg   r|   c                   @   r/   )IncludeTc                 C   r   r    )filenamesystem)r	   r   r   r   r   r   r$   *  r%   zInclude.__init__c                 c   s(    | j rd| j V  d S d| j V  d S )Nz#include <%s>z#include "%s")r   r   r   r   r   r   r   .  s   zInclude.generateNr   rb   r   r   r   r   r   )      
r   c                   @   r@   )Labelc                 C   r)   r    label)r	   r   r   r   r   r$   6  r,   zLabel.__init__c                 c       | j d V  d S )Nz:;r   r   r   r   r   r   9     zLabel.generateNrb   r   r   r   r   r   5  rq   r   c                   @   r@   )	Statementc                 C   r)   r    textr	   r   r   r   r   r$   >  r,   zStatement.__init__c                 c   r   )Nr   r   r   r   r   r   r   A  r   zStatement.generateNrb   r   r   r   r   r   =  rq   r   c                   @   r@   )AnnotatedStatementc                 C   r   r    )stmtannotations)r	   r   r   r   r   r   r$   F  r%   zAnnotatedStatement.__init__c                 c   s@    | j D ]}d|j }|j|j V  q| j D ]}|V  qd S )Nz#pragma )r   sr{   Zdepsr   r   )r	   Z	directiveZpragmar   r   r   r   r   J  s   

zAnnotatedStatement.generateNrb   r   r   r   r   r   E  rg   r   c                   @   r<   )ReturnStatementc                 c   s    d| j  d V  d S )Nzreturn r   r   r   r   r   r   r   S  s   zReturnStatement.generateNr   r   r   r   r   r   R  r?   r   c                   @   r<   )EmptyStatementc                 C   s   t | d d S r   )r   r$   r   r   r   r   r$   X     zEmptyStatement.__init__Nr>   r   r   r   r   r   W  r?   r   c                   @   r@   )Assignc                 C   r   r    lvaluervalue)r	   r   r   r   r   r   r$   ]  r%   zAssign.__init__c                 c   r   )Nz%s = %s;r   r   r   r   r   r   a  r   zAssign.generateNrb   r   r   r   r   r   \  rg   r   c                   @   r/   )Liner   c                 C   r)   r    r   r   r   r   r   r$   f  r,   zLine.__init__c                 c   s    | j V  d S r    r   r   r   r   r   r   i  s   zLine.generateN)r   rb   r   r   r   r   r   e  s    
r   c                   @   r@   )FunctionBodyc                 C   s   || _ || _dS )zInitialize a function definition. *fdecl* is expected to be
        a :class:`FunctionDeclaration` instance, while *body* is a
        :class:`Block`.
        N)fdeclr^   )r	   r   r^   r   r   r   r$   o  s   
zFunctionBody.__init__c                 c   s6    | j jddD ]}|V  q| j D ]}|V  qd S )NF)r
   )r   r   r^   )r	   rO   Zb_liner   r   r   r   w  s   zFunctionBody.generateNrb   r   r   r   r   r   n  s    r   c                   @   r[   )BlockNc                 C   s   |d u rg }|| _ d S r    )contents)r	   r   r   r   r   r$     s   
zBlock.__init__c                 c   s6    dV  | j D ]}| D ]}d| V  qqdV  d S )NrL   rM   }r   r   r	   itemZ	item_liner   r   r   r     s   

zBlock.generater    rb   r   r   r   r   r     r;   r   c                   @   r<   )Modulec                 c   s&    | j D ]}| D ]}|V  q
qd S r    r   )r	   cr   r   r   r   r     s   
zModule.generateNr   r   r   r   r   r     r?   r   c                   @   r[   )	NamespaceNc                 C   s   t | | || _d S r    )r   r$   r#   )r	   r#   r   r   r   r   r$     s   
zNamespace.__init__c                 c   sB    d| j  V  dV  | jD ]}| D ]}d| V  qqdV  d S )Nz
namespace rL   rM   r   )r#   r   r   r   r   r   r   r     s   

zNamespace.generater    rb   r   r   r   r   r     r   r   c                   @   sh   e Zd Z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S )PythonModulezO
    Wraps the creation of a Pythran module wrapped a Python native Module
    c                 C   sd   || _ g | _g | _i | _g | _g | _g | _g | _g | _|| _	|| _
| | j	dd}|| j
d< dS )z.
        Builds an empty PythonModule
        Nr   	moduledoc)r#   preambleincludes	functionsglobal_varsimplemscapsulespython_implemswrappers
docstringsmetadata	docstringget)r	   r#   r   r   r   r   r   r   r$     s   zPythonModule.__init__c                 C   s&   |  t|ddddddS )N"z\"
\nz\r)splitstringr   replacer	   docr   r   r   r     s   zPythonModule.docstringc                 C   s   d d|dS )Nz"{}"z\n""r   )r{   r   splitr   r   r   r   r        zPythonModule.splitstringc                 G      | j | d S r    )r   extend)r	   par   r   r   add_to_preamble  r   zPythonModule.add_to_preamblec                 G   r   r    )r   r   )r	   Zinclr   r   r   add_to_includes  r   zPythonModule.add_to_includesc                 C      |  | j|||| d S r    )add_function_tor   r	   funcr#   types	signaturer   r   r   add_pyfunction     zPythonModule.add_pyfunctionc                 C   s    | j ||f | j| d S r    )r   appendr   )r	   r   ptrnamesigr   r   r   add_capsule  s   zPythonModule.add_capsulec                 C   r   r    )r   r   r   r   r   r   add_function  r   zPythonModule.add_functionc                 C   s  | | g }g }td |jj }t|D ]\}	}
| d|
|	 | d|
|	 q|jjdt| }ddd |D }t	d}| j
 |j|jj|rPdnd	t|d
t| ddd tt|D d|d|ppd||d	 |||f}| j|g  | dS )ab  
        Add a function to be exposed. *func* is expected to be a
        :class:`cgen.FunctionBody`.

        Because a function can have several signatures exported,
        this method actually creates a wrapper for each specialization
        and a global wrapper that checks the argument types and
        runs the correct candidate, if any
        Zwrap_zfrom_python<{}>(args_obj[{}])z is_convertible<{}>(args_obj[{}])Nr   c                 s   s    | ]	}d  |jV  qdS )z"{}", N)r{   r#   )rE   argr   r   r   rF     s    z/PythonModule.add_function_to.<locals>.<genexpr>ac  
            static PyObject *
            {wname}(PyObject *self, PyObject *args, PyObject *kw)
            {{
                PyObject* args_obj[{size}+1];
                {silent_warning}
                char const* keywords[] = {{{keywords} nullptr}};
                if(! PyArg_ParseTupleAndKeywords(args, kw, "{fmt}",
                                                 (char**)keywords {objs}))
                    return nullptr;
                if({checks})
                    return to_python({name}({args}));
                else {{
                    return nullptr;
                }}
            }}z(void)args_obj;Oc                 s   s    | ]}d | V  qdS )z, &args_obj[%d]Nr   )rE   rY   r   r   r   rF     s    rD   z && 1)	r#   Zsilent_warningsizeZfmtZobjsargsZcheckswnamekeywords)r   r   r   r#   	enumerater{   rB   lenr   r   r   ranger   
setdefault)r	   tor   r#   ctypesr   Zargs_unboxingZargs_checkswrapper_namerY   trB   r   wrapperZfunc_descriptorr   r   r   r     s4   







zPythonModule.add_function_toc                 C   s,   | j | | jtd| d| d S )Nzstatic PyObject* zto_python({}))r   r   r   r   r{   )r	   r#   Zinitr   r   r   add_global_var"  s   
zPythonModule.add_global_varc                 C   s  g }g }g }| j D ]
}|d| q	| j D ]`\}}g }g }|D ]\}	}
}tdj|	d}|| || q#t||}td | }tdj|d|| 	|
dd|d}| | j|d	}td
j|||d}|| || q| jD ]\}}dj||d}|| q}tdjd	dd |D d}tdjd| jd|d| j}| j| j | j tdg | j dd | j| D  t|t|tdg }dt| S )zRGenerate (i.e. yield) the source code of the
        module line-by-line.
        z*PyModule_AddObject(theModule, "{0}", {0});z
                    if(PyObject* obj = {name}(self, args, kw))
                        return obj;
                    PyErr_Clear();
                    )r#   Zwrapall_a  
            static PyObject *
            {wname}(PyObject *self, PyObject *args, PyObject *kw)
            {{
                return pythonic::handle_python_exception([self, args, kw]()
                -> PyObject* {{
                {tryall}
                return pythonic::python::raise_invalid_argument(
                               "{name}", {candidates}, args, kw);
                }});
            }}
            r   r   )r#   tryall
candidatesr   r   z{{
                "{name}",
                (PyCFunction){wname},
                METH_VARARGS | METH_KEYWORDS,
                {doc}}})r#   r   r   z
            PyModule_AddObject(theModule, "{ptrname}",
                               PyCapsule_New((void*)&{ptrname}, "{sig}", NULL)
            );)r   r   z
            static PyMethodDef Methods[] = {{
                {methods}
                {{NULL, NULL, 0, NULL}}
            }};
            c                 s   s    | ]}|d  V  qdS ),Nr   )rE   mr   r   r   rF   l  rG   z'PythonModule.__str__.<locals>.<genexpr>)methodsa  
            #if PY_MAJOR_VERSION >= 3
              static struct PyModuleDef moduledef = {{
                PyModuleDef_HEAD_INIT,
                "{name}",            /* m_name */
                {moduledoc},         /* m_doc */
                -1,                  /* m_size */
                Methods,             /* m_methods */
                NULL,                /* m_reload */
                NULL,                /* m_traverse */
                NULL,                /* m_clear */
                NULL,                /* m_free */
              }};
            #define PYTHRAN_RETURN return theModule
            #define PYTHRAN_MODULE_INIT(s) PyInit_##s
            #else
            #define PYTHRAN_RETURN return
            #define PYTHRAN_MODULE_INIT(s) init##s
            #endif
            PyMODINIT_FUNC
            PYTHRAN_MODULE_INIT({name})(void)
            #ifndef _WIN32
            __attribute__ ((visibility("default")))
            #if defined(GNUC) && !defined(__clang__)
            __attribute__ ((externally_visible))
            #endif
            #endif
            ;
            PyMODINIT_FUNC
            PYTHRAN_MODULE_INIT({name})(void) {{
                import_array()
                #if PY_MAJOR_VERSION >= 3
                PyObject* theModule = PyModule_Create(&moduledef);
                #else
                PyObject* theModule = Py_InitModule3("{name}",
                                                     Methods,
                                                     {moduledoc}
                );
                #endif
                if(! theModule)
                    PYTHRAN_RETURN;
                PyObject * theDoc = Py_BuildValue("(sss)",
                                                  "{version}",
                                                  "{date}",
                                                  "{hash}");
                if(! theDoc)
                    PYTHRAN_RETURN;
                PyModule_AddObject(theModule,
                                   "__pythran__",
                                   theDoc);

                {extraobjects}
                PYTHRAN_RETURN;
            }}
            )r#   Zextraobjectsz#ifdef ENABLE_PYTHON_MODULEc                 S   s   g | ]}t |qS r   )r   )rE   coder   r   r   
<listcomp>  s    z(PythonModule.__str__.<locals>.<listcomp>z#endifNr   )r   r   r{   r   itemsr   r   r   r   r   r   r   r   r   r   r#   r   r   r   r   r   r   r   r   r   )r	   Z
themethodsZtheextraobjectsZtheoverloadsZvnamefnameZ	overloadsr   Z
signaturesZoverloadr   r   rd   r   r   	candidatefdocZ	themethodr   r   Zcapsuler   moduler^   r   r   r   __str__'  s   




668:zPythonModule.__str__N)r   r   r   r'   r$   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s    7r   c                   @   r@   )CompilationUnitc                 C   r)   r    rn   ro   r   r   r   r$     r,   zCompilationUnit.__init__c                 C   s   d dd | jD S )Nr   c                 s   s    | ]
}d  | V  qdS )r   N)r   r   )rE   r   r   r   r   rF     s    z*CompilationUnit.__str__.<locals>.<genexpr>)r   r^   r   r   r   r   r     r   zCompilationUnit.__str__N)r   r   r   r$   r   r   r   r   r   r     s    r   N)(r'   textwrapr   Zpythran.tablesr   Zpythran.specr   Z__copyright__objectr   r   r   r(   r0   r=   rA   rH   rQ   r\   rc   rh   rm   rs   ru   rx   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sJ    (
				( x