asar coverage - build #325


src/asar/
File: src/asar/math_ast.h
Date: 2025-11-04 16:32:25
Lines:
46/48
95.8%
Functions:
31/34
91.2%
Branches:
23/36
63.9%

Line Branch Exec Source
1 #include <memory>
2 #include <variant>
3 #include <vector>
4 #include <unordered_map>
5 #include "libstr.h"
6 #include "asar_math.h"
7 #include "assembleblock.h"
8
9 using owned_node = std::unique_ptr<math_ast_node>;
10
11 enum class math_binop_type {
12 pow, // **
13 mul, // *
14 div, // /
15 mod, // %
16 add, // +
17 sub, // -
18 shift_left, // <<
19 shift_right, // >>
20 bit_and, // &
21 bit_or, // |
22 bit_xor, // ^
23 logical_and, // &&
24 logical_or, // ||
25 comp_ge, // >=
26 comp_le, // <=
27 comp_gt, // >
28 comp_lt, // <
29 comp_eq, // ==
30 comp_ne, // !=
31 };
32
33 math_val evaluate_binop(math_val lhs, math_val rhs, math_binop_type type);
34
35 class math_ast_binop : public math_ast_node {
36 public:
37 owned_node m_left, m_right;
38 math_binop_type m_type;
39 5097 math_ast_binop(owned_node left_in, owned_node right_in, math_binop_type type_in)
40 5097 : m_left(std::move(left_in)), m_right(std::move(right_in)), m_type(type_in) {}
41
42 math_val evaluate(const eval_context &ctx) const;
43 int has_label() const;
44 int get_len(bool could_be_bank_ex) const;
45 };
46
47 enum class math_unop_type {
48 neg,
49 bit_not,
50 bank_extract,
51 };
52
53 class math_ast_unop : public math_ast_node {
54 public:
55 owned_node m_arg;
56 math_unop_type m_type;
57 66 math_ast_unop(owned_node arg_in, math_unop_type type_in)
58 66 : m_arg(std::move(arg_in)), m_type(type_in) {}
59 math_val evaluate(const eval_context &ctx) const;
60 int has_label() const;
61 int get_len(bool could_be_bank_ex) const;
62 };
63
64 class math_ast_ternary_cond : public math_ast_node {
65 owned_node m_cond, m_true, m_false;
66 public:
67 8 math_ast_ternary_cond(owned_node cond_in, owned_node true_in, owned_node false_in)
68 8 : m_cond(std::move(cond_in)), m_true(std::move(true_in)), m_false(std::move(false_in)) {}
69
70 math_val evaluate(const eval_context& ctx) const;
71 int has_label() const;
72 int get_len(bool could_be_bank_ex) const;
73 };
74
75 class math_ast_literal : public math_ast_node {
76 math_val m_value;
77 int m_len;
78 public:
79
2/4
✓ Branch 0 taken 9104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9238 times.
✗ Branch 3 not taken.
18342 math_ast_literal(math_val value, int len=0) : m_value(value), m_len(len) {}
80 16468 math_val evaluate(const eval_context& ctx) const { return m_value; }
81 13449 int has_label() const { return 0; }
82 2472 int get_len(bool could_be_bank_ex) const { return m_len; }
83 friend int math_ast_binop::get_len(bool) const;
84 };
85
86 class math_ast_label : public math_ast_node {
87 string m_labelname;
88 // current namespace when this label was referenced
89 string m_cur_ns;
90 public:
91 // this should be the output of labelname() already
92 1254 math_ast_label(string labelname)
93
1/2
✓ Branch 0 taken 631 times.
✗ Branch 1 not taken.
2508 : m_labelname(labelname)
94 // this is initialized with the global ns
95
3/6
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 623 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 631 times.
✗ Branch 5 not taken.
1885 , m_cur_ns(ns) {}
96 math_val evaluate(const eval_context &ctx) const;
97 int has_label() const;
98 int get_len(bool could_be_bank_ex) const;
99 };
100
101
102 class math_builtin_function {
103 using call_t = math_val(*)(const std::vector<math_val>& args);
104 using haslabel_t = int(*)();
105 using getlen_t = int(*)(const std::vector<owned_node>& args, bool could_be_bank_ex);
106 462 static int default_has_label() {
107 462 return 0;
108 }
109 66 static int default_get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) {
110 66 int res = 0;
111
4/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 33 times.
132 for(auto& v : args) {
112
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
66 res = std::max(res, v->get_len(false));
113 }
114 66 return res;
115 }
116 call_t m_call;
117 haslabel_t m_haslabel;
118 getlen_t m_getlen;
119 public:
120 414 math_builtin_function(call_t c, haslabel_t l = default_has_label, getlen_t gl = default_get_len)
121 414 : m_call(c), m_haslabel(l), m_getlen(gl) {}
122 6 math_builtin_function(call_t c, getlen_t gl)
123 6 : m_call(c), m_haslabel(default_has_label), m_getlen(gl) {}
124 887 math_val call(const std::vector<math_val>& args) const {
125 887 return m_call(args);
126 }
127 486 int has_label() const {
128 486 return m_haslabel();
129 }
130 90 int get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) const {
131 90 return m_getlen(args, could_be_bank_ex);
132 }
133 };
134
135 class math_user_function {
136 size_t m_arg_count;
137 owned_node m_func_body;
138 public:
139 48 math_user_function(owned_node body, size_t arg_count)
140 48 : m_arg_count(arg_count), m_func_body(std::move(body)) {}
141 math_val call(const std::vector<math_val> &args) const;
142 int has_label() const;
143 int get_len(const std::vector<owned_node> &args, bool could_be_bank_ex) const;
144 };
145
146 class math_function_ref {
147 public:
148 std::variant<const math_builtin_function*, const math_user_function*> inner;
149 967 math_function_ref(const math_builtin_function& fn) : inner(&fn) {}
150 30 math_function_ref(const math_user_function& fn) : inner(&fn) {}
151 913 math_val call(const std::vector<math_val>& args) const {
152
4/4
✓ Branch 0 taken 440 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 445 times.
✓ Branch 3 taken 14 times.
3179 return std::visit([&](auto& i) { return i->call(args); }, inner);
153 }
154 486 int has_label() const {
155
2/4
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✗ Branch 3 not taken.
1458 return std::visit([&](auto& i) { return i->has_label(); }, inner);
156 }
157 96 int get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) const {
158
3/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 48 times.
288 return std::visit([&](auto& i) { return i->get_len(args, could_be_bank_ex); }, inner);
159 }
160 };
161
162 extern std::unordered_map<string, math_user_function> user_functions;
163 extern const std::unordered_map<string, math_builtin_function> builtin_functions;
164
165 class math_ast_function_call : public math_ast_node {
166 std::vector<owned_node> m_arguments;
167 math_function_ref m_func;
168 static math_function_ref lookup_fname(string const &function_name);
169
170 public:
171 997 math_ast_function_call(std::vector<owned_node> args, string function_name)
172 1498 : m_arguments(std::move(args))
173
2/4
✓ Branch 0 taken 496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 501 times.
✗ Branch 3 not taken.
1994 , m_func(lookup_fname(function_name)) {}
174 math_val evaluate(const eval_context &ctx) const;
175 int has_label() const;
176 int get_len(bool could_be_bank_ex) const;
177 };
178
179 // only for use inside user function definitions
180 class math_ast_function_argument : public math_ast_node {
181 size_t m_arg_idx;
182 public:
183 54 math_ast_function_argument(size_t arg_idx) : m_arg_idx(arg_idx) {}
184
185 34 math_val evaluate(const eval_context& ctx) const {
186 34 return ctx.userfunc_params[m_arg_idx];
187 }
188
189 // if a function is called with a label as an argument, that gets checked by
190 // the function call node, not here
191 int has_label() const { return 0; }
192 // i don't think these should ever have their len gotten?
193 int get_len(bool could_be_bank_ex) const { return 0; }
194 };
195