asar coverage - build #275


src/asar/
File: src/asar/math_eval.cpp
Date: 2025-03-04 15:51:07
Lines:
188/214
87.9%
Functions:
26/27
96.3%
Branches:
315/496
63.5%

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