asar coverage - build #266


src/asar/
File: src/asar/math_eval.cpp
Date: 2025-03-01 20:27:29
Lines:
174/210
82.9%
Functions:
28/28
100.0%
Branches:
263/419
62.8%

Line Branch Exec Source
1 #include "math_ast.h"
2 #include "asar.h"
3 #include "errors.h"
4
5 // TODO: make all these conversions print the current type aswell instead of just expected type
6 1154 double math_val::get_double() const {
7
4/6
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 1149 times.
✓ Branch 2 taken 1015 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2311 switch(m_type) {
8 282 case math_val_type::floating:
9 282 return m_numeric_val.double_;
10 2018 case math_val_type::integer:
11 2018 return (double)m_numeric_val.int_;
12 11 case math_val_type::identifier:
13 11 return (double)get_integer();
14 case math_val_type::string:
15 asar_throw_error(2, error_type_block, error_id_expected_number);
16 }
17 }
18 10096 int64_t math_val::get_integer() const {
19
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9842 times.
✓ Branch 2 taken 10215 times.
✓ Branch 3 taken 258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
20340 switch(m_type) {
20 50 case math_val_type::floating:
21 // TODO: throw error on overflow?
22 50 return (int64_t)m_numeric_val.double_;
23 19778 case math_val_type::integer:
24 19778 return m_numeric_val.int_;
25 512 case math_val_type::identifier:
26
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 258 times.
512 if(!labels.exists(m_string_val)) {
27 asar_throw_error(pass, error_type_block, error_id_internal_error, "evaluating nonexistent label");
28 }
29 512 return labels.find(m_string_val).pos;
30 case math_val_type::string:
31 asar_throw_error(2, error_type_block, error_id_expected_number);
32 }
33 }
34 142 const string &math_val::get_str() const {
35
2/3
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 74 times.
✗ Branch 2 not taken.
142 if (m_type == math_val_type::string)
36 142 return m_string_val;
37 asar_throw_error(2, error_type_block, error_id_expected_string);
38 }
39
40 394 const string &math_val::get_identifier() const {
41
2/3
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 197 times.
✗ Branch 2 not taken.
394 if (m_type == math_val_type::identifier)
42 394 return m_string_val;
43 asar_throw_error(2, error_type_block, error_id_expected_ident);
44 }
45 80 bool math_val::get_bool() const {
46
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) {
47 4 case math_val_type::floating:
48 4 return get_double() != 0.0;
49 156 case math_val_type::integer:
50 case math_val_type::identifier:
51 156 return get_integer() != 0;
52 case math_val_type::string:
53 return get_str().length() != 0;
54 }
55 }
56
57 template<typename T>
58 5070 T evaluate_binop_arithmetic(T lhs, T rhs, math_binop_type type) {
59
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1955 times.
✓ Branch 2 taken 526 times.
✗ Branch 3 not taken.
5070 switch(type) {
60 108 case math_binop_type::mul: return lhs * rhs;
61 3910 case math_binop_type::add: return lhs + rhs;
62 1052 case math_binop_type::sub: return lhs - rhs;
63 default:
64 asar_throw_error(2, error_type_block, error_id_internal_error, "evaluate_binop_arithmetic with bad type");
65 }
66 }
67 template<typename T>
68 5000 bool evaluate_binop_compare(T lhs, T rhs, math_binop_type type) {
69
6/7
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 154 times.
✓ Branch 3 taken 1816 times.
✓ Branch 4 taken 466 times.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
5000 switch(type) {
70 24 case math_binop_type::comp_ge: return lhs >= rhs;
71 24 case math_binop_type::comp_le: return lhs <= rhs;
72 308 case math_binop_type::comp_gt: return lhs > rhs;
73 3632 case math_binop_type::comp_lt: return lhs < rhs;
74 932 case math_binop_type::comp_eq: return lhs == rhs;
75 80 case math_binop_type::comp_ne: return lhs != rhs;
76 default:
77 asar_throw_error(2, error_type_block, error_id_internal_error, "evaluate_binop_compare with bad type");
78 }
79 }
80
81 2540 math_val evaluate_binop(math_val lhs, math_val rhs,
82 math_binop_type type) {
83 // todo: do this a bit smarter (bit_ops shouldn't cast int->float->int)
84
3/3
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2540 times.
✓ Branch 2 taken 2512 times.
5083 if (lhs.m_type == math_val_type::floating)
85
2/3
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
62 rhs = math_val(rhs.get_double());
86
3/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2509 times.
✓ Branch 2 taken 2506 times.
5021 else if (rhs.m_type == math_val_type::floating)
87
2/3
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 lhs = math_val(lhs.get_double());
88
7/12
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ 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 2535 times.
✓ Branch 10 taken 2500 times.
✗ Branch 11 not taken.
5083 switch (type) {
89 12 case math_binop_type::pow:
90 12 return math_val(pow(lhs.get_double(), rhs.get_double()));
91 16 case math_binop_type::div:
92
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 if (rhs.get_double() == 0.0)
93 4 asar_throw_error(2, error_type_block, error_id_division_by_zero);
94 12 return math_val(lhs.get_double() / rhs.get_double());
95 case math_binop_type::mod:
96 if (rhs.get_double() == 0.0)
97 asar_throw_error(2, error_type_block, error_id_division_by_zero);
98 // TODO: negative semantics
99 if (lhs.m_type == math_val_type::floating) {
100 return math_val(fmod(lhs.get_double(), rhs.get_double()));
101 } else {
102 return math_val(lhs.get_integer() % rhs.get_integer());
103 }
104 break;
105
106 6 case math_binop_type::shift_left: {
107 6 int64_t rhs_v = rhs.get_integer();
108
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (rhs_v < 0)
109 6 asar_throw_error(2, error_type_block, error_id_negative_shift);
110 return math_val(lhs.get_integer() << (uint64_t)rhs_v);
111 }
112 12 case math_binop_type::shift_right: {
113 12 int64_t rhs_v = rhs.get_integer();
114
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rhs_v < 0)
115 6 asar_throw_error(2, error_type_block, error_id_negative_shift);
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 return math_val(lhs.get_integer() >> (uint64_t)rhs_v);
117 }
118
119 case math_binop_type::bit_and:
120 return math_val(lhs.get_integer() & rhs.get_integer());
121 2 case math_binop_type::bit_or:
122 2 return math_val(lhs.get_integer() | rhs.get_integer());
123 case math_binop_type::bit_xor:
124 return math_val(lhs.get_integer() ^ rhs.get_integer());
125
126 case math_binop_type::logical_and:
127 case math_binop_type::logical_or:
128 asar_throw_error(2, error_type_block, error_id_internal_error,
129 "evaluate_binop() on logical ops loses short-circuiting");
130
131 2535 case math_binop_type::mul:
132 case math_binop_type::add:
133 case math_binop_type::sub:
134 // TODO error on string (also TODO support string +)
135
3/3
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1266 times.
✓ Branch 2 taken 1256 times.
2535 if (lhs.m_type == math_val_type::floating)
136 return math_val(evaluate_binop_arithmetic<double>(
137 26 lhs.get_double(), rhs.get_double(), type));
138 else
139 return math_val(evaluate_binop_arithmetic<int64_t>(
140 2509 lhs.get_integer(), rhs.get_integer(), type));
141
142 2500 case math_binop_type::comp_ge:
143 case math_binop_type::comp_le:
144 case math_binop_type::comp_gt:
145 case math_binop_type::comp_lt:
146 case math_binop_type::comp_eq:
147 case math_binop_type::comp_ne:
148
3/3
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1250 times.
✓ Branch 2 taken 1226 times.
2500 if (lhs.m_type == math_val_type::floating)
149 48 return math_val((int64_t)evaluate_binop_compare<double>(
150 48 lhs.get_double(), rhs.get_double(), type));
151 else
152 2452 return math_val((int64_t)evaluate_binop_compare<int64_t>(
153 2452 lhs.get_integer(), rhs.get_integer(), type));
154 }
155 }
156
157 5060 math_val math_ast_binop::evaluate(const eval_context &ctx) const {
158
2/4
✓ Branch 0 taken 2528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2532 times.
✗ Branch 3 not taken.
5060 math_val lhs = m_left->evaluate(ctx);
159
160 // handle short-circuiting for || and &&
161
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2522 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2526 times.
5060 if (m_type == math_binop_type::logical_or) {
162
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)
163 6 return math_val((int64_t)true);
164
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);
165
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 return math_val((int64_t)rhs.get_bool());
166 6 }
167
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2513 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2517 times.
5048 if (m_type == math_binop_type::logical_and) {
168
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)
169 6 return math_val((int64_t)false);
170
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);
171
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 return math_val((int64_t)rhs.get_bool());
172 12 }
173
174
3/4
✓ Branch 0 taken 2513 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2516 times.
✓ Branch 3 taken 1 times.
5030 math_val rhs = m_right->evaluate(ctx);
175
7/11
✓ Branch 0 taken 2513 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2513 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5021 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2516 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2508 times.
✓ Branch 10 taken 8 times.
5069 return evaluate_binop(lhs, rhs, m_type);
176 5076 }
177
178 5105 int math_ast_binop::has_label() const {
179 5105 return m_left->has_label() | m_right->has_label();
180 }
181
182
183 90 int math_ast_binop::get_len(bool could_be_bank_ex) const {
184
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 60 times.
90 if(could_be_bank_ex) {
185 30 int want_rhs = 0;
186
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) {
187 12 want_rhs = 65536;
188
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) {
189 12 want_rhs = 16;
190 }
191
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 if(want_rhs) {
192 24 math_ast_node* right_ptr = m_right.get();
193
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 auto right_lit = dynamic_cast<math_ast_literal*>(right_ptr);
194
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) {
195 24 int64_t right_val = right_lit->m_value.get_integer();
196
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if(right_val == want_rhs) return 1;
197 }
198 }
199 }
200
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));
201 }
202 35 math_val math_ast_unop::evaluate(const eval_context &ctx) const {
203
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);
204
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) {
205 64 case math_unop_type::neg:
206
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 50 times.
64 if (arg.m_type == math_val_type::floating)
207
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 return math_val(-arg.get_double());
208 else
209
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 return math_val(-arg.get_integer());
210 case math_unop_type::bit_not:
211 return math_val(~arg.get_integer());
212 6 case math_unop_type::bank_extract:
213
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 return math_val(arg.get_integer() >> 16);
214 }
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 }
216
217 60 int math_ast_unop::has_label() const { return m_arg->has_label(); }
218
219 18 int math_ast_unop::get_len(bool could_be_bank_ex) const {
220
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)
221 18 return 1;
222 return m_arg->get_len(false);
223 }
224
225 560 math_val math_ast_label::evaluate(const eval_context &ctx) const {
226
21/30
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 283 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 13 times.
✓ Branch 9 taken 264 times.
✓ Branch 10 taken 10 times.
✓ Branch 11 taken 267 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 270 times.
✓ Branch 22 taken 13 times.
✓ Branch 23 taken 270 times.
✓ Branch 24 taken 10 times.
✓ Branch 25 taken 273 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
560 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
227
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);
228
4/4
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 270 times.
✓ Branch 3 taken 3 times.
540 } else if (labels.exists(m_labelname)) {
229
4/8
✓ Branch 0 taken 266 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 266 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 270 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 270 times.
✗ Branch 7 not taken.
536 return math_val::make_identifier(m_labelname);
230 } else {
231 // possibly forward label, assume without namespace.
232 // TODO: this assumption can cause moving labels :)))))
233
1/10
✗ Branch 0 not taken.
✓ Branch 1 taken 4 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.
4 if(pass == 0) return math_val::make_identifier(m_labelname);
234 // if not pass 0, we know it's not a forward label and can throw the error
235 4 asar_throw_error(2, error_type_block, error_id_label_not_found,
236 m_labelname.data());
237 }
238 }
239
240 426 int math_ast_label::has_label() const {
241
19/30
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 213 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 205 times.
✓ Branch 10 taken 8 times.
✓ Branch 11 taken 205 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 8 times.
✓ Branch 21 taken 205 times.
✓ Branch 22 taken 8 times.
✓ Branch 23 taken 205 times.
✓ Branch 24 taken 8 times.
✓ Branch 25 taken 205 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
426 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
242
7/14
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
16 return labels.find(m_cur_ns + m_labelname).is_static ? 1 : 3;
243
4/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 200 times.
✓ Branch 3 taken 5 times.
410 } else if (labels.exists(m_labelname)) {
244
5/6
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 135 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 65 times.
✓ Branch 5 taken 135 times.
400 return labels.find(m_labelname).is_static ? 1 : 3;
245 }
246 // otherwise, non-static forward label
247 10 return 7;
248 }
249
250 744 int math_ast_label::get_len(bool could_be_bank_ex) const {
251 744 snes_label label;
252
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)) {
253
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);
254
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)) {
255
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);
256 99 } else return 2;
257
1/2
✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
645 return getlenforlabel(label, true);
258 }
259
260 math_function_ref
261 1054 math_ast_function_call::lookup_fname(string const &function_name) {
262
4/6
✓ Branch 0 taken 524 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 530 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 513 times.
1584 if (auto it = user_functions.find(function_name);
263
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 507 times.
1054 it != user_functions.end()) {
264 34 return it->second;
265
3/6
✓ Branch 0 taken 507 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 513 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 513 times.
✗ Branch 5 not taken.
1533 } else if (auto it = builtin_functions.find(function_name);
266
1/2
✓ Branch 0 taken 507 times.
✗ Branch 1 not taken.
1020 it != builtin_functions.end()) {
267 1020 return it->second;
268 } else {
269 asar_throw_error(2, error_type_block, error_id_function_not_found,
270 function_name.data());
271 }
272 }
273 976 math_val math_ast_function_call::evaluate(const eval_context &ctx) const {
274 976 std::vector<math_val> arg_vals;
275
4/4
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 485 times.
✓ Branch 2 taken 622 times.
✓ Branch 3 taken 491 times.
2214 for (auto const &p : m_arguments) {
276
4/7
✓ Branch 0 taken 616 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 616 times.
✓ Branch 3 taken 622 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 622 times.
✗ Branch 6 not taken.
1238 arg_vals.push_back(p->evaluate(ctx));
277 }
278
4/4
✓ Branch 0 taken 459 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 465 times.
✓ Branch 3 taken 26 times.
1900 return m_func.call(arg_vals);
279 976 }
280
281 968 int math_ast_function_call::has_label() const {
282 968 int out = m_func.has_label();
283
4/4
✓ Branch 0 taken 609 times.
✓ Branch 1 taken 481 times.
✓ Branch 2 taken 615 times.
✓ Branch 3 taken 487 times.
2192 for (auto const &p : m_arguments) {
284
2/4
✓ Branch 0 taken 609 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 615 times.
✗ Branch 3 not taken.
1224 out |= p->has_label();
285 }
286 968 return out;
287 }
288
289 96 int math_ast_function_call::get_len(bool could_be_bank_ex) const {
290 96 return m_func.get_len(m_arguments, could_be_bank_ex);
291 }
292
293 30 math_val math_user_function::call(const std::vector<math_val> &args) const {
294 30 math_ast_node::eval_context new_ctx;
295
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 new_ctx.userfunc_params = args;
296
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)
297 asar_throw_error(2, error_type_block, error_id_argument_count, m_arg_count,
298 (int)args.size());
299
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);
300 30 }
301
302 28 int math_user_function::has_label() const { return m_func_body->has_label(); }
303
304 6 int math_user_function::get_len(const std::vector<owned_node> &args,
305 bool could_be_bank_ex) const {
306 // TODO: this doesn't forward could_be_bank_ex to the fn call...
307 // supporting that properly would require stringing some context through all
308 // get_len calls supporting it less properly (making a special return value of
309 // get_len signify bankextract) could be viable tho...
310
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);
311
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) {
312 len = std::max(len, arg->get_len(false));
313 }
314 6 return len;
315 }
316
317