<s> import operator <EOL> from collections import deque <EOL> import ast <EOL> from funcy import joining <EOL> _UNKNOWN = object ( ) <EOL> class ValueInfo ( object ) : <EOL> def __init__ ( self , value = _UNKNOWN , typ = _UNKNOWN ) : <EOL> self . value = value <EOL> self . typ = typ <EOL> self . rels = [ ] <EOL> def __str__ ( self ) : <EOL> @ joining ( '<STR_LIT>' ) <EOL> def _str ( ) : <EOL> if self . value is not _UNKNOWN : <EOL> yield self . value <EOL> if self . typ is not _UNKNOWN : <EOL> yield '<STR_LIT::>' + str ( self . typ ) <EOL> if self . rels : <EOL> yield '<STR_LIT>' + '<STR_LIT:U+002C>' . join ( '<STR_LIT>' % rel for rel in self . rels ) <EOL> return _str ( ) or '<STR_LIT:?>' <EOL> def add_rel ( self , op , value ) : <EOL> self . rels . append ( ( op , value ) ) <EOL> def __add__ ( self , other ) : <EOL> if isinstance ( self . value , ( int , long , float ) ) and isinstance ( other . value , ( int , long , float ) ) : <EOL> return ValueInfo ( self . value + other . value ) <EOL> else : <EOL> return ValueInfo ( ) <EOL> class Env ( object ) : <EOL> def __init__ ( self , scope ) : <EOL> self . scope = scope <EOL> self . locals = { } <EOL> import astor <EOL> class Inferer ( astor . ExplicitNodeVisitor ) : <EOL> def __init__ ( self ) : <EOL> self . envs = deque ( ) <EOL> @ property <EOL> def env ( self ) : <EOL> if self . envs : <EOL> return self . envs [ - <NUM_LIT:1> ] <EOL> else : <EOL> return None <EOL> def push_env ( self , node ) : <EOL> self . envs . append ( Env ( node . scope ) ) <EOL> def pop_env ( self ) : <EOL> self . envs . pop ( ) <EOL> def visit_Module ( self , node ) : <EOL> self . push_env ( node ) <EOL> self . generic_visit ( node ) <EOL> self . pop_env ( ) <EOL> def visit_Assign ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> if len ( node . targets ) == <NUM_LIT:1> : <EOL> target = node . targets [ <NUM_LIT:0> ] <EOL> assert isinstance ( target , ast . Name ) <EOL> target . val = node . value . val <EOL> self . env . locals [ target . id ] = target . val <EOL> else : <EOL> for t in node . targets : <EOL> t . val = ValueInfo ( ) <EOL> def visit_Name ( self , node ) : <EOL> node . val = self . env . locals . get ( node . id ) or ValueInfo ( ) <EOL> def visit_Expr ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> def visit_BinOp ( self , node ) : <EOL> self . visit ( node . left ) <EOL> self . visit ( node . right ) <EOL> node . left . val . add_rel ( node . op . __class__ . __name__ , node . right . val ) <EOL> node . val = OPS [ node . op . __class__ ] ( node . left . val , node . right . val ) <EOL> def visit_Num ( self , node ) : <EOL> node . val = ValueInfo ( node . n ) <EOL> def visit_Str ( self , node ) : <EOL> node . val = ValueInfo ( node . s ) <EOL> OPS = { <EOL> ast . Add : operator . __add__ , <EOL> ast . Sub : operator . __sub__ , <EOL> } </s>
