<s> '''<STR_LIT>''' <EOL> from . import ast , blocks , types , util <EOL> class Free ( util . AttribRepr ) : <EOL> fields = '<STR_LIT:value>' , <EOL> def __init__ ( self , value ) : <EOL> self . value = value <EOL> def destructify ( mod , code ) : <EOL> returns , reassign , left = { } , [ ] , { } <EOL> for i , bl in util . items ( code . flow . blocks ) : <EOL> if bl . returns : <EOL> returns [ i ] , q = set ( ) , { i } <EOL> while q : <EOL> cur = q . pop ( ) <EOL> returns [ i ] . add ( cur ) <EOL> for p in code . flow . blocks [ cur ] . preds : <EOL> if p . id in returns [ i ] or p . id in q : <EOL> continue <EOL> q . add ( p . id ) <EOL> for var , data in util . items ( code . flow . vars ) : <EOL> if bl . id not in data . get ( '<STR_LIT>' , { } ) : <EOL> continue <EOL> assigns = sorted ( data [ '<STR_LIT>' ] [ bl . id ] ) <EOL> for idx , sid in enumerate ( assigns ) : <EOL> step = bl . steps [ sid ] <EOL> if isinstance ( step , blocks . LoopHeader ) : <EOL> type = step . lvar . type <EOL> else : <EOL> type = step . right . type <EOL> if not isinstance ( type , types . owner ) : <EOL> continue <EOL> if code . flow . origins ( var , ( bl . id , sid ) ) - { None } : <EOL> reassign . append ( ( var , i , sid , type ) ) <EOL> continue <EOL> if var in bl . escapes : <EOL> continue <EOL> left . setdefault ( var , ( type , set ( ) ) ) [ <NUM_LIT:1> ] . add ( i ) <EOL> for sid , step in enumerate ( bl . steps ) : <EOL> if not isinstance ( step , ast . Assign ) : <EOL> continue <EOL> if isinstance ( step . right , blocks . Phi ) : <EOL> if isinstance ( step . right . left [ <NUM_LIT:1> ] . type , types . owner ) : <EOL> left . pop ( step . right . left [ <NUM_LIT:1> ] . name , None ) <EOL> if isinstance ( step . right . right [ <NUM_LIT:1> ] . type , types . owner ) : <EOL> left . pop ( step . right . right [ <NUM_LIT:1> ] . name , None ) <EOL> if code . irname == '<STR_LIT>' and code . args : <EOL> left [ '<STR_LIT:args>' ] = mod . type ( '<STR_LIT>' ) , { None } <EOL> for name , bid , sid , type in reassign : <EOL> node = ast . Name ( name , None ) <EOL> node . type = type <EOL> code . flow . blocks [ bid ] . steps . insert ( sid , Free ( node ) ) <EOL> for name , ( type , abls ) in sorted ( util . items ( left ) ) : <EOL> for rbli , reachable in sorted ( util . items ( returns ) ) : <EOL> if not ( abls & reachable ) : <EOL> continue <EOL> node = ast . Name ( name , None ) <EOL> node . type = type <EOL> rbl = code . flow . blocks [ rbli ] <EOL> rbl . steps . insert ( - <NUM_LIT:1> , Free ( node ) ) <EOL> def destruct ( mod ) : <EOL> for name , code in mod . code : <EOL> destructify ( mod , code ) </s>
