00001 /* 00002 * Copyright (C) 2005 Maarten Keijzer 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of version 2 of the GNU General Public License as 00006 * published by the Free Software Foundation. 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program; if not, write to the Free Software 00015 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00016 */ 00017 00018 #ifndef SYMNODE_H_ 00019 #define SYMNODE_H_ 00020 00021 #include <cassert> 00022 00023 #if __GNUC__ >= 3 00024 #include <backward/hash_map.h> 00025 #elif __GNUC__ < 3 00026 #include <hash_map.h> 00027 using std::hash_map; 00028 #endif 00029 00030 /* Empty 'extra statistics' structure, derive from this to keep other characteristics of nodes */ 00031 struct UniqueNodeStats { virtual ~UniqueNodeStats(){} }; 00032 00033 #include "SymImpl.h" 00034 #include "token.h" 00035 00036 #if __GNUC__ == 4 00037 #define USE_TR1 1 00038 #else 00039 #define USE_TR1 0 00040 #endif 00041 00042 #if USE_TR1 00043 #include <tr1/unordered_map> 00044 typedef std::tr1::unordered_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap; 00045 #else 00046 typedef hash_map<detail::SymKey, detail::SymValue, detail::SymKey::Hash> SymMap; 00047 #endif 00048 00049 typedef SymMap::iterator SymIterator; 00050 00051 /* Sym is the tree, for which all the nodes are stored in a hash table. 00052 * This makes checking for equality O(1) */ 00053 class Sym 00054 { 00055 public: 00056 00057 Sym() : node(dag.end()) {} 00058 explicit Sym(token_t token, const SymVec& args); 00059 explicit Sym(token_t token, const Sym& args); 00060 explicit Sym(token_t var); 00061 00062 explicit Sym(SymIterator it) : node(it) { incref(); } 00063 00064 Sym(const Sym& oth) : node(oth.node) { incref(); } 00065 ~Sym() { decref(); } 00066 00067 const Sym& operator=(const Sym& oth) { 00068 if (oth.node == node) return *this; 00069 decref(); 00070 node = oth.node; 00071 incref(); 00072 return *this; 00073 } 00074 00075 /* Unique Stats are user defined */ 00076 UniqueNodeStats* extra_stats() const { return empty()? 0 : node->second.uniqueNodeStats; } 00077 00078 int hashcode() const { return node->first.get_hash_code(); } //detail::SymKey::Hash hash; return hash(node->first); } 00079 00080 // Friends, need to touch the node 00081 friend struct detail::SymKey::Hash; 00082 friend struct detail::SymKey; 00083 00084 unsigned refcount() const { return empty()? 0: node->second.refcount; } 00085 00086 bool operator==(const Sym& other) const { 00087 return node == other.node; 00088 } 00089 bool operator!=(const Sym& other) const { return !(*this == other); } 00090 00091 bool empty() const { return node == dag.end(); } 00092 00093 /* Support for traversing trees */ 00094 unsigned arity() const { return node->first.arity(); } 00095 token_t token() const { return node->first.token; } 00096 00097 const SymVec& args() const { return node->first.vec(); } 00098 00099 /* size() - depth */ 00100 unsigned size() const { return empty()? 0 : node->second.size; } 00101 unsigned depth() const { return empty()? 0 : node->second.depth; } 00102 00103 SymMap::iterator iterator() const { return node; } 00104 00105 /* Statics accessing some static members */ 00106 static SymMap& get_dag() { return dag; } 00107 00108 /* This function can be set to create some UniqueNodeStats derivative that can contain extra stats for a node, 00109 * it can for instance be used to create ERC's and what not. */ 00110 static void set_factory_function(UniqueNodeStats* (*f)(const Sym&)) { factory=f; } 00111 static void clear_factory_function() { factory = 0; } 00112 00113 static const std::vector<unsigned>& token_refcount() { return token_count; } 00114 00115 unsigned address() const { return reinterpret_cast<unsigned>(&*node); } 00116 00117 private : 00118 00119 // implements getting subtrees 00120 Sym private_get(size_t w) const; 00121 00122 unsigned __unchecked_refcount() const { return node->second.refcount; } 00123 00124 void incref() { 00125 if (!empty()) { 00126 ++(node->second.refcount); 00127 ++token_count[token()]; 00128 } 00129 } 00130 void decref() { 00131 if (!empty()) { 00132 --token_count[token()]; 00133 if (--(node->second.refcount) == 0) { 00134 dag.erase(node); 00135 } 00136 } 00137 } 00138 00139 // The one and only data member, an iterator into the static map below 00140 SymIterator node; 00141 00142 // A static hash_map that contains all live nodes.. 00143 static SymMap dag; 00144 00145 static std::vector<unsigned> token_count; 00146 00147 // Factory function for creating extra node stats, default will be 0 00148 static UniqueNodeStats* (*factory)(const Sym&); 00149 00150 }; 00151 00152 /* Utility hash functor for syms */ 00153 class HashSym { 00154 public: 00155 int operator()(const Sym& sym) const { return sym.hashcode(); } 00156 }; 00157 00158 /* Utility Functions */ 00159 00160 // get_subtree retrieves a subtree by standard ordering (0=root, and then depth first) 00161 Sym get_subtree(const Sym& org, size_t w); 00162 00163 // insert_subtree uses the same ordering as get and inserts the second argument, returning a new tree 00164 Sym insert_subtree(const Sym& org, size_t w, const Sym& nw); 00165 00166 /* Get the successor from the hashtable, no particular purpose other than an interesting way to mutate */ 00167 inline Sym next(const Sym& sym) { 00168 SymIterator it = sym.iterator(); 00169 ++it; 00170 if (it == Sym::get_dag().end()) it = Sym::get_dag().begin(); 00171 return Sym(it); 00172 } 00173 00174 #endif
1.4.7