<s> import inspect <EOL> import disassembler <EOL> class BaseTrace ( object ) : <EOL> def __init__ ( self , ops , asm ) : <EOL> super ( BaseTrace , self ) . __init__ ( ) <EOL> self . asm = asm <EOL> self . sections = [ <EOL> TraceSection ( label , self . split_section ( ops ) ) <EOL> for label , ops in self . split_trace ( ops ) <EOL> ] <EOL> @ classmethod <EOL> def split_trace ( cls , ops ) : <EOL> sections = [ ] <EOL> start_idx = <NUM_LIT:0> <EOL> labels = iter ( [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] ) <EOL> for idx , op in enumerate ( ops ) : <EOL> if op . name == "<STR_LIT:label>" : <EOL> sections . append ( ( next ( labels ) , ops [ start_idx : idx ] ) ) <EOL> start_idx = idx <EOL> sections . append ( ( next ( labels ) , ops [ start_idx : ] ) ) <EOL> return sections <EOL> class PythonTrace ( BaseTrace ) : <EOL> def __init__ ( self , greenkey , ops , asm ) : <EOL> super ( PythonTrace , self ) . __init__ ( ops , asm ) <EOL> self . root_file = greenkey [ <NUM_LIT:0> ] . co_filename <EOL> self . root_function = greenkey [ <NUM_LIT:0> ] . co_name <EOL> @ classmethod <EOL> def split_section ( cls , ops ) : <EOL> chunks = [ ] <EOL> cls . _split_section ( ops , i = <NUM_LIT:0> , call_id = <NUM_LIT:0> , chunks = chunks , dis_cache = { } ) <EOL> return chunks <EOL> @ classmethod <EOL> def _split_section ( cls , ops , i , call_id , chunks , dis_cache ) : <EOL> start_idx = i <EOL> current_line = None <EOL> while i < len ( ops ) : <EOL> op = ops [ i ] <EOL> if op . name == "<STR_LIT>" : <EOL> if op . call_id > call_id : <EOL> chunks . append ( <EOL> ResOpChunk ( ops [ start_idx : i ] ) <EOL> ) <EOL> i = start_idx = cls . _split_section ( ops , i , op . call_id , chunks , dis_cache ) <EOL> elif op . call_id < call_id : <EOL> chunks . append ( <EOL> ResOpChunk ( ops [ start_idx : i ] ) <EOL> ) <EOL> return i <EOL> else : <EOL> if op . pycode not in dis_cache : <EOL> dis_cache [ op . pycode ] = disassembler . dis ( op . pycode ) <EOL> code = dis_cache [ op . pycode ] <EOL> py_op = code . map [ op . bytecode_no ] <EOL> sourcecode , startline = inspect . getsourcelines ( code . co ) <EOL> if current_line is None or py_op . lineno > current_line : <EOL> if start_idx != i : <EOL> chunks . append ( <EOL> ResOpChunk ( ops [ start_idx : i ] ) <EOL> ) <EOL> lines_end = py_op . lineno - startline <EOL> if current_line is None : <EOL> source = sourcecode [ : lines_end + <NUM_LIT:1> ] <EOL> linenos = range ( startline , py_op . lineno + <NUM_LIT:1> ) <EOL> else : <EOL> source = [ sourcecode [ lines_end ] ] <EOL> linenos = [ py_op . lineno ] <EOL> chunks . append ( PythonChunk ( source , linenos ) ) <EOL> current_line = py_op . lineno <EOL> start_idx = i <EOL> i += <NUM_LIT:1> <EOL> if start_idx < len ( ops ) : <EOL> chunks . append ( ResOpChunk ( ops [ start_idx : ] ) ) <EOL> return i <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_python_trace ( self ) <EOL> class TraceSection ( object ) : <EOL> def __init__ ( self , label , chunks ) : <EOL> self . label = label <EOL> self . chunks = chunks <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_trace_section ( self ) <EOL> class BaseChunk ( object ) : <EOL> pass <EOL> class ResOpChunk ( BaseChunk ) : <EOL> def __init__ ( self , ops ) : <EOL> self . ops = ops <EOL> def get_op_names ( self ) : <EOL> return [ op . name for op in self . ops ] <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_resop_chunk ( self ) <EOL> class PythonChunk ( BaseChunk ) : <EOL> def __init__ ( self , sourcelines , linenos ) : <EOL> self . sourcelines = sourcelines <EOL> self . linenos = linenos <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_python_chunk ( self ) </s>
