asar coverage - build #301


src/asar/
File: src/asar/math_ast.h
Date: 2025-03-18 20:16:22
Lines:
44/46
95.7%
Functions:
31/33
93.9%
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 5290 math_ast_binop(owned_node left_in, owned_node right_in, math_binop_type type_in)
40 5290 : 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 90 math_ast_unop(owned_node arg_in, math_unop_type type_in)
58 90 : 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_literal : public math_ast_node {
65 math_val m_value;
66 int m_len;
67 public:
68
2/4
✓ Branch 0 taken 9305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9459 times.
✗ Branch 3 not taken.
18764 math_ast_literal(math_val value, int len=0) : m_value(value), m_len(len) {}
69 16888 math_val evaluate(const eval_context& ctx) const { return m_value; }
70 14130 int has_label() const { return 0; }
71 2472 int get_len(bool could_be_bank_ex) const { return m_len; }
72 friend int math_ast_binop::get_len(bool) const;
73 };
74
75 class math_ast_label : public math_ast_node {
76 string m_labelname;
77 // current namespace when this label was referenced
78 string m_cur_ns;
79 public:
80 // this should be the output of labelname() already
81 1206 math_ast_label(string labelname)
82
1/2
✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
2412 : m_labelname(labelname)
83 // this is initialized with the global ns
84
3/6
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 608 times.
✗ Branch 5 not taken.
1814 , m_cur_ns(ns) {}
85 math_val evaluate(const eval_context &ctx) const;
86 int has_label() const;
87 int get_len(bool could_be_bank_ex) const;
88 };
89
90
91 class math_builtin_function {
92 using call_t = math_val(*)(const std::vector<math_val>& args);
93 using haslabel_t = int(*)();
94 using getlen_t = int(*)(const std::vector<owned_node>& args, bool could_be_bank_ex);
95 624 static int default_has_label() {
96 624 return 0;
97 }
98 66 static int default_get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) {
99 66 int res = 0;
100
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) {
101
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));
102 }
103 66 return res;
104 }
105 call_t m_call;
106 haslabel_t m_haslabel;
107 getlen_t m_getlen;
108 public:
109 483 math_builtin_function(call_t c, haslabel_t l = default_has_label, getlen_t gl = default_get_len)
110 483 : m_call(c), m_haslabel(l), m_getlen(gl) {}
111 7 math_builtin_function(call_t c, getlen_t gl)
112 7 : m_call(c), m_haslabel(default_has_label), m_getlen(gl) {}
113 1011 math_val call(const std::vector<math_val>& args) const {
114 1011 return m_call(args);
115 }
116 672 int has_label() const {
117 672 return m_haslabel();
118 }
119 90 int get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) const {
120 90 return m_getlen(args, could_be_bank_ex);
121 }
122 };
123
124 class math_user_function {
125 size_t m_arg_count;
126 owned_node m_func_body;
127 public:
128 48 math_user_function(owned_node body, size_t arg_count)
129 48 : m_arg_count(arg_count), m_func_body(std::move(body)) {}
130 math_val call(const std::vector<math_val> &args) const;
131 int has_label() const;
132 int get_len(const std::vector<owned_node> &args, bool could_be_bank_ex) const;
133 };
134
135 class math_function_ref {
136 public:
137 std::variant<const math_builtin_function*, const math_user_function*> inner;
138 1091 math_function_ref(const math_builtin_function& fn) : inner(&fn) {}
139 34 math_function_ref(const math_user_function& fn) : inner(&fn) {}
140 1041 math_val call(const std::vector<math_val>& args) const {
141
4/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 495 times.
✓ Branch 3 taken 30 times.
4104 return std::visit([&](auto& i) { return i->call(args); }, inner);
142 }
143 678 int has_label() const {
144
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✗ Branch 3 not taken.
2034 return std::visit([&](auto& i) { return i->has_label(); }, inner);
145 }
146 96 int get_len(const std::vector<owned_node>& args, bool could_be_bank_ex) const {
147
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);
148 }
149 };
150
151 extern std::unordered_map<string, math_user_function> user_functions;
152 extern const std::unordered_map<string, math_builtin_function> builtin_functions;
153
154 class math_ast_function_call : public math_ast_node {
155 std::vector<owned_node> m_arguments;
156 math_function_ref m_func;
157 static math_function_ref lookup_fname(string const &function_name);
158
159 public:
160 1125 math_ast_function_call(std::vector<owned_node> args, string function_name)
161 1692 : m_arguments(std::move(args))
162
2/4
✓ Branch 0 taken 558 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567 times.
✗ Branch 3 not taken.
2250 , m_func(lookup_fname(function_name)) {}
163 math_val evaluate(const eval_context &ctx) const;
164 int has_label() const;
165 int get_len(bool could_be_bank_ex) const;
166 };
167
168 // only for use inside user function definitions
169 class math_ast_function_argument : public math_ast_node {
170 size_t m_arg_idx;
171 public:
172 54 math_ast_function_argument(size_t arg_idx) : m_arg_idx(arg_idx) {}
173
174 34 math_val evaluate(const eval_context& ctx) const {
175 34 return ctx.userfunc_params[m_arg_idx];
176 }
177
178 // if a function is called with a label as an argument, that gets checked by
179 // the function call node, not here
180 int has_label() const { return 0; }
181 // i don't think these should ever have their len gotten?
182 int get_len(bool could_be_bank_ex) const { return 0; }
183 };
184