<s> '''<STR_LIT>''' <EOL> from . import ast , types , util <EOL> class Specializer ( object ) : <EOL> def __init__ ( self , mod , fun ) : <EOL> self . mod = mod <EOL> self . fun = fun <EOL> self . cfg = fun . flow <EOL> self . track = { } <EOL> def visit ( self , node , type = None ) : <EOL> getattr ( self , node . __class__ . __name__ ) ( node , type ) <EOL> def specialize ( self , node , dst ) : <EOL> if node . type == dst : <EOL> return <EOL> elif node . type == types . anyint ( ) and dst is None : <EOL> node . type = self . mod . type ( '<STR_LIT:int>' ) <EOL> elif node . type == types . anyfloat ( ) and dst is None : <EOL> node . type = self . mod . type ( '<STR_LIT:float>' ) <EOL> elif dst is None : <EOL> return <EOL> elif node . type == types . anyint ( ) and types . unwrap ( dst ) in types . INTS : <EOL> if isinstance ( node , ast . Int ) : <EOL> dst = types . unwrap ( dst ) <EOL> node . type = dst <EOL> if not dst . signed : <EOL> assert int ( node . val ) >= <NUM_LIT:0> <EOL> else : <EOL> assert False , ( node . type , dst ) <EOL> elif node . type == types . anyfloat ( ) and types . unwrap ( dst ) in types . FLOATS : <EOL> if isinstance ( node , ast . Float ) : <EOL> node . type = types . unwrap ( dst ) <EOL> else : <EOL> assert False , ( node . type , dst ) <EOL> elif isinstance ( dst , types . concrete ) : <EOL> ttypes = [ ] <EOL> for i , e in enumerate ( node . type . params ) : <EOL> assert types . compat ( e , dst . params [ i ] ) <EOL> ttypes . append ( dst . params [ i ] ) <EOL> node . type = self . mod . type ( ( '<STR_LIT>' , ttypes ) ) <EOL> elif isinstance ( types . unwrap ( dst ) , types . trait ) : <EOL> if node . type == types . anyint ( ) : <EOL> node . type = self . mod . type ( '<STR_LIT:int>' ) <EOL> elif node . type == types . anyfloat ( ) : <EOL> node . type = self . mod . type ( '<STR_LIT:float>' ) <EOL> else : <EOL> assert False , '<STR_LIT>' % node . type <EOL> else : <EOL> assert False , '<STR_LIT>' % ( node . type , dst ) <EOL> def binspec ( self , node , type ) : <EOL> if types . generic ( node . left . type ) and types . generic ( node . right . type ) : <EOL> self . visit ( node . left ) <EOL> self . visit ( node . right ) <EOL> elif types . generic ( node . left . type ) : <EOL> self . visit ( node . left , node . right . type ) <EOL> self . visit ( node . right ) <EOL> elif types . generic ( node . right . type ) : <EOL> self . visit ( node . right , node . left . type ) <EOL> self . visit ( node . left ) <EOL> def NoneVal ( self , node , type = None ) : <EOL> pass <EOL> def Bool ( self , node , type = None ) : <EOL> pass <EOL> def Int ( self , node , type = None ) : <EOL> self . specialize ( node , type ) <EOL> def Float ( self , node , type = None ) : <EOL> self . specialize ( node , type ) <EOL> def String ( self , node , type = None ) : <EOL> pass <EOL> def Name ( self , node , type = None ) : <EOL> params = [ ] <EOL> if hasattr ( node . type , '<STR_LIT>' ) : <EOL> params = [ types . generic ( t ) for t in node . type . params ] <EOL> if not types . generic ( node . type ) and not any ( params ) : <EOL> return <EOL> else : <EOL> self . specialize ( node , type ) <EOL> def Tuple ( self , node , type = None ) : <EOL> ttypes = [ None ] * len ( node . values ) if type is None else type . params <EOL> for i , e in enumerate ( node . values ) : <EOL> if types . generic ( e . type ) : <EOL> self . specialize ( e , ttypes [ i ] ) <EOL> node . type = self . mod . type ( ( '<STR_LIT>' , ( n . type for n in node . values ) ) ) <EOL> def Init ( self , node , type = None ) : <EOL> pass <EOL> def Not ( self , node , type = None ) : <EOL> self . specialize ( node . value , None ) <EOL> def And ( self , node , type = None ) : <EOL> self . specialize ( node . left , None ) <EOL> self . specialize ( node . right , None ) <EOL> def Or ( self , node , type = None ) : <EOL> self . specialize ( node . left , None ) <EOL> self . specialize ( node . right , None ) <EOL> def Is ( self , node , type ) : <EOL> self . binspec ( node , type ) <EOL> def compare ( self , node , type ) : <EOL> self . binspec ( node , type ) <EOL> def EQ ( self , node , type = None ) : <EOL> self . compare ( node , type ) <EOL> def NE ( self , node , type = None ) : <EOL> self . compare ( node , type ) <EOL> def LT ( self , node , type = None ) : <EOL> self . compare ( node , type ) <EOL> def GT ( self , node , type = None ) : <EOL> self . compare ( node , type ) <EOL> def arith ( self , op , node , type ) : <EOL> self . binspec ( node , type ) <EOL> assert node . left . type == node . right . type <EOL> node . type = node . left . type <EOL> def Add ( self , node , type = None ) : <EOL> self . arith ( '<STR_LIT>' , node , type ) <EOL> def Sub ( self , node , type = None ) : <EOL> self . arith ( '<STR_LIT>' , node , type ) <EOL> def Mod ( self , node , type = None ) : <EOL> self . arith ( '<STR_LIT>' , node , type ) <EOL> def Mul ( self , node , type = None ) : <EOL> self . arith ( '<STR_LIT>' , node , type ) <EOL> def Div ( self , node , type = None ) : <EOL> self . arith ( '<STR_LIT>' , node , type ) <EOL> def bitwise ( self , op , node , type ) : <EOL> self . binspec ( node , type ) <EOL> def BWAnd ( self , node , type = None ) : <EOL> self . bitwise ( '<STR_LIT>' , node , type ) <EOL> def BWOr ( self , node , type = None ) : <EOL> self . bitwise ( '<STR_LIT>' , node , type ) <EOL> def BWXor ( self , node , type = None ) : <EOL> self . bitwise ( '<STR_LIT>' , node , type ) <EOL> def Pass ( self , node , type = None ) : <EOL> pass <EOL> def LPad ( self , node , type = None ) : <EOL> pass <EOL> def Resume ( self , node , type = None ) : <EOL> pass <EOL> def As ( self , node , type = None ) : <EOL> if types . generic ( node . left . type ) : <EOL> self . visit ( node . left , node . type ) <EOL> else : <EOL> self . visit ( node . left ) <EOL> def LoopSetup ( self , node , type = None ) : <EOL> self . visit ( node . loop . source , type ) <EOL> def LoopHeader ( self , node , type = None ) : <EOL> self . visit ( node . lvar , self . track . get ( node . lvar . name ) ) <EOL> def CondBranch ( self , node , type = None ) : <EOL> self . visit ( node . cond , self . mod . type ( '<STR_LIT>' ) ) <EOL> def Assign ( self , node , type = None ) : <EOL> if isinstance ( node . left , ast . Name ) : <EOL> self . visit ( node . right , self . track . get ( node . left . name ) ) <EOL> else : <EOL> self . visit ( node . right , node . left . type ) <EOL> def IAdd ( self , node , type = None ) : <EOL> if isinstance ( node . left , ast . Name ) : <EOL> self . visit ( node . right , self . track . get ( node . left . name ) ) <EOL> else : <EOL> self . visit ( node . right , node . left . type ) <EOL> def Elem ( self , node , type = None ) : <EOL> self . visit ( node . obj ) <EOL> self . visit ( node . key ) <EOL> assert not types . generic ( node . type ) <EOL> def Attrib ( self , node , type = None ) : <EOL> self . visit ( node . obj ) <EOL> assert not types . generic ( node . type ) <EOL> def SetAttr ( self , node , type = None ) : <EOL> self . Attrib ( node , type ) <EOL> def Return ( self , node , type = None ) : <EOL> if node . value is not None : <EOL> self . visit ( node . value , self . fun . rtype ) <EOL> def Yield ( self , node , type = None ) : <EOL> if node . value is not None : <EOL> self . visit ( node . value , self . fun . rtype . params [ <NUM_LIT:0> ] ) <EOL> def Call ( self , node , type = None ) : <EOL> for i , arg in enumerate ( node . args ) : <EOL> if not types . generic ( arg . type ) : <EOL> self . visit ( arg ) <EOL> continue <EOL> self . visit ( arg , node . fun . type . over [ <NUM_LIT:1> ] [ i ] ) <EOL> if not isinstance ( arg , ast . Name ) : <EOL> assert not types . generic ( arg . type ) , arg . type <EOL> def Phi ( self , node , type = None ) : <EOL> self . visit ( node . left [ <NUM_LIT:1> ] , type ) <EOL> self . visit ( node . right [ <NUM_LIT:1> ] , type ) <EOL> if node . left [ <NUM_LIT:1> ] . type == node . right [ <NUM_LIT:1> ] . type : <EOL> node . type = node . left [ <NUM_LIT:1> ] . type <EOL> return <EOL> if node . left [ <NUM_LIT:1> ] . type == self . mod . type ( '<STR_LIT>' ) : <EOL> assert node . type == types . opt ( node . right [ <NUM_LIT:1> ] . type ) <EOL> node . left [ <NUM_LIT:1> ] . type = node . type <EOL> return <EOL> elif node . right [ <NUM_LIT:1> ] . type == self . mod . type ( '<STR_LIT>' ) : <EOL> assert node . type == types . opt ( node . left [ <NUM_LIT:1> ] . type ) <EOL> node . right [ <NUM_LIT:1> ] . type = node . type <EOL> return <EOL> assert False , ( node . left [ <NUM_LIT:1> ] . type , node . right [ <NUM_LIT:1> ] . type ) <EOL> def Branch ( self , node , type = None ) : <EOL> pass <EOL> def Raise ( self , node , type = None ) : <EOL> pass <EOL> def propagate ( self ) : <EOL> for i , bl in util . items ( self . cfg . blocks ) : <EOL> for step in reversed ( bl . steps ) : <EOL> self . visit ( step ) <EOL> def specialize ( mod ) : <EOL> for name , code in mod . code : <EOL> Specializer ( mod , code ) . propagate ( ) </s>
