|
2 | 2 | #define WASM_SYMBOLIC_RT_HPP
|
3 | 3 |
|
4 | 4 | #include "concrete_rt.hpp"
|
| 5 | +#include <cassert> |
| 6 | +#include <iterator> |
| 7 | +#include <memory> |
5 | 8 | #include <variant>
|
6 | 9 |
|
7 | 10 | class SymVal {
|
@@ -75,18 +78,93 @@ static SymVal Concrete(Num num) {
|
75 | 78 | return SymVal();
|
76 | 79 | }
|
77 | 80 |
|
| 81 | +struct Node; |
| 82 | + |
| 83 | +struct NodeBox { |
| 84 | + explicit NodeBox(); |
| 85 | + std::unique_ptr<Node> node; |
| 86 | + NodeBox *parent; |
| 87 | +}; |
| 88 | + |
| 89 | +struct Node { |
| 90 | + virtual ~Node(){}; |
| 91 | + virtual std::string to_string() = 0; |
| 92 | +}; |
| 93 | + |
| 94 | +struct IfElseNode : Node { |
| 95 | + SymVal cond; |
| 96 | + std::unique_ptr<NodeBox> true_branch; |
| 97 | + std::unique_ptr<NodeBox> false_branch; |
| 98 | + |
| 99 | + IfElseNode(SymVal cond) |
| 100 | + : cond(cond), true_branch(std::make_unique<NodeBox>()), |
| 101 | + false_branch(std::make_unique<NodeBox>()) {} |
| 102 | + |
| 103 | + std::string to_string() override { |
| 104 | + std::string result = "IfElseNode {\n"; |
| 105 | + result += " true_branch: "; |
| 106 | + if (true_branch) { |
| 107 | + result += true_branch->node->to_string(); |
| 108 | + } else { |
| 109 | + result += "nullptr"; |
| 110 | + } |
| 111 | + result += "\n"; |
| 112 | + |
| 113 | + result += " false_branch: "; |
| 114 | + if (false_branch) { |
| 115 | + result += false_branch->node->to_string(); |
| 116 | + } else { |
| 117 | + result += "nullptr"; |
| 118 | + } |
| 119 | + result += "\n"; |
| 120 | + result += "}"; |
| 121 | + return result; |
| 122 | + } |
| 123 | +}; |
| 124 | + |
| 125 | +struct UnExploredNode : Node { |
| 126 | + UnExploredNode() {} |
| 127 | + std::string to_string() override { return "UnexploredNode"; } |
| 128 | +}; |
| 129 | + |
| 130 | +static UnExploredNode unexplored; |
| 131 | + |
| 132 | +inline NodeBox::NodeBox() |
| 133 | + : node(std::make_unique< |
| 134 | + UnExploredNode>() /* TODO: avoid allocation of unexplored node */) {} |
| 135 | + |
78 | 136 | class ExploreTree_t {
|
79 | 137 | public:
|
80 |
| - std::monostate fillIfElseNode(SymVal s) { |
81 |
| - // fill the current node with the branch condition s |
82 |
| - // parameter branch is redundant, to hint which branch we've entered |
83 |
| - // Not implemented yet |
| 138 | + explicit ExploreTree_t() |
| 139 | + : root(std::make_unique<NodeBox>()), cursor(root.get()) {} |
| 140 | + std::monostate fillIfElseNode(SymVal cond) { |
| 141 | + // fill the current node with an ifelse branch node |
| 142 | + cursor->node = std::make_unique<IfElseNode>(cond); |
84 | 143 | return std::monostate();
|
85 | 144 | }
|
86 | 145 |
|
87 | 146 | std::monostate moveCursor(bool branch) {
|
| 147 | + assert(cursor != nullptr); |
| 148 | + auto if_else_node = dynamic_cast<IfElseNode *>(cursor->node.get()); |
| 149 | + assert( |
| 150 | + if_else_node != nullptr && |
| 151 | + "Can't move cursor when the branch node is not initialized correctly!"); |
| 152 | + if (branch) { |
| 153 | + cursor = if_else_node->true_branch.get(); |
| 154 | + } else { |
| 155 | + cursor = if_else_node->false_branch.get(); |
| 156 | + } |
88 | 157 | return std::monostate();
|
89 | 158 | }
|
| 159 | + |
| 160 | + std::monostate print() { |
| 161 | + std::cout << root->node->to_string() << std::endl; |
| 162 | + return std::monostate(); |
| 163 | + } |
| 164 | + |
| 165 | +private: |
| 166 | + std::unique_ptr<NodeBox> root; |
| 167 | + NodeBox *cursor; |
90 | 168 | };
|
91 | 169 |
|
92 | 170 | static ExploreTree_t ExploreTree;
|
|
0 commit comments