Inferno
0.2
|
00001 #include "uniquify_identifiers.hpp" 00002 #include "helpers/walk.hpp" 00003 #include "tree/misc.hpp" 00004 00005 using namespace CPPTree; 00006 00007 // TODO lose the underscore 00008 #define UID_FORMAT "%s_%u" 00009 00010 //TODO Apparently labels do not scope in subblocks like types and instances, but instead are 00011 // always function scope (opbvious when you think about it) so uniquify them accordingly. 00012 00013 string VisibleIdentifiers::MakeUniqueName( string b, unsigned n ) // note static 00014 { 00015 if( n>0 ) 00016 return SSPrintf( UID_FORMAT, b.c_str(), n ); 00017 else 00018 return b; // n==0 means no change to identifier name; the "_0" is implied in this case 00019 } 00020 00021 00022 void VisibleIdentifiers::SplitName( TreePtr<SpecificIdentifier> i, string *b, unsigned *n ) // note static 00023 { 00024 char cb[256]; // hope that's big enough! 00025 string original_name = i->GetName(); 00026 int c = sscanf( original_name.c_str(), UID_FORMAT, cb, n ); // TODO maybe add %s at the end to catch junk after the number 00027 if( c == 2 && *n > 0 ) // note that x_0 is *not* in standard form, so it become eg x_0_1 etc 00028 { 00029 *b = string(cb); 00030 } 00031 else // no match to standard form 00032 { 00033 *n = 0; 00034 *b = original_name; 00035 } 00036 } 00037 00038 00039 string VisibleIdentifiers::AddIdentifierNumber( NameUsage &nu, TreePtr<SpecificIdentifier> i, string b, unsigned n ) 00040 { 00041 // Uniqueify the number n, by incrementing it until there are no conflicts 00042 bool tryagain; 00043 do 00044 { 00045 // See if the number n is already used 00046 tryagain = false; 00047 FOREACH( unsigned u, nu ) 00048 if( u == n ) 00049 { 00050 tryagain = true; 00051 break; 00052 } 00053 00054 // if so, try another number 00055 if( tryagain ) 00056 n++; 00057 00058 } while(tryagain); 00059 00060 // Store the number 00061 nu.insert( n ); 00062 00063 // Return the name that the new identifier should take 00064 return MakeUniqueName( b, n ); 00065 } 00066 00067 00068 string VisibleIdentifiers::AddIdentifier( TreePtr<SpecificIdentifier> i ) 00069 { 00070 // Get canonical form of identifier name 00071 string b; 00072 unsigned n; 00073 SplitName( i, &b, &n ); 00074 00075 // Do we have the base name already? If so, add this new instance 00076 FOREACH( NameUsagePair &p, name_usages ) 00077 if( b == p.first ) 00078 return AddIdentifierNumber( p.second, i, b, n ); 00079 00080 // Otherwise start a new record for this base name. 00081 NameUsage nu; 00082 string nn = AddIdentifierNumber( nu, i, b, n ); 00083 name_usages.insert( NameUsagePair( b, nu ) ); 00084 return nn; 00085 } 00086 00087 00088 void UniquifyIdentifiers::UniquifyScope( TreePtr<Node> root, VisibleIdentifiers v ) 00089 { 00090 bool func = false; 00091 if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>(root) ) 00092 func = !!dynamic_pointer_cast<Callable>(i->type); 00093 00094 if(func) 00095 { 00096 // At function level just do everything together - this is the safe option, 00097 // even with function inside functions. Required for Labels, which are always 00098 // whole function scope 00099 Walk t( root ); 00100 FOREACH( TreePtr<Node> p, t ) 00101 { 00102 if( TreePtr<Declaration> d = dynamic_pointer_cast<Declaration>(p) ) 00103 if( TreePtr<Identifier> i = GetIdentifierOfDeclaration(d) ) 00104 if( TreePtr<SpecificIdentifier> si = dynamic_pointer_cast<SpecificIdentifier>(i) ) 00105 { 00106 string nn = v.AddIdentifier( si ); 00107 insert( IdentifierNamePair( si, nn ) ); 00108 } 00109 } 00110 } 00111 else 00112 { 00113 // Above function level (top level, classes etc), 00114 // look for declarations in the current scope (directly, not in sub scopes). 00115 FlattenNode t( root ); 00116 FOREACH( TreePtr<Node> p, t ) 00117 { 00118 if( TreePtr<Declaration> d = dynamic_pointer_cast<Declaration>(p) ) 00119 if( TreePtr<Identifier> i = GetIdentifierOfDeclaration(d) ) 00120 if( TreePtr<SpecificIdentifier> si = dynamic_pointer_cast<SpecificIdentifier>(i) ) 00121 { 00122 string nn = v.AddIdentifier( si ); 00123 insert( IdentifierNamePair( si, nn ) ); 00124 } 00125 } 00126 00127 // Recurse, to find sub-scopes. Pass v by value so our copy remains the same. 00128 // This means names must be local. But we will rename more conservatively. 00129 FOREACH( TreePtr<Node> p, t ) 00130 UniquifyScope( p, v ); 00131 } 00132 } 00133 00134