7 #include "ast/ExprNode.h"
8 #include "diagnostics/Location.h"
14 using op_array = std::pmr::vector<T>;
16 virtual T mapValue(exprnode::
ExprValue& node)
const = 0;
17 virtual T evalBinaryOp(exprnode::BinaryOp& op,
const T lhs,
18 const T rhs)
const = 0;
19 virtual T evalUnaryOp(exprnode::UnaryOp& op,
const T rhs)
const = 0;
20 virtual T evalMemberAccess(exprnode::MemberAccess& op,
const T lhs,
21 const T field)
const = 0;
22 virtual T evalMethodCall(exprnode::MethodInvocation& op,
const T method,
23 const op_array& args)
const = 0;
24 virtual T evalNewObject(exprnode::ClassInstanceCreation& op,
const T object,
25 const op_array& args)
const = 0;
26 virtual T evalNewArray(exprnode::ArrayInstanceCreation& op,
const T type,
27 const T size)
const = 0;
28 virtual T evalArrayAccess(exprnode::ArrayAccess& op,
const T array,
29 const T index)
const = 0;
30 virtual T evalCast(exprnode::Cast& op,
const T type,
const T value)
const = 0;
56 using namespace ast::exprnode;
58 std::pmr::vector<T> op_args;
59 const auto getArgs = [&op_args,
this](
int nargs) {
61 for(
int i = 0; i < nargs; ++i) op_args.push_back(popSafe());
65 while(!op_stack_.empty()) popSafe();
68 for(
auto const* nodes : subexpr
.nodes()) {
73 auto* node = subexpr.mut_head();
74 for(size_t i = 0; i < subexpr
.size(); ++i) {
76 if(dyn_cast<
ExprValue*>(node)) arg_locs_.push_back(node->location());
78 auto next_node = node->mut_next();
80 cur_op = dyn_cast<
ExprOp*>(node);
81 if(
auto* value = dyn_cast<
ExprValue*>(node)) {
82 op_stack_.push(mapValue(*value));
83 }
else if(
auto* unary = dyn_cast<UnaryOp*>(node)) {
85 op_stack_.push(evalUnaryOp(*unary, rhs));
86 }
else if(
auto* binary = dyn_cast<BinaryOp*>(node)) {
89 op_stack_.push(evalBinaryOp(*binary, lhs, rhs));
90 }
else if(
auto op = dyn_cast<MemberAccess*>(node)) {
91 auto field = popSafe();
93 op_stack_.push(evalMemberAccess(*op, lhs, field));
94 }
else if(
auto* method = dyn_cast<MethodInvocation*>(node)) {
96 if(method->nargs() > 1) getArgs(method->nargs() - 1);
97 auto method_name = popSafe();
98 op_stack_.push(evalMethodCall(*method, method_name, op_args));
99 }
else if(
auto* newObj = dyn_cast<ClassInstanceCreation*>(node)) {
101 if(newObj->nargs() > 1) getArgs(newObj->nargs() - 1);
102 auto type = popSafe();
103 op_stack_.push(evalNewObject(*newObj, type, op_args));
104 }
else if(
auto op = dyn_cast<ArrayInstanceCreation*>(node)) {
105 auto size = popSafe();
106 auto type = popSafe();
107 op_stack_.push(evalNewArray(*op, type, size));
108 }
else if(
auto op = dyn_cast<ArrayAccess*>(node)) {
109 auto index = popSafe();
110 auto array = popSafe();
111 op_stack_.push(evalArrayAccess(*op, array, index));
112 }
else if(
auto op = dyn_cast<Cast*>(node)) {
113 auto value = popSafe();
114 auto type = popSafe();
115 op_stack_.push(evalCast(*op, type, value));
117 assert(validate(op_stack_.top()));
119 if(cur_op) mergeLocations(cur_op->nargs());
123 auto result = popSafe();
124 assert(op_stack_.empty() &&
"Stack not empty after evaluation");
129 virtual bool validate(T
const&)
const {
return true; }
130 virtual bool validatePop(T
const&)
const {
return true; }
131 int opStackSize()
const {
return op_stack_.size(); }
140 assert(argno < cur_op->nargs() && argno >= 0);
142 return arg_locs_[arg_locs_.size() - cur_op->nargs() + argno];
147 assert(!op_stack_.empty() &&
"Stack underflow");
148 T value = op_stack_.top();
150 assert(validatePop(value));
153 void mergeLocations(
int num) {
155 arg_locs_.pop_back();
156 for(
int i = 1; i < num; i++) {
158 arg_locs_.pop_back();
160 arg_locs_.push_back(loc);
164 std::stack<T> op_stack_;
166 ast::exprnode::
ExprOp* cur_op;