<s> """<STR_LIT>""" <EOL> import sys <EOL> import itertools <EOL> from pypy . interpreter . astcompiler import ast , consts , misc <EOL> from pypy . tool import stdlib_opcode as ops <EOL> from pypy . interpreter . error import OperationError <EOL> from pypy . rlib . unroll import unrolling_iterable <EOL> def optimize_ast ( space , tree , compile_info ) : <EOL> return tree . mutate_over ( OptimizingVisitor ( space , compile_info ) ) <EOL> CONST_NOT_CONST = - <NUM_LIT:1> <EOL> CONST_FALSE = <NUM_LIT:0> <EOL> CONST_TRUE = <NUM_LIT:1> <EOL> class __extend__ ( ast . AST ) : <EOL> def as_constant_truth ( self , space ) : <EOL> """<STR_LIT>""" <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> def as_constant ( self ) : <EOL> """<STR_LIT>""" <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> def accept_jump_if ( self , gen , condition , target ) : <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> class __extend__ ( ast . expr ) : <EOL> def as_constant_truth ( self , space ) : <EOL> const = self . as_constant ( ) <EOL> if const is None : <EOL> return CONST_NOT_CONST <EOL> return int ( space . is_true ( const ) ) <EOL> def as_constant ( self ) : <EOL> return None <EOL> def accept_jump_if ( self , gen , condition , target ) : <EOL> self . walkabout ( gen ) <EOL> if condition : <EOL> gen . emit_jump ( ops . JUMP_IF_TRUE , target ) <EOL> else : <EOL> gen . emit_jump ( ops . JUMP_IF_FALSE , target ) <EOL> class __extend__ ( ast . Num ) : <EOL> def as_constant ( self ) : <EOL> return self . n <EOL> class __extend__ ( ast . Str ) : <EOL> def as_constant ( self ) : <EOL> return self . s <EOL> class __extend__ ( ast . Const ) : <EOL> def as_constant ( self ) : <EOL> return self . value <EOL> class __extend__ ( ast . UnaryOp ) : <EOL> def accept_jump_if ( self , gen , condition , target ) : <EOL> if self . op == ast . Not : <EOL> self . operand . accept_jump_if ( gen , not condition , target ) <EOL> else : <EOL> ast . expr . accept_jump_if ( self , gen , condition , target ) <EOL> class __extend__ ( ast . BoolOp ) : <EOL> def _accept_jump_if_any_is ( self , gen , condition , target ) : <EOL> self . values [ <NUM_LIT:0> ] . accept_jump_if ( gen , condition , target ) <EOL> for i in range ( <NUM_LIT:1> , len ( self . values ) ) : <EOL> gen . emit_op ( ops . POP_TOP ) <EOL> self . values [ i ] . accept_jump_if ( gen , condition , target ) <EOL> def accept_jump_if ( self , gen , condition , target ) : <EOL> if condition and self . op == ast . And or ( not condition and self . op == ast . Or ) : <EOL> end = gen . new_block ( ) <EOL> self . _accept_jump_if_any_is ( gen , not condition , end ) <EOL> gen . emit_jump ( ops . JUMP_FORWARD , target ) <EOL> gen . use_next_block ( end ) <EOL> else : <EOL> self . _accept_jump_if_any_is ( gen , condition , target ) <EOL> def _binary_fold ( name ) : <EOL> def do_fold ( space , left , right ) : <EOL> return getattr ( space , name ) ( left , right ) <EOL> return do_fold <EOL> def _unary_fold ( name ) : <EOL> def do_fold ( space , operand ) : <EOL> return getattr ( space , name ) ( operand ) <EOL> return do_fold <EOL> def _fold_pow ( space , left , right ) : <EOL> return space . pow ( left , right , space . w_None ) <EOL> def _fold_not ( space , operand ) : <EOL> return space . wrap ( not space . is_true ( operand ) ) <EOL> binary_folders = { <EOL> ast . Add : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . Sub : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . Mult : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . Div : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . FloorDiv : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . Mod : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . Pow : _fold_pow , <EOL> ast . LShift : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . RShift : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . BitOr : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . BitXor : _binary_fold ( "<STR_LIT>" ) , <EOL> ast . BitAnd : _binary_fold ( "<STR_LIT>" ) <EOL> } <EOL> unrolling_binary_folders = unrolling_iterable ( binary_folders . items ( ) ) <EOL> unary_folders = { <EOL> ast . Not : _fold_not , <EOL> ast . USub : _unary_fold ( "<STR_LIT>" ) , <EOL> ast . UAdd : _unary_fold ( "<STR_LIT>" ) , <EOL> ast . Invert : _unary_fold ( "<STR_LIT>" ) <EOL> } <EOL> unrolling_unary_folders = unrolling_iterable ( unary_folders . items ( ) ) <EOL> for folder in itertools . chain ( binary_folders . itervalues ( ) , <EOL> unary_folders . itervalues ( ) ) : <EOL> folder . _always_inline_ = True <EOL> del folder <EOL> opposite_compare_operations = misc . dict_to_switch ( { <EOL> ast . Is : ast . IsNot , <EOL> ast . IsNot : ast . Is , <EOL> ast . In : ast . NotIn , <EOL> ast . NotIn : ast . In <EOL> } ) <EOL> class OptimizingVisitor ( ast . ASTVisitor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , space , compile_info ) : <EOL> self . space = space <EOL> self . compile_info = compile_info <EOL> def default_visitor ( self , node ) : <EOL> return node <EOL> def visit_BinOp ( self , binop ) : <EOL> left = binop . left . as_constant ( ) <EOL> if left is not None : <EOL> right = binop . right . as_constant ( ) <EOL> if right is not None : <EOL> op = binop . op <EOL> if op == ast . Div and not self . compile_info . flags & consts . CO_FUTURE_DIVISION : <EOL> return binop <EOL> try : <EOL> for op_kind , folder in unrolling_binary_folders : <EOL> if op_kind == op : <EOL> w_const = folder ( self . space , left , right ) <EOL> break <EOL> else : <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> except OperationError : <EOL> pass <EOL> else : <EOL> try : <EOL> w_len = self . space . len ( w_const ) <EOL> except OperationError : <EOL> pass <EOL> else : <EOL> if self . space . int_w ( w_len ) > <NUM_LIT:20> : <EOL> return binop <EOL> return ast . Const ( w_const , binop . lineno , binop . col_offset ) <EOL> return binop <EOL> def visit_UnaryOp ( self , unary ) : <EOL> w_operand = unary . operand . as_constant ( ) <EOL> op = unary . op <EOL> if w_operand is not None : <EOL> try : <EOL> for op_kind , folder in unrolling_unary_folders : <EOL> if op_kind == op : <EOL> w_const = folder ( self . space , w_operand ) <EOL> break <EOL> else : <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> w_minint = self . space . wrap ( - sys . maxint - <NUM_LIT:1> ) <EOL> if self . space . eq_w ( w_minint , w_const ) : <EOL> w_const = w_minint <EOL> except OperationError : <EOL> pass <EOL> else : <EOL> return ast . Const ( w_const , unary . lineno , unary . col_offset ) <EOL> elif op == ast . Not : <EOL> compare = unary . operand <EOL> if isinstance ( compare , ast . Compare ) and len ( compare . ops ) == <NUM_LIT:1> : <EOL> cmp_op = compare . ops [ <NUM_LIT:0> ] <EOL> try : <EOL> opposite = opposite_compare_operations ( cmp_op ) <EOL> except KeyError : <EOL> pass <EOL> else : <EOL> compare . ops [ <NUM_LIT:0> ] = opposite <EOL> return compare <EOL> return unary <EOL> def visit_BoolOp ( self , bop ) : <EOL> values = bop . values <EOL> we_are_and = bop . op == ast . And <EOL> i = <NUM_LIT:0> <EOL> while i < len ( values ) - <NUM_LIT:1> : <EOL> truth = values [ i ] . as_constant_truth ( self . space ) <EOL> if truth != CONST_NOT_CONST : <EOL> if ( truth != CONST_TRUE ) == we_are_and : <EOL> del values [ i + <NUM_LIT:1> : ] <EOL> break <EOL> else : <EOL> del values [ i ] <EOL> else : <EOL> i += <NUM_LIT:1> <EOL> if len ( values ) == <NUM_LIT:1> : <EOL> return values [ <NUM_LIT:0> ] <EOL> return bop <EOL> def visit_Repr ( self , rep ) : <EOL> w_const = rep . value . as_constant ( ) <EOL> if w_const is not None : <EOL> w_repr = self . space . repr ( w_const ) <EOL> return ast . Const ( w_repr , rep . lineno , rep . col_offset ) <EOL> return rep <EOL> def visit_Name ( self , name ) : <EOL> if name . id == "<STR_LIT:None>" : <EOL> assert name . ctx == ast . Load <EOL> return ast . Const ( self . space . w_None , name . lineno , name . col_offset ) <EOL> return name <EOL> def visit_Tuple ( self , tup ) : <EOL> """<STR_LIT>""" <EOL> if tup . elts : <EOL> consts_w = [ None ] * len ( tup . elts ) <EOL> for i in range ( len ( tup . elts ) ) : <EOL> node = tup . elts [ i ] <EOL> w_const = node . as_constant ( ) <EOL> if w_const is None : <EOL> return tup <EOL> consts_w [ i ] = w_const <EOL> else : <EOL> consts_w = [ ] <EOL> w_consts = self . space . newtuple ( consts_w ) <EOL> return ast . Const ( w_consts , tup . lineno , tup . col_offset ) </s>
