[cfe-commits] r42290 - in /cfe/trunk/include/clang/Analysis/ADT: ./ PersistentMap.h

Ted Kremenek kremenek at apple.com
Mon Sep 24 21:26:20 PDT 2007


Author: kremenek
Date: Mon Sep 24 23:26:20 2007
New Revision: 42290

URL: http://llvm.org/viewvc/llvm-project?rev=42290&view=rev
Log:
Added PersistentMap, an ADT that implements a map data structure that
is persistent.  Adds/removals to a PersistentMap do not result in
a map being modified, but a new map being created.  This will be useful
for path-sensitive analyses.  

The current implementation mainly makes copies to implement this
functionality.  If the map turns out to be extensively used, this
implementation will be replaced with a more efficient one that uses
data sharing (see comments in PersistentMap.h for more information).

Added:
    cfe/trunk/include/clang/Analysis/ADT/
    cfe/trunk/include/clang/Analysis/ADT/PersistentMap.h

Added: cfe/trunk/include/clang/Analysis/ADT/PersistentMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ADT/PersistentMap.h?rev=42290&view=auto

==============================================================================
--- cfe/trunk/include/clang/Analysis/ADT/PersistentMap.h (added)
+++ cfe/trunk/include/clang/Analysis/ADT/PersistentMap.h Mon Sep 24 23:26:20 2007
@@ -0,0 +1,138 @@
+//===--- PersistentMap.h - Peristent Map Data Structure ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Ted Kremenek and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines PersistentMap, a template class that implements a
+// persistent map.  A persistent map is an immutable data structure that
+// records a mapping from key to values.  "Insertions" and "deletions" 
+// to a persistent map result in the construction of a new map.
+//
+// FIXME: There are efficient ways to implement such data structures.
+//  For example, the persistent red-black tree implementation described
+//  in Okasaki's book "Purely Functional Data Structures."  The current
+//  implementation is inefficient but simple, and will be improved as needed.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PERSISTENT_MAP
+#define LLVM_CLANG_ANALYSIS_PERSISTENT_MAP
+
+#include "clang/Analysis/Support/IntrusiveSPtr.h"
+#include <vector>
+#include <functional>
+
+namespace clang {
+  
+template <typename KeyTy, typename ValTy,
+          typename EqualKey = std::equal_to<KeyTy>,
+          typename EqualVal = std::equal_to<ValTy> >
+class PersistentMap : public RefCounted {
+public:
+  // Smart-pointer typedef.  All instances of PersistentMap should be
+  // access via smart pointers.
+  typedef IntrusiveSPtr<PersistentMap> Ptr;
+  
+  // Typedefs for iterators.
+  typedef std::vector< std::pair<KeyTy,ValTy> >              KeyValuesTy;
+  typedef typename KeyValuesTy::const_iterator               iterator;
+  typedef typename KeyValuesTy::const_iterator               const_iterator;
+  
+  // STL-like interface for traversal/lookup.
+  iterator begin() const { return KeyValues.begin(); }
+  iterator end() const { return KeyValues.end(); }
+  bool empty() const { return size() == 0; }
+  
+  iterator find(const KeyTy& K) const {
+    EqualKey eq;    
+    for (iterator I = begin(), E = end(); I!=E; ++I) { if (eq(*I,K)) return I; }    
+    return end();
+  }    
+
+  // More user-friendly.
+  bool contains(const KeyTy& K) const { return find(K) == end(); }
+  unsigned size() const { return KeyValues.size(); }
+
+  // Creation of an empty map.
+  static Ptr create() { return Ptr(new PersistentMap()); }
+
+  // Addition/Removal of elements to create new maps.
+  Ptr add(const KeyTy& K, const ValTy& V) const {
+    EqualKey eq_key;
+    EqualKey eq_val;
+    
+    unsigned i = 0;
+    for (; i < KeyValues.size(); ++i) {
+      if (eq_key(KeyValues[i].first,K))
+        if (eq_val(KeyValues[i].second,V)) { return Ptr(this); }
+        else break;
+    }
+
+    PersistentMap* M = new PersistentMap(*this);
+    
+    if (i != KeyValues.size()) // Overwrite the old value.
+      M->KeyValues[i].second = V;
+    else // Key-Value not in the map.  Add it.
+      M->KeyValues.push_back(std::make_pair<KeyTy,ValTy>(K,V));
+    
+    return Ptr(M);
+  }
+  
+  Ptr remove(const KeyTy& K) const {
+    unsigned i = 0;
+    EqualKey eq_key;
+      
+    for(; i < KeyValues.size(); ++i)
+      if (eq_key(KeyValues[i].first,K)) break;
+    
+    if (i == KeyValues.size())
+      return Ptr(this);
+
+    PersistentMap* M = new PersistentMap(*this);
+    M->KeyValues[i] = M->KeyValues.back();
+    M->KeyValues.pop_back();
+
+    return Ptr(M);
+  }
+  
+  // Do two maps have the same key-value pairs?
+  bool operator==(PersistentMap& M) {
+    if (&M == this) { return true; }
+    
+    EqualVal eq;
+    
+    for (iterator I = M.begin(), E = M.end(); I!=E; ++I) {
+      iterator X = find(I->first);
+      
+      if (X == end() || !eq(I->second,X->second))
+        return false;
+    }
+    
+    for (iterator I = begin(), E = end(); I!=E; ++I) {
+      iterator X = M.find(I->first);
+      
+      if (X == M.end() || !eq(I->second,X->second))
+        return false;
+    }
+    
+    return true;
+  }
+  
+protected:
+  PersistentMap() {}
+  
+  // Used by "add" and "remove".
+  PersistentMap(const PersistentMap& M) : RefCounted(),KeyValues(M.KeyValues) {}
+  
+  virtual ~PersistentMap() {}
+  
+  KeyValuesTy KeyValues;
+};
+  
+} // end namespace clang
+
+#endif





More information about the cfe-commits mailing list