Browse Source

cmMakefile: Decouple the container of cmDefinitions from scoping logic.

Maintain a Parent tree node for writing to in RaiseScope.
Stephen Kelly 10 years ago
parent
commit
0f070dd3e1
1 changed files with 56 additions and 24 deletions
  1. 56 24
      Source/cmMakefile.cxx

+ 56 - 24
Source/cmMakefile.cxx

@@ -47,73 +47,105 @@
 class cmMakefile::Internals
 {
 public:
+
+  enum ScopeType
+  {
+    BaseScope,
+    MacroScope,
+    FunctionScope,
+    VariableScope
+  };
+
+  struct VarScope
+  {
+    ScopeType Type;
+    cmLinkedTree<cmDefinitions>::iterator Vars;
+    cmLinkedTree<cmDefinitions>::iterator ParentScope;
+  };
+
   cmLinkedTree<cmDefinitions> VarTree;
-  cmLinkedTree<cmDefinitions>::iterator VarTreeIter;
+  cmLinkedTree<VarScope> VarScopes;
+  cmLinkedTree<VarScope>::iterator VarScopeIter;
   bool IsSourceFileTryCompile;
 
-  void PushDefinitions()
+  void PushDefinitions(ScopeType scope)
   {
-    assert(this->VarTreeIter.IsValid());
-    this->VarTreeIter = this->VarTree.Extend(this->VarTreeIter);
+    assert(this->VarScopeIter.IsValid());
+    assert(this->VarScopeIter->Vars.IsValid());
+    cmLinkedTree<cmDefinitions>::iterator origin =
+        this->VarScopeIter->Vars;
+    cmLinkedTree<cmDefinitions>::iterator parentScope =
+//         this->VarTree.Extend(origin);
+        origin;
+    this->VarScopeIter->Vars = parentScope;
+    this->VarScopeIter = this->VarScopes.Extend(this->VarScopeIter);
+    this->VarScopeIter->ParentScope = parentScope;
+    this->VarScopeIter->Vars = this->VarTree.Extend(origin);
+    this->VarScopeIter->Type = scope;
   }
 
   void InitializeVarScope()
   {
-    this->VarTreeIter = this->VarTree.Root();
-    this->PushDefinitions();
+    assert(!this->VarScopeIter.IsValid());
+    this->VarScopeIter = this->VarScopes.Extend(this->VarScopes.Root());
+    this->VarScopeIter->Vars = this->VarTree.Extend(this->VarTree.Root());
+    this->VarScopeIter->ParentScope = this->VarTree.Root();
+    this->VarScopeIter->Type = BaseScope;
   }
 
   void InitializeDefinitions(cmMakefile* parent)
   {
-    *this->VarTreeIter =
-        cmDefinitions::MakeClosure(parent->Internal->VarTreeIter,
+    assert(this->VarScopeIter.IsValid());
+    assert(this->VarScopeIter->Vars.IsValid());
+    *this->VarScopeIter->Vars =
+        cmDefinitions::MakeClosure(parent->Internal->VarScopeIter->Vars,
                                    parent->Internal->VarTree.Root());
   }
 
   const char* GetDefinition(std::string const& name)
   {
-    assert(this->VarTreeIter != this->VarTree.Root());
+    assert(this->VarScopeIter.IsValid());
+    assert(this->VarScopeIter->Vars.IsValid());
     return cmDefinitions::Get(name,
-                              this->VarTreeIter, this->VarTree.Root());
+                              this->VarScopeIter->Vars, this->VarTree.Root());
   }
 
   bool IsInitialized(std::string const& name)
   {
     return cmDefinitions::HasKey(name,
-                                 this->VarTreeIter, this->VarTree.Root());
+                              this->VarScopeIter->Vars, this->VarTree.Root());
   }
 
   void SetDefinition(std::string const& name, std::string const& value)
   {
-    this->VarTreeIter->Set(name, value.c_str());
+    this->VarScopeIter->Vars->Set(name, value.c_str());
   }
 
   void RemoveDefinition(std::string const& name)
   {
-    this->VarTreeIter->Set(name, 0);
+    this->VarScopeIter->Vars->Set(name, 0);
   }
 
   std::vector<std::string> UnusedKeys() const
   {
-    return this->VarTreeIter->UnusedKeys();
+    return this->VarScopeIter->Vars->UnusedKeys();
   }
 
   std::vector<std::string> ClosureKeys() const
   {
-    return cmDefinitions::ClosureKeys(this->VarTreeIter, this->VarTree.Root());
+    return cmDefinitions::ClosureKeys(this->VarScopeIter->Vars,
+                                      this->VarTree.Root());
   }
 
   void PopDefinitions()
   {
-    ++this->VarTreeIter;
+    ++this->VarScopeIter;
   }
 
   bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf)
   {
-    cmLinkedTree<cmDefinitions>::iterator it = this->VarTreeIter;
-    assert(it != this->VarTree.Root());
-    ++it;
-    if(it == this->VarTree.Root())
+    assert(this->VarScopeIter->Vars != this->VarTree.Root());
+    if(this->VarScopeIter->ParentScope == this->VarTree.Root())
       {
       cmLocalGenerator* plg = mf->LocalGenerator->GetParent();
       if(!plg)
@@ -135,10 +167,10 @@ public:
       return true;
       }
     // First localize the definition in the current scope.
-    cmDefinitions::Raise(var, this->VarTreeIter, this->VarTree.Root());
+    cmDefinitions::Raise(var, this->VarScopeIter->Vars, this->VarTree.Root());
 
     // Now update the definition in the parent scope.
-    it->Set(var, varDef);
+    this->VarScopeIter->ParentScope->Set(var, varDef);
     return true;
   }
 };
@@ -1642,7 +1674,7 @@ void cmMakefile::PushFunctionScope(std::string const& fileName,
         fileName);
   assert(this->StateSnapshot.IsValid());
 
-  this->Internal->PushDefinitions();
+  this->Internal->PushDefinitions(Internals::FunctionScope);
 
   this->PushLoopBlockBarrier();
 
@@ -4430,7 +4462,7 @@ std::string cmMakefile::FormatListFileStack() const
 
 void cmMakefile::PushScope()
 {
-  this->Internal->PushDefinitions();
+  this->Internal->PushDefinitions(Internals::VariableScope);
 
   this->PushLoopBlockBarrier();