-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathnode.cpp
More file actions
125 lines (105 loc) · 3.41 KB
/
Copy pathnode.cpp
File metadata and controls
125 lines (105 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <algorithm>
#include <string>
#include <vector>
#include "constant.h"
#include "context.h"
#include "error.h"
#include "node.h"
using std::back_inserter;
using std::ostream;
using std::string;
using std::transform;
using std::vector;
BigDecimal VariableNode::eval(Context &context) {
return context.get(name_, range_).get_variable(context, range_);
}
BigDecimal BinOpNode::eval_wrapper(Context &context) {
switch (type_) {
case BinOp_ADD:
return lhs_->eval(context) + rhs_->eval(context);
case BinOp_SUB:
return lhs_->eval(context) - rhs_->eval(context);
case BinOp_MUL:
return lhs_->eval(context) * rhs_->eval(context);
case BinOp_DIV:
return lhs_->eval(context).div_with_scale(rhs_->eval(context), context.scale());
case BinOp_MOD:
return lhs_->eval(context) % rhs_->eval(context);
case BinOp_LE:
return lhs_->eval(context) < rhs_->eval(context) ? BIG_DECIMAL_ONE : BIG_DECIMAL_ZERO;
case BinOp_GE:
return lhs_->eval(context) > rhs_->eval(context) ? BIG_DECIMAL_ONE : BIG_DECIMAL_ZERO;
default:
throw ranged_error(range_, string("unexpected operator: ") + static_cast<char>(type_));
}
}
BigDecimal BinOpNode::eval(Context &context) {
BigDecimal result = eval_wrapper(context);
if (!context.disabled_divergent_check() && result.mantissa().digits().size() > kDivergentLimit)
throw divergent_warning(range_, "divergent warning");
return result;
}
BigDecimal SequenceNode::eval(Context &context) {
lhs_->eval(context);
return rhs_->eval(context);
}
BigDecimal FunctionNode::eval(Context &context) {
vector<Expression*> arguments;
transform(args_.begin(), args_.end(), back_inserter(arguments),
[](auto &expression) { return expression.get(); });
return context.get(name_, range_).invoke_function(arguments, context, range_);
}
BigDecimal AssignmentNode::eval(Context &context) {
BigDecimal result = expression_->eval(context);
context.insert(name_, Entry::variable(result));
return result;
}
BigDecimal FunctionDefineNode::eval(Context &context) {
context.insert(name_, Entry::function(arguments_names_, expression_));
return BIG_DECIMAL_ZERO;
}
void NumericNode::print(ostream &stream) const {
stream << number_;
}
void VariableNode::print(ostream &stream) const {
stream << name_;
}
void BinOpNode::print(ostream &stream) const {
stream << "(";
lhs_->print(stream);
stream << " " << static_cast<char>(type_) << " ";
rhs_->print(stream);
stream << ")";
}
void SequenceNode::print(ostream &stream) const {
stream << "(";
lhs_->print(stream);
stream << "; ";
rhs_->print(stream);
stream << ")";
}
void FunctionNode::print(ostream &stream) const {
stream << name_ << "[";
bool is_first = true;
for (const auto &arg : args_) {
if (!is_first)
stream << ", ";
is_first = false;
arg->print(stream);
}
stream << "]";
}
void AssignmentNode::print(ostream &stream) const {
stream << name_ << " = ";
expression_->print(stream);
}
void FunctionDefineNode::print(ostream &stream) const {
stream << name_ << "";
bool is_first = true;
for (auto &x : arguments_names_) {
stream << (is_first ? "[" : ", ") << x;
is_first = false;
}
stream << "] = ";
expression_->print(stream);
}