a
    V$c\                     @   sx  d dl mZmZmZmZmZ d 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 d dlZd dlZd dlmZ d dlZd dlZd dlmZmZ h dZedd eeD Zeh d	8 Zh d
ZddheB eB Z e Z!e Z"dd Z#dd Z$dd Z%G dd de&Z'dZ(dZ)d Z*G dd de&Z+G dd de&Z,G dd dej-Z.G dd de&Z/e/ Z0e/ Z1dZ2d d! Z3d"d# Z4dS )$    )divisionabsolute_importwith_statementprint_functionunicode_literals)PY2
basestringbchrbordchropenpystrrangeroundstrtobytesunicodeN)
py_compile)loadsdumps>   FalseTrueNonec                 c   s   | ]}| d s|V  qdS )__N)
startswith.0i r   renpy/py3analysis.py	<genexpr>*       r    >   Zcreditshelpprintnextinputr   	enumeratelicense	copyrightreversedmap
memoryview>R   SnowBlossomzui.jumpsLiveCompositeText	CharacterMotionPushMovezui.invokesinnewcontextSolidDynamicCharacter__renpy__dict__ImageReferenceComposeTransitionFixedzrenpy.version_tupleVBoxAlphaFadeMoveFactorycolorMoveDragRevolveDissolvezrenpy.version_onlyFlattenRotoZoomMultipleTransitionRevolveInOutGridPanMoveTransitionImageDissolvez
ui.returns	ZoomInOutImageLiveTilezui.gamemenus__renpy__set__zui.jumpsoutofcontextAt_absolutezrenpy.version_string	AlphaMask
AlphaBlend	Animation__renpy__list__Window	Particles	Transform	PixellateADVCharacterConditionSwitchParameterizedTextzrenpy.licenseMoveInzui.callsinnewcontextViewportCropMoveMoveOutNullSizeZoomAlphaDissolveHBoxMovieSpeakerColorOldMoveTransition_pPauseSubTransitionzrenpy.version_name	FontGroup
FactorZoom
ADVSpeakerShowingSwitchZoomFrameLiveCropDynamicDisplayablePositionconfigstylec                 C   s   | t vrt|  dS )at  
    :doc: const

    Declares a variable in the store to be constant.

    A variable is constant if nothing can change its value, or any value
    reached by indexing it or accessing its attributes. Variables must
    remain constant out of define, init, and translate python blocks.

    `name`
        A string giving the name of the variable to declare constant.
    N)not_constants	constantsaddnamer   r   r   const^   s    rz   c                 C   s"   t |  t|  t|  dS )z
    :doc: const

    Declares a name in the store to be not constant.

    This undoes the effect of calls to :func:`renpy.const` and
    :func:`renpy.pure`.

    `name`
        The name to declare not constant.
    N)rv   discardpure_functionsru   rw   rx   r   r   r   	not_constp   s    

r}   c                 C   s\   | }t |ts&| j}| j}|d | }|dr<|dd }|tvrXt| t| | S )a8  
    :doc: const

    Declares a function as pure. A pure function must always return the
    same value when it is called with the same arguments, outside of
    define, init, and translate python blocks.

    `fn`
        The name of the function to declare pure. This may either be a string
        containing the name of the function, or the function itself.
        If a string is passed and the function is inside a module,
        this string should contain the module name with the dot.

    Returns `fn`, allowing this function to be used as a decorator.
    .zstore.   N)	
isinstancer   __name__
__module__r   ru   r|   rw   rv   )fnry   moduler   r   r   pure   s    



r   c                   @   s   e Zd ZdZdd ZdS )Controlz
    Represents control flow.

    `const`
        True if this statement always executes.

    `loop`
        True if this corresponds to a loop.

    `imagemap`
        True if this control is in a non-constant imagemap.
    c                 C   s   || _ || _|| _d S N)rz   loopimagemapselfrz   r   r   r   r   r   __init__   s    zControl.__init__N)r   r   __qualname____doc__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d	 Zd
d Zdd ZdS )DeltaSetNc                 C   sB   || _ |dur(t|j| _t|j| _nt | _t | _d| _dS )zc
        Represents a set that stores its contents as differences from a base
        set.
        NF)basesetaddedremovedchanged)r   r   copyr   r   r   r      s    zDeltaSet.__init__c                 C   sH   || j v r| j | d| _n&|| jvrD|| jvrD| j| d| _d S NT)r   r{   r   r   r   rw   r   vr   r   r   rw      s    
zDeltaSet.addc                 C   sH   || j v r| j | d| _n&|| jv rD|| jvrD| j| d| _d S r   )r   r{   r   r   r   rw   r   r   r   r   r{      s    
zDeltaSet.discardc                 C   s   || j v p|| jv o|| jvS r   )r   r   r   r   r   r   r   __contains__   s    zDeltaSet.__contains__c                 C   s   t | j| S r   )r   r   r   r   r   r   r      s    zDeltaSet.copyc                 c   s2   | j D ]}|| jvr|V  q| jD ]
}|V  q"d S r   )r   r   r   r   r   r   r   r   __iter__   s
    


zDeltaSet.__iter__)N)	r   r   r   r   rw   r{   r   r   r   r   r   r   r   r      s   
		r   c                   @   s|   e Zd ZdZdddZdd Zd 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 )!Analysiszb
    Represents the result of code analysis, and provides tools to perform
    code analysis.
    Nc                 C   sP   || _ i | _tt| _tt| _tt| _tt	| _	t
ddd| _| jg| _d S )NTF)parentchildrenr   ru   not_constantlocal_constantslocal_constantalways_constantsglobal_constantr|   r   controlcontrol_stack)r   r   r   r   r   r      s    



zAnalysis.__init__c                 C   s*   || j v r| j | S t| }|| j |< |S r   )r   r   )r   
identifierrvr   r   r   	get_child  s
    


zAnalysis.get_childTFc                 C   s.   t | jjo||| jp|| _| j| j d S r   )r   r   rz   r   r   appendr   r   r   r   push_control  s    zAnalysis.push_controlc                 C   s   | j  }| j d | _|S )N)r   popr   )r   r   r   r   r   pop_control"  s    
zAnalysis.pop_controlc                 C   s   | j jrtS tS dS )zH
        Returns NOT_CONST if we're in a non-constant imagemap.
        N)r   r   	NOT_CONSTGLOBAL_CONSTr   r   r   r   r   '  s    zAnalysis.imagemapc                 C   s0   t | j}|  |D ]}d|_|jr q,qdS )zu
        Call this to indicate the current loop is being exited by the
        continue or break statements.
        FN)listr   reverserz   r   )r   lr   r   r   r   	exit_loop1  s    
zAnalysis.exit_loopc                 C   sf   | j  D ]}| s
 dS q
| jjs>| jjs>| jjs>| jjrbd| j_d| j_d| j_d| j_dS dS )z
        Returns True if we've reached a fixed point, where the analysis has
        not changed since the last time we called this function.
        FT)r   valuesat_fixed_pointr   r   r   r   r|   r   r   r   r   r   @  s     zAnalysis.at_fixed_pointc                 C   s2   || j vr.| j| | j| | j| dS )z=
        Marks `name` as a potential local constant.
        N)r   r   rw   r   r{   r|   r   ry   r   r   r   mark_constantX  s    
zAnalysis.mark_constantc                 C   s4   | j | | j| | j| | j| dS )z:
        Marks `name` as definitely not-constant.
        N)r   rw   r|   r{   r   r   r   r   r   r   mark_not_constantb  s    zAnalysis.mark_not_constantc                    s6    fdd fdd fdd|S )z
        Returns true if `node` is constant for the purpose of screen
        language. Node should be a python AST node.

        Screen language ignores object identity for the purposes of
        object equality.
        c                    s   t | tjrt}| j}n>t | tjrJ | j\}}|durV|d | j }n| dfS |jv rht|fS |j	v rzt
|fS |jv rt|fS ||fS dS )a5  
            Check nodes that make up a name. This returns a pair:

            * The first element is True if the node is constant, and False
              otherwise.
            * The second element is None if the node is constant or the name is
              not known, and the name otherwise.
            Nr~   )r   astNamer   id	Attributevalueattrr   r   r   r   LOCAL_CONSTnoderz   ry   )
check_name
check_noder   r   r   r   v  s    



z(Analysis.is_constant.<locals>.check_namec                    s&   t | } | stS t fdd| D S )z?
            Checks a list of nodes for constness.
            c                 3   s   | ]} |V  qd S r   r   r   r   r   r   r      r!   z<Analysis.is_constant.<locals>.check_nodes.<locals>.<genexpr>)r   r   min)nodesr   r   r   check_nodes  s    z)Analysis.is_constant.<locals>.check_nodesc                    sD  | du rt S t| tjrt S t| tjr2| jS t| tjrH| jS t| tjrjt	| j
| jS t| tjr| jS t| tjrt	| j| j| jS t| tjrt	| j| jS t| tj r| jS t| tjrt	| j
| jS t| tjr^ | j\}}|t ks:|jvr>tS t	| jdd | jD S t| tjrt	| j| jS t| tj r| jS t| tj!tj"fr | d S t| tj#rt	| j| j$S t| tj%r| jS t| tj&tj'fr| jS t| tj(r@t	| j)| j*| j+S tS )zz
            When given `node`, part of a Python expression, returns how
            const the expression is.
            Nc                 s   s   | ]}|j V  qd S r   )r   r   r   r   r   r      r!   z;Analysis.is_constant.<locals>.check_node.<locals>.<genexpr>r   ),r   r   r   ConstantBoolOpr   	NamedExprr   BinOpr   leftrightUnaryOpoperandIfExptestbodyorelseDictkeysSeteltsComparecomparatorsCallfuncr|   r   argskeywordsFormattedValueformat_spec	JoinedStrr   r   	SubscriptsliceStarredListTupleSlicelowerupperstepr   r   r   r   r   r   r   r     s    






z(Analysis.is_constant.<locals>.check_noder   r   r   r   r   r   is_constantm  s    	 rzAnalysis.is_constantc                 C   s$   t |\}}|rtS | |S dS )z|
        Compiles `expr` into an AST node, then returns the result of
        self.is_constant called on that node.
        N)ccacheast_eval_literalr   r   )r   exprr   literalr   r   r   is_constant_expr  s    zAnalysis.is_constant_exprc                 C   s*   t |}t| }|D ]}|| qdS )z>
        Performs analysis on a block of python code.
        N)r   ast_exec
PyAnalysisvisit)r   coder   ar   r   r   r   python#  s    
zAnalysis.pythonc                 C   sT   t t| _|jD ]\}}| | q|jdur:| |j |jdurP| |j dS )z8
        Analyzes the parameters to the screen.
        N)r   rv   r   
parametersr   extraposextrakw)r   r   ry   _defaultr   r   r   r   /  s    


zAnalysis.parameters)N)TFF)r   r   r   r   r   r   r   r   r   r   r   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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&S )'r   z
    This analyzes Python code to determine which variables should be
    marked const, and which should be marked non-const.
    c                 C   s
   || _ d S r   )analysis)r   r   r   r   r   r   H  s    zPyAnalysis.__init__c                 C   sX   t |jtjr| j|j n6t |jtjrT| jjj	rF| j
|j n| j|j d S r   )r   ctxr   AugStorer   r   r   Storer   rz   r   r   r   r   r   
visit_NameM  s    
zPyAnalysis.visit_Namec                 C   s4   | j |j}| j |d | | | j   d S NFr   r   r   r   generic_visitr   r   r   rz   r   r   r   visit_NamedExprX  s    
zPyAnalysis.visit_NamedExprc                 C   s   | j |j d S r   r   r   ry   r   r   r   r   visit_FunctionDefc  s    zPyAnalysis.visit_FunctionDefc                 C   s   | j |j d S r   r	  r   r   r   r   visit_AsyncFunctionDeff  s    z!PyAnalysis.visit_AsyncFunctionDefc                 C   s   | j |j d S r   r	  r   r   r   r   visit_ClassDefi  s    zPyAnalysis.visit_ClassDefc                 C   s4   | j |j}| j |d | | | j   d S r  r  r  r   r   r   visit_Assignr  s    
zPyAnalysis.visit_Assignc                 C   s&   | j dd | | | j   d S r  r   r   r  r   r   r   r   r   visit_AugAssign{  s    
zPyAnalysis.visit_AugAssignc                 C   s4   | j |j}| j |d | | | j   d S r  r  r  r   r   r   visit_AnnAssign  s    
zPyAnalysis.visit_AnnAssignc                 C   sX   | j |j}| j j|dd | j jj}| | | j jj|krJ| | | j   d S NT)rz   r   )r   r   iterr   r   rz   r  r   r   r   rz   	old_constr   r   r   	visit_For  s    


zPyAnalysis.visit_Forc                 C   s
   |  |S r   )r  r   r   r   r   visit_AsyncFor  s    zPyAnalysis.visit_AsyncForc                 C   sX   | j |j}| j j|dd | j jj}| | | j jj|krJ| | | j   d S r  )r   r   r   r   r   rz   r  r   r  r   r   r   visit_While  s    


zPyAnalysis.visit_Whilec                 C   s4   | j |j}| j |d | | | j   d S r  )r   r   r   r   r  r   r  r   r   r   visit_If  s    
zPyAnalysis.visit_Ifc                 C   sL   | j |j}| |j | j |d |jd ur>| |j | j   d S r  )r   r   context_exprr   r   optional_varsr   r  r   r   r   visit_withitem  s    
zPyAnalysis.visit_withitemc                 C   s$   | j d | | | j   d S r  r  r   r   r   r   visit_Match  s    
zPyAnalysis.visit_Matchc                 C   s.   |j D ]}|jr| j|j q| | d S r   )handlersry   r   r   r  )r   r   r   r   r   r   	visit_Try  s    
zPyAnalysis.visit_Tryc                 C   s   | j   d S r   r   r   r   r   r   r   visit_Break  s    zPyAnalysis.visit_Breakc                 C   s   | j   d S r   r  r   r   r   r   visit_Continue  s    zPyAnalysis.visit_ContinueN)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   r   B  s&   			r   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )CompilerCachezR
    Objects of this class are used to cache the compiliation of Python code.
    c                 C   s   i | _ i | _d| _d| _d S )NFr   )ast_eval_cacheast_exec_cacheupdatedversionr   r   r   r   r     s    zCompilerCache.__init__c                 C   s   t |tjjr|j}|j}nd}d}|||f}| j|d}|du rt|ddd}zt	| d}W n t
yz   d}Y n0 ||f}|| j|< d| _|tj|< |S )z5
        Compiles an expression into an AST.
        NevalTast_nodeF)r   renpyr   PyExprfilename
linenumberr#  getr   literal_eval	Exceptionr%  
new_ccache)r   r   r,  r-  keyr   r   r   r   r   r     s&    




zCompilerCache.ast_eval_literalc                 C   s   |  |d S )Nr   )r   )r   r   r   r   r   ast_eval  s    zCompilerCache.ast_evalc                 C   sj   t |tjjr||j|jf}n
|ddf}| j|d}|du r\t|ddd}|| j|< d| _	|t
j|< |S )z/
        Compiles a block into an AST.
        NexecTr(  )r   r*  r   r+  r,  r-  r$  r.  r   r%  r1  )r   r   r2  r   r   r   r   r     s    


zCompilerCache.ast_execN)r   r   r   r   r   r   r3  r   r   r   r   r   r"    s
   
"r"  zcache/py3analysis.rpybc                  C   s   t jjjrd S zjt jt"} tt	| 
 }W d    n1 sD0    Y  |jtjkrvtj|j tj|j W n ty   Y n0 d S r   )r*  gamer   compileloaderloadCACHE_FILENAMEr   zlib
decompressreadr&  r   r#  updater$  r0  )fcr   r   r   
load_cache4  s    
0r@  c                  C   s~   t js
d S tjrd S zRtttdd} ttj	
td}||  W d    n1 sZ0    Y  W n tyx   Y n0 d S )NT   wb)r   r%  r*  macappr:  compressr   r1  r   r7  get_pathr9  writer0  )datar>  r   r   r   
save_cacheC  s    ,rH  )5
__future__r   r   r   r   r   renpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   builtinsr*  renpy.pythonr   r   r:  renpy.compat.pickler   r   r   r   dirr|   rv   ru   r   rz   r}   r   objectr   r   r   r   r   r   NodeVisitorr   r"  r   r1  r9  r@  rH  r   r   r   r   <module>   sB   8)#5  P #J