<s> from __future__ import print_function , division , absolute_import <EOL> import collections <EOL> import dis <EOL> from functools import reduce <EOL> import operator <EOL> import sys <EOL> from . import ir , controlflow , dataflow , utils , errors , consts <EOL> from . utils import builtins <EOL> class Assigner ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . dest_to_src = { } <EOL> self . src_invalidate = collections . defaultdict ( list ) <EOL> self . unused_dests = set ( ) <EOL> def assign ( self , srcvar , destvar ) : <EOL> """<STR_LIT>""" <EOL> srcname = srcvar . name <EOL> destname = destvar . name <EOL> if destname in self . src_invalidate : <EOL> for d in self . src_invalidate . pop ( destname ) : <EOL> self . dest_to_src . pop ( d ) <EOL> if srcname in self . dest_to_src : <EOL> srcvar = self . dest_to_src [ srcname ] <EOL> if destvar . is_temp : <EOL> self . dest_to_src [ destname ] = srcvar <EOL> self . src_invalidate [ srcname ] . append ( destname ) <EOL> self . unused_dests . add ( destname ) <EOL> return srcvar <EOL> def get_assignment_source ( self , destname ) : <EOL> """<STR_LIT>""" <EOL> if destname in self . dest_to_src : <EOL> return self . dest_to_src [ destname ] <EOL> self . unused_dests . discard ( destname ) <EOL> return None <EOL> class YieldPoint ( object ) : <EOL> def __init__ ( self , block , inst ) : <EOL> assert isinstance ( block , ir . Block ) <EOL> assert isinstance ( inst , ir . Yield ) <EOL> self . block = block <EOL> self . inst = inst <EOL> self . live_vars = None <EOL> self . weak_live_vars = None <EOL> class GeneratorInfo ( object ) : <EOL> def __init__ ( self ) : <EOL> self . yield_points = { } <EOL> self . state_vars = [ ] <EOL> def get_yield_points ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . yield_points . values ( ) <EOL> class Interpreter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , bytecode ) : <EOL> self . bytecode = bytecode <EOL> self . loc = ir . Loc ( filename = bytecode . filename , line = <NUM_LIT:1> ) <EOL> self . arg_count = bytecode . arg_count <EOL> self . arg_names = bytecode . arg_names <EOL> self . blocks = { } <EOL> self . used_globals = { } <EOL> self . definitions = collections . defaultdict ( list ) <EOL> self . block_entry_vars = { } <EOL> self . reset ( ) <EOL> def reset ( self ) : <EOL> """<STR_LIT>""" <EOL> self . scopes = [ ] <EOL> global_scope = ir . Scope ( parent = None , loc = self . loc ) <EOL> self . scopes . append ( global_scope ) <EOL> self . cfa = controlflow . ControlFlowAnalysis ( self . bytecode ) <EOL> self . cfa . run ( ) <EOL> self . dfa = dataflow . DataFlowAnalysis ( self . cfa ) <EOL> self . dfa . run ( ) <EOL> self . consts = consts . ConstantInference ( self ) <EOL> if self . bytecode . is_generator : <EOL> self . generator_info = GeneratorInfo ( ) <EOL> else : <EOL> self . generator_info = None <EOL> self . current_block = None <EOL> self . current_block_offset = None <EOL> self . syntax_blocks = [ ] <EOL> self . dfainfo = None <EOL> def get_used_globals ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . used_globals <EOL> def get_block_entry_vars ( self , block ) : <EOL> """<STR_LIT>""" <EOL> return self . block_entry_vars [ block ] <EOL> def infer_constant ( self , name ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( name , ir . Var ) : <EOL> name = name . name <EOL> return self . consts . infer_constant ( name ) <EOL> def interpret ( self ) : <EOL> """<STR_LIT>""" <EOL> firstblk = min ( self . cfa . blocks . keys ( ) ) <EOL> self . loc = ir . Loc ( filename = self . bytecode . filename , <EOL> line = self . bytecode [ firstblk ] . lineno ) <EOL> self . scopes . append ( ir . Scope ( parent = self . current_scope , loc = self . loc ) ) <EOL> for inst , kws in self . _iter_inst ( ) : <EOL> self . _dispatch ( inst , kws ) <EOL> var_def_map , var_dead_map = self . _insert_var_dels ( ) <EOL> self . _compute_live_variables ( var_def_map , var_dead_map ) <EOL> if self . generator_info : <EOL> self . _compute_generator_info ( ) <EOL> def _compute_live_variables ( self , var_def_map , var_dead_map ) : <EOL> """<STR_LIT>""" <EOL> block_entry_vars = collections . defaultdict ( set ) <EOL> def fix_point_progress ( ) : <EOL> return tuple ( map ( len , block_entry_vars . values ( ) ) ) <EOL> cfg = self . cfa . graph <EOL> old_point = None <EOL> new_point = fix_point_progress ( ) <EOL> while old_point != new_point : <EOL> for offset in self . blocks : <EOL> avail = block_entry_vars [ offset ] | var_def_map [ offset ] <EOL> avail -= var_dead_map [ offset ] <EOL> for succ , _data in cfg . successors ( offset ) : <EOL> block_entry_vars [ succ ] |= avail <EOL> old_point = new_point <EOL> new_point = fix_point_progress ( ) <EOL> for offset , ir_block in self . blocks . items ( ) : <EOL> self . block_entry_vars [ ir_block ] = block_entry_vars [ offset ] <EOL> def _compute_generator_info ( self ) : <EOL> """<STR_LIT>""" <EOL> gi = self . generator_info <EOL> for yp in gi . get_yield_points ( ) : <EOL> live_vars = set ( self . block_entry_vars [ yp . block ] ) <EOL> weak_live_vars = set ( ) <EOL> stmts = iter ( yp . block . body ) <EOL> for stmt in stmts : <EOL> if isinstance ( stmt , ir . Assign ) : <EOL> if stmt . value is yp . inst : <EOL> break <EOL> live_vars . add ( stmt . target . name ) <EOL> elif isinstance ( stmt , ir . Del ) : <EOL> live_vars . remove ( stmt . value ) <EOL> else : <EOL> assert <NUM_LIT:0> , "<STR_LIT>" <EOL> for stmt in stmts : <EOL> if isinstance ( stmt , ir . Del ) : <EOL> name = stmt . value <EOL> if name in live_vars : <EOL> live_vars . remove ( name ) <EOL> weak_live_vars . add ( name ) <EOL> else : <EOL> break <EOL> yp . live_vars = live_vars <EOL> yp . weak_live_vars = weak_live_vars <EOL> st = set ( ) <EOL> for yp in gi . get_yield_points ( ) : <EOL> st |= yp . live_vars <EOL> st |= yp . weak_live_vars <EOL> gi . state_vars = sorted ( st ) <EOL> def _insert_var_dels ( self ) : <EOL> """<STR_LIT>""" <EOL> var_use_map , var_def_map = self . _compute_use_defs ( ) <EOL> live_map = self . _compute_live_map ( var_use_map , var_def_map ) <EOL> dead_maps = self . _compute_dead_maps ( live_map , var_def_map ) <EOL> internal_dead_map , escaping_dead_map = dead_maps <EOL> self . _patch_var_dels ( internal_dead_map , escaping_dead_map ) <EOL> var_dead_map = dict ( ( k , internal_dead_map [ k ] | escaping_dead_map [ k ] ) <EOL> for k in self . blocks ) <EOL> return var_def_map , var_dead_map <EOL> def _compute_use_defs ( self ) : <EOL> """<STR_LIT>""" <EOL> var_use_map = { } <EOL> var_def_map = { } <EOL> for offset , ir_block in self . blocks . items ( ) : <EOL> var_use_map [ offset ] = use_set = set ( ) <EOL> var_def_map [ offset ] = def_set = set ( ) <EOL> for stmt in ir_block . body : <EOL> if isinstance ( stmt , ir . Assign ) : <EOL> if isinstance ( stmt . value , ir . Inst ) : <EOL> rhs_set = set ( var . name <EOL> for var in stmt . value . list_vars ( ) ) <EOL> elif isinstance ( stmt . value , ir . Var ) : <EOL> rhs_set = set ( [ stmt . value . name ] ) <EOL> elif isinstance ( stmt . value , ( ir . Arg , ir . Const , ir . Global , <EOL> ir . FreeVar ) ) : <EOL> rhs_set = ( ) <EOL> else : <EOL> raise AssertionError ( '<STR_LIT>' , type ( stmt . value ) ) <EOL> if stmt . target . name not in rhs_set : <EOL> def_set . add ( stmt . target . name ) <EOL> for var in stmt . list_vars ( ) : <EOL> if var . name not in def_set : <EOL> use_set . add ( var . name ) <EOL> return var_use_map , var_def_map <EOL> def _compute_live_map ( self , var_use_map , var_def_map ) : <EOL> """<STR_LIT>""" <EOL> live_map = { } <EOL> for offset in self . blocks . keys ( ) : <EOL> live_map [ offset ] = var_use_map [ offset ] <EOL> def fix_point_progress ( ) : <EOL> return tuple ( len ( v ) for v in live_map . values ( ) ) <EOL> old_point = None <EOL> new_point = fix_point_progress ( ) <EOL> while old_point != new_point : <EOL> for offset in live_map . keys ( ) : <EOL> for inc_blk , _data in self . cfa . graph . predecessors ( offset ) : <EOL> live_map [ inc_blk ] |= live_map [ offset ] - var_def_map [ inc_blk ] <EOL> old_point = new_point <EOL> new_point = fix_point_progress ( ) <EOL> return live_map <EOL> def _compute_dead_maps ( self , live_map , var_def_map ) : <EOL> """<STR_LIT>""" <EOL> escaping_dead_map = collections . defaultdict ( set ) <EOL> internal_dead_map = collections . defaultdict ( set ) <EOL> exit_dead_map = collections . defaultdict ( set ) <EOL> for offset , ir_block in self . blocks . items ( ) : <EOL> cur_live_set = live_map [ offset ] | var_def_map [ offset ] <EOL> outgoing_live_map = dict ( ( out_blk , live_map [ out_blk ] ) <EOL> for out_blk , _data <EOL> in self . cfa . graph . successors ( offset ) ) <EOL> terminator_liveset = set ( v . name <EOL> for v in ir_block . terminator . list_vars ( ) ) <EOL> combined_liveset = reduce ( operator . or_ , outgoing_live_map . values ( ) , <EOL> set ( ) ) <EOL> combined_liveset |= terminator_liveset <EOL> internal_set = cur_live_set - combined_liveset <EOL> internal_dead_map [ offset ] = internal_set <EOL> escaping_live_set = cur_live_set - internal_set <EOL> for out_blk , new_live_set in outgoing_live_map . items ( ) : <EOL> new_live_set = new_live_set | var_def_map [ out_blk ] <EOL> escaping_dead_map [ out_blk ] |= escaping_live_set - new_live_set <EOL> if not outgoing_live_map : <EOL> exit_dead_map [ offset ] = terminator_liveset <EOL> all_vars = reduce ( operator . or_ , live_map . values ( ) , set ( ) ) <EOL> internal_dead_vars = reduce ( operator . or_ , internal_dead_map . values ( ) , <EOL> set ( ) ) <EOL> escaping_dead_vars = reduce ( operator . or_ , escaping_dead_map . values ( ) , <EOL> set ( ) ) <EOL> exit_dead_vars = reduce ( operator . or_ , exit_dead_map . values ( ) , set ( ) ) <EOL> dead_vars = ( internal_dead_vars | escaping_dead_vars | exit_dead_vars ) <EOL> missing_vars = all_vars - dead_vars <EOL> if missing_vars : <EOL> if not self . cfa . graph . exit_points ( ) : <EOL> pass <EOL> else : <EOL> msg = '<STR_LIT>' . format ( missing_vars ) <EOL> raise RuntimeError ( msg ) <EOL> return internal_dead_map , escaping_dead_map <EOL> def _patch_var_dels ( self , internal_dead_map , escaping_dead_map ) : <EOL> """<STR_LIT>""" <EOL> for offset , ir_block in self . blocks . items ( ) : <EOL> internal_dead_set = internal_dead_map [ offset ] . copy ( ) <EOL> delete_pts = [ ] <EOL> for stmt in reversed ( ir_block . body [ : - <NUM_LIT:1> ] ) : <EOL> live_set = set ( v . name for v in stmt . list_vars ( ) ) <EOL> dead_set = live_set & internal_dead_set <EOL> delete_pts . append ( ( stmt , dead_set ) ) <EOL> internal_dead_set -= dead_set <EOL> body = [ ] <EOL> for stmt , delete_set in reversed ( delete_pts ) : <EOL> body . append ( stmt ) <EOL> for var_name in sorted ( delete_set , reverse = True ) : <EOL> body . append ( ir . Del ( var_name , loc = ir_block . loc ) ) <EOL> body . append ( ir_block . body [ - <NUM_LIT:1> ] ) <EOL> ir_block . body = body <EOL> escape_dead_set = escaping_dead_map [ offset ] <EOL> for var_name in sorted ( escape_dead_set ) : <EOL> ir_block . prepend ( ir . Del ( var_name , loc = ir_block . loc ) ) <EOL> def init_first_block ( self ) : <EOL> for index , name in enumerate ( self . arg_names ) : <EOL> val = ir . Arg ( index = index , name = name , loc = self . loc ) <EOL> self . store ( val , name ) <EOL> def _iter_inst ( self ) : <EOL> for blkct , block in enumerate ( self . cfa . iterliveblocks ( ) ) : <EOL> firstinst = self . bytecode [ block . body [ <NUM_LIT:0> ] ] <EOL> self . _start_new_block ( firstinst ) <EOL> if blkct == <NUM_LIT:0> : <EOL> self . init_first_block ( ) <EOL> for offset , kws in self . dfainfo . insts : <EOL> inst = self . bytecode [ offset ] <EOL> self . loc = ir . Loc ( filename = self . bytecode . filename , <EOL> line = inst . lineno ) <EOL> yield inst , kws <EOL> self . _end_current_block ( ) <EOL> def _start_new_block ( self , inst ) : <EOL> self . loc = ir . Loc ( filename = self . bytecode . filename , line = inst . lineno ) <EOL> oldblock = self . current_block <EOL> self . insert_block ( inst . offset ) <EOL> if oldblock is not None and not oldblock . is_terminated : <EOL> jmp = ir . Jump ( inst . offset , loc = self . loc ) <EOL> oldblock . append ( jmp ) <EOL> self . dfainfo = self . dfa . infos [ self . current_block_offset ] <EOL> self . assigner = Assigner ( ) <EOL> def _end_current_block ( self ) : <EOL> self . _remove_unused_temporaries ( ) <EOL> self . _insert_outgoing_phis ( ) <EOL> def _remove_unused_temporaries ( self ) : <EOL> """<STR_LIT>""" <EOL> new_body = [ ] <EOL> for inst in self . current_block . body : <EOL> if ( isinstance ( inst , ir . Assign ) <EOL> and inst . target . is_temp <EOL> and inst . target . name in self . assigner . unused_dests ) : <EOL> continue <EOL> new_body . append ( inst ) <EOL> self . current_block . body = new_body <EOL> def _insert_outgoing_phis ( self ) : <EOL> """<STR_LIT>""" <EOL> for phiname , varname in self . dfainfo . outgoing_phis . items ( ) : <EOL> target = self . current_scope . get_or_define ( phiname , <EOL> loc = self . loc ) <EOL> stmt = ir . Assign ( value = self . get ( varname ) , target = target , <EOL> loc = self . loc ) <EOL> if not self . current_block . is_terminated : <EOL> self . current_block . append ( stmt ) <EOL> else : <EOL> self . current_block . insert_before_terminator ( stmt ) <EOL> def get_global_value ( self , name ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> return utils . get_function_globals ( self . bytecode . func ) [ name ] <EOL> except KeyError : <EOL> return getattr ( builtins , name , ir . UNDEFINED ) <EOL> def get_closure_value ( self , index ) : <EOL> """<STR_LIT>""" <EOL> return self . bytecode . func . __closure__ [ index ] . cell_contents <EOL> @ property <EOL> def current_scope ( self ) : <EOL> return self . scopes [ - <NUM_LIT:1> ] <EOL> @ property <EOL> def code_consts ( self ) : <EOL> return self . bytecode . co_consts <EOL> @ property <EOL> def code_locals ( self ) : <EOL> return self . bytecode . co_varnames <EOL> @ property <EOL> def code_names ( self ) : <EOL> return self . bytecode . co_names <EOL> @ property <EOL> def code_freevars ( self ) : <EOL> return self . bytecode . co_freevars <EOL> def _dispatch ( self , inst , kws ) : <EOL> assert self . current_block is not None <EOL> fname = "<STR_LIT>" % inst . opname . replace ( '<STR_LIT:+>' , '<STR_LIT:_>' ) <EOL> try : <EOL> fn = getattr ( self , fname ) <EOL> except AttributeError : <EOL> raise NotImplementedError ( inst ) <EOL> else : <EOL> try : <EOL> return fn ( inst , ** kws ) <EOL> except errors . NotDefinedError as e : <EOL> if e . loc is None : <EOL> e . loc = self . loc <EOL> raise e <EOL> def dump ( self , file = None ) : <EOL> file = file or sys . stdout <EOL> for offset , block in sorted ( self . blocks . items ( ) ) : <EOL> print ( '<STR_LIT>' % ( offset , ) , file = file ) <EOL> block . dump ( file = file ) <EOL> def dump_generator_info ( self , file = None ) : <EOL> file = file or sys . stdout <EOL> gi = self . generator_info <EOL> print ( "<STR_LIT>" , sorted ( gi . state_vars ) , file = file ) <EOL> for index , yp in sorted ( gi . yield_points . items ( ) ) : <EOL> print ( "<STR_LIT>" <EOL> % ( index , sorted ( yp . live_vars ) , sorted ( yp . weak_live_vars ) ) , <EOL> file = file ) <EOL> def store ( self , value , name , redefine = False ) : <EOL> """<STR_LIT>""" <EOL> if redefine or self . current_block_offset in self . cfa . backbone : <EOL> target = self . current_scope . redefine ( name , loc = self . loc ) <EOL> else : <EOL> target = self . current_scope . get_or_define ( name , loc = self . loc ) <EOL> if isinstance ( value , ir . Var ) : <EOL> value = self . assigner . assign ( value , target ) <EOL> stmt = ir . Assign ( value = value , target = target , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> self . definitions [ target . name ] . append ( value ) <EOL> def get ( self , name ) : <EOL> """<STR_LIT>""" <EOL> var = self . assigner . get_assignment_source ( name ) <EOL> if var is None : <EOL> var = self . current_scope . get ( name ) <EOL> return var <EOL> def get_definition ( self , value ) : <EOL> """<STR_LIT>""" <EOL> while True : <EOL> if isinstance ( value , ir . Var ) : <EOL> name = value . name <EOL> elif isinstance ( value , str ) : <EOL> name = value <EOL> else : <EOL> return value <EOL> defs = self . definitions [ name ] <EOL> if len ( defs ) == <NUM_LIT:0> : <EOL> raise KeyError ( "<STR_LIT>" <EOL> % ( name , ) ) <EOL> if len ( defs ) > <NUM_LIT:1> : <EOL> raise KeyError ( "<STR_LIT>" <EOL> % ( name , ) ) <EOL> value = defs [ <NUM_LIT:0> ] <EOL> def insert_block ( self , offset , scope = None , loc = None ) : <EOL> scope = scope or self . current_scope <EOL> loc = loc or self . loc <EOL> blk = ir . Block ( scope = scope , loc = loc ) <EOL> self . blocks [ offset ] = blk <EOL> self . current_block = blk <EOL> self . current_block_offset = offset <EOL> return blk <EOL> def op_PRINT_ITEM ( self , inst , item , printvar , res ) : <EOL> item = self . get ( item ) <EOL> printgv = ir . Global ( "<STR_LIT>" , print , loc = self . loc ) <EOL> self . store ( value = printgv , name = printvar ) <EOL> call = ir . Expr . call ( self . get ( printvar ) , ( item , ) , ( ) , loc = self . loc ) <EOL> self . store ( value = call , name = res ) <EOL> def op_PRINT_NEWLINE ( self , inst , printvar , res ) : <EOL> printgv = ir . Global ( "<STR_LIT>" , print , loc = self . loc ) <EOL> self . store ( value = printgv , name = printvar ) <EOL> call = ir . Expr . call ( self . get ( printvar ) , ( ) , ( ) , loc = self . loc ) <EOL> self . store ( value = call , name = res ) <EOL> def op_UNPACK_SEQUENCE ( self , inst , iterable , stores , tupleobj ) : <EOL> count = len ( stores ) <EOL> tup = ir . Expr . exhaust_iter ( value = self . get ( iterable ) , loc = self . loc , <EOL> count = count ) <EOL> self . store ( name = tupleobj , value = tup ) <EOL> for i , st in enumerate ( stores ) : <EOL> expr = ir . Expr . static_getitem ( self . get ( tupleobj ) , <EOL> index = i , index_var = None , <EOL> loc = self . loc ) <EOL> self . store ( expr , st ) <EOL> def op_BUILD_SLICE ( self , inst , start , stop , step , res , slicevar ) : <EOL> start = self . get ( start ) <EOL> stop = self . get ( stop ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> if step is None : <EOL> sliceinst = ir . Expr . call ( self . get ( slicevar ) , ( start , stop ) , ( ) , <EOL> loc = self . loc ) <EOL> else : <EOL> step = self . get ( step ) <EOL> sliceinst = ir . Expr . call ( self . get ( slicevar ) , ( start , stop , step ) , <EOL> ( ) , loc = self . loc ) <EOL> self . store ( value = sliceinst , name = res ) <EOL> def op_SLICE_0 ( self , inst , base , res , slicevar , indexvar , nonevar ) : <EOL> base = self . get ( base ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , none ) , ( ) , loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> expr = ir . Expr . getitem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . store ( value = expr , name = res ) <EOL> def op_SLICE_1 ( self , inst , base , start , nonevar , res , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , none ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> expr = ir . Expr . getitem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . store ( value = expr , name = res ) <EOL> def op_SLICE_2 ( self , inst , base , nonevar , stop , res , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> stop = self . get ( stop ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , stop , ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> expr = ir . Expr . getitem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . store ( value = expr , name = res ) <EOL> def op_SLICE_3 ( self , inst , base , start , stop , res , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> stop = self . get ( stop ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , stop ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> expr = ir . Expr . getitem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . store ( value = expr , name = res ) <EOL> def op_STORE_SLICE_0 ( self , inst , base , value , slicevar , indexvar , nonevar ) : <EOL> base = self . get ( base ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , none ) , ( ) , loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . SetItem ( base , self . get ( indexvar ) , self . get ( value ) , <EOL> loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_STORE_SLICE_1 ( self , inst , base , start , nonevar , value , slicevar , <EOL> indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , none ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . SetItem ( base , self . get ( indexvar ) , self . get ( value ) , <EOL> loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_STORE_SLICE_2 ( self , inst , base , nonevar , stop , value , slicevar , <EOL> indexvar ) : <EOL> base = self . get ( base ) <EOL> stop = self . get ( stop ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , stop , ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . SetItem ( base , self . get ( indexvar ) , self . get ( value ) , <EOL> loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_STORE_SLICE_3 ( self , inst , base , start , stop , value , slicevar , <EOL> indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> stop = self . get ( stop ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , stop ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . SetItem ( base , self . get ( indexvar ) , self . get ( value ) , <EOL> loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_DELETE_SLICE_0 ( self , inst , base , slicevar , indexvar , nonevar ) : <EOL> base = self . get ( base ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , none ) , ( ) , loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . DelItem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_DELETE_SLICE_1 ( self , inst , base , start , nonevar , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , none ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . DelItem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_DELETE_SLICE_2 ( self , inst , base , nonevar , stop , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> stop = self . get ( stop ) <EOL> nonegv = ir . Const ( None , loc = self . loc ) <EOL> self . store ( value = nonegv , name = nonevar ) <EOL> none = self . get ( nonevar ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( none , stop , ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . DelItem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_DELETE_SLICE_3 ( self , inst , base , start , stop , slicevar , indexvar ) : <EOL> base = self . get ( base ) <EOL> start = self . get ( start ) <EOL> stop = self . get ( stop ) <EOL> slicegv = ir . Global ( "<STR_LIT>" , slice , loc = self . loc ) <EOL> self . store ( value = slicegv , name = slicevar ) <EOL> index = ir . Expr . call ( self . get ( slicevar ) , ( start , stop ) , ( ) , <EOL> loc = self . loc ) <EOL> self . store ( value = index , name = indexvar ) <EOL> stmt = ir . DelItem ( base , self . get ( indexvar ) , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_LOAD_FAST ( self , inst , res ) : <EOL> srcname = self . code_locals [ inst . arg ] <EOL> self . store ( value = self . get ( srcname ) , name = res ) <EOL> def op_STORE_FAST ( self , inst , value ) : <EOL> dstname = self . code_locals [ inst . arg ] <EOL> value = self . get ( value ) <EOL> self . store ( value = value , name = dstname ) <EOL> def op_DUP_TOPX ( self , inst , orig , duped ) : <EOL> for src , dst in zip ( orig , duped ) : <EOL> self . store ( value = self . get ( src ) , name = dst ) <EOL> op_DUP_TOP = op_DUP_TOPX <EOL> op_DUP_TOP_TWO = op_DUP_TOPX <EOL> def op_STORE_ATTR ( self , inst , target , value ) : <EOL> attr = self . code_names [ inst . arg ] <EOL> sa = ir . SetAttr ( target = self . get ( target ) , value = self . get ( value ) , <EOL> attr = attr , loc = self . loc ) <EOL> self . current_block . append ( sa ) <EOL> def op_DELETE_ATTR ( self , inst , target ) : <EOL> attr = self . code_names [ inst . arg ] <EOL> sa = ir . DelAttr ( target = self . get ( target ) , attr = attr , loc = self . loc ) <EOL> self . current_block . append ( sa ) <EOL> def op_LOAD_ATTR ( self , inst , item , res ) : <EOL> item = self . get ( item ) <EOL> attr = self . code_names [ inst . arg ] <EOL> getattr = ir . Expr . getattr ( item , attr , loc = self . loc ) <EOL> self . store ( getattr , res ) <EOL> def op_LOAD_CONST ( self , inst , res ) : <EOL> value = self . code_consts [ inst . arg ] <EOL> const = ir . Const ( value , loc = self . loc ) <EOL> self . store ( const , res ) <EOL> def op_LOAD_GLOBAL ( self , inst , res ) : <EOL> name = self . code_names [ inst . arg ] <EOL> value = self . get_global_value ( name ) <EOL> self . used_globals [ name ] = value <EOL> gl = ir . Global ( name , value , loc = self . loc ) <EOL> self . store ( gl , res ) <EOL> def op_LOAD_DEREF ( self , inst , res ) : <EOL> name = self . code_freevars [ inst . arg ] <EOL> value = self . get_closure_value ( inst . arg ) <EOL> gl = ir . FreeVar ( inst . arg , name , value , loc = self . loc ) <EOL> self . store ( gl , res ) <EOL> def op_SETUP_LOOP ( self , inst ) : <EOL> assert self . blocks [ inst . offset ] is self . current_block <EOL> loop = ir . Loop ( inst . offset , exit = ( inst . next + inst . arg ) ) <EOL> self . syntax_blocks . append ( loop ) <EOL> def op_CALL_FUNCTION ( self , inst , func , args , kws , res , vararg ) : <EOL> func = self . get ( func ) <EOL> args = [ self . get ( x ) for x in args ] <EOL> if vararg is not None : <EOL> vararg = self . get ( vararg ) <EOL> keyvalues = [ ] <EOL> removethese = [ ] <EOL> for k , v in kws : <EOL> k , v = self . get ( k ) , self . get ( v ) <EOL> for inst in self . current_block . body : <EOL> if isinstance ( inst , ir . Assign ) and inst . target is k : <EOL> removethese . append ( inst ) <EOL> keyvalues . append ( ( inst . value . value , v ) ) <EOL> for inst in removethese : <EOL> self . current_block . remove ( inst ) <EOL> expr = ir . Expr . call ( func , args , keyvalues , loc = self . loc , <EOL> vararg = vararg ) <EOL> self . store ( expr , res ) <EOL> op_CALL_FUNCTION_VAR = op_CALL_FUNCTION <EOL> def op_GET_ITER ( self , inst , value , res ) : <EOL> expr = ir . Expr . getiter ( value = self . get ( value ) , loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_FOR_ITER ( self , inst , iterator , pair , indval , pred ) : <EOL> """<STR_LIT>""" <EOL> assert inst . offset in self . blocks , "<STR_LIT>" <EOL> val = self . get ( iterator ) <EOL> pairval = ir . Expr . iternext ( value = val , loc = self . loc ) <EOL> self . store ( pairval , pair ) <EOL> iternext = ir . Expr . pair_first ( value = self . get ( pair ) , loc = self . loc ) <EOL> self . store ( iternext , indval ) <EOL> isvalid = ir . Expr . pair_second ( value = self . get ( pair ) , loc = self . loc ) <EOL> self . store ( isvalid , pred ) <EOL> br = ir . Branch ( cond = self . get ( pred ) , truebr = inst . next , <EOL> falsebr = inst . get_jump_target ( ) , <EOL> loc = self . loc ) <EOL> self . current_block . append ( br ) <EOL> def op_BINARY_SUBSCR ( self , inst , target , index , res ) : <EOL> index = self . get ( index ) <EOL> target = self . get ( target ) <EOL> expr = ir . Expr . getitem ( target , index = index , loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_STORE_SUBSCR ( self , inst , target , index , value ) : <EOL> index = self . get ( index ) <EOL> target = self . get ( target ) <EOL> value = self . get ( value ) <EOL> stmt = ir . SetItem ( target = target , index = index , value = value , <EOL> loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_DELETE_SUBSCR ( self , inst , target , index ) : <EOL> index = self . get ( index ) <EOL> target = self . get ( target ) <EOL> stmt = ir . DelItem ( target = target , index = index , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_BUILD_TUPLE ( self , inst , items , res ) : <EOL> expr = ir . Expr . build_tuple ( items = [ self . get ( x ) for x in items ] , <EOL> loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_BUILD_LIST ( self , inst , items , res ) : <EOL> expr = ir . Expr . build_list ( items = [ self . get ( x ) for x in items ] , <EOL> loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_BUILD_SET ( self , inst , items , res ) : <EOL> expr = ir . Expr . build_set ( items = [ self . get ( x ) for x in items ] , <EOL> loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_BUILD_MAP ( self , inst , items , size , res ) : <EOL> items = [ ( self . get ( k ) , self . get ( v ) ) for k , v in items ] <EOL> expr = ir . Expr . build_map ( items = items , size = size , loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_STORE_MAP ( self , inst , dct , key , value ) : <EOL> stmt = ir . StoreMap ( dct = self . get ( dct ) , key = self . get ( key ) , <EOL> value = self . get ( value ) , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_UNARY_NEGATIVE ( self , inst , value , res ) : <EOL> value = self . get ( value ) <EOL> expr = ir . Expr . unary ( '<STR_LIT:->' , value = value , loc = self . loc ) <EOL> return self . store ( expr , res ) <EOL> def op_UNARY_POSITIVE ( self , inst , value , res ) : <EOL> value = self . get ( value ) <EOL> expr = ir . Expr . unary ( '<STR_LIT:+>' , value = value , loc = self . loc ) <EOL> return self . store ( expr , res ) <EOL> def op_UNARY_INVERT ( self , inst , value , res ) : <EOL> value = self . get ( value ) <EOL> expr = ir . Expr . unary ( '<STR_LIT>' , value = value , loc = self . loc ) <EOL> return self . store ( expr , res ) <EOL> def op_UNARY_NOT ( self , inst , value , res ) : <EOL> value = self . get ( value ) <EOL> expr = ir . Expr . unary ( '<STR_LIT>' , value = value , loc = self . loc ) <EOL> return self . store ( expr , res ) <EOL> def _binop ( self , op , lhs , rhs , res ) : <EOL> lhs = self . get ( lhs ) <EOL> rhs = self . get ( rhs ) <EOL> expr = ir . Expr . binop ( op , lhs = lhs , rhs = rhs , loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def _inplace_binop ( self , op , lhs , rhs , res ) : <EOL> lhs = self . get ( lhs ) <EOL> rhs = self . get ( rhs ) <EOL> expr = ir . Expr . inplace_binop ( op + '<STR_LIT:=>' , op , lhs = lhs , rhs = rhs , loc = self . loc ) <EOL> self . store ( expr , res ) <EOL> def op_BINARY_ADD ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:+>' , lhs , rhs , res ) <EOL> def op_BINARY_SUBTRACT ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:->' , lhs , rhs , res ) <EOL> def op_BINARY_MULTIPLY ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:*>' , lhs , rhs , res ) <EOL> def op_BINARY_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_BINARY_TRUE_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:/>' , lhs , rhs , res ) <EOL> def op_BINARY_FLOOR_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_BINARY_MODULO ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:%>' , lhs , rhs , res ) <EOL> def op_BINARY_POWER ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_BINARY_MATRIX_MULTIPLY ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:@>' , lhs , rhs , res ) <EOL> def op_BINARY_LSHIFT ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_BINARY_RSHIFT ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_BINARY_AND ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:&>' , lhs , rhs , res ) <EOL> def op_BINARY_OR ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT:|>' , lhs , rhs , res ) <EOL> def op_BINARY_XOR ( self , inst , lhs , rhs , res ) : <EOL> self . _binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_ADD ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:+>' , lhs , rhs , res ) <EOL> def op_INPLACE_SUBTRACT ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:->' , lhs , rhs , res ) <EOL> def op_INPLACE_MULTIPLY ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:*>' , lhs , rhs , res ) <EOL> def op_INPLACE_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_TRUE_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:/>' , lhs , rhs , res ) <EOL> def op_INPLACE_FLOOR_DIVIDE ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_MODULO ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:%>' , lhs , rhs , res ) <EOL> def op_INPLACE_POWER ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_MATRIX_MULTIPLY ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:@>' , lhs , rhs , res ) <EOL> def op_INPLACE_LSHIFT ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_RSHIFT ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_INPLACE_AND ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:&>' , lhs , rhs , res ) <EOL> def op_INPLACE_OR ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT:|>' , lhs , rhs , res ) <EOL> def op_INPLACE_XOR ( self , inst , lhs , rhs , res ) : <EOL> self . _inplace_binop ( '<STR_LIT>' , lhs , rhs , res ) <EOL> def op_JUMP_ABSOLUTE ( self , inst ) : <EOL> jmp = ir . Jump ( inst . get_jump_target ( ) , loc = self . loc ) <EOL> self . current_block . append ( jmp ) <EOL> def op_JUMP_FORWARD ( self , inst ) : <EOL> jmp = ir . Jump ( inst . get_jump_target ( ) , loc = self . loc ) <EOL> self . current_block . append ( jmp ) <EOL> def op_POP_BLOCK ( self , inst ) : <EOL> self . syntax_blocks . pop ( ) <EOL> def op_RETURN_VALUE ( self , inst , retval , castval ) : <EOL> self . store ( ir . Expr . cast ( self . get ( retval ) , loc = self . loc ) , castval ) <EOL> ret = ir . Return ( self . get ( castval ) , loc = self . loc ) <EOL> self . current_block . append ( ret ) <EOL> def op_COMPARE_OP ( self , inst , lhs , rhs , res ) : <EOL> op = dis . cmp_op [ inst . arg ] <EOL> self . _binop ( op , lhs , rhs , res ) <EOL> def op_BREAK_LOOP ( self , inst ) : <EOL> loop = self . syntax_blocks [ - <NUM_LIT:1> ] <EOL> assert isinstance ( loop , ir . Loop ) <EOL> jmp = ir . Jump ( target = loop . exit , loc = self . loc ) <EOL> self . current_block . append ( jmp ) <EOL> def _op_JUMP_IF ( self , inst , pred , iftrue ) : <EOL> brs = { <EOL> True : inst . get_jump_target ( ) , <EOL> False : inst . next , <EOL> } <EOL> truebr = brs [ iftrue ] <EOL> falsebr = brs [ not iftrue ] <EOL> bra = ir . Branch ( cond = self . get ( pred ) , truebr = truebr , falsebr = falsebr , <EOL> loc = self . loc ) <EOL> self . current_block . append ( bra ) <EOL> def op_JUMP_IF_FALSE ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = False ) <EOL> def op_JUMP_IF_TRUE ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = True ) <EOL> def op_POP_JUMP_IF_FALSE ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = False ) <EOL> def op_POP_JUMP_IF_TRUE ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = True ) <EOL> def op_JUMP_IF_FALSE_OR_POP ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = False ) <EOL> def op_JUMP_IF_TRUE_OR_POP ( self , inst , pred ) : <EOL> self . _op_JUMP_IF ( inst , pred = pred , iftrue = True ) <EOL> def op_RAISE_VARARGS ( self , inst , exc ) : <EOL> if exc is not None : <EOL> exc = self . get ( exc ) <EOL> stmt = ir . Raise ( exception = exc , loc = self . loc ) <EOL> self . current_block . append ( stmt ) <EOL> def op_YIELD_VALUE ( self , inst , value , res ) : <EOL> dct = self . generator_info . yield_points <EOL> index = len ( dct ) + <NUM_LIT:1> <EOL> inst = ir . Yield ( value = self . get ( value ) , index = index , loc = self . loc ) <EOL> yp = YieldPoint ( self . current_block , inst ) <EOL> dct [ index ] = yp <EOL> return self . store ( inst , res ) </s>
