asar coverage - build #


src/asar/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
202 of 247, 0 excluded
81.8%
Functions:
26 of 30, 0 excluded
86.7%
Branches:
397 of 662, 0 excluded
60.0%

math_eval.cpp
Line Branch Exec Source
1 #include "math_ast.h"
2 #include "asar.h"
3 #include "errors.h"
4
5 234 double math_val::get_double() const {
6
8/10
✓ Branch 2 → 3 taken 64 times.
✓ Branch 2 → 4 taken 49 times.
✓ Branch 2 → 5 taken 2 times.
✓ Branch 2 → 7 taken 1 time.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 64 times.
✓ Branch 3 → 7 taken 50 times.
✓ Branch 3 → 10 taken 3 times.
✓ Branch 3 → 13 taken 1 time.
✗ Branch 3 → 16 not taken.
234 switch(m_type) {
7 128 case math_val_type::floating:
8 128 return m_numeric_val.double_;
9 99 case math_val_type::integer:
10 99 return (double)m_numeric_val.int_;
11 5 case math_val_type::identifier:
12 5 return (double)get_integer();
13 2 case math_val_type::string:
14 2 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 21911 int64_t math_val::get_integer() const {
22
8/10
✓ Branch 2 → 3 taken 15 times.
✓ Branch 2 → 4 taken 10607 times.
✓ Branch 2 → 5 taken 268 times.
✓ Branch 2 → 14 taken 1 time.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 15 times.
✓ Branch 3 → 7 taken 10733 times.
✓ Branch 3 → 10 taken 271 times.
✓ Branch 3 → 32 taken 1 time.
✗ Branch 3 → 35 not taken.
21911 switch(m_type) {
23 30 case math_val_type::floating:
24 // TODO: throw error on overflow?
25 30 return (int64_t)m_numeric_val.double_;
26 21340 case math_val_type::integer:
27 21340 return m_numeric_val.int_;
28 539 case math_val_type::identifier:
29
2/4
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 11 taken 268 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 22 taken 271 times.
539 if(!labels.exists(m_string_val)) {
30 throw_err_block(pass, err_internal_error, "evaluating nonexistent label");
31 }
32 539 return labels.find(m_string_val).pos;
33 2 case math_val_type::string:
34 2 throw_err_block(2, err_bad_type, "number", "string");
35 }
36 throw_err_block(pass, err_internal_error, "math_val invalid type");
37 }
38 357 const string &math_val::get_str() const {
39
4/4
✓ Branch 2 → 3 taken 173 times.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 3 → 4 taken 182 times.
✓ Branch 3 → 10 taken 1 time.
357 if (m_type == math_val_type::string)
40 355 return m_string_val;
41 2 throw_err_block(2, err_bad_type, "string", "number"); // TODO is "number" a good name for identifier/int/float?
42 }
43
44 404 const string &math_val::get_identifier() const {
45
4/4
✓ Branch 2 → 3 taken 201 times.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 3 → 4 taken 201 times.
✓ Branch 3 → 10 taken 1 time.
404 if (m_type == math_val_type::identifier)
46 402 return m_string_val;
47
2/4
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 1 time.
2 const char* type_name = (m_type == math_val_type::string) ? "string" : "number";
48 2 throw_err_block(2, err_bad_type, "identifier", type_name);
49 }
50 2850 bool math_val::get_bool() const {
51
4/8
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 5 taken 1422 times.
✗ Branch 2 → 7 not taken.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 7 taken 1424 times.
✗ Branch 3 → 10 not taken.
✗ Branch 3 → 15 not taken.
2850 switch (m_type) {
52 4 case math_val_type::floating:
53 4 return get_double() != 0.0;
54 2846 case math_val_type::integer:
55 case math_val_type::identifier:
56 2846 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 1990 bool evaluate_binop_compare(const T& lhs, const T& rhs, math_binop_type type) {
65
11/26
bool evaluate_binop_compare<string>(string const&, string const&, math_binop_type):
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
✓ Branch 2 → 5 taken 2 times.
✓ Branch 2 → 6 taken 4 times.
✗ Branch 2 → 7 not taken.
bool evaluate_binop_compare<double>(double const&, double const&, math_binop_type):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
✗ Branch 2 → 5 not taken.
✗ Branch 2 → 6 not taken.
✗ Branch 2 → 7 not taken.
✗ Branch 2 → 9 not taken.
✗ Branch 2 → 12 not taken.
✗ Branch 2 → 15 not taken.
bool evaluate_binop_compare<long>(long const&, long const&, math_binop_type):
✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 4 not taken.
✗ Branch 2 → 5 not taken.
✓ Branch 2 → 6 taken 4 times.
✗ Branch 2 → 7 not taken.
✓ Branch 2 → 9 taken 77 times.
✓ Branch 2 → 12 taken 904 times.
✗ Branch 2 → 15 not taken.
bool evaluate_binop_compare<long long>(long long const&, long long const&, math_binop_type):
✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 4 taken 4 times.
✓ Branch 2 → 5 taken 77 times.
✓ Branch 2 → 6 taken 904 times.
✗ Branch 2 → 7 not taken.
1990 switch(type) {
66 14 case math_binop_type::comp_ge: return lhs >= rhs;
67 8 case math_binop_type::comp_le: return lhs <= rhs;
68 156 case math_binop_type::comp_gt: return lhs > rhs;
69 1812 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 416 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 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 207 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 207 times.
416 if((lhs.m_type == math_val_type::string) != (rhs.m_type == math_val_type::string)) {
78 2 return false;
79 }
80
4/4
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 8 taken 202 times.
✓ Branch 7 → 8 taken 5 times.
✓ Branch 7 → 11 taken 202 times.
414 if(lhs.m_type == math_val_type::string) {
81 // both strings: compare as strings
82 10 return lhs.get_str() == rhs.get_str();
83 } else {
84 // both non strings: compare as numbers
85
8/8
✓ Branch 8 → 9 taken 194 times.
✓ Branch 8 → 10 taken 8 times.
✓ Branch 9 → 10 taken 6 times.
✓ Branch 9 → 13 taken 188 times.
✓ Branch 12 → 13 taken 194 times.
✓ Branch 12 → 15 taken 8 times.
✓ Branch 14 → 15 taken 6 times.
✓ Branch 14 → 18 taken 188 times.
404 if(lhs.m_type == math_val_type::floating || rhs.m_type == math_val_type::floating)
86 // one floating: compare as floats
87 28 return lhs.get_double() == rhs.get_double();
88 else
89 // both ints: compare as ints
90 376 return lhs.get_integer() == rhs.get_integer();
91 }
92 }
93
94 4988 math_val evaluate_binop(math_val lhs, math_val rhs,
95 math_binop_type type) {
96
6/7
✓ Branch 2 → 3 taken 2478 times.
✓ Branch 2 → 4 taken 15 times.
✓ Branch 3 → 4 taken 2480 times.
✓ Branch 3 → 5 taken 2478 times.
✓ Branch 3 → 6 taken 15 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 2480 times.
4988 bool has_string = (lhs.m_type == math_val_type::string) || (rhs.m_type == math_val_type::string);
97
8/8
✓ Branch 6 → 7 taken 2476 times.
✓ Branch 6 → 8 taken 17 times.
✓ Branch 7 → 8 taken 6 times.
✓ Branch 7 → 9 taken 2470 times.
✓ Branch 9 → 10 taken 2478 times.
✓ Branch 9 → 12 taken 17 times.
✓ Branch 11 → 12 taken 6 times.
✓ Branch 11 → 13 taken 2472 times.
4988 bool has_float = (lhs.m_type == math_val_type::floating) || (rhs.m_type == math_val_type::floating);
98
24/32
✓ Branch 10 → 11 taken 6 times.
✓ Branch 10 → 14 taken 8 times.
✓ Branch 10 → 22 taken 1 time.
✓ Branch 10 → 34 taken 1 time.
✓ Branch 10 → 41 taken 4 times.
✗ Branch 10 → 48 not taken.
✓ Branch 10 → 51 taken 1 time.
✗ Branch 10 → 54 not taken.
✗ Branch 10 → 57 not taken.
✓ Branch 10 → 60 taken 975 times.
✓ Branch 10 → 76 taken 27 times.
✓ Branch 10 → 83 taken 267 times.
✓ Branch 10 → 90 taken 995 times.
✓ Branch 10 → 106 taken 191 times.
✓ Branch 10 → 113 taken 17 times.
✗ Branch 10 → 120 not taken.
✓ Branch 14 → 15 taken 6 times.
✓ Branch 14 → 18 taken 8 times.
✓ Branch 14 → 26 taken 1 time.
✓ Branch 14 → 40 taken 1 time.
✓ Branch 14 → 49 taken 4 times.
✗ Branch 14 → 58 not taken.
✓ Branch 14 → 61 taken 1 time.
✗ Branch 14 → 64 not taken.
✗ Branch 14 → 67 not taken.
✓ Branch 14 → 70 taken 977 times.
✓ Branch 14 → 88 taken 27 times.
✓ Branch 14 → 95 taken 267 times.
✓ Branch 14 → 102 taken 995 times.
✓ Branch 14 → 128 taken 191 times.
✓ Branch 14 → 138 taken 17 times.
✗ Branch 14 → 148 not taken.
4988 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
4/4
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 19 taken 6 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 23 taken 6 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 2 case math_binop_type::mod:
106
0/4
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 27 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 31 not taken.
2 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 2 case math_binop_type::shift_left: {
117 2 int64_t rhs_v = rhs.get_integer();
118
2/4
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 39 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 45 not taken.
2 if (rhs_v < 0)
119 2 throw_err_block(2, err_negative_shift);
120 return math_val(lhs.get_integer() << (uint64_t)rhs_v);
121 }
122 8 case math_binop_type::shift_right: {
123 8 int64_t rhs_v = rhs.get_integer();
124
4/4
✓ Branch 42 → 43 taken 1 time.
✓ Branch 42 → 46 taken 3 times.
✓ Branch 50 → 51 taken 1 time.
✓ Branch 50 → 54 taken 3 times.
8 if (rhs_v < 0)
125 2 throw_err_block(2, err_negative_shift);
126
1/2
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 57 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 1952 case math_binop_type::add:
141
14/20
✓ Branch 60 → 61 taken 3 times.
✓ Branch 60 → 69 taken 972 times.
✓ Branch 61 → 62 taken 2 times.
✓ Branch 61 → 126 taken 1 time.
✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 126 not taken.
✓ Branch 64 → 65 taken 2 times.
✗ Branch 64 → 126 not taken.
✓ Branch 65 → 66 taken 2 times.
✗ Branch 65 → 124 not taken.
✓ Branch 70 → 71 taken 3 times.
✓ Branch 70 → 81 taken 974 times.
✓ Branch 72 → 73 taken 2 times.
✓ Branch 72 → 154 taken 1 time.
✓ Branch 75 → 76 taken 2 times.
✗ Branch 75 → 154 not taken.
✓ Branch 76 → 77 taken 2 times.
✗ Branch 76 → 154 not taken.
✓ Branch 77 → 78 taken 2 times.
✗ Branch 77 → 152 not taken.
1952 if(has_string) return math_val(lhs.get_str() + rhs.get_str());
142
4/4
✓ Branch 69 → 70 taken 5 times.
✓ Branch 69 → 73 taken 967 times.
✓ Branch 81 → 82 taken 5 times.
✓ Branch 81 → 85 taken 969 times.
1946 else if(has_float) return math_val(lhs.get_double() + rhs.get_double());
143 1936 else return math_val(lhs.get_integer() + rhs.get_integer());
144 54 case math_binop_type::mul:
145
4/4
✓ Branch 76 → 77 taken 4 times.
✓ Branch 76 → 80 taken 23 times.
✓ Branch 88 → 89 taken 4 times.
✓ Branch 88 → 92 taken 23 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 534 case math_binop_type::sub:
148
2/4
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 87 taken 267 times.
✗ Branch 95 → 96 not taken.
✓ Branch 95 → 99 taken 267 times.
534 if(has_float) return math_val(lhs.get_double() - rhs.get_double());
149 534 else return math_val(lhs.get_integer() - rhs.get_integer());
150
151 1990 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
4/4
✓ Branch 90 → 91 taken 4 times.
✓ Branch 90 → 95 taken 991 times.
✓ Branch 102 → 103 taken 4 times.
✓ Branch 102 → 107 taken 991 times.
1990 if(has_string) return (int64_t)evaluate_binop_compare(lhs.get_str(), rhs.get_str(), type);
156
2/16
✗ Branch 95 → 96 not taken.
✓ Branch 95 → 101 taken 991 times.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 128 not taken.
✗ Branch 97 → 98 not taken.
✗ Branch 97 → 127 not taken.
✗ Branch 98 → 99 not taken.
✗ Branch 98 → 127 not taken.
✗ Branch 107 → 108 not taken.
✓ Branch 107 → 118 taken 991 times.
✗ Branch 109 → 110 not taken.
✗ Branch 109 → 158 not taken.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 156 not taken.
✗ Branch 114 → 115 not taken.
✗ Branch 114 → 156 not taken.
1982 else if(has_float) return (int64_t)evaluate_binop_compare(lhs.get_double(), rhs.get_double(), type);
157
6/12
✓ Branch 101 → 102 taken 991 times.
✗ Branch 101 → 130 not taken.
✓ Branch 102 → 103 taken 991 times.
✗ Branch 102 → 129 not taken.
✓ Branch 103 → 104 taken 991 times.
✗ Branch 103 → 129 not taken.
✓ Branch 119 → 120 taken 991 times.
✗ Branch 119 → 162 not taken.
✓ Branch 122 → 123 taken 991 times.
✗ Branch 122 → 160 not taken.
✓ Branch 124 → 125 taken 991 times.
✗ Branch 124 → 160 not taken.
1982 else return (int64_t)evaluate_binop_compare(lhs.get_integer(), rhs.get_integer(), type);
158
159
6/12
✓ Branch 106 → 107 taken 191 times.
✗ Branch 106 → 136 not taken.
✓ Branch 107 → 108 taken 191 times.
✗ Branch 107 → 133 not taken.
✓ Branch 108 → 109 taken 191 times.
✗ Branch 108 → 131 not taken.
✓ Branch 129 → 130 taken 191 times.
✗ Branch 129 → 170 not taken.
✓ Branch 131 → 132 taken 191 times.
✗ Branch 131 → 166 not taken.
✓ Branch 132 → 133 taken 191 times.
✗ Branch 132 → 164 not taken.
382 case math_binop_type::comp_eq: return (int64_t)evaluate_eq(lhs, rhs);
160
6/12
✓ Branch 113 → 114 taken 17 times.
✗ Branch 113 → 142 not taken.
✓ Branch 114 → 115 taken 17 times.
✗ Branch 114 → 139 not taken.
✓ Branch 115 → 116 taken 17 times.
✗ Branch 115 → 137 not taken.
✓ Branch 139 → 140 taken 17 times.
✗ Branch 139 → 178 not taken.
✓ Branch 141 → 142 taken 17 times.
✗ Branch 141 → 174 not taken.
✓ Branch 142 → 143 taken 17 times.
✗ Branch 142 → 172 not taken.
34 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 4957 math_val math_ast_binop::evaluate(const eval_context &ctx) const {
166
2/4
✓ Branch 3 → 4 taken 2477 times.
✗ Branch 3 → 52 not taken.
✓ Branch 11 → 12 taken 2480 times.
✗ Branch 11 → 106 not taken.
4957 math_val lhs = m_left->evaluate(ctx);
167
168 // handle short-circuiting for || and &&
169
4/4
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 14 taken 2473 times.
✓ Branch 16 → 17 taken 4 times.
✓ Branch 16 → 34 taken 2476 times.
4957 if (m_type == math_binop_type::logical_or) {
170
6/8
✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 38 not taken.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 3 times.
✓ Branch 17 → 18 taken 4 times.
✗ Branch 17 → 88 not taken.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 20 taken 3 times.
8 if (lhs.get_bool() == true)
171 2 return math_val((int64_t)true);
172
2/4
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 38 not taken.
✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 88 not taken.
6 math_val rhs = m_right->evaluate(ctx);
173
2/4
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 36 not taken.
✓ Branch 30 → 31 taken 3 times.
✗ Branch 30 → 86 not taken.
6 return math_val((int64_t)rhs.get_bool());
174 6 }
175
4/4
✓ Branch 14 → 15 taken 7 times.
✓ Branch 14 → 24 taken 2466 times.
✓ Branch 38 → 39 taken 7 times.
✓ Branch 38 → 56 taken 2469 times.
4949 if (m_type == math_binop_type::logical_and) {
176
6/8
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 41 not taken.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 18 taken 6 times.
✓ Branch 39 → 40 taken 7 times.
✗ Branch 39 → 92 not taken.
✓ Branch 40 → 41 taken 1 time.
✓ Branch 40 → 42 taken 6 times.
14 if (lhs.get_bool() == false)
177 2 return math_val((int64_t)false);
178
2/4
✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 41 not taken.
✓ Branch 51 → 52 taken 6 times.
✗ Branch 51 → 92 not taken.
12 math_val rhs = m_right->evaluate(ctx);
179
2/4
✓ Branch 20 → 21 taken 6 times.
✗ Branch 20 → 39 not taken.
✓ Branch 52 → 53 taken 6 times.
✗ Branch 52 → 90 not taken.
12 return math_val((int64_t)rhs.get_bool());
180 12 }
181
182
3/4
✓ Branch 25 → 26 taken 2466 times.
✗ Branch 25 → 50 not taken.
✓ Branch 65 → 66 taken 2468 times.
✓ Branch 65 → 104 taken 1 time.
4935 math_val rhs = m_right->evaluate(ctx);
183
8/12
✓ Branch 26 → 27 taken 2466 times.
✗ Branch 26 → 47 not taken.
✓ Branch 27 → 28 taken 2466 times.
✗ Branch 27 → 44 not taken.
✓ Branch 28 → 29 taken 2459 times.
✓ Branch 28 → 42 taken 7 times.
✓ Branch 71 → 72 taken 2468 times.
✗ Branch 71 → 100 not taken.
✓ Branch 73 → 74 taken 2468 times.
✗ Branch 73 → 96 not taken.
✓ Branch 75 → 76 taken 2461 times.
✓ Branch 75 → 94 taken 7 times.
4969 return evaluate_binop(lhs, rhs, m_type);
184 4971 }
185
186 4710 int math_ast_binop::has_label() const {
187 4710 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
3/3
✓ Branch 2 → 3 taken 30 times.
✓ Branch 2 → 17 taken 30 times.
✓ Branch 2 → 37 taken 30 times.
90 if(could_be_bank_ex) {
193 30 int want_rhs = 0;
194
4/4
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 5 taken 9 times.
✓ Branch 7 → 8 taken 6 times.
✓ Branch 7 → 9 taken 9 times.
30 if(m_type == math_binop_type::div) {
195 12 want_rhs = 65536;
196
4/4
✓ Branch 5 → 6 taken 6 times.
✓ Branch 5 → 7 taken 3 times.
✓ Branch 13 → 14 taken 6 times.
✓ Branch 13 → 15 taken 3 times.
18 } else if(m_type == math_binop_type::shift_right) {
197 12 want_rhs = 16;
198 }
199
4/4
✓ Branch 7 → 8 taken 12 times.
✓ Branch 7 → 17 taken 3 times.
✓ Branch 15 → 16 taken 12 times.
✓ Branch 15 → 37 taken 3 times.
30 if(want_rhs) {
200 24 math_ast_node* right_ptr = m_right.get();
201
2/4
✓ Branch 9 → 10 taken 12 times.
✗ Branch 9 → 11 not taken.
✓ Branch 22 → 23 taken 12 times.
✗ Branch 22 → 24 not taken.
24 auto right_lit = dynamic_cast<math_ast_literal*>(right_ptr);
202
4/8
✓ Branch 12 → 13 taken 12 times.
✗ Branch 12 → 17 not taken.
✓ Branch 13 → 14 taken 12 times.
✗ Branch 13 → 17 not taken.
✓ Branch 25 → 26 taken 12 times.
✗ Branch 25 → 37 not taken.
✓ Branch 30 → 31 taken 12 times.
✗ Branch 30 → 37 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
2/4
✓ Branch 15 → 16 taken 12 times.
✗ Branch 15 → 17 not taken.
✓ Branch 35 → 36 taken 12 times.
✗ Branch 35 → 37 not taken.
24 if(right_val == want_rhs) return 1;
205 }
206 }
207 }
208
4/8
✓ Branch 18 → 19 taken 33 times.
✗ Branch 18 → 26 not taken.
✓ Branch 20 → 21 taken 33 times.
✗ Branch 20 → 25 not taken.
✓ Branch 50 → 51 taken 33 times.
✗ Branch 50 → 75 not taken.
✓ Branch 65 → 66 taken 33 times.
✗ Branch 65 → 73 not taken.
66 return std::max(m_left->get_len(false), m_right->get_len(false));
209 }
210 46 math_val math_ast_unop::evaluate(const eval_context &ctx) const {
211
2/4
✓ Branch 3 → 4 taken 23 times.
✗ Branch 3 → 22 not taken.
✓ Branch 11 → 12 taken 23 times.
✗ Branch 11 → 34 not taken.
46 math_val arg = m_arg->evaluate(ctx);
212
4/8
✓ Branch 4 → 5 taken 20 times.
✗ Branch 4 → 10 not taken.
✓ Branch 4 → 12 taken 3 times.
✗ Branch 4 → 14 not taken.
✓ Branch 16 → 17 taken 20 times.
✗ Branch 16 → 22 not taken.
✓ Branch 16 → 24 taken 3 times.
✗ Branch 16 → 26 not taken.
46 switch (m_type) {
213 40 case math_unop_type::neg:
214
4/4
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 8 taken 15 times.
✓ Branch 17 → 18 taken 5 times.
✓ Branch 17 → 20 taken 15 times.
40 if (arg.m_type == math_val_type::floating)
215
2/4
✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 20 not taken.
✓ Branch 18 → 19 taken 5 times.
✗ Branch 18 → 32 not taken.
10 return math_val(-arg.get_double());
216 else
217
2/4
✓ Branch 8 → 9 taken 15 times.
✗ Branch 8 → 20 not taken.
✓ Branch 20 → 21 taken 15 times.
✗ Branch 20 → 32 not taken.
30 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
2/4
✓ Branch 12 → 13 taken 3 times.
✗ Branch 12 → 20 not taken.
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 32 not taken.
6 return math_val(arg.get_integer() >> 16);
222 }
223 throw_err_block(pass, err_internal_error, "evaluate_unop invalid unop");
224 46 }
225
226 6 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/7
✓ Branch 2 → 3 taken 18 times.
✗ Branch 2 → 5 not taken.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 9 times.
✗ Branch 3 → 5 not taken.
✓ Branch 7 → 8 taken 9 times.
✗ Branch 7 → 9 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 8 math_val math_ast_ternary_cond::evaluate(const eval_context& ctx) const {
235
8/12
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 14 not taken.
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 12 not taken.
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 9 taken 1 time.
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 40 not taken.
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 38 not taken.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 27 taken 1 time.
8 if(m_cond->evaluate(ctx).get_bool()) {
236 6 return m_true->evaluate(ctx);
237 } else {
238 2 return m_false->evaluate(ctx);
239 }
240 }
241
242 int math_ast_ternary_cond::has_label() const {
243 return m_cond->has_label() | m_true->has_label() | m_false->has_label();
244 }
245
246 int math_ast_ternary_cond::get_len(bool could_be_bank_ex) const {
247 return std::max(m_true->get_len(false), m_false->get_len(false));
248 }
249
250 594 math_val math_ast_label::evaluate(const eval_context &ctx) const {
251
21/31
✓ Branch 3 → 4 taken 13 times.
✓ Branch 3 → 10 taken 282 times.
✓ Branch 5 → 6 taken 13 times.
✗ Branch 5 → 39 not taken.
✓ Branch 7 → 8 taken 13 times.
✗ Branch 7 → 39 not taken.
✓ Branch 8 → 9 taken 23 times.
✓ Branch 8 → 10 taken 3 times.
✓ Branch 8 → 25 taken 286 times.
✓ Branch 11 → 12 taken 13 times.
✓ Branch 11 → 13 taken 282 times.
✓ Branch 13 → 14 taken 10 times.
✓ Branch 13 → 20 taken 285 times.
✓ Branch 19 → 20 taken 13 times.
✗ Branch 19 → 90 not taken.
✓ Branch 22 → 23 taken 13 times.
✗ Branch 22 → 90 not taken.
✓ Branch 23 → 24 taken 10 times.
✓ Branch 23 → 25 taken 3 times.
✓ Branch 26 → 27 taken 13 times.
✓ Branch 26 → 28 taken 286 times.
✓ Branch 28 → 29 taken 13 times.
✓ Branch 28 → 30 taken 286 times.
✓ Branch 30 → 31 taken 10 times.
✓ Branch 30 → 46 taken 289 times.
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 41 not taken.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 92 not taken.
✗ Branch 93 → 94 not taken.
✗ Branch 93 → 95 not taken.
594 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
252
4/8
✓ Branch 15 → 16 taken 10 times.
✗ Branch 15 → 45 not taken.
✓ Branch 16 → 17 taken 10 times.
✗ Branch 16 → 43 not taken.
✓ Branch 40 → 41 taken 10 times.
✗ Branch 40 → 98 not taken.
✓ Branch 42 → 43 taken 10 times.
✗ Branch 42 → 96 not taken.
30 return math_val::make_identifier(m_cur_ns + m_labelname);
253
4/4
✓ Branch 22 → 23 taken 283 times.
✓ Branch 22 → 28 taken 2 times.
✓ Branch 54 → 55 taken 286 times.
✓ Branch 54 → 67 taken 3 times.
574 } else if (labels.exists(m_labelname)) {
254
4/8
✓ Branch 23 → 24 taken 283 times.
✗ Branch 23 → 48 not taken.
✓ Branch 24 → 25 taken 283 times.
✗ Branch 24 → 46 not taken.
✓ Branch 61 → 62 taken 286 times.
✗ Branch 61 → 102 not taken.
✓ Branch 63 → 64 taken 286 times.
✗ Branch 63 → 100 not taken.
855 return math_val::make_identifier(m_labelname);
255 } else {
256 // possibly forward label, assume without namespace.
257 // TODO: this assumption can cause moving labels :)))))
258
2/12
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 34 taken 2 times.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 51 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 49 not taken.
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 80 taken 3 times.
✗ Branch 74 → 75 not taken.
✗ Branch 74 → 106 not taken.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 104 not taken.
5 if(pass == 0) return math_val::make_identifier(m_labelname);
259 // if not pass 0, we know it's not a forward label and can throw the error
260 5 throw_err_block(2, err_label_not_found, m_labelname.data());
261 }
262 }
263
264 304 int math_ast_label::has_label() const {
265
19/31
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 10 taken 150 times.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 35 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 35 not taken.
✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 10 not taken.
✓ Branch 8 → 25 taken 150 times.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 150 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 24 taken 150 times.
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 80 not taken.
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 80 not taken.
✓ Branch 23 → 24 taken 2 times.
✗ Branch 23 → 25 not taken.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 28 taken 150 times.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 30 taken 150 times.
✓ Branch 30 → 31 taken 2 times.
✓ Branch 30 → 54 taken 150 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
✗ Branch 83 → 84 not taken.
✗ Branch 83 → 85 not taken.
304 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
266
7/14
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 41 not taken.
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 2 times.
✓ Branch 41 → 42 taken 2 times.
✗ Branch 41 → 88 not taken.
✓ Branch 44 → 45 taken 2 times.
✗ Branch 44 → 86 not taken.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 2 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 2 times.
4 return labels.find(m_cur_ns + m_labelname).is_static ? 1 : 3;
267
4/4
✓ Branch 26 → 27 taken 144 times.
✓ Branch 26 → 33 taken 6 times.
✓ Branch 62 → 63 taken 144 times.
✓ Branch 62 → 78 taken 6 times.
300 } else if (labels.exists(m_labelname)) {
268
5/6
✓ Branch 29 → 30 taken 64 times.
✓ Branch 29 → 31 taken 80 times.
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 74 taken 144 times.
✓ Branch 74 → 75 taken 64 times.
✓ Branch 74 → 76 taken 80 times.
288 return labels.find(m_labelname).is_static ? 1 : 3;
269 }
270 // otherwise, non-static forward label
271 12 return 7;
272 }
273
274 792 int math_ast_label::get_len(bool could_be_bank_ex) const {
275 792 snes_label label;
276
22/31
✓ Branch 4 → 5 taken 15 times.
✓ Branch 4 → 11 taken 378 times.
✓ Branch 6 → 7 taken 15 times.
✗ Branch 6 → 32 not taken.
✓ Branch 8 → 9 taken 15 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 5 times.
✓ Branch 9 → 11 taken 10 times.
✓ Branch 10 → 11 taken 15 times.
✓ Branch 10 → 27 taken 384 times.
✓ Branch 12 → 13 taken 15 times.
✓ Branch 12 → 14 taken 378 times.
✓ Branch 14 → 15 taken 5 times.
✓ Branch 14 → 21 taken 388 times.
✓ Branch 21 → 22 taken 15 times.
✗ Branch 21 → 76 not taken.
✓ Branch 24 → 25 taken 15 times.
✗ Branch 24 → 76 not taken.
✓ Branch 25 → 26 taken 5 times.
✓ Branch 25 → 27 taken 10 times.
✓ Branch 28 → 29 taken 15 times.
✓ Branch 28 → 30 taken 384 times.
✓ Branch 30 → 31 taken 15 times.
✓ Branch 30 → 32 taken 384 times.
✓ Branch 32 → 33 taken 5 times.
✗ Branch 32 → 34 not taken.
✓ Branch 32 → 51 taken 394 times.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
✗ Branch 79 → 80 not taken.
✗ Branch 79 → 81 not taken.
792 if (m_cur_ns && labels.exists(m_cur_ns + m_labelname)) {
277
4/8
✓ Branch 16 → 17 taken 5 times.
✗ Branch 16 → 38 not taken.
✓ Branch 18 → 19 taken 5 times.
✗ Branch 18 → 36 not taken.
✓ Branch 43 → 44 taken 5 times.
✗ Branch 43 → 84 not taken.
✓ Branch 46 → 47 taken 5 times.
✗ Branch 46 → 82 not taken.
10 label = labels.find(m_cur_ns + m_labelname);
278
6/8
✓ Branch 22 → 23 taken 388 times.
✗ Branch 22 → 39 not taken.
✓ Branch 23 → 24 taken 337 times.
✓ Branch 23 → 27 taken 51 times.
✓ Branch 58 → 59 taken 394 times.
✗ Branch 58 → 86 not taken.
✓ Branch 59 → 60 taken 342 times.
✓ Branch 59 → 71 taken 52 times.
782 } else if (labels.exists(m_labelname)) {
279
2/4
✓ Branch 25 → 26 taken 337 times.
✗ Branch 25 → 39 not taken.
✓ Branch 67 → 68 taken 342 times.
✗ Branch 67 → 86 not taken.
679 label = labels.find(m_labelname);
280 103 } else return 2;
281
2/4
✓ Branch 28 → 29 taken 342 times.
✗ Branch 28 → 39 not taken.
✓ Branch 72 → 73 taken 347 times.
✗ Branch 72 → 86 not taken.
689 return getlenforlabel(label, true);
282 }
283
284 math_function_ref
285 997 math_ast_function_call::lookup_fname(string const &function_name) {
286
4/7
✓ Branch 2 → 3 taken 496 times.
✗ Branch 2 → 22 not taken.
✗ Branch 2 → 25 not taken.
✓ Branch 5 → 6 taken 501 times.
✗ Branch 5 → 50 not taken.
✓ Branch 12 → 13 taken 15 times.
✓ Branch 12 → 21 taken 486 times.
1498 if (auto it = user_functions.find(function_name);
287
2/3
✓ Branch 5 → 6 taken 15 times.
✓ Branch 5 → 8 taken 481 times.
✗ Branch 5 → 10 not taken.
997 it != user_functions.end()) {
288 30 return it->second;
289
3/8
✓ Branch 8 → 9 taken 481 times.
✗ Branch 8 → 21 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 24 not taken.
✓ Branch 24 → 25 taken 486 times.
✗ Branch 24 → 48 not taken.
✓ Branch 31 → 32 taken 486 times.
✗ Branch 31 → 41 not taken.
1453 } else if (auto it = builtin_functions.find(function_name);
290
1/4
✓ Branch 11 → 12 taken 481 times.
✗ Branch 11 → 14 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 18 not taken.
967 it != builtin_functions.end()) {
291 967 return it->second;
292 } else {
293 throw_err_block(2, err_function_not_found, function_name.data());
294 }
295 }
296 919 math_val math_ast_function_call::evaluate(const eval_context &ctx) const {
297 919 std::vector<math_val> arg_vals;
298
4/4
✓ Branch 12 → 5 taken 576 times.
✓ Branch 12 → 13 taken 454 times.
✓ Branch 29 → 15 taken 581 times.
✓ Branch 29 → 30 taken 459 times.
2070 for (auto const &p : m_arguments) {
299
6/8
✓ Branch 7 → 8 taken 573 times.
✓ Branch 7 → 20 taken 3 times.
✓ Branch 8 → 9 taken 573 times.
✗ Branch 8 → 18 not taken.
✓ Branch 22 → 23 taken 578 times.
✓ Branch 22 → 42 taken 3 times.
✓ Branch 24 → 25 taken 578 times.
✗ Branch 24 → 40 not taken.
1157 arg_vals.push_back(p->evaluate(ctx));
300 }
301
4/4
✓ Branch 13 → 14 taken 440 times.
✓ Branch 13 → 22 taken 14 times.
✓ Branch 35 → 36 taken 445 times.
✓ Branch 35 → 47 taken 14 times.
1798 return m_func.call(arg_vals);
302 919 }
303
304 486 int math_ast_function_call::has_label() const {
305 486 int out = m_func.has_label();
306
4/4
✓ Branch 10 → 5 taken 240 times.
✓ Branch 10 → 11 taken 243 times.
✓ Branch 32 → 19 taken 240 times.
✓ Branch 32 → 33 taken 243 times.
966 for (auto const &p : m_arguments) {
307
2/4
✓ Branch 7 → 8 taken 240 times.
✗ Branch 7 → 13 not taken.
✓ Branch 29 → 30 taken 240 times.
✗ Branch 29 → 37 not taken.
480 out |= p->has_label();
308 }
309 486 return out;
310 }
311
312 96 int math_ast_function_call::get_len(bool could_be_bank_ex) const {
313 96 return m_func.get_len(m_arguments, could_be_bank_ex);
314 }
315
316 26 math_val math_user_function::call(const std::vector<math_val> &args) const {
317 26 math_ast_node::eval_context new_ctx;
318
2/4
✓ Branch 3 → 4 taken 13 times.
✗ Branch 3 → 16 not taken.
✓ Branch 4 → 5 taken 13 times.
✗ Branch 4 → 29 not taken.
26 new_ctx.userfunc_params = args;
319
2/4
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 10 taken 13 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 15 taken 13 times.
26 if (args.size() != m_arg_count)
320 throw_err_block(2, err_argument_count, (int)m_arg_count, (int)args.size());
321
2/4
✓ Branch 11 → 12 taken 13 times.
✗ Branch 11 → 16 not taken.
✓ Branch 24 → 25 taken 13 times.
✗ Branch 24 → 29 not taken.
52 return m_func_body->evaluate(new_ctx);
322 26 }
323
324 int math_user_function::has_label() const { return m_func_body->has_label(); }
325
326 6 int math_user_function::get_len(const std::vector<owned_node> &args,
327 bool could_be_bank_ex) const {
328 // TODO: this doesn't forward could_be_bank_ex to the fn call...
329 // supporting that properly would require stringing some context through all
330 // get_len calls; supporting it less properly (making a special return value of
331 // get_len signify bankextract) could be viable tho...
332
2/4
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 17 not taken.
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 50 not taken.
6 int len = m_func_body->get_len(false);
333
2/4
✗ Branch 12 → 6 not taken.
✓ Branch 12 → 13 taken 3 times.
✗ Branch 40 → 22 not taken.
✓ Branch 40 → 41 taken 3 times.
6 for (auto &arg : args) {
334 len = std::max(len, arg->get_len(false));
335 }
336 6 return len;
337 }
338
339