asar coverage - build #284


src/asar/
File: src/asar/math_eval.cpp
Date: 2025-03-07 20:42:43
Lines:
188/215
87.4%
Functions:
26/27
96.3%
Branches:
314/496
63.3%

Line Branch Exec Source
1 #include "math_ast.h"
2 #include "asar.h"
3 #include "errors.h"
4
5 335 double math_val::get_double() const {
6
5/6
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
335 switch(m_type) {
7 208 case math_val_type::floating:
8 208 return m_numeric_val.double_;
9 116 case math_val_type::integer:
10 116 return (double)m_numeric_val.int_;
11 5 case math_val_type::identifier:
12 5 return (double)get_integer();
13 6 case math_val_type::string:
14 6 throw_err_block(2, err_bad_type, "number", "string");
15 }
16 // this is actually unreachable because the switch case above is
17 // exhaustive, but c++ standard allows storing invalid values inside
18 // enums, so everything except clang complains about it...
19 throw_err_block(pass, err_internal_error, "math_val invalid type");
20 }
21 22366 int64_t math_val::get_integer() const {
22
5/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 10844 times.
✓ Branch 2 taken 11225 times.
✓ Branch 3 taken 269 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
22366 switch(m_type) {
23 50 case math_val_type::floating:
24 // TODO: throw error on overflow?
25 50 return (int64_t)m_numeric_val.double_;
26 21782 case math_val_type::integer:
27 21782 return m_numeric_val.int_;
28 528 case math_val_type::identifier:
29
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 266 times.
528 if(!labels.exists(m_string_val)) {
30 throw_err_block(pass, err_internal_error, "evaluating nonexistent label");
31 }
32 528 return labels.find(m_string_val).pos;
33 6 case math_val_type::string:
34 6 throw_err_block(2, err_bad_type, "number", "string");
35 }
36 throw_err_block(pass, err_internal_error, "math_val invalid type");
37 }
38 447 const string &math_val::get_str() const {
39
3/3
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 231 times.
✓ Branch 2 taken 3 times.
447 if (m_type == math_val_type::string)
40 441 return m_string_val;
41 6 throw_err_block(2, err_bad_type, "string", "number"); // TODO is "number" a good name for identifier/int/float?
42 }
43
44 406 const string &math_val::get_identifier() const {
45
3/3
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 3 times.
406 if (m_type == math_val_type::identifier)
46 400 return m_string_val;
47
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 const char* type_name = (m_type == math_val_type::string) ? "string" : "number";
48 6 throw_err_block(2, err_bad_type, "identifier", type_name);
49 }
50 160 bool math_val::get_bool() const {
51
3/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
160 switch (m_type) {
52 4 case math_val_type::floating:
53 4 return get_double() != 0.0;
54 156 case math_val_type::integer:
55 case math_val_type::identifier:
56 156 return get_integer() != 0;
57 case math_val_type::string:
58 return get_str().length() != 0;
59 }
60 throw_err_block(pass, err_internal_error, "math_val invalid type");
61 }
62
63 template<typename T>
64 4036 bool evaluate_binop_compare(const T& lhs, const T& rhs, math_binop_type type) {
65
4/5
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 1828 times.
✗ Branch 4 not taken.
4036 switch(type) {
66 36 case math_binop_type::comp_ge: return lhs >= rhs;
67 24 case math_binop_type::comp_le: return lhs <= rhs;
68 320 case math_binop_type::comp_gt: return lhs > rhs;
69 3656 case math_binop_type::comp_lt: return lhs < rhs;
70 default:
71 throw_err_block(2, err_internal_error, "evaluate_binop_compare with bad type");
72 }
73 }
74
75 530 static bool evaluate_eq(math_val lhs, math_val rhs) {
76 // if only one is string, they can never be equal
77
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 262 times.
530 if((lhs.m_type == math_val_type::string) ^ (rhs.m_type == math_val_type::string)) {
78 6 return false;
79 }
80
3/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 256 times.
524 if(lhs.m_type == math_val_type::string) {
81 // both strings: compare as strings
82 12 return lhs.get_str() == rhs.get_str();
83 } else {
84 // both non strings: compare as numbers
85
6/6
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 232 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 232 times.
512 if(lhs.m_type == math_val_type::floating || rhs.m_type == math_val_type::floating)
86 // one floating: compare as floats
87 48 return lhs.get_double() == rhs.get_double();
88 else
89 // both ints: compare as ints
90 464 return lhs.get_integer() == rhs.get_integer();
91 }
92 }
93
94 5167 math_val evaluate_binop(math_val lhs, math_val rhs,
95 math_binop_type type) {
96
5/6
✓ Branch 0 taken 2546 times.
✓ Branch 1 taken 2585 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 2546 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2549 times.
5167 bool has_string = (lhs.m_type == math_val_type::string) || (rhs.m_type == math_val_type::string);
97
6/6
✓ Branch 0 taken 2551 times.
✓ Branch 1 taken 2585 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 2545 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2548 times.
5167 bool has_float = (lhs.m_type == math_val_type::floating) || (rhs.m_type == math_val_type::floating);
98
12/16
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1973 times.
✓ Branch 10 taken 54 times.
✓ Branch 11 taken 538 times.
✓ Branch 12 taken 2018 times.
✓ Branch 13 taken 478 times.
✓ Branch 14 taken 52 times.
✗ Branch 15 not taken.
5167 switch (type) {
99 12 case math_binop_type::pow:
100 12 return math_val(pow(lhs.get_double(), rhs.get_double()));
101 16 case math_binop_type::div:
102
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 if (rhs.get_double() == 0.0)
103 4 throw_err_block(2, err_division_by_zero);
104 12 return math_val(lhs.get_double() / rhs.get_double());
105 6 case math_binop_type::mod:
106
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
6 if (rhs.get_double() == 0.0)
107 throw_err_block(2, err_division_by_zero);
108 // TODO: negative semantics
109 if (has_float) {
110 return math_val(fmod(lhs.get_double(), rhs.get_double()));
111 } else {
112 return math_val(lhs.get_integer() % rhs.get_integer());
113 }
114 break;
115
116 6 case math_binop_type::shift_left: {
117 6 int64_t rhs_v = rhs.get_integer();
118
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (rhs_v < 0)
119 6 throw_err_block(2, err_negative_shift);
120 return math_val(lhs.get_integer() << (uint64_t)rhs_v);
121 }
122 12 case math_binop_type::shift_right: {
123 12 int64_t rhs_v = rhs.get_integer();
124
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rhs_v < 0)
125 6 throw_err_block(2, err_negative_shift);
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 return math_val(lhs.get_integer() >> (uint64_t)rhs_v);
127 }
128
129 case math_binop_type::bit_and:
130 return math_val(lhs.get_integer() & rhs.get_integer());
131 2 case math_binop_type::bit_or:
132 2 return math_val(lhs.get_integer() | rhs.get_integer());
133 case math_binop_type::bit_xor:
134 return math_val(lhs.get_integer() ^ rhs.get_integer());
135
136 case math_binop_type::logical_and:
137 case math_binop_type::logical_or:
138 throw_err_block(2, err_internal_error, "evaluate_binop() on logical ops loses short-circuiting");
139
140 1973 case math_binop_type::add:
141
10/15
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1955 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 14 not taken.
1985 if(has_string) return math_val(lhs.get_str() + rhs.get_str());
142
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1937 times.
1955 else if(has_float) return math_val(lhs.get_double() + rhs.get_double());
143 1937 else return math_val(lhs.get_integer() + rhs.get_integer());
144 54 case math_binop_type::mul:
145
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 46 times.
54 if(has_float) return math_val(lhs.get_double() * rhs.get_double());
146 46 else return math_val(lhs.get_integer() * rhs.get_integer());
147 538 case math_binop_type::sub:
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 538 times.
538 if(has_float) return math_val(lhs.get_double() - rhs.get_double());
149 538 else return math_val(lhs.get_integer() - rhs.get_integer());
150
151 2018 case math_binop_type::comp_ge:
152 case math_binop_type::comp_le:
153 case math_binop_type::comp_gt:
154 case math_binop_type::comp_lt:
155
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1994 times.
2018 if(has_string) return (int64_t)evaluate_binop_compare(lhs.get_str(), rhs.get_str(), type);
156
1/11
✗ Branch 0 not taken.
✓ Branch 1 taken 1994 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
1994 else if(has_float) return (int64_t)evaluate_binop_compare(lhs.get_double(), rhs.get_double(), type);
157
6/9
✓ Branch 0 taken 997 times.
✓ Branch 1 taken 997 times.
✓ Branch 2 taken 997 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 997 times.
✓ Branch 5 taken 997 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 997 times.
✗ Branch 8 not taken.
1994 else return (int64_t)evaluate_binop_compare(lhs.get_integer(), rhs.get_integer(), type);
158
159
6/10
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 239 times.
✓ Branch 5 taken 239 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 239 times.
✗ Branch 9 not taken.
478 case math_binop_type::comp_eq: return (int64_t)evaluate_eq(lhs, rhs);
160
6/10
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
52 case math_binop_type::comp_ne: return (int64_t)!evaluate_eq(lhs, rhs);
161 }
162 throw_err_block(pass, err_internal_error, "evaluate_binop invalid binop");
163 }
164
165 5144 math_val math_ast_binop::evaluate(const eval_context &ctx) const {
166
2/4
✓ Branch 0 taken 2570 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2574 times.
✗ Branch 3 not taken.
5144 math_val lhs = m_left->evaluate(ctx);
167
168 // handle short-circuiting for || and &&
169
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2564 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2568 times.
5144 if (m_type == math_binop_type::logical_or) {
170
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 if (lhs.get_bool() == true)
171 6 return math_val((int64_t)true);
172
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 math_val rhs = m_right->evaluate(ctx);
173
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 return math_val((int64_t)rhs.get_bool());
174 6 }
175
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2555 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2559 times.
5132 if (m_type == math_binop_type::logical_and) {
176
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 12 times.
18 if (lhs.get_bool() == false)
177 6 return math_val((int64_t)false);
178
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 math_val rhs = m_right->evaluate(ctx);
179
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 return math_val((int64_t)rhs.get_bool());
180 12 }
181
182
3/4
✓ Branch 0 taken 2555 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2558 times.
✓ Branch 3 taken 1 times.
5114 math_val rhs = m_right->evaluate(ctx);
183
7/11
✓ Branch 0 taken 2555 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2555 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5096 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2558 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2541 times.
✓ Branch 10 taken 17 times.
5198 return evaluate_binop(lhs, rhs, m_type);
184 5178 }
185
186 5022 int math_ast_binop::has_label() const {
187 5022 return m_left->has_label() | m_right->has_label();
188 }
189
190
191 90 int math_ast_binop::get_len(bool could_be_bank_ex) const {
192
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 60 times.
90 if(could_be_bank_ex) {
193 30 int want_rhs = 0;
194
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 9 times.
30 if(m_type == math_binop_type::div) {
195 12 want_rhs = 65536;
196
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
18 } else if(m_type == math_binop_type::shift_right) {
197 12 want_rhs = 16;
198 }
199
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 if(want_rhs) {
200 24 math_ast_node* right_ptr = m_right.get();
201
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 auto right_lit = dynamic_cast<math_ast_literal*>(right_ptr);
202
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
24 if(right_lit && right_lit->m_value.m_type == math_val_type::integer) {
203 24 int64_t right_val = right_lit->m_value.get_integer();
204
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if(right_val == want_rhs) return 1;
205 }
206 }
207 }
208
4/8
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
66 return std::max(m_left->get_len(false), m_right->get_len(false));
209 }
210 70 math_val math_ast_unop::evaluate(const eval_context &ctx) const {
211
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
70 math_val arg = m_arg->evaluate(ctx);
212
4/8
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
70 switch (m_type) {
213 64 case math_unop_type::neg:
214
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 50 times.
64 if (arg.m_type == math_val_type::floating)
215
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 return math_val(-arg.get_double());
216 else
217
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 return math_val(-arg.get_integer());
218 case math_unop_type::bit_not:
219 return math_val(~arg.get_integer());
220 6 case math_unop_type::bank_extract:
221
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 return math_val(arg.get_integer() >> 16);
222 }
223 throw_err_block(pass, err_internal_error, "evaluate_unop invalid unop");
224 70 }
225
226 42 int math_ast_unop::has_label() const { return m_arg->has_label(); }
227
228 18 int math_ast_unop::get_len(bool could_be_bank_ex) const {
229
3/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 if (could_be_bank_ex && m_type == math_unop_type::bank_extract)
230 18 return 1;
231 return m_arg->get_len(false);
232 }
233
234 584 math_val math_ast_label::evaluate(const eval_context &ctx) const {
235
21/30
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 276 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 295 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 13 times.
✓ Branch 9 taken 276 times.
✓ Branch 10 taken 10 times.
✓ Branch 11 taken 279 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 13 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 3 times.
✓ Branch 20 taken 13 times.
✓ Branch 21 taken 282 times.
✓ Branch 22 taken 13 times.
✓ Branch 23 taken 282 times.
✓ Branch 24 taken 10 times.
✓ Branch 25 taken 285 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
584 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
236
4/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
40 return math_val::make_identifier(m_cur_ns + m_labelname);
237
4/4
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 281 times.
✓ Branch 3 taken 4 times.
564 } else if (labels.exists(m_labelname)) {
238
4/8
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 277 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 281 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 281 times.
✗ Branch 7 not taken.
558 return math_val::make_identifier(m_labelname);
239 } else {
240 // possibly forward label, assume without namespace.
241 // TODO: this assumption can cause moving labels :)))))
242
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
6 if(pass == 0) return math_val::make_identifier(m_labelname);
243 // if not pass 0, we know it's not a forward label and can throw the error
244 6 throw_err_block(2, err_label_not_found, m_labelname.data());
245 }
246 }
247
248 340 int math_ast_label::has_label() const {
249
19/30
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 170 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 168 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 168 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 168 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 168 times.
✓ Branch 24 taken 2 times.
✓ Branch 25 taken 168 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
340 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
250
7/14
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
4 return labels.find(m_cur_ns + m_labelname).is_static ? 1 : 3;
251
4/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 6 times.
336 } else if (labels.exists(m_labelname)) {
252
5/6
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 162 times.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 98 times.
324 return labels.find(m_labelname).is_static ? 1 : 3;
253 }
254 // otherwise, non-static forward label
255 12 return 7;
256 }
257
258 744 int math_ast_label::get_len(bool could_be_bank_ex) const {
259 744 snes_label label;
260
21/30
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 354 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 375 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 354 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 364 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 15 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 15 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 5 times.
✓ Branch 19 taken 10 times.
✓ Branch 20 taken 15 times.
✓ Branch 21 taken 360 times.
✓ Branch 22 taken 15 times.
✓ Branch 23 taken 360 times.
✓ Branch 24 taken 5 times.
✓ Branch 25 taken 370 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
744 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
261
4/8
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
10 label = labels.find(m_cur_ns + m_labelname);
262
6/8
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 370 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 320 times.
✓ Branch 7 taken 50 times.
734 } else if (labels.exists(m_labelname)) {
263
2/4
✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
635 label = labels.find(m_labelname);
264 99 } else return 2;
265
1/2
✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
645 return getlenforlabel(label, true);
266 }
267
268 math_function_ref
269 1123 math_ast_function_call::lookup_fname(string const &function_name) {
270
4/6
✓ Branch 0 taken 557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 549 times.
1689 if (auto it = user_functions.find(function_name);
271
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 540 times.
1123 it != user_functions.end()) {
272 34 return it->second;
273
3/6
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 549 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 549 times.
✗ Branch 5 not taken.
1638 } else if (auto it = builtin_functions.find(function_name);
274
1/2
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
1089 it != builtin_functions.end()) {
275 1089 return it->second;
276 } else {
277 throw_err_block(2, err_function_not_found, function_name.data());
278 }
279 }
280 1045 math_val math_ast_function_call::evaluate(const eval_context &ctx) const {
281 1045 std::vector<math_val> arg_vals;
282
4/4
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 515 times.
✓ Branch 2 taken 674 times.
✓ Branch 3 taken 524 times.
2378 for (auto const &p : m_arguments) {
283
6/7
✓ Branch 0 taken 662 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 662 times.
✓ Branch 3 taken 671 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 671 times.
✗ Branch 6 not taken.
1339 arg_vals.push_back(p->evaluate(ctx));
284 }
285
4/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 495 times.
✓ Branch 3 taken 29 times.
2020 return m_func.call(arg_vals);
286 1045 }
287
288 678 int math_ast_function_call::has_label() const {
289 678 int out = m_func.has_label();
290
4/4
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 381 times.
✓ Branch 3 taken 342 times.
1434 for (auto const &p : m_arguments) {
291
2/4
✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 381 times.
✗ Branch 3 not taken.
756 out |= p->has_label();
292 }
293 678 return out;
294 }
295
296 96 int math_ast_function_call::get_len(bool could_be_bank_ex) const {
297 96 return m_func.get_len(m_arguments, could_be_bank_ex);
298 }
299
300 30 math_val math_user_function::call(const std::vector<math_val> &args) const {
301 30 math_ast_node::eval_context new_ctx;
302
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 new_ctx.userfunc_params = args;
303
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
30 if (args.size() != m_arg_count)
304 throw_err_block(2, err_argument_count, (int)m_arg_count, (int)args.size());
305
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
60 return m_func_body->evaluate(new_ctx);
306 30 }
307
308 6 int math_user_function::has_label() const { return m_func_body->has_label(); }
309
310 6 int math_user_function::get_len(const std::vector<owned_node> &args,
311 bool could_be_bank_ex) const {
312 // TODO: this doesn't forward could_be_bank_ex to the fn call...
313 // supporting that properly would require stringing some context through all
314 // get_len calls; supporting it less properly (making a special return value of
315 // get_len signify bankextract) could be viable tho...
316
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 int len = m_func_body->get_len(false);
317
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6 for (auto &arg : args) {
318 len = std::max(len, arg->get_len(false));
319 }
320 6 return len;
321 }
322
323