8
8
#include < memory>
9
9
#include < ostream>
10
10
#include < variant>
11
+ #include < vector>
11
12
12
- class SymVal {
13
+ class Symbolic {};
14
+
15
+ class SymConcrete : public Symbolic {
13
16
public:
14
- SymVal operator +(const SymVal &other) const {
15
- // Define how to add two symbolic values
16
- // Not implemented yet
17
- return SymVal ();
18
- }
17
+ Num value;
18
+ SymConcrete (Num num) : value(num) {}
19
+ };
19
20
20
- SymVal is_zero () const {
21
- // Check if the symbolic value is zero
22
- // Not implemented yet
23
- return SymVal ();
24
- }
21
+ struct SymBinary ;
25
22
26
- SymVal negate () const {
27
- // negate the symbolic condition by creating a new symbolic value
28
- // not implemented yet
29
- return SymVal ();
30
- }
23
+ struct SymVal {
24
+ std::shared_ptr<Symbolic> symptr;
25
+
26
+ SymVal () : symptr(nullptr ) {}
27
+ SymVal (std::shared_ptr<Symbolic> symptr) : symptr(symptr) {}
28
+
29
+ SymVal add (const SymVal &other) const ;
30
+ SymVal minus (const SymVal &other) const ;
31
+ SymVal mul (const SymVal &other) const ;
32
+ SymVal div (const SymVal &other) const ;
33
+ SymVal eq (const SymVal &other) const ;
34
+ SymVal neq (const SymVal &other) const ;
35
+ SymVal lt (const SymVal &other) const ;
36
+ SymVal leq (const SymVal &other) const ;
37
+ SymVal gt (const SymVal &other) const ;
38
+ SymVal geq (const SymVal &other) const ;
39
+ };
40
+
41
+ inline SymVal Concrete (Num num) {
42
+ return SymVal (std::make_shared<SymConcrete>(num));
43
+ }
44
+
45
+ enum Operation { ADD, SUB, MUL, DIV, EQ, NEQ, LT, LEQ, GT, GEQ };
46
+
47
+ struct SymBinary : Symbolic {
48
+ Operation op;
49
+ SymVal lhs;
50
+ SymVal rhs;
51
+
52
+ SymBinary (Operation op, SymVal lhs, SymVal rhs)
53
+ : op(op), lhs(lhs), rhs(rhs) {}
31
54
};
32
55
56
+ inline SymVal SymVal::add (const SymVal &other) const {
57
+ return SymVal (std::make_shared<SymBinary>(ADD, this , other));
58
+ }
59
+
60
+ inline SymVal SymVal::minus (const SymVal &other) const {
61
+ return SymVal (std::make_shared<SymBinary>(SUB, this , other));
62
+ }
63
+
64
+ inline SymVal SymVal::mul (const SymVal &other) const {
65
+ return SymVal (std::make_shared<SymBinary>(MUL, this , other));
66
+ }
67
+
68
+ inline SymVal SymVal::div (const SymVal &other) const {
69
+ return SymVal (std::make_shared<SymBinary>(DIV, this , other));
70
+ }
71
+
72
+ inline SymVal SymVal::eq (const SymVal &other) const {
73
+ return SymVal (std::make_shared<SymBinary>(EQ, this , other));
74
+ }
75
+
76
+ inline SymVal SymVal::neq (const SymVal &other) const {
77
+ return SymVal (std::make_shared<SymBinary>(NEQ, this , other));
78
+ }
79
+ inline SymVal SymVal::lt (const SymVal &other) const {
80
+ return SymVal (std::make_shared<SymBinary>(LT, this , other));
81
+ }
82
+ inline SymVal SymVal::leq (const SymVal &other) const {
83
+ return SymVal (std::make_shared<SymBinary>(LEQ, this , other));
84
+ }
85
+ inline SymVal SymVal::gt (const SymVal &other) const {
86
+ return SymVal (std::make_shared<SymBinary>(GT, this , other));
87
+ }
88
+ inline SymVal SymVal::geq (const SymVal &other) const {
89
+ return SymVal (std::make_shared<SymBinary>(GEQ, this , other));
90
+ }
91
+
33
92
class SymStack_t {
34
93
public:
35
94
void push (SymVal val) {
36
95
// Push a symbolic value to the stack
37
- // Not implemented yet
96
+ stack. push_back (val);
38
97
}
39
98
40
99
SymVal pop () {
41
100
// Pop a symbolic value from the stack
42
- // Not implemented yet
43
- return SymVal ();
101
+ auto ret = stack.back ();
102
+ stack.pop_back ();
103
+ return ret;
44
104
}
45
105
46
- SymVal peek () { return SymVal (); }
106
+ SymVal peek () { return stack.back (); }
107
+
108
+ std::vector<SymVal> stack;
47
109
};
48
110
49
111
static SymStack_t SymStack;
@@ -52,34 +114,30 @@ class SymFrames_t {
52
114
public:
53
115
void pushFrame (int size) {
54
116
// Push a new frame with the given size
55
- // Not implemented yet
117
+ stack. resize (size + stack. size ());
56
118
}
57
119
std::monostate popFrame (int size) {
58
120
// Pop the frame of the given size
59
- // Not implemented yet
121
+ stack. resize (stack. size () - size);
60
122
return std::monostate ();
61
123
}
62
124
63
125
SymVal get (int index) {
64
- // Get the symbolic value at the given index
65
- // Not implemented yet
66
- return SymVal ();
126
+ // Get the symbolic value at the given frame index
127
+ return stack[stack.size () - 1 - index];
67
128
}
68
129
69
130
void set (int index, SymVal val) {
70
131
// Set the symbolic value at the given index
71
132
// Not implemented yet
133
+ stack[stack.size () - 1 - index] = val;
72
134
}
135
+
136
+ std::vector<SymVal> stack;
73
137
};
74
138
75
139
static SymFrames_t SymFrames;
76
140
77
- static SymVal Concrete (Num num) {
78
- // Convert a concrete number to a symbolic value
79
- // Not implemented yet
80
- return SymVal ();
81
- }
82
-
83
141
struct Node ;
84
142
85
143
struct NodeBox {
@@ -115,11 +173,11 @@ struct Node {
115
173
int Node::current_id = 0 ;
116
174
117
175
struct IfElseNode : Node {
118
- SymVal cond;
176
+ Symbolic cond;
119
177
std::unique_ptr<NodeBox> true_branch;
120
178
std::unique_ptr<NodeBox> false_branch;
121
179
122
- IfElseNode (SymVal cond)
180
+ IfElseNode (Symbolic cond)
123
181
: cond(cond), true_branch(std::make_unique<NodeBox>()),
124
182
false_branch (std::make_unique<NodeBox>()) {}
125
183
@@ -205,7 +263,7 @@ class ExploreTree_t {
205
263
public:
206
264
explicit ExploreTree_t ()
207
265
: root(std::make_unique<NodeBox>()), cursor(root.get()) {}
208
- std::monostate fillIfElseNode (SymVal cond) {
266
+ std::monostate fillIfElseNode (Symbolic cond) {
209
267
// fill the current node with an ifelse branch node
210
268
cursor->node = std::make_unique<IfElseNode>(cond);
211
269
return std::monostate ();
0 commit comments