Skip to content

Commit e1d7fc8

Browse files
put symbolic expression on the SymStack
1 parent 92ab8ba commit e1d7fc8

File tree

1 file changed

+92
-34
lines changed

1 file changed

+92
-34
lines changed

headers/wasm/symbolic_rt.hpp

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,104 @@
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 {
1316
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+
};
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+
3392
class SymStack_t {
3493
public:
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

49111
static SymStack_t SymStack;
@@ -52,34 +114,30 @@ class SymFrames_t {
52114
public:
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

75139
static 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-
83141
struct Node;
84142

85143
struct NodeBox {
@@ -115,11 +173,11 @@ struct Node {
115173
int Node::current_id = 0;
116174

117175
struct 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 {
205263
public:
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

Comments
 (0)