88#include < memory>
99#include < ostream>
1010#include < variant>
11+ #include < vector>
1112
12- class SymVal {
13+ class Symbolic {};
14+
15+ class SymConcrete : public Symbolic {
1316public:
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+ };
1920
20- SymVal is_zero () const {
21- // Check if the symbolic value is zero
22- // Not implemented yet
23- return SymVal ();
24- }
21+ struct SymBinary ;
2522
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) {}
3154};
3255
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+
3392class SymStack_t {
3493public:
3594 void push (SymVal val) {
3695 // Push a symbolic value to the stack
37- // Not implemented yet
96+ stack. push_back (val);
3897 }
3998
4099 SymVal pop () {
41100 // 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;
44104 }
45105
46- SymVal peek () { return SymVal (); }
106+ SymVal peek () { return stack.back (); }
107+
108+ std::vector<SymVal> stack;
47109};
48110
49111static SymStack_t SymStack;
@@ -52,34 +114,30 @@ class SymFrames_t {
52114public:
53115 void pushFrame (int size) {
54116 // Push a new frame with the given size
55- // Not implemented yet
117+ stack. resize (size + stack. size ());
56118 }
57119 std::monostate popFrame (int size) {
58120 // Pop the frame of the given size
59- // Not implemented yet
121+ stack. resize (stack. size () - size);
60122 return std::monostate ();
61123 }
62124
63125 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];
67128 }
68129
69130 void set (int index, SymVal val) {
70131 // Set the symbolic value at the given index
71132 // Not implemented yet
133+ stack[stack.size () - 1 - index] = val;
72134 }
135+
136+ std::vector<SymVal> stack;
73137};
74138
75139static SymFrames_t SymFrames;
76140
77- static SymVal Concrete (Num num) {
78- // Convert a concrete number to a symbolic value
79- // Not implemented yet
80- return SymVal ();
81- }
82-
83141struct Node ;
84142
85143struct NodeBox {
@@ -115,11 +173,11 @@ struct Node {
115173int Node::current_id = 0 ;
116174
117175struct IfElseNode : Node {
118- SymVal cond;
176+ Symbolic cond;
119177 std::unique_ptr<NodeBox> true_branch;
120178 std::unique_ptr<NodeBox> false_branch;
121179
122- IfElseNode (SymVal cond)
180+ IfElseNode (Symbolic cond)
123181 : cond(cond), true_branch(std::make_unique<NodeBox>()),
124182 false_branch (std::make_unique<NodeBox>()) {}
125183
@@ -205,7 +263,7 @@ class ExploreTree_t {
205263public:
206264 explicit ExploreTree_t ()
207265 : root(std::make_unique<NodeBox>()), cursor(root.get()) {}
208- std::monostate fillIfElseNode (SymVal cond) {
266+ std::monostate fillIfElseNode (Symbolic cond) {
209267 // fill the current node with an ifelse branch node
210268 cursor->node = std::make_unique<IfElseNode>(cond);
211269 return std::monostate ();
0 commit comments