From 086c4497c53016ba29552814afb694885c8da67d Mon Sep 17 00:00:00 2001
From: Petr Rockai <me@mornfall.net>
Date: Tue, 25 Jun 2019 10:24:40 +0000
Subject: [PATCH] MC: Make machine::compute parametric with respect to the
 weaver tasks it emits.

---
 divine/mc/machine.hpp   | 170 +++++++++++++++++++++-------------------
 divine/mc/t-machine.hpp |   6 +-
 2 files changed, 93 insertions(+), 83 deletions(-)

diff --git a/divine/mc/machine.hpp b/divine/mc/machine.hpp
index 488c9abe7..57abf0ae9 100644
--- a/divine/mc/machine.hpp
+++ b/divine/mc/machine.hpp
@@ -88,45 +88,37 @@ namespace divine::mc
     /* TODO get rid of the debug */
     using context = brq::compose_stack< ctx_choice, ctx_assume, ctx::legacy, ctx::fault, ctx::debug,
                                         ctx::with_tracking, ctx::common< vm::Program, vm::CowHeap > >;
+}
 
-    using StateTQ = GraphTQ< State, Label >;
+namespace divine::mc::task
+{
+    using Boot     = Start;
 
-    struct Origin
+    struct origin
     {
         Snapshot snap;
         HT ht_loop;
-        explicit Origin( Snapshot s ) : snap( s ) {}
+        explicit origin( Snapshot s ) : snap( s ) {}
     };
 
-    struct Task
+    struct Compute
     {
-        using GraphTs = StateTQ::Tasks;
-        using Boot = GraphTs::Start;
-        using Schedule = GraphTs::Expand;
-
-        struct Compute
-        {
-            Snapshot snap;
-            Origin origin;
-            vm::State state;
-            Compute( Snapshot snap, Origin orig, vm::State state )
-                : snap( snap ), origin( orig ), state( state )
-            {}
-        };
-
-        struct Choose : Compute
-        {
-            int choice, total;
-            Choose( Snapshot snap, Origin orig, vm::State state, int c, int t )
-                : Compute( snap, orig, state ), choice( c ), total( t )
-            {}
-        };
-
-        using TQ = StateTQ::Extend< Task, Choose >;
-        using Weaver = mc::Weaver< TQ >;
+        Snapshot snap;
+        task::origin origin;
+        vm::State state;
+        Compute( Snapshot snap, task::origin orig, vm::State state )
+            : snap( snap ), origin( orig ), state( state )
+        {}
     };
 
-    using TQ = Task::TQ;
+    struct Choose : Compute
+    {
+        int choice, total;
+        void cancel() { total = 0; }
+        Choose( Snapshot snap, task::origin orig, vm::State state, int c, int t )
+            : Compute( snap, orig, state ), choice( c ), total( t )
+        {}
+    };
 }
 
 namespace divine::mc::machine
@@ -169,31 +161,37 @@ namespace divine::mc::machine
     };
 
     template< typename solver, typename next >
-    struct base_ : TQ::Skel, with_pools, with_counters, with_bc, with_solver< solver >, next
+    struct base_ : with_pools, with_counters, with_bc, with_solver< solver >, next
     {
-        using task_choose   = Task::Choose;
-        using task_schedule = Task::Schedule;
-        using task_edge     = StateTQ::Tasks::Edge;
-
-        void boot( TQ & ) {}
+        using origin        = task::origin;
+        using task_choose   = task::Choose;
+        using task_schedule = task::Expand< State >;
+        using task_edge     = task::Edge< State, Label >;
+        using tq            = task_queue< task_choose, task::Start, task_schedule, task_edge >;
+
+        template< typename T > void run( tq &, T ) {}
+        void boot( tq & ) {}
     };
 
     template< typename next >
     struct choose_ : next
     {
-        void queue_choices( TQ &tq, Snapshot snap, Origin origin, vm::State state, int take, int total )
+        using typename next::origin;
+        using typename next::tq;
+
+        void queue_choices( tq &q, Snapshot snap, origin o, vm::State state, int take, int total )
         {
             for ( int i = 0; i < total; ++i )
                 if ( i != take )
                 {
                     this->_snap_refcnt.get( snap );
-                    tq.add< typename next::task_choose >( snap, origin, state, i, total );
+                    q.template add< typename next::task_choose >( snap, o, state, i, total );
                 }
         }
 
-        int select_choice( TQ &tq, Snapshot snap, Origin origin, vm::State state, int count )
+        int select_choice( tq &q, Snapshot snap, origin o, vm::State state, int count )
         {
-            queue_choices( tq, snap, origin, state, 0, count );
+            queue_choices( q, snap, o, state, 0, count );
             return 0;
         }
     };
@@ -201,13 +199,15 @@ namespace divine::mc::machine
     template< typename next >
     struct choose_random_ : next
     {
+        using typename next::origin;
+        using typename next::tq;
         std::mt19937 rand;
 
-        int select_choice( TQ &tq, Snapshot snap, Origin origin, vm::State state, int count )
+        int select_choice( tq &q, Snapshot snap, origin o, vm::State state, int count )
         {
             using dist = std::uniform_int_distribution< int >;
             int c = dist( 0, count - 1 )( rand );
-            this->queue_choices( tq, snap, origin, state, c, count );
+            this->queue_choices( q, snap, o, state, c, count );
         }
     };
 
@@ -234,9 +234,11 @@ namespace divine::mc::machine
     template< typename next >
     struct compute_ : next
     {
+        using typename next::origin;
+        using typename next::tq;
         using Eval = vm::Eval< typename next::context_t >;
 
-        void eval_choice( TQ &tq, Origin origin )
+        void eval_choice( tq &q, origin o )
         {
             auto snap = this->context().snapshot( this->_snap_pool );
             auto state = this->context()._state;
@@ -249,11 +251,11 @@ namespace divine::mc::machine
             eval.dispatch();
 
             this->context()._choice_take =
-                this->select_choice( tq, snap, origin, state, this->context()._choice_count );
-            compute( tq, origin, snap );
+                this->select_choice( q, snap, o, state, this->context()._choice_count );
+            compute( q, o, snap );
         }
 
-        void eval_interrupt( TQ &tq, Origin origin, Snapshot cont_from )
+        void eval_interrupt( tq &q, origin o, Snapshot cont_from )
         {
             if ( this->context().frame().null() )
             {
@@ -261,14 +263,14 @@ namespace divine::mc::machine
                 lbl.accepting = this->context().flags_any( _VM_CF_Accepting );
                 lbl.error = this->context().flags_any( _VM_CF_Error );
                 auto [ state, isnew ] = this->store();
-                tq.add< typename next::task_edge >( State( origin.snap ), state, lbl, isnew );
+                q.template add< typename next::task_edge >( State( o.snap ), state, lbl, isnew );
             }
-            else if ( this->loop_closed( origin ) )
+            else if ( this->loop_closed( o ) )
             {
                 /* TODO: check for error/accepting flags */
             }
             else
-                return compute( tq, origin, cont_from );
+                return compute( q, o, cont_from );
         }
 
         bool feasible()
@@ -281,7 +283,7 @@ namespace divine::mc::machine
             return this->_solver.feasible( this->context().heap(), this->context()._assume );
         }
 
-        void compute( TQ &tq, Origin origin, Snapshot cont_from = Snapshot() )
+        void compute( tq &q, origin o, Snapshot cont_from = Snapshot() )
         {
             auto destroy = [&]( auto p ) { this->heap().snap_put( this->_snap_pool, p, false ); };
             auto cleanup = [&]
@@ -298,34 +300,34 @@ namespace divine::mc::machine
                 return;
 
             if ( choice )
-                eval_choice( tq, origin );
+                eval_choice( q, o );
             else
-                eval_interrupt( tq, origin, cont_from );
+                eval_interrupt( q, o, cont_from );
         }
 
-        bool boot( TQ &tq )
+        bool boot( tq &q )
         {
             this->context().program( this->program() );
             Eval eval( this->context() );
             vm::setup::boot( this->context() );
             eval.run();
-            next::boot( tq );
+            next::boot( q );
 
             if ( vm::setup::postboot_check( this->context() ) )
-                return tq.add< typename next::task_schedule >( this->store().first ), true;
+                return q.template add< typename next::task_schedule >( this->store().first ), true;
             else
                 return false;
         }
 
-        void schedule( TQ &tq, Task::Schedule e )
+        void schedule( tq &q, typename next::task_schedule e )
         {
             TRACE( "task (schedule)", e );
             this->context().load( this->_state_pool, e.from.snap );
             vm::setup::scheduler( this->context() );
-            compute( tq, Origin( e.from.snap ) );
+            compute( q, task::origin( e.from.snap ) );
         }
 
-        void choose( TQ &tq, Task::Choose c )
+        void choose( tq &q, typename next::task_choose c )
         {
             TRACE( "task (choose)", c );
             if ( !c.total )
@@ -336,19 +338,19 @@ namespace divine::mc::machine
             this->context()._choice_count = c.total;
             this->context().flush_ptr2i();
             this->context().load_pc();
-            compute( tq, c.origin, c.snap );
+            compute( q, c.origin, c.snap );
         }
     };
 
     template< typename next >
-    struct tree_store_ : next
+    struct tree_search_ : next
     {
         virtual std::pair< State, bool > store()
         {
             return { State( this->context().snapshot( this->_state_pool ) ), true };
         }
 
-        virtual bool loop_closed( Origin & )
+        virtual bool loop_closed( typename next::origin & )
         {
             return false;
         }
@@ -366,7 +368,7 @@ namespace divine::mc::machine
             return make_hasher().equal_symbolic( a, b );
         }
 
-        ~tree_store_()
+        ~tree_search_()
         {
             ASSERT_EQ( this->_snap_pool.stats().total.count.used, 0 );
         }
@@ -374,8 +376,9 @@ namespace divine::mc::machine
     };
 
     template< typename next >
-    struct graph_store_ : next
+    struct graph_search_ : next
     {
+        using typename next::origin;
         using Hasher = mc::Hasher< typename next::solver_t >;
 
         Hasher _hasher;
@@ -383,7 +386,7 @@ namespace divine::mc::machine
 
         auto &hasher() { return _hasher; }
         bool equal( Snapshot a, Snapshot b ) { return hasher().equal_symbolic( a, b ); }
-        graph_store_() : _hasher( this->_state_pool, this->heap(), this->_solver ) {}
+        graph_search_() : _hasher( this->_state_pool, this->heap(), this->_solver ) {}
 
         std::pair< State, bool > store( HT &table )
         {
@@ -403,9 +406,9 @@ namespace divine::mc::machine
             return store( _ht_sched );
         }
 
-        bool loop_closed( Origin &origin )
+        bool loop_closed( origin &o )
         {
-            auto [ state, isnew ] = store( origin.ht_loop );
+            auto [ state, isnew ] = store( o.ht_loop );
             if ( isnew )
                 this->context().flush_ptr2i();
             else
@@ -417,21 +420,22 @@ namespace divine::mc::machine
             return !isnew;
         }
 
-        void boot( TQ &tq )
+        void boot( typename next::tq &q )
         {
-            next::boot( tq );
+            next::boot( q );
             hasher()._root = this->context().state_ptr();
         }
     };
 
     template< typename next >
-    struct dispatch_ : next
+    struct graph_dispatch_ : next
     {
+        using typename next::tq;
         using next::run;
 
-        void run( TQ &tq, Task::Boot ) { next::boot( tq ); }
-        void run( TQ &tq, Task::Schedule e ) { next::schedule( tq, e ); }
-        void run( TQ &tq, Task::Choose c ) { next::choose( tq, c ); }
+        void run( tq &q, task::Boot ) { next::boot( q ); }
+        void run( tq &q, typename next::task_schedule e ) { next::schedule( q, e ); }
+        void run( tq &q, typename next::task_choose c ) { next::choose( q, c ); }
     };
 
     template< typename solver >
@@ -440,20 +444,26 @@ namespace divine::mc::machine
     template< typename ctx >
     using with_context = brq::module< with_context_, ctx >;
 
-    using compute = brq::module< compute_ >;
+    template< typename solver >
+    using common = brq::compose< with_context< context >, base< solver > >;
+
     using choose = brq::module< choose_ >;
     using choose_random = brq::module< choose_random_ >;
-    using tree_store = brq::module< tree_store_ >;
-    using graph_store = brq::module< graph_store_ >;
-    using dispatch = brq::module< dispatch_ >;
+
+    using tree_search = brq::module< tree_search_ >;
+    using graph_search = brq::module< graph_search_ >;
+
+    using compute = brq::module< compute_ >;
+    using graph_dispatch = brq::module< graph_dispatch_ >;
+
+    using tree_compute  = brq::compose< graph_dispatch, compute,  tree_search, choose >;
+    using graph_compute = brq::compose< graph_dispatch, compute, graph_search, choose >;
 
     template< typename solver >
-    using tree = brq::compose_stack< dispatch, compute, tree_store, choose,
-                                     with_context< context >, base< solver > >;
+    using tree = brq::compose_stack< tree_compute, common< solver > >;
 
     template< typename solver >
-    using graph = brq::compose_stack< dispatch, compute, graph_store, choose,
-                                      with_context< context >, base< solver > >;
+    using graph = brq::compose_stack< graph_compute, common< solver > >;
 }
 
 namespace divine::mc
@@ -464,6 +474,6 @@ namespace divine::mc
     template< typename M >
     auto weave( M &machine )
     {
-        return mc::Task::Weaver().extend_ref( machine );
+        return mc::Weaver< typename M::tq >().extend_ref( machine );
     }
 }
diff --git a/divine/mc/t-machine.hpp b/divine/mc/t-machine.hpp
index d7e455f21..4759d6242 100644
--- a/divine/mc/t-machine.hpp
+++ b/divine/mc/t-machine.hpp
@@ -89,9 +89,9 @@ namespace divine::t_mc
             m.bc( bc );
         }
 
-        using Search = mc::Search< mc::TQ >;
-        using Expand = mc::TQ::Tasks::Expand;
-        using Edge = mc::TQ::Tasks::Edge;
+        using Search = mc::Search< mc::State, mc::Label >;
+        using Expand = mc::task::Expand< mc::State >;
+        using Edge   = mc::task::Edge< mc::State, mc::Label >;
 
         auto tmachine( mc::BC bc ) { mc::TMachine tm; tm.bc( bc ); return tm; }
         auto gmachine( mc::BC bc ) { mc::GMachine tm; tm.bc( bc ); return tm; }
-- 
GitLab