@@ -193,6 +193,13 @@ struct NodeBox {
193193 explicit NodeBox ();
194194 std::unique_ptr<Node> node;
195195 NodeBox *parent;
196+
197+ std::monostate fillIfElseNode (SymVal cond);
198+ std::monostate fillFinishedNode ();
199+ std::monostate fillFailedNode ();
200+ std::monostate fillUnreachableNode ();
201+
202+ std::vector<SymVal> collect_path_conds ();
196203};
197204
198205struct Node {
@@ -334,13 +341,87 @@ struct Failed : Node {
334341 }
335342};
336343
337- static UnExploredNode unexplored;
344+ struct Unreachable : Node {
345+ Unreachable () {}
346+ std::string to_string () override { return " UnreachableNode" ; }
347+
348+ protected:
349+ void generate_dot (std::ostream &os, int parent_dot_id,
350+ const std::string &edge_label) override {
351+ int current_node_dot_id = current_id++;
352+ graphviz_node (os, current_node_dot_id, " Unreachable" , " box" , " orange" );
353+
354+ if (parent_dot_id != -1 ) {
355+ graphviz_edge (os, parent_dot_id, current_node_dot_id, edge_label);
356+ }
357+ }
358+ };
338359
339360inline NodeBox::NodeBox ()
340361 : node(std::make_unique<UnExploredNode>()),
341362 /* TODO: avoid allocation of unexplored node */
342363 parent(nullptr ) {}
343364
365+ inline std::monostate NodeBox::fillIfElseNode (SymVal cond) {
366+ // fill the current NodeBox with an ifelse branch node it's unexplored
367+ if (dynamic_cast <UnExploredNode *>(node.get ())) {
368+ node = std::make_unique<IfElseNode>(cond);
369+ }
370+ assert (dynamic_cast <IfElseNode *>(node.get ()) != nullptr &&
371+ " Current node is not an IfElseNode, cannot fill it!" );
372+ return std::monostate ();
373+ }
374+
375+ inline std::monostate NodeBox::fillFinishedNode () {
376+ if (dynamic_cast <UnExploredNode *>(node.get ())) {
377+ node = std::make_unique<Finished>();
378+ } else {
379+ assert (dynamic_cast <Finished *>(node.get ()) != nullptr );
380+ }
381+ return std::monostate ();
382+ }
383+
384+ inline std::monostate NodeBox::fillFailedNode () {
385+ if (dynamic_cast <UnExploredNode *>(node.get ())) {
386+ node = std::make_unique<Failed>();
387+ } else {
388+ assert (dynamic_cast <Failed *>(node.get ()) != nullptr );
389+ }
390+ return std::monostate ();
391+ }
392+
393+ inline std::monostate NodeBox::fillUnreachableNode () {
394+ if (dynamic_cast <UnExploredNode *>(node.get ())) {
395+ node = std::make_unique<Unreachable>();
396+ } else {
397+ assert (dynamic_cast <Unreachable *>(node.get ()) != nullptr );
398+ }
399+ return std::monostate ();
400+ }
401+
402+ inline std::vector<SymVal> NodeBox::collect_path_conds () {
403+ auto box = this ;
404+ auto result = std::vector<SymVal>();
405+ while (box->parent ) {
406+ auto parent = box->parent ;
407+ auto if_else_node = dynamic_cast <IfElseNode *>(parent->node .get ());
408+ if (if_else_node) {
409+ if (if_else_node->true_branch .get () == box) {
410+ // If the current box is the true branch, add the condition
411+ result.push_back (if_else_node->cond );
412+ } else if (if_else_node->false_branch .get () == box) {
413+ // If the current box is the false branch, add the negated condition
414+ result.push_back (if_else_node->cond .negate ());
415+ } else {
416+ throw std::runtime_error (" Unexpected node structure in explore tree" );
417+ }
418+ }
419+ // Move to parent
420+ box = box->parent ;
421+ }
422+ return result;
423+ }
424+
344425class ExploreTree_t {
345426public:
346427 explicit ExploreTree_t ()
@@ -351,32 +432,12 @@ class ExploreTree_t {
351432 cursor = root.get ();
352433 }
353434
354- std::monostate fillFinishedNode () {
355- if (dynamic_cast <UnExploredNode *>(cursor->node .get ())) {
356- cursor->node = std::make_unique<Finished>();
357- } else {
358- assert (dynamic_cast <Finished *>(cursor->node .get ()) != nullptr );
359- }
360- return std::monostate{};
361- }
435+ std::monostate fillFinishedNode () { return cursor->fillFinishedNode (); }
362436
363- std::monostate fillFailedNode () {
364- if (dynamic_cast <UnExploredNode *>(cursor->node .get ())) {
365- cursor->node = std::make_unique<Failed>();
366- } else {
367- assert (dynamic_cast <Failed *>(cursor->node .get ()) != nullptr );
368- }
369- return std::monostate{};
370- }
437+ std::monostate fillFailedNode () { return cursor->fillFailedNode (); }
371438
372439 std::monostate fillIfElseNode (SymVal cond) {
373- // fill the current NodeBox with an ifelse branch node it's unexplored
374- if (dynamic_cast <UnExploredNode *>(cursor->node .get ())) {
375- cursor->node = std::make_unique<IfElseNode>(cond);
376- }
377- assert (dynamic_cast <IfElseNode *>(cursor->node .get ()) != nullptr &&
378- " Current node is not an IfElseNode, cannot fill it!" );
379- return std::monostate ();
440+ return cursor->fillIfElseNode (cond);
380441 }
381442
382443 std::monostate moveCursor (bool branch) {
@@ -419,24 +480,7 @@ class ExploreTree_t {
419480 if (!box) {
420481 return std::nullopt ;
421482 }
422- while (box->parent ) {
423- auto parent = box->parent ;
424- auto if_else_node = dynamic_cast <IfElseNode *>(parent->node .get ());
425- if (if_else_node) {
426- if (if_else_node->true_branch .get () == box) {
427- // If the current box is the true branch, add the condition
428- result.push_back (if_else_node->cond );
429- } else if (if_else_node->false_branch .get () == box) {
430- // If the current box is the false branch, add the negated condition
431- result.push_back (if_else_node->cond .negate ());
432- } else {
433- throw std::runtime_error (" Unexpected node structure in explore tree" );
434- }
435- }
436- // Move to parent
437- box = box->parent ;
438- }
439- return result;
483+ return box->collect_path_conds ();
440484 }
441485
442486 NodeBox *pick_unexplored () {
0 commit comments