Sym.h

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

Generated on Thu Oct 19 05:06:42 2006 for EO by  doxygen 1.3.9.1