@@ -273,7 +273,8 @@ struct NodeBox {
273273 std::monostate fillFinishedNode ();
274274 std::monostate fillFailedNode ();
275275 std::monostate fillUnreachableNode ();
276-
276+ std::monostate fillSnapshotNode ();
277+ bool isUnexplored () const ;
277278 std::vector<SymVal> collect_path_conds ();
278279};
279280
@@ -384,6 +385,22 @@ struct UnExploredNode : Node {
384385 }
385386};
386387
388+ struct SnapshotNode : Node {
389+ SnapshotNode () {}
390+ std::string to_string () override { return " SnapshotNode" ; }
391+
392+ protected:
393+ void generate_dot (std::ostream &os, int parent_dot_id,
394+ const std::string &edge_label) override {
395+ int current_node_dot_id = current_id++;
396+ graphviz_node (os, current_node_dot_id, " Snapshot" , " box" , " lightblue" );
397+
398+ if (parent_dot_id != -1 ) {
399+ graphviz_edge (os, parent_dot_id, current_node_dot_id, edge_label);
400+ }
401+ }
402+ };
403+
387404struct Finished : Node {
388405 Finished () {}
389406 std::string to_string () override { return " FinishedNode" ; }
@@ -439,7 +456,7 @@ inline NodeBox::NodeBox(NodeBox *parent)
439456
440457inline std::monostate NodeBox::fillIfElseNode (SymVal cond) {
441458 // fill the current NodeBox with an ifelse branch node when it's unexplored
442- if (dynamic_cast <UnExploredNode *>(node. get () )) {
459+ if (this -> isUnexplored ( )) {
443460 node = std::make_unique<IfElseNode>(cond, this );
444461 }
445462 assert (
@@ -448,8 +465,15 @@ inline std::monostate NodeBox::fillIfElseNode(SymVal cond) {
448465 return std::monostate ();
449466}
450467
468+ inline std::monostate NodeBox::fillSnapshotNode () {
469+ if (this ->isUnexplored ()) {
470+ node = std::make_unique<SnapshotNode>();
471+ }
472+ return std::monostate ();
473+ }
474+
451475inline std::monostate NodeBox::fillFinishedNode () {
452- if (dynamic_cast <UnExploredNode *>(node. get () )) {
476+ if (this -> isUnexplored ( )) {
453477 node = std::make_unique<Finished>();
454478 } else {
455479 assert (dynamic_cast <Finished *>(node.get ()) != nullptr );
@@ -458,7 +482,7 @@ inline std::monostate NodeBox::fillFinishedNode() {
458482}
459483
460484inline std::monostate NodeBox::fillFailedNode () {
461- if (dynamic_cast <UnExploredNode *>(node. get () )) {
485+ if (this -> isUnexplored ( )) {
462486 node = std::make_unique<Failed>();
463487 } else {
464488 assert (dynamic_cast <Failed *>(node.get ()) != nullptr );
@@ -467,14 +491,19 @@ inline std::monostate NodeBox::fillFailedNode() {
467491}
468492
469493inline std::monostate NodeBox::fillUnreachableNode () {
470- if (dynamic_cast <UnExploredNode *>(node. get () )) {
494+ if (this -> isUnexplored ( )) {
471495 node = std::make_unique<Unreachable>();
472496 } else {
473497 assert (dynamic_cast <Unreachable *>(node.get ()) != nullptr );
474498 }
475499 return std::monostate ();
476500}
477501
502+ inline bool NodeBox::isUnexplored () const {
503+ return dynamic_cast <UnExploredNode *>(node.get ()) != nullptr ||
504+ dynamic_cast <SnapshotNode *>(node.get ()) != nullptr ;
505+ }
506+
478507inline std::vector<SymVal> NodeBox::collect_path_conds () {
479508 auto box = this ;
480509 auto result = std::vector<SymVal>();
@@ -554,8 +583,10 @@ class ExploreTree_t {
554583 if_else_node != nullptr &&
555584 " Can't move cursor when the branch node is not initialized correctly!" );
556585 if (branch) {
586+ if_else_node->false_branch ->fillSnapshotNode ();
557587 cursor = if_else_node->true_branch .get ();
558588 } else {
589+ if_else_node->true_branch ->fillSnapshotNode ();
559590 cursor = if_else_node->false_branch .get ();
560591 }
561592
@@ -599,7 +630,7 @@ class ExploreTree_t {
599630
600631private:
601632 NodeBox *pick_unexplored_of (NodeBox *node) {
602- if (dynamic_cast <UnExploredNode *>( node->node . get ()) != nullptr ) {
633+ if (node->isUnexplored () ) {
603634 return node;
604635 }
605636 auto if_else_node = dynamic_cast <IfElseNode *>(node->node .get ());
0 commit comments