Inferno  0.2
uniquify_identifiers.cpp
Go to the documentation of this file.
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