Changeset 184557e for src/Common


Ignore:
Timestamp:
Jul 6, 2018, 5:10:14 PM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
new-env
Children:
5c14030
Parents:
b21c77a
Message:

First draft of persistent-hash-based TypeEnvironment?

Location:
src/Common
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/Common/PersistentDisjointSet.h

    rb21c77a r184557e  
    128128                }
    129129        }
     130
     131        /// Non-initializing constructor; should call init() before use
     132        PersistentDisjointSet( Mode m ) : data(), mode(m) {}
    130133
    131134        PersistentDisjointSet( Mode m, Base&& b ) : data(), mode(m) {
     
    291294        size_type count(Elm i) const { return rerooted().count( i ); }
    292295
    293         /// Finds root for element i, assertfs i is present
     296        /// Finds root for element i, undefined behaviour if i is not present
    294297        Elm find(Elm i) const {
    295298                const Base& self = rerooted();
     
    375378        }
    376379
    377         /// Reports all members of a class to `out`; none if i does not exist in map
    378         template<typename OutputIterator>
    379         void find_class(Elm i, OutputIterator&& out) const {
     380private:
     381        /// Removes the children of the tree rooted at `root` as `root_node`, returning a new
     382        /// uninitialized node and editing `next_edit` to point toward this new node.
     383        static Self* remove_children(Elm root, Node& root_node, Base& base_map, Self* next_edit) {
     384                // Invariant: root.next is *always* a pointer to a leaf of the most-recently added
     385                // subtree.
     386                //
     387                // Proof: By induction on height:
     388                // * height == 0: root.next == root, trivially true
     389                // * added.height < root.height: true by ind. hyp.
     390                // * added.height == root.height: no node may have a child the same height, ergo
     391                //   property holds for added, therefore root.
     392                //
     393                // Corollary: next of most-recently-added subtree root is previously added subtree
     394
     395                // remove all subtrees
     396                while ( root != root_node.next ) {
     397                        // find added child
     398                        auto it = base_map.find( root_node.next );
     399                        while ( it->second.parent != root ) it = base_map.find( it->second.parent );
     400                        Elm added = it->first;
     401                        Node& added_node = it->second;
     402
     403                        // unlink subtree and set up previous map as ADDTO new map
     404                        std::swap( root_node.next, added_node.next );
     405                        Self* new_edit = new Self{ BASE };
     406                        next_edit->init<AddTo>( new_edit, root, added, false );  // assume unchanged root height
     407                        next_edit->mode = ADDTO;
     408
     409                        // remove subtree children from map
     410                        next_edit = remove_children( added, added_node, base_map, new_edit );
     411
     412                        // remove subtree root from map and set up previous map as ADD to new map
     413                        base_map.erase( added );
     414                        new_edit = new Self{ BASE };
     415                        next_edit->init<Add>( new_edit, added );
     416                        next_edit->mode = ADD;
     417
     418                        next_edit = new_edit;
     419                }
     420
     421                return next_edit;
     422        }
     423
     424public:
     425        /// Removes all elements of a class given by its root; returns updated map.
     426        Self* remove_class(Elm root) {
     427                reroot();
     428
     429                // remove map from self
     430                Base base_map = take_as<Base>();
     431                reset_as_base();
     432
     433                // find root node and remove children
     434                auto it = base_map.find( root );
     435                assertf(it != base_map.end(), "root node must exist in map");
     436                Self* next_edit = remove_children( root, it->second, base_map, this);
     437
     438                // root is alone in class, remove from map
     439                base_map.erase( root );
     440                Self* ret = new Self{ BASE, std::move(base_map) };
     441                // reinitialize previous node as ADD to new map
     442                next_edit->init<Add>( ret, root );
     443                next_edit->mode = ADD;
     444
     445                return ret;
     446        }
     447
     448        /// Applies `f` to all members of a class containing `i` (undefined behaviour if not present).
     449        /// `f` should take members by const reference or copy
     450        template<typename F>
     451        void apply_to_class(Elm i, F&& f) const {
    380452                const Base& self = rerooted();
    381 
    382                 // skip empty classes
    383                 if ( ! self.count( i ) ) return;
    384453
    385454                Elm crnt = i;
    386455                do {
    387                         *out++ = crnt;
     456                        f( crnt );
    388457                        auto it = self.find( crnt );
    389458                        assertf( it != self.end(), "current node must exist in base" );
  • src/Common/PersistentMap.h

    rb21c77a r184557e  
    114114        }
    115115
     116        /// Non-initializing constructor; should call init() before use
     117        PersistentMap( Mode m ) : data(), mode(m) {}
     118
    116119        PersistentMap( Mode m, Base&& b ) : data(), mode(m) {
    117120                assertf(m == BASE, "invalid mode");
     
    420423                }
    421424        }
     425
     426        /// Applies the function `f` to all elements of the map, returning a pointer to the updated map.
     427        /// `f` should take two parameters, `const Key&` and `Val&`, returning option<Val> filled with
     428        /// the previous value if mutated, an empty option<Val> otherwise.
     429        /// NOTE: when porting to C++17, this should work fine with std::optional
     430        template<typename F>
     431        Self* apply_to_all(F&& f) {
     432                // reset to root and exit early if no change
     433                if ( rerooted().empty() ) return this;
     434
     435                // remove map from self
     436                Base base_map = take_as<Base>();
     437                reset_as_base();
     438
     439                // apply all edits
     440                Self* next_edit = this;
     441                for ( auto& entry : base_map ) {
     442                        auto res = f( entry.first, entry.second );
     443                        if ( res ) {
     444                                // entry has been mutated; reset next_edit node as mutation
     445                                Self* new_node = new Self{ BASE };
     446                                next_edit->init<Ins>( new_node, entry.first, *std::move(res) );
     447                                next_edit->mode = UPD;
     448                                next_edit = new_node;
     449                        }
     450                }
     451
     452                // set map into final node and return
     453                next_edit->init<Base>( std::move(base_map) );
     454                return next_edit;
     455        }
     456
     457        /// Applies the function `f` to all elements of the map.
     458        /// `f` should take two parameters, `const Key&` and `const Val&`.
     459        template<typename F>
     460        void apply_to_all(F&& f) const {
     461                for ( const auto& entry : rerooted() ) { f( entry.first, entry.second ); }
     462        }
    422463};
    423464
Note: See TracChangeset for help on using the changeset viewer.