File Coverage

lib/SPVM/Builder/src/spvm_api_basic_type.c
Criterion Covered Total %
statement 151 191 79.0
branch 58 98 59.1
condition n/a
subroutine n/a
pod n/a
total 209 289 72.3


line stmt bran cond sub pod time code
1             // Copyright (c) 2023 Yuki Kimoto
2             // MIT License
3              
4             #include
5              
6             #include "spvm_native.h"
7              
8             #include "spvm_api_runtime.h"
9             #include "spvm_api_basic_type.h"
10             #include "spvm_api_method.h"
11             #include "spvm_api_arg.h"
12             #include "spvm_api_type.h"
13              
14             #include "spvm_allocator.h"
15             #include "spvm_runtime_basic_type.h"
16             #include "spvm_runtime_class_var.h"
17             #include "spvm_runtime_field.h"
18             #include "spvm_runtime_method.h"
19             #include "spvm_runtime_arg.h"
20              
21 119269           SPVM_API_BASIC_TYPE* SPVM_API_BASIC_TYPE_new_api() {
22            
23 119269           void* native_apis_init[] = {
24             SPVM_API_BASIC_TYPE_get_name,
25             SPVM_API_BASIC_TYPE_get_id,
26             SPVM_API_BASIC_TYPE_get_category,
27             SPVM_API_BASIC_TYPE_get_parent,
28             SPVM_API_BASIC_TYPE_get_version_string,
29             SPVM_API_BASIC_TYPE_get_class_dir,
30             SPVM_API_BASIC_TYPE_get_class_rel_file,
31             SPVM_API_BASIC_TYPE_is_pointer,
32             SPVM_API_BASIC_TYPE_is_anon,
33             SPVM_API_BASIC_TYPE_get_class_var_by_index,
34             SPVM_API_BASIC_TYPE_get_class_var_by_name,
35             SPVM_API_BASIC_TYPE_get_class_vars_length,
36             SPVM_API_BASIC_TYPE_get_field_by_index,
37             SPVM_API_BASIC_TYPE_get_field_by_name,
38             SPVM_API_BASIC_TYPE_get_fields_length,
39             SPVM_API_BASIC_TYPE_get_method_by_index,
40             SPVM_API_BASIC_TYPE_get_method_by_name,
41             SPVM_API_BASIC_TYPE_get_methods_length,
42             SPVM_API_BASIC_TYPE_get_anon_basic_type_by_index,
43             SPVM_API_BASIC_TYPE_get_anon_basic_types_length,
44             SPVM_API_BASIC_TYPE_has_interface,
45             SPVM_API_BASIC_TYPE_is_super_class,
46             };
47            
48 119269           SPVM_API_BASIC_TYPE* native_apis = calloc(1, sizeof(native_apis_init));
49            
50 119269           memcpy(native_apis, native_apis_init, sizeof(native_apis_init));
51            
52 119269           return native_apis;
53             }
54              
55 119269           void SPVM_API_BASIC_TYPE_free_api(SPVM_API_BASIC_TYPE* api) {
56            
57 119269           free(api);
58 119269           }
59              
60 9807           const char* SPVM_API_BASIC_TYPE_get_name(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
61            
62 9807           return basic_type->name;
63             }
64              
65 523557           int32_t SPVM_API_BASIC_TYPE_get_id(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
66            
67 523557           return basic_type->id;
68             }
69              
70 502813           int32_t SPVM_API_BASIC_TYPE_get_category(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
71            
72 502813           return basic_type->category;
73             }
74              
75 478           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_BASIC_TYPE_get_parent(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
76            
77 478           return basic_type->parent;
78             }
79              
80 0           const char* SPVM_API_BASIC_TYPE_get_version_string(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
81            
82 0           return basic_type->version_string;
83             }
84              
85 9796           const char* SPVM_API_BASIC_TYPE_get_class_dir(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
86            
87 9796           return basic_type->class_dir;
88             }
89              
90 9682           const char* SPVM_API_BASIC_TYPE_get_class_rel_file(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
91            
92 9682           return basic_type->class_rel_file;
93             }
94              
95 0           int32_t SPVM_API_BASIC_TYPE_is_pointer(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
96            
97 0           return basic_type->is_pointer;
98             }
99              
100 0           int32_t SPVM_API_BASIC_TYPE_is_anon(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
101            
102 0           return basic_type->is_anon;
103             }
104              
105 8485           SPVM_RUNTIME_CLASS_VAR* SPVM_API_BASIC_TYPE_get_class_var_by_index(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t class_var_index) {
106            
107 8485 50         if (class_var_index < 0) {
108 0           return NULL;
109             }
110            
111 8485 50         if (class_var_index >= basic_type->class_vars_length) {
112 0           return NULL;
113             }
114            
115 8485           SPVM_RUNTIME_CLASS_VAR* class_var = &basic_type->class_vars[class_var_index];
116            
117 8485           return class_var;
118             }
119              
120 1142           SPVM_RUNTIME_CLASS_VAR* SPVM_API_BASIC_TYPE_get_class_var_by_name(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, const char* class_var_name) {
121            
122 1142           SPVM_RUNTIME_CLASS_VAR* found_class_var = NULL;
123 1142 50         if (basic_type->class_vars_length > 0) {
124 2757 100         for (int32_t class_var_index = 0; class_var_index < basic_type->class_vars_length; class_var_index++) {
125 2729           SPVM_RUNTIME_CLASS_VAR* class_var = SPVM_API_BASIC_TYPE_get_class_var_by_index(runtime, basic_type, class_var_index);
126 2729           const char* class_var_name_current = class_var->name;
127 2729 100         if (strcmp(class_var_name_current, class_var_name) == 0) {
128 1114           found_class_var = class_var;
129 1114           break;
130             }
131             }
132             }
133            
134 1142           return found_class_var;
135             }
136              
137 0           int32_t SPVM_API_BASIC_TYPE_get_class_vars_length(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
138            
139 0           return basic_type->class_vars_length;
140             }
141              
142 1400346           SPVM_RUNTIME_FIELD* SPVM_API_BASIC_TYPE_get_field_by_index(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t field_index) {
143            
144 1400346 50         if (field_index < 0) {
145 0           return NULL;
146             }
147            
148 1400346 50         if (field_index >= basic_type->fields_length) {
149 0           return NULL;
150             }
151            
152 1400346           SPVM_RUNTIME_FIELD* field = &basic_type->fields[field_index];
153            
154 1400346           return field;
155             }
156              
157 768603           SPVM_RUNTIME_FIELD* SPVM_API_BASIC_TYPE_get_field_by_name(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, const char* field_name) {
158            
159 768603           SPVM_RUNTIME_FIELD* found_field = NULL;
160 768603 50         if (basic_type->fields_length > 0) {
161 773139 100         for (int32_t field_index = 0; field_index < basic_type->fields_length; field_index++) {
162 773109           SPVM_RUNTIME_FIELD* field = SPVM_API_BASIC_TYPE_get_field_by_index(runtime, basic_type, field_index);
163 773109           const char* field_name_current = field->name;
164 773109 100         if (strcmp(field_name_current, field_name) == 0) {
165 768573           found_field = field;
166 768573           break;
167             }
168             }
169             }
170            
171 768603           return found_field;
172             }
173              
174 320           int32_t SPVM_API_BASIC_TYPE_get_fields_length(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
175            
176 320           return basic_type->fields_length;
177             }
178              
179 5657122           SPVM_RUNTIME_METHOD* SPVM_API_BASIC_TYPE_get_method_by_index(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t method_index) {
180            
181 5657122 50         if (method_index < 0) {
182 0           return NULL;
183             }
184            
185 5657122 50         if (method_index >= basic_type->methods_length) {
186 0           return NULL;
187             }
188            
189 5657122           SPVM_RUNTIME_METHOD* method = &basic_type->methods[method_index];
190            
191 5657122           return method;
192             }
193              
194 805224           SPVM_RUNTIME_METHOD* SPVM_API_BASIC_TYPE_get_method_by_name(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, const char* method_name) {
195            
196 805224           SPVM_RUNTIME_METHOD* found_method = NULL;
197 805224 50         if (basic_type->methods_length > 0) {
198             // Performe binary searching because methods are sorted by the names
199 805224           int32_t current_min_index = 0;
200 805224           int32_t current_max_index = basic_type->methods_length - 1;
201            
202             while (1) {
203 3179849 100         if (current_max_index < current_min_index) {
204 106           break;
205             }
206            
207 3179743           int32_t current_half_index = current_min_index +(current_max_index - current_min_index) / 2;
208            
209 3179743           SPVM_RUNTIME_METHOD* method = SPVM_API_BASIC_TYPE_get_method_by_index(runtime, basic_type, current_half_index);
210 3179743           const char* current_half_method_name = method->name;
211            
212 3179743           int32_t cmp_result = strcmp(method_name, current_half_method_name);
213            
214 3179743 100         if (cmp_result > 0) {
215 1605483           current_min_index = current_half_index + 1;
216             }
217 1574260 100         else if (cmp_result < 0) {
218 769142           current_max_index = current_half_index - 1;
219             }
220             else {
221 805118           found_method = method;
222 805118           break;
223             }
224 2374625           }
225             }
226            
227 805224           return found_method;
228             }
229              
230 18397           int32_t SPVM_API_BASIC_TYPE_get_methods_length(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
231            
232 18397           return basic_type->methods_length;
233             }
234              
235 0           int32_t SPVM_API_BASIC_TYPE_get_anon_basic_types_length(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
236            
237 0           return basic_type->anon_basic_types_length;
238             }
239              
240 123           SPVM_RUNTIME_BASIC_TYPE* SPVM_API_BASIC_TYPE_get_anon_basic_type_by_index(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, int32_t anon_basic_type_index) {
241            
242 123 50         if (anon_basic_type_index < 0) {
243 0           return NULL;
244             }
245            
246 123 50         if (anon_basic_type_index >= basic_type->anon_basic_types_length) {
247 0           return NULL;
248             }
249            
250 123           SPVM_RUNTIME_BASIC_TYPE* anon_basic_type = basic_type->anon_basic_types[anon_basic_type_index];
251            
252 123           return anon_basic_type;
253             }
254              
255 18           int32_t SPVM_API_BASIC_TYPE_has_interface(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, SPVM_RUNTIME_BASIC_TYPE* interface_basic_type) {
256            
257 18 50         if (!(interface_basic_type->category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE)) {
258 0           return 0;
259             }
260            
261 18 50         if (!(basic_type->category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS || basic_type->category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE)) {
    0          
262 0           return 0;
263             }
264            
265 36 100         for (int32_t interface_method_index = 0; interface_method_index < interface_basic_type->methods_length; interface_method_index++) {
266 18           SPVM_RUNTIME_METHOD* interface_method = SPVM_API_BASIC_TYPE_get_method_by_index(runtime, interface_basic_type, interface_method_index);
267            
268 180 100         for (int32_t method_index = 0; method_index < basic_type->methods_length; method_index++) {
269 162           SPVM_RUNTIME_METHOD* method = SPVM_API_BASIC_TYPE_get_method_by_name(runtime, interface_basic_type, interface_method->name);
270            
271 162           int32_t method_compatibility = SPVM_API_BASIC_TYPE_check_method_compatibility(runtime, basic_type, method, interface_basic_type, interface_method);
272            
273 162 50         if (method_compatibility == 0) {
274 0           return 0;
275             }
276             }
277             }
278            
279 18           return 1;
280             }
281              
282 162           int32_t SPVM_API_BASIC_TYPE_check_method_compatibility(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type, SPVM_RUNTIME_METHOD* method, SPVM_RUNTIME_BASIC_TYPE* dist_basic_type, SPVM_RUNTIME_METHOD* dist_method) {
283            
284 162 50         if (dist_method->is_required && !method) {
    50          
285 0 0         if (!dist_method->is_class_method) {
286 0           return 0;
287             }
288             }
289            
290 162 50         if (method) {
291 162 50         if (method->is_class_method) {
292 0 0         if (!dist_method->is_class_method) {
293 0           return 0;
294             }
295             }
296            
297 162 50         if (!(method->required_args_length == dist_method->required_args_length)) {
298 0           return 0;
299             }
300            
301 162 50         if (!(method->args_length >= dist_method->args_length)) {
302 0           return 0;
303             }
304            
305 182 100         for (int32_t arg_index = 1; arg_index < dist_method->args_length; arg_index++) {
306 20           SPVM_RUNTIME_ARG* method_arg = SPVM_API_METHOD_get_arg_by_index(runtime, method, arg_index);
307 20           SPVM_RUNTIME_ARG* dist_method_arg = SPVM_API_METHOD_get_arg_by_index(runtime, dist_method, arg_index);
308            
309 20           SPVM_RUNTIME_BASIC_TYPE* method_arg_basic_type = method_arg->basic_type;
310 20           int32_t method_arg_type_dimension = method_arg->type_dimension;
311 20           int32_t method_arg_type_flag = method_arg->type_flag;
312            
313 20           SPVM_RUNTIME_BASIC_TYPE* dist_method_arg_basic_type = dist_method_arg->basic_type;
314 20           int32_t dist_method_arg_type_dimension = dist_method_arg->type_dimension;
315 20           int32_t dist_method_arg_type_flag = dist_method_arg->type_flag;
316            
317 20           int32_t assignability_for_method = SPVM_API_BASIC_TYPE_can_assign_for_method_definition(runtime, method_arg->basic_type, method_arg->type_dimension, method_arg->type_flag, dist_method_arg->basic_type, dist_method_arg->type_dimension, dist_method_arg->type_flag);
318            
319 20 50         if (!assignability_for_method) {
320 0           return 0;
321             }
322             }
323            
324 162           SPVM_RUNTIME_BASIC_TYPE* method_return_basic_type = method->return_basic_type;
325 162           int32_t method_return_type_dimension = method->return_type_dimension;
326 162           int32_t method_return_type_flag = method->return_type_flag;
327            
328 162           SPVM_RUNTIME_BASIC_TYPE* dist_method_return_basic_type = dist_method->return_basic_type;
329 162           int32_t dist_method_return_type_dimension = dist_method->return_type_dimension;
330 162           int32_t dist_method_return_type_flag = dist_method->return_type_flag;
331            
332 162           int32_t assignability_for_method_definition = SPVM_API_BASIC_TYPE_can_assign_for_method_definition(
333             runtime,
334             dist_method_return_basic_type, dist_method_return_type_dimension, dist_method_return_type_flag,
335             method_return_basic_type, method_return_type_dimension, method_return_type_flag
336             );
337            
338 162 50         if (!assignability_for_method_definition) {
339 0           return 0;
340             }
341             }
342            
343 162           return 1;
344             }
345              
346 182           int32_t SPVM_API_BASIC_TYPE_can_assign_for_method_definition (
347             SPVM_RUNTIME* runtime,
348             SPVM_RUNTIME_BASIC_TYPE* dist_type_basic_type, int32_t dist_type_dimension, int32_t dist_type_flag,
349             SPVM_RUNTIME_BASIC_TYPE* src_type_basic_type, int32_t src_type_dimension, int32_t src_type_flag)
350             {
351 182           int32_t assignability = 0;
352            
353 182 100         if (SPVM_API_RUNTIME_is_any_object_type(runtime, dist_type_basic_type, dist_type_dimension, dist_type_flag)) {
354 50 50         if (SPVM_API_TYPE_is_object_type(runtime, src_type_basic_type, src_type_dimension, src_type_flag)) {
355 50           assignability = 1;
356             }
357             else {
358 50           assignability = 0;
359             }
360             }
361 132 50         else if (SPVM_API_RUNTIME_is_any_object_array_type(runtime, dist_type_basic_type, dist_type_dimension, dist_type_flag)) {
362 0 0         if (SPVM_API_RUNTIME_is_object_array_type(runtime, src_type_basic_type, src_type_dimension, src_type_flag)) {
363 0           assignability = 1;
364             }
365             else {
366 0           assignability = 0;
367             }
368             }
369             else {
370 132 50         if (dist_type_dimension == src_type_dimension && dist_type_flag == src_type_flag) {
    50          
371 264 50         if (SPVM_API_BASIC_TYPE_is_class_type(runtime, dist_type_basic_type)) {
372 0 0         if (dist_type_basic_type->id == src_type_basic_type->id) {
373 0           assignability = 1;
374             }
375             else {
376 0           assignability = SPVM_API_BASIC_TYPE_is_super_class(runtime, dist_type_basic_type, src_type_basic_type);
377             }
378             }
379             else {
380 132 50         if (dist_type_basic_type->id == src_type_basic_type->id) {
381 132           assignability = 1;
382             }
383             else {
384 0           assignability = 0;
385             }
386             }
387             }
388             else {
389 0           assignability = 0;
390             }
391             }
392            
393 182           return assignability;
394             }
395              
396 132           int32_t SPVM_API_BASIC_TYPE_is_class_type(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* basic_type) {
397            
398             int32_t is_class_type;
399            
400 132           int32_t basic_type_category = basic_type->category;
401            
402 132 50         switch (basic_type_category) {
403             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS:
404             {
405 0           is_class_type = 1;
406 0           break;
407             }
408             default: {
409 132           is_class_type = 0;
410             }
411             }
412            
413 132           return is_class_type;
414             }
415              
416 56           int32_t SPVM_API_BASIC_TYPE_is_super_class(SPVM_RUNTIME* runtime, SPVM_RUNTIME_BASIC_TYPE* super_basic_type, SPVM_RUNTIME_BASIC_TYPE* child_basic_type) {
417              
418 56           int32_t is_super_class_basic_type = 0;
419            
420 56 50         if (!(super_basic_type->category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS)) {
421 0           return 0;
422             }
423            
424 56 100         if (!(child_basic_type->category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS)) {
425 14           return 0;
426             }
427            
428 42           SPVM_RUNTIME_BASIC_TYPE* parent_basic_type = child_basic_type->parent;
429            
430             while (1) {
431 44 100         if (parent_basic_type) {
432 12 100         if (parent_basic_type->id == super_basic_type->id) {
433 10           is_super_class_basic_type = 1;
434 10           break;
435             }
436             else {
437 2           parent_basic_type = parent_basic_type->parent;
438             }
439             }
440             else {
441 32           is_super_class_basic_type = 0;
442 32           break;
443             }
444 2           }
445            
446 42           return is_super_class_basic_type;
447             }