File Coverage

SPVM.xs
Criterion Covered Total %
statement 2399 2546 94.2
branch 1060 1778 59.6
condition n/a
subroutine n/a
pod n/a
total 3459 4324 80.0


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT /* For performance */
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include "ppport.h"
7              
8             #undef call_method
9             #undef leave_scope
10              
11             #include "spvm_native.h"
12              
13             #if !defined(SvIsBOOL)
14             #define SvIsBOOL(value) 0
15             #endif
16              
17             static const char* FILE_NAME = "SPVM.xs";
18              
19 2332574           void* SPVM_XS_UTIL_get_pointer(pTHX_ SV* sv_data) {
20            
21 2332574 50         if (SvOK(sv_data)) {
    0          
    0          
22 2332574           HV* hv_data = (HV*)SvRV(sv_data);
23            
24 2332574           SV** sv_pointer_ptr = hv_fetch(hv_data, "pointer", strlen("pointer"), 0);
25 2332574 50         SV* sv_pointer = sv_pointer_ptr ? *sv_pointer_ptr : &PL_sv_undef;
26 2332574 50         size_t iv_pointer = SvIV(SvRV(sv_pointer));
27 2332574           void* pointer = INT2PTR(void*, iv_pointer);
28            
29 2332574           return pointer;
30             }
31             else {
32 0           return NULL;
33             }
34             }
35              
36 692505           void* SPVM_XS_UTIL_get_spvm_object(pTHX_ SV* sv_blessed_object) {
37            
38 692505 100         if (SvOK(sv_blessed_object)) {
    50          
    50          
39 692115           HV* hv_blessed_object = (HV*)SvRV(sv_blessed_object);
40            
41 692115           SV** sv_spvm_object_ptr = hv_fetch(hv_blessed_object, "spvm_object", strlen("spvm_object"), 0);
42 692115 50         SV* sv_spvm_object = sv_spvm_object_ptr ? *sv_spvm_object_ptr : &PL_sv_undef;
43 692115 50         void** spvm_object_ref = (void**)SvPV_nolen(sv_spvm_object);
44 692115           void* spvm_object = *spvm_object_ref;
45            
46 692115           return spvm_object;
47             }
48             else {
49 390           return NULL;
50             }
51             }
52              
53 1193181           SPVM_ENV* SPVM_XS_UTIL_get_env(pTHX_ SV* sv_env) {
54            
55             SPVM_ENV* env;
56 1193181 50         if (sv_isobject(sv_env) && sv_derived_from(sv_env, "SPVM::Builder::Env")) {
    100          
57 1134497           env = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env);
58             }
59 58684 50         else if (sv_isobject(sv_env) && sv_derived_from(sv_env, "SPVM::BlessedObject::Class")) {
    50          
60 58684           void* spvm_env = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_env);
61            
62 58684           SPVM_ENV* env_api = SPVM_API_new_env();
63            
64 58684           env = env_api->get_pointer(env_api, NULL, spvm_env);
65            
66 58684           env_api->free_env(env_api);
67             }
68            
69 1193181           return env;
70             }
71              
72 1193181           SPVM_VALUE* SPVM_XS_UTIL_get_stack(pTHX_ SV* sv_stack) {
73            
74             SPVM_VALUE* stack;
75 1193181 50         if (sv_isobject(sv_stack) && sv_derived_from(sv_stack, "SPVM::Builder::Stack")) {
    100          
76 1134497           stack = SPVM_XS_UTIL_get_pointer(aTHX_ sv_stack);
77             }
78 58684 50         else if (sv_isobject(sv_stack) && sv_derived_from(sv_stack, "SPVM::BlessedObject::Class")) {
    50          
79 58684           void* spvm_stack = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_stack);
80            
81 58684           SPVM_ENV* env_api = SPVM_API_new_env();
82            
83 58684           stack = env_api->get_pointer(env_api, NULL, spvm_stack);
84            
85 58684           env_api->free_env(env_api);
86             }
87            
88 1193181           return stack;
89             }
90              
91 349347           SV* SPVM_XS_UTIL_new_sv_blessed_object(pTHX_ SV* sv_api, void* spvm_object, const char* class) {
92            
93 349347           HV* hv_self = (HV*)SvRV(sv_api);
94            
95 349347           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
96 349347 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
97 349347           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
98            
99 349347           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
100 349347 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
101 349347           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
102            
103 349347           SV* sv_spvm_object = sv_2mortal(newSVpv("", sizeof(void*)));
104 349347 50         void** spvm_object_ref = (void**)SvPV_nolen(sv_spvm_object);
105 349347           *spvm_object_ref = NULL;
106            
107 349347           env->assign_object(env, stack, spvm_object_ref, spvm_object);
108            
109 349347           HV* hv_blessed_object = (HV*)sv_2mortal((SV*)newHV());
110 349347           SV* sv_blessed_object = sv_2mortal(newRV_inc((SV*)hv_blessed_object));
111            
112 349347           (void)hv_store(hv_blessed_object, "spvm_object", strlen("spvm_object"), SvREFCNT_inc(sv_spvm_object), 0);
113            
114 349347 50         if (SvOK(sv_api)) {
    0          
    0          
115 349347           (void)hv_store(hv_blessed_object, "__api", strlen("__api"), SvREFCNT_inc(sv_api), 0);
116             }
117            
118 349347           HV* hv_class = gv_stashpv(class, 0);
119 349347           sv_bless(sv_blessed_object, hv_class);
120            
121 349347           return sv_blessed_object;
122             }
123              
124 2982           SV* SPVM_XS_UTIL_new_sv_pointer_object(pTHX_ void* pointer, const char* class) {
125            
126 2982           size_t iv_pointer = PTR2IV(pointer);
127 2982           SV* sviv_pointer = sv_2mortal(newSViv(iv_pointer));
128 2982           SV* sv_pointer = sv_2mortal(newRV_inc(sviv_pointer));
129            
130 2982           HV* hv_pointer_object = (HV*)sv_2mortal((SV*)newHV());
131 2982           (void)hv_store(hv_pointer_object, "pointer", strlen("pointer"), SvREFCNT_inc(sv_pointer), 0);
132 2982           SV* sv_pointer_object = sv_2mortal(newRV_inc((SV*)hv_pointer_object));
133            
134 2982           HV* hv_class = gv_stashpv(class, 0);
135 2982           sv_bless(sv_pointer_object, hv_class);
136            
137 2982           return sv_pointer_object;
138             }
139              
140 69135           SV* SPVM_XS_UTIL_new_string(pTHX_ SV* sv_api, SV* sv_string, SV** sv_error) {
141            
142 69135           HV* hv_self = (HV*)SvRV(sv_api);
143            
144 69135           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
145 69135 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
146 69135           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
147            
148 69135           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
149 69135 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
150 69135           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
151            
152 69135 100         if (SvOK(sv_string)) {
    50          
    50          
153 136566 100         if (sv_isobject(sv_string) && sv_derived_from(sv_string, "SPVM::BlessedObject::String")) {
    100          
154             // Nothing
155             }
156 67801 100         else if (SvROK(sv_string)) {
157 8           *sv_error = sv_2mortal(newSVpvf(" cannnot be a reference"));
158 8           return &PL_sv_undef;
159             }
160             else {
161 67793           STRLEN length = -1;
162 67793 100         const char* string = SvPV(sv_string, length);
163 67793           void* spvm_string = env->new_string_no_mortal(env, stack, string, (int32_t)length);
164 67793           sv_string = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_string, "SPVM::BlessedObject::String");
165             }
166             }
167             else {
168 362           sv_string = &PL_sv_undef;
169             }
170            
171 69127           return sv_string;
172             }
173              
174 30972           SV* SPVM_XS_UTIL_new_address_object(pTHX_ SV* sv_api, SV* sv_address, SV** sv_error) {
175 30972           HV* hv_self = (HV*)SvRV(sv_api);
176            
177 30972           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
178 30972 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
179 30972           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
180            
181 30972           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
182 30972 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
183 30972           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
184            
185 30972           int32_t error_id = 0;
186            
187 30972           *sv_error = &PL_sv_undef;
188            
189 30972 50         if (SvOK(sv_address)) {
    0          
    0          
190 61944 50         if (sv_isobject(sv_address) && sv_derived_from(sv_address, "SPVM::BlessedObject::Class")) {
    0          
191 0           void* spvm_address = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_address);
192 0           int32_t type_dimension = 1;
193 0 0         if (!env->is_type_by_name(env, stack, spvm_address, "Address", type_dimension)) {
194 0           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Class object, it must be the Address type"));
195 0           return &PL_sv_undef;
196             }
197             }
198 30972 50         else if (SvROK(sv_address)) {
199 0           *sv_error = sv_2mortal(newSVpvf(" cannnot be a reference"));
200 0           return &PL_sv_undef;
201             }
202             else {
203 30972 50         void* address = (void*)(intptr_t)SvIV(sv_address);
204 30972           void* basic_type = env->get_basic_type(env, stack, "Address");
205            
206 30972           void* spvm_address = env->new_pointer_object_no_mortal(env, stack, basic_type, address);
207            
208 30972           sv_address = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_address, "SPVM::BlessedObject::Class");
209             }
210             }
211             else {
212 0           sv_address = &PL_sv_undef;
213             }
214            
215 30972           return sv_address;
216             }
217              
218 56           SV* SPVM_XS_UTIL_new_byte_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
219 56           HV* hv_self = (HV*)SvRV(sv_api);
220            
221 56           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
222 56 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
223 56           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
224            
225 56           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
226 56 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
227 56           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
228            
229 56           *sv_error = &PL_sv_undef;
230            
231 56 100         if (SvOK(sv_array)) {
    50          
    50          
232 96 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
233 12           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
234 12           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
235 12           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
236 12 100         if (!(strcmp(spvm_array_basic_type_name, "byte") == 0 && spvm_array_type_dimension == 1)) {
    50          
237 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the byte[] type"));
238 2           return &PL_sv_undef;
239             }
240             }
241 38 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
242 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
243 2           return &PL_sv_undef;
244             }
245             else {
246             // Elements
247 36           AV* av_array = (AV*)SvRV(sv_array);
248            
249             // Array length
250 36           int32_t length = av_len(av_array) + 1;
251            
252             // New array
253 36           void* spvm_array = env->new_byte_array_no_mortal(env, stack, length);
254            
255 36           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
256 130 100         for (int32_t i = 0; i < length; i++) {
257 94           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
258 94 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
259            
260 94 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
261 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
262 0           return &PL_sv_undef;
263             }
264 94 50         elems[i] = (int8_t)SvIV(sv_elem);
265             }
266            
267 36           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
268             }
269             }
270             else {
271 6           sv_array = &PL_sv_undef;
272             }
273            
274 52           return sv_array;
275             }
276              
277 14           SV* SPVM_XS_UTIL_new_byte_array_unsigned(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
278 14           HV* hv_self = (HV*)SvRV(sv_api);
279            
280 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
281 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
282 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
283            
284 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
285 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
286 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
287            
288 14           *sv_error = &PL_sv_undef;
289            
290 14 100         if (SvOK(sv_array)) {
    50          
    50          
291 20 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
292 4           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
293 4           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
294 4           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
295 4 100         if (!(strcmp(spvm_array_basic_type_name, "byte") == 0 && spvm_array_type_dimension == 1)) {
    50          
296 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the byte[] type"));
297 2           return &PL_sv_undef;
298             }
299             }
300 8 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
301 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
302 2           return &PL_sv_undef;
303             }
304             else {
305             // Elements
306 6           AV* av_array = (AV*)SvRV(sv_array);
307            
308             // Array length
309 6           int32_t length = av_len(av_array) + 1;
310            
311             // New array
312 6           void* spvm_array = env->new_byte_array_no_mortal(env, stack, length);
313            
314 6           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
315 18 100         for (int32_t i = 0; i < length; i++) {
316 12           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
317 12 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
318            
319 12 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
320 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
321 0           return &PL_sv_undef;
322             }
323 12 50         elems[i] = (int8_t)(uint8_t)SvUV(sv_elem);
324             }
325            
326 6           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
327             }
328             }
329             else {
330 2           sv_array = &PL_sv_undef;
331             }
332            
333 10           return sv_array;
334             }
335              
336 46           SV* SPVM_XS_UTIL_new_short_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
337 46           HV* hv_self = (HV*)SvRV(sv_api);
338            
339 46           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
340 46 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
341 46           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
342            
343 46           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
344 46 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
345 46           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
346            
347 46           *sv_error = &PL_sv_undef;
348            
349 46 100         if (SvOK(sv_array)) {
    50          
    50          
350 76 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
351 10           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
352 10           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
353 10           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
354 10 100         if (!(strcmp(spvm_array_basic_type_name, "short") == 0 && spvm_array_type_dimension == 1)) {
    50          
355 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the short[] type"));
356 2           return &PL_sv_undef;
357             }
358             }
359 30 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
360 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
361 2           return &PL_sv_undef;
362             }
363             else {
364             // Elements
365 28           AV* av_array = (AV*)SvRV(sv_array);
366            
367             // Array length
368 28           int32_t length = av_len(av_array) + 1;
369            
370             // New array
371 28           void* spvm_array = env->new_short_array_no_mortal(env, stack, length);
372            
373 28           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
374 98 100         for (int32_t i = 0; i < length; i++) {
375 70           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
376 70 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
377            
378 70 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
379 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
380 0           return &PL_sv_undef;
381             }
382 70 50         elems[i] = (int16_t)SvIV(sv_elem);
383             }
384            
385 28           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
386             }
387             }
388             else {
389 6           sv_array = &PL_sv_undef;
390             }
391            
392 42           return sv_array;
393             }
394              
395 14           SV* SPVM_XS_UTIL_new_short_array_unsigned(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
396 14           HV* hv_self = (HV*)SvRV(sv_api);
397            
398 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
399 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
400 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
401            
402 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
403 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
404 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
405            
406 14           *sv_error = &PL_sv_undef;
407            
408 14 100         if (SvOK(sv_array)) {
    50          
    50          
409 20 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
410 4           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
411 4           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
412 4           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
413 4 100         if (!(strcmp(spvm_array_basic_type_name, "short") == 0 && spvm_array_type_dimension == 1)) {
    50          
414 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the short[] type"));
415 2           return &PL_sv_undef;
416             }
417             }
418 8 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
419 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
420 2           return &PL_sv_undef;
421             }
422             else {
423             // Elements
424 6           AV* av_array = (AV*)SvRV(sv_array);
425            
426             // Array length
427 6           int32_t length = av_len(av_array) + 1;
428            
429             // New array
430 6           void* spvm_array = env->new_short_array_no_mortal(env, stack, length);
431            
432 6           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
433 18 100         for (int32_t i = 0; i < length; i++) {
434 12           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
435 12 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
436            
437 12 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
438 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
439 0           return &PL_sv_undef;
440             }
441 12 50         elems[i] = (int16_t)(uint16_t)SvUV(sv_elem);
442             }
443            
444 6           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
445             }
446             }
447             else {
448 2           sv_array = &PL_sv_undef;
449             }
450            
451 10           return sv_array;
452             }
453              
454 68           SV* SPVM_XS_UTIL_new_int_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
455 68           HV* hv_self = (HV*)SvRV(sv_api);
456            
457 68           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
458 68 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
459 68           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
460            
461 68           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
462 68 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
463 68           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
464            
465 68           *sv_error = &PL_sv_undef;
466            
467 68 100         if (SvOK(sv_array)) {
    50          
    50          
468 118 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
469 14           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
470 14           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
471 14           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
472 14 100         if (!(strcmp(spvm_array_basic_type_name, "int") == 0 && spvm_array_type_dimension == 1)) {
    50          
473 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the int[] type"));
474 2           return &PL_sv_undef;
475             }
476             }
477 48 100         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
478 4           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
479 4           return &PL_sv_undef;
480             }
481             else {
482             // Elements
483 44           AV* av_array = (AV*)SvRV(sv_array);
484            
485             // Array length
486 44           int32_t length = av_len(av_array) + 1;
487            
488             // New array
489 44           void* spvm_array = env->new_int_array_no_mortal(env, stack, length);
490            
491 44           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
492 150 100         for (int32_t i = 0; i < length; i++) {
493 106           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
494 106 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
495            
496 106 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
497 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
498 0           return &PL_sv_undef;
499             }
500 106 50         elems[i] = (int32_t)SvIV(sv_elem);
501             }
502            
503 44           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
504             }
505             }
506             else {
507 6           sv_array = &PL_sv_undef;
508             }
509            
510 62           return sv_array;
511             }
512              
513 14           SV* SPVM_XS_UTIL_new_int_array_unsigned(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
514            
515 14           *sv_error = &PL_sv_undef;
516            
517 14           HV* hv_self = (HV*)SvRV(sv_api);
518            
519 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
520 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
521 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
522            
523 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
524 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
525 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
526            
527 14 100         if (SvOK(sv_array)) {
    50          
    50          
528 20 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
529 4           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
530 4           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
531 4           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
532 4 100         if (!(strcmp(spvm_array_basic_type_name, "int") == 0 && spvm_array_type_dimension == 1)) {
    50          
533 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the int[] type"));
534 2           return &PL_sv_undef;
535             }
536             }
537 8 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
538 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
539 2           return &PL_sv_undef;
540             }
541             else {
542             // Elements
543 6           AV* av_array = (AV*)SvRV(sv_array);
544            
545             // Array length
546 6           int32_t length = av_len(av_array) + 1;
547            
548             // New array
549 6           void* spvm_array = env->new_int_array_no_mortal(env, stack, length);
550            
551 6           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
552 18 100         for (int32_t i = 0; i < length; i++) {
553 12           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
554 12 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
555            
556 12 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
557 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
558 0           return &PL_sv_undef;
559             }
560 12 50         elems[i] = (int32_t)(uint32_t)SvUV(sv_elem);
561             }
562            
563 6           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
564             }
565             }
566             else {
567 2           sv_array = &PL_sv_undef;
568             }
569            
570 10           return sv_array;
571             }
572              
573 46           SV* SPVM_XS_UTIL_new_long_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
574            
575 46           *sv_error = &PL_sv_undef;
576            
577 46           HV* hv_self = (HV*)SvRV(sv_api);
578            
579 46           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
580 46 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
581 46           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
582            
583 46           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
584 46 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
585 46           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
586            
587 46 100         if (SvOK(sv_array)) {
    50          
    50          
588 76 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
589 10           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
590 10           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
591 10           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
592 10 100         if (!(strcmp(spvm_array_basic_type_name, "long") == 0 && spvm_array_type_dimension == 1)) {
    50          
593 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the long[] type"));
594 2           return &PL_sv_undef;
595             }
596             }
597 30 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
598 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
599 2           return &PL_sv_undef;
600             }
601             else {
602             // Elements
603 28           AV* av_array = (AV*)SvRV(sv_array);
604            
605             // Array length
606 28           int32_t length = av_len(av_array) + 1;
607            
608             // New array
609 28           void* spvm_array = env->new_long_array_no_mortal(env, stack, length);
610            
611 28           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
612 98 100         for (int32_t i = 0; i < length; i++) {
613 70           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
614 70 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
615            
616 70 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
617 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
618 0           return &PL_sv_undef;
619             }
620 70 50         elems[i] = (int64_t)SvIV(sv_elem);
621             }
622            
623 28           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
624             }
625             }
626             else {
627 6           sv_array = &PL_sv_undef;
628             }
629            
630 42           return sv_array;
631             }
632              
633 14           SV* SPVM_XS_UTIL_new_long_array_unsigned(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
634            
635 14           *sv_error = &PL_sv_undef;
636            
637 14           HV* hv_self = (HV*)SvRV(sv_api);
638            
639 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
640 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
641 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
642            
643 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
644 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
645 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
646            
647 14 100         if (SvOK(sv_array)) {
    50          
    50          
648 20 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
649 4           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
650 4           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
651 4           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
652 4 100         if (!(strcmp(spvm_array_basic_type_name, "long") == 0 && spvm_array_type_dimension == 1)) {
    50          
653 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the long[] type"));
654 2           return &PL_sv_undef;
655             }
656             }
657 8 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
658 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
659 2           return &PL_sv_undef;
660             }
661             else {
662             // Elements
663 6           AV* av_array = (AV*)SvRV(sv_array);
664            
665             // Array length
666 6           int32_t length = av_len(av_array) + 1;
667            
668             // New array
669 6           void* spvm_array = env->new_long_array_no_mortal(env, stack, length);
670            
671 6           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
672 18 100         for (int32_t i = 0; i < length; i++) {
673 12           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
674 12 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
675            
676 12 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
677 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
678 0           return &PL_sv_undef;
679             }
680 12 100         elems[i] = (int64_t)(uint64_t)SvUV(sv_elem);
681             }
682            
683 6           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
684             }
685             }
686             else {
687 2           sv_array = &PL_sv_undef;
688             }
689            
690 10           return sv_array;
691             }
692              
693 50           SV* SPVM_XS_UTIL_new_float_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
694            
695 50           *sv_error = &PL_sv_undef;
696            
697 50           HV* hv_self = (HV*)SvRV(sv_api);
698            
699 50           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
700 50 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
701 50           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
702            
703 50           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
704 50 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
705 50           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
706            
707 50 100         if (SvOK(sv_array)) {
    50          
    50          
708 84 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
709 10           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
710 10           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
711 10           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
712 10 100         if (!(strcmp(spvm_array_basic_type_name, "float") == 0 && spvm_array_type_dimension == 1)) {
    50          
713 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the float[] type"));
714 2           return &PL_sv_undef;
715             }
716             }
717 34 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
718 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
719 2           return &PL_sv_undef;
720             }
721             else {
722             // Elements
723 32           AV* av_array = (AV*)SvRV(sv_array);
724            
725             // Array length
726 32           int32_t length = av_len(av_array) + 1;
727            
728             // New array
729 32           void* spvm_array = env->new_float_array_no_mortal(env, stack, length);
730            
731 32           float* elems = env->get_elems_float(env, stack, spvm_array);
732 108 100         for (int32_t i = 0; i < length; i++) {
733 76           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
734 76 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
735            
736 76 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
737 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
738 0           return &PL_sv_undef;
739             }
740 76 100         elems[i] = (float)SvNV(sv_elem);
741             }
742            
743 32           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
744             }
745             }
746             else {
747 6           sv_array = &PL_sv_undef;
748             }
749            
750 46           return sv_array;
751             }
752              
753 46           SV* SPVM_XS_UTIL_new_double_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
754            
755 46           *sv_error = &PL_sv_undef;
756            
757 46           HV* hv_self = (HV*)SvRV(sv_api);
758            
759 46           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
760 46 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
761 46           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
762            
763 46           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
764 46 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
765 46           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
766            
767 46 100         if (SvOK(sv_array)) {
    50          
    50          
768 76 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
769 10           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
770 10           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
771 10           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
772 10 100         if (!(strcmp(spvm_array_basic_type_name, "double") == 0 && spvm_array_type_dimension == 1)) {
    50          
773 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the double[] type"));
774 2           return &PL_sv_undef;
775             }
776             }
777 30 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
778 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
779 2           return &PL_sv_undef;
780             }
781             else {
782             // Elements
783 28           AV* av_array = (AV*)SvRV(sv_array);
784            
785             // Array length
786 28           int32_t length = av_len(av_array) + 1;
787            
788             // New array
789 28           void* spvm_array = env->new_double_array_no_mortal(env, stack, length);
790            
791 28           double* elems = env->get_elems_double(env, stack, spvm_array);
792 96 100         for (int32_t i = 0; i < length; i++) {
793 68           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
794 68 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
795            
796 68 50         if (!(SvOK(sv_elem) && !SvROK(sv_elem))) {
    0          
    0          
    50          
797 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
798 0           return &PL_sv_undef;
799             }
800 68 100         elems[i] = (double)SvNV(sv_elem);
801             }
802            
803 28           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
804             }
805             }
806             else {
807 6           sv_array = &PL_sv_undef;
808             }
809            
810 42           return sv_array;
811             }
812              
813 368           SV* SPVM_XS_UTIL_new_string_array(pTHX_ SV* sv_api, SV* sv_array, SV** sv_error) {
814            
815 368           *sv_error = &PL_sv_undef;
816            
817 368           HV* hv_self = (HV*)SvRV(sv_api);
818            
819 368           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
820 368 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
821 368           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
822            
823 368           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
824 368 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
825 368           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
826            
827 368 100         if (SvOK(sv_array)) {
    50          
    50          
828 720 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
829 6           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
830 6           const char* spvm_array_basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
831 6           int32_t spvm_array_type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
832 6 100         if (!(strcmp(spvm_array_basic_type_name, "string") == 0 && spvm_array_type_dimension == 1)) {
    50          
833 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be the string[] type"));
834 2           return &PL_sv_undef;
835             }
836             }
837 356 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
838 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
839 2           return &PL_sv_undef;
840             }
841             else {
842             // Elements
843 354           AV* av_array = (AV*)SvRV(sv_array);
844            
845             // Array length
846 354           int32_t length = av_len(av_array) + 1;
847            
848             // New array
849 354           void* spvm_array = env->new_string_array_no_mortal(env, stack, length);
850            
851 473 100         for (int32_t i = 0; i < length; i++) {
852 119           SV** sv_elem_ptr = av_fetch(av_array, i, 0);
853 119 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
854 119           SV* sv_error_elem = &PL_sv_undef;
855 119           sv_elem = SPVM_XS_UTIL_new_string(aTHX_ sv_api, sv_elem, &sv_error_elem);
856            
857 119 50         if (SvOK(sv_error_elem)) {
    50          
    50          
858 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a non-reference scalar", i + 1));
859 0           return &PL_sv_undef;
860             }
861 119           void* spvm_elem = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_elem);
862 119           env->set_elem_string(env, stack, spvm_array, i, spvm_elem);
863             }
864            
865 354           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
866             }
867             }
868             else {
869 6           sv_array = &PL_sv_undef;
870             }
871            
872 364           return sv_array;
873             }
874              
875 16008           SV* SPVM_XS_UTIL_new_object_array(pTHX_ SV* sv_api, void* basic_type, SV* sv_array, SV** sv_error) {
876            
877 16008           *sv_error = &PL_sv_undef;
878            
879 16008           HV* hv_self = (HV*)SvRV(sv_api);
880            
881 16008           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
882 16008 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
883 16008           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
884            
885 16008           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
886 16008 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
887 16008           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
888            
889 16008 100         if (SvOK(sv_array)) {
    50          
    50          
890 32004 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
891 428           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
892 428           int32_t type_dimension = 1;
893 428 100         if (!env->isa(env, stack, spvm_array, basic_type, type_dimension)) {
894 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be assignable"));
895 2           return &PL_sv_undef;
896             }
897             }
898 15576 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
899 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
900 2           return &PL_sv_undef;
901             }
902             else {
903             // Elements
904 15574           AV* av_array = (AV*)SvRV(sv_array);
905            
906             // Array length
907 15574           int32_t length = av_len(av_array) + 1;
908            
909             // New array
910 15574           void* spvm_array = env->new_object_array_no_mortal(env, stack, basic_type, length);
911            
912 46240 100         for (int32_t index = 0; index < length; index++) {
913 30666           SV** sv_elem_ptr = av_fetch(av_array, index, 0);
914 30666 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
915            
916 30666 100         if (!SvOK(sv_elem)) {
    50          
    50          
917 2           env->set_elem_object(env, stack, spvm_array, index, NULL);
918             }
919 61328 50         else if (sv_isobject(sv_elem) && sv_derived_from(sv_elem, "SPVM::BlessedObject")) {
    50          
920 30664           void* elem = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_elem);
921            
922 30664           int32_t elem_isa = env->elem_isa(env, stack, spvm_array, elem);
923 30664 50         if (elem_isa) {
924 30664           env->set_elem_object(env, stack, spvm_array, index, elem);
925             }
926             else {
927 0           void* spvm_elem_type_name = env->get_type_name(env, stack, elem);
928 0           const char* elem_type_name = env->get_chars(env, stack, spvm_elem_type_name);
929 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be the \"%s\" assignable type", index + 1, elem_type_name));
930 0           return &PL_sv_undef;
931             }
932             }
933             else {
934 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a SPVM::BlessedObject or undef", index + 1));
935 0           return &PL_sv_undef;
936             }
937             }
938            
939 15574           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
940             }
941             }
942             else {
943 4           sv_array = &PL_sv_undef;
944             }
945            
946 16004           return sv_array;
947             }
948              
949 32           SV* SPVM_XS_UTIL_new_muldim_array(pTHX_ SV* sv_api, void* basic_type, int32_t type_dimension, SV* sv_array, SV** sv_error) {
950            
951 32           *sv_error = &PL_sv_undef;
952            
953 32           HV* hv_self = (HV*)SvRV(sv_api);
954            
955 32           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
956 32 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
957 32           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
958            
959 32           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
960 32 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
961 32           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
962            
963 32 50         if (SvOK(sv_array)) {
    0          
    0          
964 60 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
965 16           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
966 16 100         if (!env->isa(env, stack, spvm_array, basic_type, type_dimension)) {
967 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be assignable"));
968 2           return &PL_sv_undef;
969             }
970             }
971 16 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
972 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
973 2           return &PL_sv_undef;
974             }
975             else {
976             // Elements
977 14           AV* av_array = (AV*)SvRV(sv_array);
978            
979             // Array length
980 14           int32_t length = av_len(av_array) + 1;
981            
982             // New array
983 14           void* spvm_array = env->new_muldim_array_no_mortal(env, stack, basic_type, type_dimension, length);
984            
985 38 100         for (int32_t index = 0; index < length; index++) {
986 24           SV** sv_elem_ptr = av_fetch(av_array, index, 0);
987 24 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
988            
989 24 50         if (!SvOK(sv_elem)) {
    0          
    0          
990 0           env->set_elem_object(env, stack, spvm_array, index, NULL);
991             }
992 48 50         else if (sv_isobject(sv_elem) && sv_derived_from(sv_elem, "SPVM::BlessedObject")) {
    50          
993 24           void* elem = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_elem);
994            
995 24           int32_t elem_isa = env->elem_isa(env, stack, spvm_array, elem);
996 24 50         if (elem_isa) {
997 24           env->set_elem_object(env, stack, spvm_array, index, elem);
998             }
999             else {
1000 0           void* spvm_elem_type_name = env->get_type_name(env, stack, elem);
1001 0           const char* elem_type_name = env->get_chars(env, stack, spvm_elem_type_name);
1002 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be the \"%s\" assignable type", index + 1, elem_type_name));
1003 0           return &PL_sv_undef;
1004             }
1005             }
1006             else {
1007 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a SPVM::BlessedObject or undef", index + 1));
1008 0           return &PL_sv_undef;
1009             }
1010             }
1011            
1012 14           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
1013             }
1014             }
1015             else {
1016 0           sv_array = &PL_sv_undef;
1017             }
1018            
1019 28           return sv_array;
1020             }
1021              
1022 66           SV* SPVM_XS_UTIL_new_mulnum_array(pTHX_ SV* sv_api, void* basic_type, SV* sv_array, SV** sv_error) {
1023            
1024 66           *sv_error = &PL_sv_undef;
1025            
1026 66           HV* hv_self = (HV*)SvRV(sv_api);
1027            
1028 66           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
1029 66 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
1030 66           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
1031            
1032 66           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
1033 66 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
1034 66           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
1035            
1036 66 50         if (SvOK(sv_array)) {
    0          
    0          
1037 128 100         if (sv_isobject(sv_array) && sv_derived_from(sv_array, "SPVM::BlessedObject::Array")) {
    50          
1038 26           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_array);
1039 26           int32_t type_dimension = 1;
1040 26 100         if (!env->isa(env, stack, spvm_array, basic_type, type_dimension)) {
1041 2           *sv_error = sv_2mortal(newSVpvf(": If it is a SPVM::BlessedObject::Array object, the type must be assignable"));
1042 2           return &PL_sv_undef;
1043             }
1044             }
1045 40 50         else if (!(SvROK(sv_array) && sv_derived_from(sv_array, "ARRAY"))) {
    100          
1046 2           *sv_error = sv_2mortal(newSVpvf(": If it is a reference, it must be an array reference"));
1047 2           return &PL_sv_undef;
1048             }
1049             else {
1050 38           AV* av_array = (AV*)SvRV(sv_array);
1051            
1052 38           int32_t length = av_len(av_array) + 1;
1053            
1054             // Runtime
1055 38           void* runtime = env->runtime;
1056            
1057             // New array
1058 38           void* spvm_array = env->new_mulnum_array_no_mortal(env, stack, basic_type, length);
1059            
1060 152 100         for (int32_t index = 0; index < length; index++) {
1061 114           SV** sv_elem_ptr = av_fetch(av_array, index, 0);
1062 114 50         SV* sv_elem = sv_elem_ptr ? *sv_elem_ptr : &PL_sv_undef;
1063            
1064 228 50         if (SvROK(sv_elem) && sv_derived_from(sv_elem, "HASH")) {
    50          
1065            
1066 114           const char* basic_type_name = env->api->basic_type->get_name(env->runtime, basic_type);
1067 114           int32_t basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, basic_type);
1068            
1069 114           void* elems = (void*)env->get_elems_int(env, stack, spvm_array);
1070            
1071 114           HV* hv_value = (HV*)SvRV(sv_elem);
1072 114           int32_t fields_length = basic_type_fields_length;
1073             // Field exists check
1074 114           int32_t hash_keys_length = 0;
1075 456 100         while (hv_iternext(hv_value)) {
1076 342           hash_keys_length++;
1077             }
1078            
1079 456 100         for (int32_t field_index = 0; field_index < basic_type_fields_length; field_index++) {
1080 342           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, basic_type, field_index);
1081            
1082 342           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
1083            
1084 342           SV** sv_field_value_ptr = hv_fetch(hv_value, mulnum_field_name, strlen(mulnum_field_name), 0);
1085             SV* sv_field_value;
1086 342 50         if (sv_field_value_ptr) {
1087 342           sv_field_value = *sv_field_value_ptr;
1088             }
1089             else {
1090 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element's hash reference must have the \"%s\" key for the \"%s\" field of the \"%s\" basic type\n %s at %s line %d\n", index + 1, mulnum_field_name, mulnum_field_name, basic_type_name, __func__, FILE_NAME, __LINE__));
1091 0           return &PL_sv_undef;
1092             }
1093            
1094 342           void* mulnum_field_basic_type = env->api->field->get_basic_type(env->runtime, mulnum_field);
1095 342           int32_t mulnum_field_basic_type_id = env->api->basic_type->get_id(env->runtime, mulnum_field_basic_type);
1096 342           switch (mulnum_field_basic_type_id) {
1097             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1098 72 50         ((int8_t*)elems)[(fields_length * index) + field_index] = (int8_t)SvIV(sv_field_value);
1099 72           break;
1100             }
1101             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1102 54 50         ((int16_t*)elems)[(fields_length * index) + field_index] = (int16_t)SvIV(sv_field_value);
1103 54           break;
1104             }
1105             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1106 54 50         ((int32_t*)elems)[(fields_length * index) + field_index] = (int32_t)SvIV(sv_field_value);
1107 54           break;
1108             }
1109             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1110 54 50         ((int64_t*)elems)[(fields_length * index) + field_index] = (int64_t)SvIV(sv_field_value);
1111 54           break;
1112             }
1113             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1114 54 100         ((float*)elems)[(fields_length * index) + field_index] = (float)SvNV(sv_field_value);
1115 54           break;
1116             }
1117             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1118 54 100         ((double*)elems)[(fields_length * index) + field_index] = (double)SvNV(sv_field_value);
1119 54           break;
1120             }
1121             default: {
1122             assert(0);
1123             }
1124             }
1125             }
1126             }
1127             else {
1128 0           *sv_error = sv_2mortal(newSVpvf("'s %dth element must be a hash reference\n %s at %s line %d\n", index + 1, __func__, FILE_NAME, __LINE__));
1129 0           return &PL_sv_undef;
1130             }
1131             }
1132            
1133 38           sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_array, "SPVM::BlessedObject::Array");
1134             }
1135             }
1136             else {
1137 0           sv_array = &PL_sv_undef;
1138             }
1139            
1140 62           return sv_array;
1141             }
1142              
1143             MODULE = SPVM::ExchangeAPI PACKAGE = SPVM::ExchangeAPI
1144              
1145             SV*
1146             _xs_call_method(...)
1147             PPCODE:
1148             {
1149            
1150 197152           int32_t args_length = items;
1151            
1152             // SPVM::ExchangeAPI::Error
1153 197152           SV* sv_error_ret = ST(args_length - 1);
1154 197152 100         if (sv_isobject(sv_error_ret) && sv_derived_from(sv_error_ret, "SPVM::ExchangeAPI::Error")) {
    100          
1155 4           args_length -= 1;
1156             }
1157             else {
1158 197148           sv_error_ret = &PL_sv_undef;
1159             }
1160            
1161 197152           SV* sv_self = ST(0);
1162 197152           HV* hv_self = (HV*)SvRV(sv_self);
1163            
1164             // Env
1165 197152           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
1166 197152 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
1167 197152           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
1168            
1169             // Stack
1170 197152           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
1171 197152 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
1172 197152           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
1173            
1174             // Invocant
1175 197152           SV* sv_invocant = ST(1);
1176            
1177             // Method name
1178 197152           SV* sv_method_name = ST(2);
1179 197152 50         const char* method_name = SvPV_nolen(sv_method_name);
1180            
1181             // Basic Type Name
1182 197152           void* method = NULL;
1183 197152           const char* basic_type_name = NULL;
1184             int32_t class_method_call;
1185 197152 100         if (sv_isobject(sv_invocant)) {
1186 168926           class_method_call = 0;
1187 168926 50         if (!(sv_isobject(sv_invocant) && sv_derived_from(sv_invocant, "SPVM::BlessedObject::Class"))) {
    50          
1188 0           croak("$invocant must be a SPVM::BlessedObject::Class object\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
1189             }
1190            
1191 168926           HV* hv_invocant = (HV*)SvRV(sv_invocant);
1192            
1193 168926           void* object = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_invocant);
1194 168926           basic_type_name = env->get_object_basic_type_name(env, stack, object);
1195            
1196 168926           char* found_char = strrchr(method_name, ':');
1197 168926 100         if (found_char) {
1198 6 50         if (!(*(found_char - 1) == ':')) {
1199 0           croak("The static method call must be valid\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
1200             }
1201 6           *(found_char - 1) = '\0';
1202 6           const char* basic_type_name = method_name;
1203 6           method_name = found_char + 1;
1204            
1205 6           void* static_call_basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
1206 6 50         if (!static_call_basic_type) {
1207 0           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
1208             }
1209            
1210 6           int32_t isa = env->isa(env, stack, object, static_call_basic_type, 0);
1211 6 100         if (!isa) {
1212 2           croak("The invocant must be assinged to the \"%s\" basic type\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
1213             }
1214            
1215 4           method = env->api->basic_type->get_method_by_name(env->runtime, static_call_basic_type, method_name);
1216 4           *(found_char - 1) = ':';
1217             }
1218             else {
1219 168920           method = env->get_instance_method(env, stack, object, method_name);
1220             }
1221            
1222 168924 100         if (method) {
1223 168922           int32_t is_class_method = env->api->method->is_class_method(env->runtime, method);
1224 168922 50         if (is_class_method) {
1225 0           method = NULL;
1226             }
1227             }
1228            
1229 168924           ST(1) = sv_method_name;
1230 168924           ST(2) = sv_invocant;
1231             }
1232             else {
1233 28226           class_method_call = 1;
1234 28226 50         basic_type_name = SvPV_nolen(sv_invocant);
1235 28226           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
1236            
1237 28226           method = env->api->basic_type->get_method_by_name(env->runtime, basic_type, method_name);
1238            
1239 28226 50         if (method) {
1240 28226           int32_t is_class_method = env->api->method->is_class_method(env->runtime, method);
1241 28226 50         if (!is_class_method) {
1242 0           method = NULL;
1243             }
1244             }
1245             }
1246            
1247             // Runtime
1248 197150           void* runtime = env->runtime;
1249            
1250             // Method not found
1251 197150 100         if (!method) {
1252 2           croak("The \"%s\" method in the \"%s\" class is not found\n %s at %s line %d\n", method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1253             }
1254            
1255             // Base index of SPVM arguments
1256             int32_t spvm_args_base;
1257 197148 100         if (class_method_call) {
1258 28226           spvm_args_base = 3;
1259             }
1260             else {
1261 168922           spvm_args_base = 2;
1262             }
1263              
1264 197148           int32_t method_args_length = env->api->method->get_args_length(env->runtime, method);
1265 197148           int32_t method_required_args_length = env->api->method->get_required_args_length(env->runtime, method);
1266            
1267             // Check argument count
1268 197148           int32_t call_method_args_length = args_length - spvm_args_base;
1269            
1270 197148 100         if (call_method_args_length < method_required_args_length) {
1271 2           croak("Too few arguments are passed to the \"%s\" method in the \"%s\" class\n %s at %s line %d\n", method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1272             }
1273 197146 100         else if (call_method_args_length > method_args_length) {
1274 2           croak("Too many arguments are passed to the \"%s\" method in the \"%s\" class\n %s at %s line %d\n", method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1275             }
1276            
1277 197144           int32_t stack_index = 0;
1278            
1279 197144           AV* av_refs = NULL;
1280            
1281 197144           int32_t has_ref_arg = 0;
1282 492361 100         for (int32_t arg_index = 0; arg_index < method_args_length; arg_index++) {
1283 295305           void* arg = env->api->method->get_arg_by_index(env->runtime, method, arg_index);
1284 295305           int32_t arg_type_flag = env->api->arg->get_type_flag(env->runtime, arg);
1285 295305 100         if (arg_type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF) {
1286 88           has_ref_arg = 1;
1287 88           av_refs = (AV*)sv_2mortal((SV*)newAV());
1288 88           break;
1289             }
1290             }
1291            
1292             // Arguments conversion
1293 492285 100         for (int32_t arg_index = 0; arg_index < method_args_length; arg_index++) {
1294            
1295 295307 100         if (arg_index >= call_method_args_length) {
1296 36           break;
1297             }
1298            
1299 295271           int32_t arg_index_nth = arg_index + (spvm_args_base - 2);
1300            
1301             // Get value from Perl argument native_stack
1302 295271           SV* sv_value = ST(spvm_args_base + arg_index);
1303            
1304 295271           void* arg = env->api->method->get_arg_by_index(env->runtime, method, arg_index);
1305 295271           void* arg_basic_type = env->api->arg->get_basic_type(env->runtime, arg);
1306 295271           int32_t arg_basic_type_id = env->api->basic_type->get_id(env->runtime, arg_basic_type);
1307 295271           int32_t arg_type_dimension = env->api->arg->get_type_dimension(env->runtime, arg);
1308 295271           int32_t arg_type_flag = env->api->arg->get_type_flag(env->runtime, arg);
1309 295271           int32_t arg_basic_type_category = env->api->basic_type->get_category(env->runtime, arg_basic_type);
1310            
1311 295271           int32_t arg_type_is_not_ref = !(arg_type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF);
1312            
1313             // Argument conversion
1314 295271 100         if (arg_type_dimension == 0) {
1315 294347 100         if (arg_type_is_not_ref) {
1316 294253           switch (arg_basic_type_category) {
1317             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC: {
1318 37815 100         if (!(SvOK(sv_value) && !SvROK(sv_value))) {
    50          
    50          
    100          
1319 38           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a non-reference scalar\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1320             }
1321            
1322 37777           switch(arg_basic_type_id) {
1323             // Argument conversion - byte
1324             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
1325 18 100         int8_t value = (int8_t)SvIV(sv_value);
1326 18           stack[stack_index].bval = value;
1327 18           break;
1328             }
1329             // Argument conversion - short
1330             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
1331 14 100         int16_t value = (int16_t)SvIV(sv_value);
1332 14           stack[stack_index].sval = value;
1333 14           break;
1334             }
1335             // Argument conversion - int
1336             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
1337 37125 100         int32_t value = (int32_t)SvIV(sv_value);
1338 37125           stack[stack_index].ival = value;
1339 37125           break;
1340             }
1341             // Argument conversion - long
1342             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
1343 522 100         int64_t value = (int64_t)SvIV(sv_value);
1344 522           stack[stack_index].lval = value;
1345 522           break;
1346             }
1347             // Argument conversion - float
1348             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
1349 48 100         float value = (float)SvNV(sv_value);
1350 48           stack[stack_index].fval = value;
1351 48           break;
1352             }
1353             // Argument conversion - double
1354             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
1355 50 100         double value = (double)SvNV(sv_value);
1356 50           stack[stack_index].dval = value;
1357 50           break;
1358             }
1359             default: {
1360             assert(0);
1361             }
1362             }
1363 37777           stack_index++;
1364 37777           break;
1365             }
1366             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_STRING: {
1367             // Argument conversion - string
1368 53802           SV* sv_error = &PL_sv_undef;
1369 53802           sv_value = SPVM_XS_UTIL_new_string(aTHX_ sv_self, sv_value, &sv_error);
1370 53802 100         if (SvOK(sv_error)) {
    50          
    50          
1371 2 50         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1372             }
1373 53800           void* spvm_string = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1374            
1375 53800           stack[stack_index].oval = spvm_string;
1376            
1377 53800           stack_index++;
1378 53800           break;
1379             }
1380             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_ANY_OBJECT: {
1381             // Argument conversion - any object
1382             void* spvm_value;
1383 22 50         if (!SvOK(sv_value)) {
    0          
    0          
1384 0           spvm_value = NULL;
1385             }
1386             else {
1387 22           int32_t created_as_string = SvPOK(sv_value) && !SvIsBOOL(sv_value);
1388            
1389 22 100         if (sv_isobject(sv_value) && sv_derived_from(sv_value, "SPVM::BlessedObject")) {
    50          
1390 18           spvm_value = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1391             }
1392 4 100         else if (created_as_string) {
1393 2           warn("AAA");
1394 2           STRLEN length = -1;
1395 2 50         const char* string = SvPV(sv_value, length);
1396 2           spvm_value = env->new_string_no_mortal(env, stack, string, (int32_t)length);
1397 2           SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_value, "SPVM::BlessedObject::String");
1398             }
1399             else {
1400 2           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a SPVM::BlessedObject object or a string or undef\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1401             }
1402             }
1403 20           stack[stack_index].oval = spvm_value;
1404            
1405 20           stack_index++;
1406 20           break;
1407             }
1408             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS:
1409             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE:
1410             {
1411 202576           int32_t error = 0;
1412             void* spvm_value;
1413 202576 100         if (!SvOK(sv_value)) {
    50          
    50          
1414 2           spvm_value = NULL;
1415             }
1416 202574 50         else if (sv_isobject(sv_value) && sv_derived_from(sv_value, "SPVM::BlessedObject::Class")) {
    50          
1417 202574           spvm_value = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1418            
1419 202574 50         if (!env->isa(env, stack, spvm_value, arg_basic_type, arg_type_dimension)) {
1420 0           error = 1;
1421             }
1422             }
1423             else {
1424 0           error = 1;
1425             }
1426            
1427 202576 50         if (error) {
1428 0           const char* arg_basic_type_name = env->api->basic_type->get_name(env->runtime, arg_basic_type);
1429 0           void* spvm_compile_type_name = env->get_compile_type_name(env, stack, arg_basic_type_name, arg_type_dimension, arg_type_flag);
1430 0           const char* compile_type_name = env->get_chars(env, stack, spvm_compile_type_name);
1431 0           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a SPVM::BlessedObject::Class object of a \"%s\" assignable type or undef\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, compile_type_name, __func__, FILE_NAME, __LINE__);
1432             }
1433            
1434 202576           stack[stack_index].oval = spvm_value;
1435            
1436 202576           stack_index++;
1437 202576           break;
1438             }
1439             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
1440             {
1441             // Argument conversion - multi-numeric
1442 38 100         if (!(SvROK(sv_value) && sv_derived_from(sv_value, "HASH"))) {
    50          
1443 12           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a hash reference\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1444             }
1445            
1446 26           int32_t arg_basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, arg_basic_type);
1447 26           void* arg_basic_type_field_first = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, 0);
1448              
1449 26           void* arg_basic_type_field_basic_type = env->api->field->get_basic_type(env->runtime, arg_basic_type_field_first);
1450 26           int32_t arg_basic_type_field_basic_type_id = env->api->basic_type->get_id(env->runtime, arg_basic_type_field_basic_type);
1451             assert(arg_basic_type_field_basic_type_id >= 0);
1452            
1453 26           HV* hv_value = (HV*)SvRV(sv_value);
1454 90 100         for (int32_t field_index = 0; field_index < arg_basic_type_fields_length; field_index++) {
1455 76           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, field_index);
1456 76           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
1457 76           SV** sv_field_value_ptr = hv_fetch(hv_value, mulnum_field_name, strlen(mulnum_field_name), 0);
1458             SV* sv_field_value;
1459 76 100         if (sv_field_value_ptr) {
1460 64           sv_field_value = *sv_field_value_ptr;
1461             }
1462             else {
1463 12           const char* arg_basic_type_name = env->api->basic_type->get_name(env->runtime, arg_basic_type);
1464 12           croak("The hash reference for the %dth argument of the \"%s\" method in the \"%s\" class must have the \"%s\" key for the \"%s\" field of the \"%s\" basic type\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, mulnum_field_name, mulnum_field_name, arg_basic_type_name, __func__, FILE_NAME, __LINE__);
1465              
1466             }
1467            
1468 64           switch (arg_basic_type_field_basic_type_id) {
1469             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1470             // Argument conversion - multi-numeric byte
1471 10 50         int8_t value = (int8_t)SvIV(sv_field_value);
1472 10           stack[stack_index + field_index].bval = value;
1473 10           break;
1474             }
1475             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1476             // Argument conversion - multi-numeric short
1477 10 50         int16_t value = (int16_t)SvIV(sv_field_value);
1478 10           stack[stack_index + field_index].sval = value;
1479 10           break;
1480             }
1481             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1482             // Argument conversion - multi-numeric int
1483 10 50         int32_t value = (int32_t)SvIV(sv_field_value);
1484 10           stack[stack_index + field_index].ival = value;
1485 10           break;
1486             }
1487             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1488             // Argument conversion - multi-numeric long
1489 10 50         int64_t value = (int64_t)SvIV(sv_field_value);
1490 10           stack[stack_index + field_index].lval = value;
1491 10           break;
1492             }
1493             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1494             // Argument conversion - multi-numeric float
1495 10 100         float value = (float)SvNV(sv_field_value);
1496 10           stack[stack_index + field_index].fval = value;
1497 10           break;
1498             }
1499             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1500             // Argument conversion - multi-numeric double
1501 14 100         double value = (double)SvNV(sv_field_value);
1502 14           stack[stack_index + field_index].dval = value;
1503 14           break;
1504             }
1505             default: {
1506             assert(0);
1507             }
1508             }
1509             }
1510 14           stack_index += arg_basic_type_fields_length;
1511 294187           break;
1512             }
1513             default: {
1514             assert(0);
1515             }
1516             }
1517             }
1518             // Reference argument
1519             else {
1520            
1521 94           switch (arg_basic_type_category) {
1522             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC: {
1523             // Argument conversion - numeric reference
1524 54 100         if (!(SvROK(sv_value) && sv_derived_from(sv_value , "SCALAR"))) {
    100          
1525 24           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a scalar reference\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1526             }
1527            
1528 30           SV* sv_value_deref = SvRV(sv_value);
1529            
1530 30           switch (arg_basic_type_id) {
1531             // Argument conversion - byte reference
1532             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1533 6 100         int8_t value = (int8_t)SvIV(sv_value_deref);
1534            
1535 6           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int8_t)));
1536 6 50         int8_t* ref = (int8_t*)SvPV_nolen(sv_ref);
1537 6           memcpy((void*)ref, &value, sizeof(int8_t));
1538 6           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1539 6           stack[stack_index].bref = ref;
1540            
1541 6           break;
1542             }
1543             // Argument conversion - short reference
1544             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1545 4 100         int16_t value = (int16_t)SvIV(sv_value_deref);
1546            
1547 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int16_t)));
1548 4 50         int16_t* ref = (int16_t*)SvPV_nolen(sv_ref);
1549 4           memcpy((void*)ref, &value, sizeof(int16_t));
1550 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1551 4           stack[stack_index].sref = ref;
1552            
1553 4           break;
1554             }
1555             // Argument conversion - int reference
1556             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1557 8 100         int32_t value = (int32_t)SvIV(sv_value_deref);
1558            
1559 8           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int32_t)));
1560 8 50         int32_t* ref = (int32_t*)SvPV_nolen(sv_ref);
1561 8           memcpy((void*)ref, &value, sizeof(int32_t));
1562 8           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1563 8           stack[stack_index].iref = ref;
1564            
1565 8           break;
1566             }
1567             // Argument conversion - long reference
1568             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1569 4 100         int64_t value = (int64_t)SvIV(sv_value_deref);
1570            
1571 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int64_t)));
1572 4 50         int64_t* ref = (int64_t*)SvPV_nolen(sv_ref);
1573 4           memcpy((void*)ref, &value, sizeof(int64_t));
1574 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1575 4           stack[stack_index].lref = ref;
1576            
1577 4           break;
1578             }
1579             // Argument conversion - float reference
1580             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1581 4 100         float value = (float)SvNV(sv_value_deref);
1582            
1583 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(float)));
1584 4 50         float* ref = (float*)SvPV_nolen(sv_ref);
1585 4           memcpy((void*)ref, &value, sizeof(float));
1586 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1587 4           stack[stack_index].fref = ref;
1588            
1589 4           break;
1590             }
1591             // Argument conversion - double reference
1592             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1593 4 100         double value = (double)SvNV(sv_value_deref);
1594            
1595 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(double)));
1596 4 50         double* ref = (double*)SvPV_nolen(sv_ref);
1597 4           memcpy((void*)ref, &value, sizeof(double));
1598 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1599 4           stack[stack_index].dref = ref;
1600            
1601 4           break;
1602             }
1603             }
1604            
1605 30           stack_index++;
1606            
1607 30           break;
1608             }
1609             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
1610             {
1611             // Argument conversion - multi-numeric reference
1612 40 50         if (!(SvROK(sv_value) && SvROK(SvRV(sv_value)) && sv_derived_from(SvRV(sv_value) , "HASH"))) {
    100          
    50          
1613 12           croak("The %dth argument of the \"%s\" method in the \"%s\" class must be a reference to a hash reference\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
1614             }
1615            
1616 28           SV* hv_value_ref = SvRV(sv_value);
1617            
1618 28           HV* hv_value = (HV*)SvRV(hv_value_ref);
1619 28           int32_t arg_basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, arg_basic_type);
1620 28           void* arg_basic_type_field_first = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, 0);
1621 28           void* arg_basic_type_field_basic_type = env->api->field->get_basic_type(env->runtime, arg_basic_type_field_first);
1622 28           int32_t arg_basic_type_field_basic_type_id = env->api->basic_type->get_id(env->runtime, arg_basic_type_field_basic_type);
1623             assert(arg_basic_type_field_basic_type_id >= 0);
1624              
1625 28           switch(arg_basic_type_field_basic_type_id) {
1626             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1627 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int8_t) * arg_basic_type_fields_length));
1628 4 50         int8_t* ref = (int8_t*)SvPV_nolen(sv_ref);
1629 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1630 4           stack[stack_index].bref = ref;
1631            
1632 4           break;
1633             }
1634             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1635 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int16_t) * arg_basic_type_fields_length));
1636 4 50         int16_t* ref = (int16_t*)SvPV_nolen(sv_ref);
1637 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1638 4           stack[stack_index].sref = ref;
1639            
1640 4           break;
1641             }
1642             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1643 8           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int32_t) * arg_basic_type_fields_length));
1644 8 50         int32_t* ref = (int32_t*)SvPV_nolen(sv_ref);
1645 8           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1646 8           stack[stack_index].iref = ref;
1647            
1648 8           break;
1649             }
1650             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1651 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(int64_t) * arg_basic_type_fields_length));
1652 4 50         int64_t* ref = (int64_t*)SvPV_nolen(sv_ref);
1653 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1654 4           stack[stack_index].lref = ref;
1655            
1656 4           break;
1657             }
1658             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1659 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(float) * arg_basic_type_fields_length));
1660 4 50         float* ref = (float*)SvPV_nolen(sv_ref);
1661 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1662 4           stack[stack_index].fref = ref;
1663            
1664 4           break;
1665             }
1666             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1667 4           SV* sv_ref = sv_2mortal(newSVpv("", sizeof(double) * arg_basic_type_fields_length));
1668 4 50         double* ref = (double*)SvPV_nolen(sv_ref);
1669 4           av_store(av_refs, arg_index,SvREFCNT_inc(sv_ref));
1670 4           stack[stack_index].dref = ref;
1671            
1672 4           break;
1673             }
1674             default: {
1675             assert(0);
1676             }
1677             }
1678            
1679 100 100         for (int32_t field_index = 0; field_index < arg_basic_type_fields_length; field_index++) {
1680 84           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, field_index);
1681 84           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
1682 84           SV** sv_field_value_ptr = hv_fetch(hv_value, mulnum_field_name, strlen(mulnum_field_name), 0);
1683             SV* sv_field_value;
1684 84 100         if (sv_field_value_ptr) {
1685 72           sv_field_value = *sv_field_value_ptr;
1686             }
1687             else {
1688 12           const char* arg_basic_type_name = env->api->basic_type->get_name(env->runtime, arg_basic_type);
1689 12           croak("The hash reference for the %dth argument of the \"%s\" method in the \"%s\" class must have the \"%s\" key for the \"%s\" field of the \"%s\" basic type\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, mulnum_field_name, mulnum_field_name, arg_basic_type_name, __func__, FILE_NAME, __LINE__);
1690             }
1691 72           switch(arg_basic_type_field_basic_type_id) {
1692             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1693             // Argument conversion - multi-numeric byte reference
1694 10 50         int8_t value = (int8_t)SvIV(sv_field_value);
1695            
1696 10           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1697 10 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1698 10 50         int8_t* ref = (int8_t*)SvPV_nolen(sv_ref);
1699 10           memcpy((void*)(ref + field_index), &value, sizeof(int8_t));
1700            
1701 10           break;
1702             }
1703             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1704             // Argument conversion - multi-numeric short reference
1705 10 50         int16_t value = (int16_t)SvIV(sv_field_value);
1706            
1707 10           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1708 10 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1709 10 50         int16_t* ref = (int16_t*)SvPV_nolen(sv_ref);
1710 10           memcpy((void*)(ref + field_index), &value, sizeof(int16_t));
1711            
1712 10           break;
1713             }
1714             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1715             // Argument conversion - multi-numeric int reference
1716 22 50         int32_t value = (int32_t)SvIV(sv_field_value);
1717            
1718 22           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1719 22 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1720 22 50         int32_t* ref = (int32_t*)SvPV_nolen(sv_ref);
1721 22           memcpy((void*)(ref + field_index), &value, sizeof(int32_t));
1722            
1723 22           break;
1724             }
1725             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1726             // Argument conversion - multi-numeric long reference
1727 10 50         int64_t value = (int64_t)SvIV(sv_field_value);
1728            
1729 10           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1730 10 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1731 10 50         int64_t* ref = (int64_t*)SvPV_nolen(sv_ref);
1732 10           memcpy((void*)(ref + field_index), &value, sizeof(int64_t));
1733            
1734 10           break;
1735             }
1736             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1737             // Argument conversion - multi-numeric float reference
1738 10 100         float value = (float)SvNV(sv_field_value);
1739            
1740 10           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1741 10 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1742 10 50         float* ref = (float*)SvPV_nolen(sv_ref);
1743 10           memcpy((void*)(ref + field_index), &value, sizeof(float));
1744            
1745 10           break;
1746             }
1747             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1748             // Argument conversion - multi-numeric double reference
1749 10 100         double value = (double)SvNV(sv_field_value);
1750            
1751 10           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
1752 10 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
1753 10 50         double* ref = (double*)SvPV_nolen(sv_ref);
1754 10           memcpy((void*)(ref + field_index), &value, sizeof(double));
1755            
1756 10           break;
1757             }
1758             default: {
1759             assert(0);
1760             }
1761             }
1762             }
1763            
1764 16           stack_index++;
1765 294233           break;
1766             }
1767             default: {
1768             assert(0);
1769             }
1770             }
1771             }
1772             }
1773 924 100         else if (arg_type_dimension == 1) {
1774 910           switch (arg_basic_type_category) {
1775             // Argument conversion - numeric array
1776             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC: {
1777 100           SV* sv_error = &PL_sv_undef;
1778 100           switch (arg_basic_type_id) {
1779             // Argument conversion - byte array
1780             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1781 16           sv_value = SPVM_XS_UTIL_new_byte_array(aTHX_ sv_self, sv_value, &sv_error);
1782 16           break;
1783             }
1784             // Argument conversion - short array
1785             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1786 14           sv_value = SPVM_XS_UTIL_new_short_array(aTHX_ sv_self, sv_value, &sv_error);
1787 14           break;
1788             }
1789             // Argument conversion - int array
1790             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1791 26           sv_value = SPVM_XS_UTIL_new_int_array(aTHX_ sv_self, sv_value, &sv_error);
1792 26           break;
1793             }
1794             // Argument conversion - long array
1795             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1796 14           sv_value = SPVM_XS_UTIL_new_long_array(aTHX_ sv_self, sv_value, &sv_error);
1797 14           break;
1798             }
1799             // Argument conversion - float array
1800             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1801 16           sv_value = SPVM_XS_UTIL_new_float_array(aTHX_ sv_self, sv_value, &sv_error);
1802 16           break;
1803             }
1804             // Argument conversion - double array
1805             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1806 14           sv_value = SPVM_XS_UTIL_new_double_array(aTHX_ sv_self, sv_value, &sv_error);
1807 14           break;
1808             }
1809             default: {
1810             assert(0);
1811             }
1812             }
1813            
1814 100 100         if (SvOK(sv_error)) {
    50          
    50          
1815 2 50         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1816             }
1817            
1818 98           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1819            
1820 98           stack[stack_index].oval = spvm_array;
1821            
1822 98           stack_index++;
1823 98           break;
1824             }
1825             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
1826             {
1827 36           SV* sv_error = &PL_sv_undef;
1828 36           sv_value = SPVM_XS_UTIL_new_mulnum_array(aTHX_ sv_self, arg_basic_type, sv_value, &sv_error);
1829            
1830 36 50         if (SvOK(sv_error)) {
    50          
    50          
1831 0 0         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1832             }
1833            
1834 36           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1835            
1836 36           stack[stack_index].oval = spvm_array;
1837            
1838 36           stack_index++;
1839 36           break;
1840             }
1841             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_STRING: {
1842 346           SV* sv_error = &PL_sv_undef;
1843            
1844 346           sv_value = SPVM_XS_UTIL_new_string_array(aTHX_ sv_self, sv_value, &sv_error);
1845            
1846 346 50         if (SvOK(sv_error)) {
    50          
    50          
1847 0 0         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1848             }
1849            
1850 346           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1851            
1852 346           stack[stack_index].oval = spvm_array;
1853            
1854 346           stack_index++;
1855 346           break;
1856             }
1857             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS:
1858             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE:
1859             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_ANY_OBJECT:
1860             {
1861 428           SV* sv_error = &PL_sv_undef;
1862            
1863 428           sv_value = SPVM_XS_UTIL_new_object_array(aTHX_ sv_self, arg_basic_type, sv_value, &sv_error);
1864            
1865 428 50         if (SvOK(sv_error)) {
    50          
    50          
1866 0 0         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1867             }
1868            
1869 428           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1870            
1871 428           stack[stack_index].oval = spvm_array;
1872            
1873 428           stack_index++;
1874 908           break;
1875             }
1876             default: {
1877             assert(0);
1878             }
1879             }
1880             }
1881 14 50         else if (arg_type_dimension > 1) {
1882            
1883             // Argument conversion - multi-type_dimensional array
1884 14           SV* sv_error = &PL_sv_undef;
1885            
1886 14           sv_value = SPVM_XS_UTIL_new_muldim_array(aTHX_ sv_self, arg_basic_type, arg_type_dimension, sv_value, &sv_error);
1887            
1888 14 50         if (SvOK(sv_error)) {
    50          
    50          
1889 0 0         croak("The %dth argument of the \"%s\" method in the \"%s\" class%s\n %s at %s line %d\n", arg_index_nth, method_name, basic_type_name, SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
1890             }
1891            
1892 14           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_value);
1893            
1894 14           stack[stack_index].oval = spvm_array;
1895            
1896 14           stack_index++;
1897 14           break;
1898             }
1899             else {
1900             assert(0);
1901             }
1902             }
1903            
1904             // Return
1905 197028           void* method_return_basic_type = env->api->method->get_return_basic_type(env->runtime, method);
1906 197028           int32_t method_return_basic_type_id = env->api->basic_type->get_id(env->runtime, method_return_basic_type);
1907 197028           int32_t method_return_type_dimension = env->api->method->get_return_type_dimension(env->runtime, method);
1908            
1909 197028           int32_t method_return_basic_type_category = env->api->basic_type->get_category(env->runtime, method_return_basic_type);
1910            
1911             // Call method
1912 197028           int32_t call_method_args_width = stack_index;
1913 197028           int32_t error_id = env->call_method_no_mortal(env, stack, method, call_method_args_width);
1914            
1915 197028 100         if (error_id) {
1916 32 100         if (SvOK(sv_error_ret)) {
    50          
    50          
1917 4           HV* hv_error_ret = (HV*)SvRV(sv_error_ret);
1918 4           SV* sv_error_id = sv_2mortal(newSViv(error_id));
1919 4           (void)hv_store(hv_error_ret, "id", strlen("id"), SvREFCNT_inc(sv_error_id), 0);
1920             }
1921            
1922 32           void* exception = env->get_exception(env, stack);
1923 32           int32_t length = env->length(env, stack, exception);
1924 32           const char* exception_chars = env->get_chars(env, stack, exception);
1925 32           SV* sv_exception = sv_2mortal(newSVpvn((char*)exception_chars, length));
1926 32 50         croak("%s\n %s at %s line %d\n", SvPV_nolen(sv_exception), __func__, FILE_NAME, __LINE__);
1927             }
1928            
1929             // Return value conversion
1930 196996           SV* sv_return_value = NULL;
1931 196996 100         if (method_return_type_dimension == 0) {
1932 181142           switch (method_return_basic_type_category) {
1933             // Return value conversion - void
1934             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_VOID: {
1935 37542           break;
1936             }
1937             // Return value conversion - numeric
1938             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC: {
1939 26241           switch (method_return_basic_type_id) {
1940             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1941             // Return value conversion - byte
1942 12           sv_return_value = sv_2mortal(newSViv(stack[0].bval));
1943 12           break;
1944             }
1945             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1946             // Return value conversion - short
1947 10           sv_return_value = sv_2mortal(newSViv(stack[0].sval));
1948 10           break;
1949             }
1950             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1951             // Return value conversion - int
1952 18039           sv_return_value = sv_2mortal(newSViv(stack[0].ival));
1953 18039           break;
1954             }
1955             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1956             // Return value conversion - long
1957 92           sv_return_value = sv_2mortal(newSViv(stack[0].lval));
1958 92           break;
1959             }
1960             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1961             // Return value conversion - float
1962 42           sv_return_value = sv_2mortal(newSVnv(stack[0].fval));
1963 42           break;
1964             }
1965             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1966             // Return value conversion - double
1967 8046           sv_return_value = sv_2mortal(newSVnv(stack[0].dval));
1968 8046           break;
1969             }
1970             default: {
1971             assert(0);
1972             }
1973             }
1974 26241           break;
1975             }
1976             // Return value conversion - multi-numeric
1977             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
1978             {
1979 26           int32_t method_return_basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, method_return_basic_type);
1980 26           void* method_return_mulnum_field = env->api->basic_type->get_field_by_index(runtime, method_return_basic_type, 0);
1981 26           void* method_return_mulnum_field_basic_type = env->api->field->get_basic_type(env->runtime, method_return_mulnum_field);
1982 26           int32_t method_return_mulnum_field_basic_type_id = env->api->basic_type->get_id(env->runtime, method_return_mulnum_field_basic_type);
1983            
1984 26           HV* hv_value = (HV*)sv_2mortal((SV*)newHV());
1985 102 100         for (int32_t field_index = 0; field_index < method_return_basic_type_fields_length; field_index++) {
1986 76           SV* sv_field_value = NULL;
1987 76           switch (method_return_mulnum_field_basic_type_id) {
1988             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
1989             // Return value conversion - multi-numeric byte
1990 12           sv_field_value = sv_2mortal(newSViv(stack[field_index].bval));
1991 12           break;
1992             }
1993             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
1994             // Return value conversion - multi-numeric short
1995 12           sv_field_value = sv_2mortal(newSViv(stack[field_index].sval));
1996 12           break;
1997             }
1998             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1999             // Return value conversion - multi-numeric int
2000 12           sv_field_value = sv_2mortal(newSViv(stack[field_index].ival));
2001 12           break;
2002             }
2003             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
2004             // Return value conversion - multi-numeric long
2005 12           sv_field_value = sv_2mortal(newSViv(stack[field_index].lval));
2006 12           break;
2007             }
2008             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
2009             // Return value conversion - multi-numeric float
2010 12           sv_field_value = sv_2mortal(newSVnv(stack[field_index].fval));
2011 12           break;
2012             }
2013             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
2014             // Return value conversion - multi-numeric double
2015 16           sv_field_value = sv_2mortal(newSVnv(stack[field_index].dval));
2016 16           break;
2017             }
2018             default: {
2019             assert(0);
2020             }
2021             }
2022            
2023 76           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, method_return_basic_type, field_index);
2024 76           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
2025 76           (void)hv_store(hv_value, mulnum_field_name, strlen(mulnum_field_name), SvREFCNT_inc(sv_field_value), 0);
2026 76           sv_return_value = sv_2mortal(newRV_inc((SV*)hv_value));
2027             }
2028 26           break;
2029             }
2030             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_STRING: {
2031             // Return value conversion - string
2032 36571           void* return_value = (void*)stack[0].oval;
2033 36571           sv_return_value = NULL;
2034 36571 100         if (return_value != NULL) {
2035 36497           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::String");
2036             }
2037             // undef
2038             else {
2039 74           sv_return_value = &PL_sv_undef;
2040             }
2041 36571           break;
2042             }
2043             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_ANY_OBJECT:
2044             {
2045             // Return value conversion - any object
2046 36           void* return_value = (void*)stack[0].oval;
2047 36           sv_return_value = NULL;
2048 36 100         if (return_value != NULL) {
2049 32           const char* return_value_basic_type_name = env->get_object_basic_type_name(env, stack, return_value);
2050 32           int32_t return_value_type_dimension = env->get_object_type_dimension(env, stack, return_value);
2051 32 100         if (return_value_type_dimension > 0) {
2052 6           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::Array");
2053             }
2054             else {
2055 26 100         if (strcmp(return_value_basic_type_name, "string") == 0) {
2056 6           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::String");
2057             }
2058             else {
2059 32           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::Class");
2060             }
2061             }
2062             }
2063             // undef
2064             else {
2065 4           sv_return_value = &PL_sv_undef;
2066             }
2067 36           break;
2068             }
2069             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS:
2070             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE:
2071             {
2072 80726           void* return_value = (void*)stack[0].oval;
2073 80726           sv_return_value = NULL;
2074 80726 100         if (return_value != NULL) {
2075 80236           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::Class");
2076             }
2077             // undef
2078             else {
2079 490           sv_return_value = &PL_sv_undef;
2080             }
2081 181142           break;
2082             }
2083             default: {
2084             assert(0);
2085             }
2086             }
2087             }
2088 15854 50         else if (method_return_type_dimension > 0) {
2089             // Return value conversion - array
2090 15854           void* return_value = (void*)stack[0].oval;
2091 15854           sv_return_value = NULL;
2092 15854 100         if (return_value != NULL) {
2093 15846           sv_return_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, return_value, "SPVM::BlessedObject::Array");
2094             }
2095             else {
2096 8           sv_return_value = &PL_sv_undef;
2097             }
2098             }
2099            
2100             // Restore reference
2101 196996 100         if (has_ref_arg) {
2102 86 100         for (int32_t arg_index = 0; arg_index < method_args_length; arg_index++) {
2103 46           SV* sv_value = ST(spvm_args_base + arg_index);
2104            
2105             // Argument type
2106 46           void* arg = env->api->method->get_arg_by_index(env->runtime, method, arg_index);
2107 46           void* arg_basic_type = env->api->arg->get_basic_type(env->runtime, arg);
2108 46           int32_t arg_basic_type_id = env->api->basic_type->get_id(env->runtime, arg_basic_type);
2109 46           int32_t arg_type_dimension = env->api->arg->get_type_dimension(env->runtime, arg);
2110 46           int32_t arg_type_flag = env->api->arg->get_type_flag(env->runtime, arg);
2111 46           int32_t arg_basic_type_category = env->api->basic_type->get_category(env->runtime, arg_basic_type);
2112            
2113             // Restore reference - numeric
2114 46 50         if (arg_type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF) {
2115 46           switch (arg_basic_type_category) {
2116             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC: {
2117 30           switch (arg_basic_type_id) {
2118             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
2119             // Restore reference - byte
2120 6           SV* sv_value_deref = SvRV(sv_value);
2121 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2122 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2123 6 50         int8_t* ref = (int8_t*)SvPV_nolen(sv_ref);
2124 6           sv_setiv(sv_value_deref, *ref);
2125            
2126 6           break;
2127             }
2128             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
2129             // Restore reference - short
2130 4           SV* sv_value_deref = SvRV(sv_value);
2131 4           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2132 4 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2133 4 50         int16_t* ref = (int16_t*)SvPV_nolen(sv_ref);
2134 4           sv_setiv(sv_value_deref, *ref);
2135            
2136 4           break;
2137             }
2138             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
2139             // Restore reference - int
2140 8           SV* sv_value_deref = SvRV(sv_value);
2141 8           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2142 8 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2143 8 50         int32_t* ref = (int32_t*)SvPV_nolen(sv_ref);
2144 8           sv_setiv(sv_value_deref, *ref);
2145            
2146 8           break;
2147             }
2148             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
2149             // Restore reference - long
2150 4           SV* sv_value_deref = SvRV(sv_value);
2151 4           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2152 4 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2153 4 50         int64_t* ref = (int64_t*)SvPV_nolen(sv_ref);
2154 4           sv_setiv(sv_value_deref, *ref);
2155            
2156 4           break;
2157             }
2158             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
2159             // Restore reference - float
2160 4           SV* sv_value_deref = SvRV(sv_value);
2161 4           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2162 4 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2163 4 50         float* ref = (float*)SvPV_nolen(sv_ref);
2164 4           sv_setnv(sv_value_deref, *ref);
2165            
2166 4           break;
2167             }
2168             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
2169             // Restore reference - double
2170 4           SV* sv_value_deref = SvRV(sv_value);
2171 4           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2172 4 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2173 4 50         double* ref = (double*)SvPV_nolen(sv_ref);
2174 4           sv_setnv(sv_value_deref, *ref);
2175            
2176 4           break;
2177             }
2178             default: {
2179             assert(0);
2180             }
2181             }
2182 30           break;
2183             }
2184             // Restore reference value - multi-numeric
2185             case SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM:
2186             {
2187 16           HV* hv_value = (HV*)SvRV(SvRV(sv_value));
2188 16           int32_t arg_basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, arg_basic_type);
2189 16           void* arg_basic_type_field_first = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, 0);
2190 16           void* arg_basic_type_field_basic_type = env->api->field->get_basic_type(env->runtime, arg_basic_type_field_first);
2191 16           int32_t arg_basic_type_field_basic_type_id = env->api->basic_type->get_id(env->runtime, arg_basic_type_field_basic_type);
2192 94 100         for (int32_t field_index = 0; field_index < arg_basic_type_fields_length; field_index++) {
2193 48           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, arg_basic_type, field_index);
2194 48           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
2195             SV* sv_field_value;
2196 48           switch (arg_basic_type_field_basic_type_id) {
2197             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
2198             // Restore reference value - multi-numeric byte
2199 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2200 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2201 6 50         int8_t* ref = (int8_t*)SvPV_nolen(sv_ref);
2202 6           sv_field_value = sv_2mortal(newSViv(*(ref + field_index)));
2203            
2204 6           break;
2205             }
2206             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
2207             // Restore reference value - multi-numeric short
2208 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2209 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2210 6 50         int16_t* ref = (int16_t*)SvPV_nolen(sv_ref);
2211 6           sv_field_value = sv_2mortal(newSViv(*(ref + field_index)));
2212            
2213 6           break;
2214             }
2215             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
2216             // Restore reference value - multi-numeric int
2217 18           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2218 18 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2219 18 50         int32_t* ref = (int32_t*)SvPV_nolen(sv_ref);
2220 18           sv_field_value = sv_2mortal(newSViv(*(ref + field_index)));
2221            
2222 18           break;
2223             }
2224             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
2225             // Restore reference value - multi-numeric long
2226 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2227 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2228 6 50         int64_t* ref = (int64_t*)SvPV_nolen(sv_ref);
2229 6           sv_field_value = sv_2mortal(newSViv(*(ref + field_index)));
2230            
2231 6           break;
2232             }
2233             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
2234             // Restore reference value - multi-numeric float
2235 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2236 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2237 6 50         float* ref = (float*)SvPV_nolen(sv_ref);
2238 6           sv_field_value = sv_2mortal(newSVnv(*(ref + field_index)));
2239            
2240 6           break;
2241             }
2242             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
2243             // Restore reference value - multi-numeric double
2244 6           SV** sv_ref_ptr = av_fetch(av_refs, arg_index, 0);
2245 6 50         SV* sv_ref = sv_ref_ptr ? *sv_ref_ptr : &PL_sv_undef;
2246 6 50         double* ref = (double*)SvPV_nolen(sv_ref);
2247 6           sv_field_value = sv_2mortal(newSVnv(*(ref + field_index)));
2248            
2249 6           break;
2250             }
2251             default: {
2252             assert(0);
2253             }
2254             }
2255 48           (void)hv_store(hv_value, mulnum_field_name, strlen(mulnum_field_name), SvREFCNT_inc(sv_field_value), 0);
2256             }
2257             }
2258             }
2259             }
2260             else {
2261             assert(0);
2262             }
2263             }
2264             }
2265            
2266             // Count of return value
2267             int32_t return_count;
2268 196996 100         if (method_return_type_dimension == 0 && method_return_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_VOID) {
    100          
2269 37542           return_count = 0;
2270             }
2271             else {
2272 159454 50         XPUSHs(sv_return_value);
2273 159454           return_count = 1;
2274             }
2275              
2276 196996           XSRETURN(return_count);
2277             }
2278              
2279             SV*
2280             _xs_dump(...)
2281             PPCODE:
2282             {
2283            
2284 6           SV* sv_self = ST(0);
2285 6           HV* hv_self = (HV*)SvRV(sv_self);
2286            
2287             // Env
2288 6           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2289 6 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2290 6           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2291            
2292             // Stack
2293 6           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2294 6 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2295 6           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2296            
2297 6           SV* sv_object = ST(1);
2298            
2299             // Array must be a SPVM::BlessedObject or SPVM::BlessedObject
2300 6 100         if (SvOK(sv_object)) {
    50          
    50          
2301 4 100         if (!(SvROK(sv_object) && sv_derived_from(sv_object, "SPVM::BlessedObject"))) {
    50          
2302 2           croak("$object must be a SPVM::BlessedObject object\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2303             }
2304             }
2305            
2306             // Get object
2307 4           void* object = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_object);
2308            
2309 4           void* spvm_dump = env->dump_no_mortal(env, stack, object);
2310            
2311 4           const char* dump = env->get_chars(env, stack, spvm_dump);
2312 4           int32_t dump_length = env->length(env, stack, spvm_dump);
2313            
2314 4           SV* sv_dump = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_dump, "SPVM::BlessedObject::String");
2315            
2316 4 50         XPUSHs(sv_dump);
2317 4           XSRETURN(1);
2318             }
2319              
2320             SV*
2321             _xs_new_string(...)
2322             PPCODE:
2323             {
2324            
2325 15192           SV* sv_self = ST(0);
2326 15192           HV* hv_self = (HV*)SvRV(sv_self);
2327            
2328             // Env
2329 15192           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2330 15192 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2331 15192           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2332            
2333             // Stack
2334 15192           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2335 15192 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2336 15192           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2337            
2338 15192           SV* sv_string = ST(1);
2339            
2340 15192           SV* sv_error = &PL_sv_undef;
2341 15192           sv_string = SPVM_XS_UTIL_new_string(aTHX_ sv_self, sv_string, &sv_error);
2342            
2343 15192 100         if (SvOK(sv_error)) {
    50          
    50          
2344 4 50         croak("$string%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2345             }
2346            
2347 15188 50         XPUSHs(sv_string);
2348 15188           XSRETURN(1);
2349             }
2350              
2351             SV*
2352             _xs_new_address_object(...)
2353             PPCODE:
2354             {
2355            
2356 30972           int32_t error_id = 0;
2357            
2358 30972           SV* sv_self = ST(0);
2359 30972           HV* hv_self = (HV*)SvRV(sv_self);
2360            
2361             // Env
2362 30972           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2363 30972 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2364 30972           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2365            
2366             // Stack
2367 30972           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2368 30972 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2369 30972           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2370            
2371 30972           SV* sv_address = ST(1);
2372            
2373 30972           SV* sv_error = &PL_sv_undef;
2374 30972           sv_address = SPVM_XS_UTIL_new_address_object(aTHX_ sv_self, sv_address, &sv_error);
2375            
2376 30972 50         if (SvOK(sv_error)) {
    50          
    50          
2377 0 0         croak("$address%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2378             }
2379            
2380 30972 50         XPUSHs(sv_address);
2381 30972           XSRETURN(1);
2382             }
2383              
2384             SV*
2385             _xs_new_byte_array(...)
2386             PPCODE:
2387             {
2388            
2389 40           SV* sv_self = ST(0);
2390 40           HV* hv_self = (HV*)SvRV(sv_self);
2391            
2392             // Env
2393 40           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2394 40 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2395 40           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2396            
2397             // Stack
2398 40           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2399 40 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2400 40           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2401            
2402 40           SV* sv_array = ST(1);
2403            
2404 40           SV* sv_error = &PL_sv_undef;
2405 40           sv_array = SPVM_XS_UTIL_new_byte_array(aTHX_ sv_self, sv_array, &sv_error);
2406            
2407 40 100         if (SvOK(sv_error)) {
    50          
    50          
2408 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2409             }
2410            
2411 36 50         XPUSHs(sv_array);
2412 36           XSRETURN(1);
2413             }
2414              
2415             SV*
2416             _xs_new_byte_array_unsigned(...)
2417             PPCODE:
2418             {
2419            
2420 14           SV* sv_self = ST(0);
2421 14           HV* hv_self = (HV*)SvRV(sv_self);
2422            
2423             // Env
2424 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2425 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2426 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2427            
2428             // Stack
2429 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2430 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2431 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2432            
2433 14           SV* sv_array = ST(1);
2434            
2435 14           SV* sv_error = &PL_sv_undef;
2436 14           sv_array = SPVM_XS_UTIL_new_byte_array_unsigned(aTHX_ sv_self, sv_array, &sv_error);
2437            
2438 14 100         if (SvOK(sv_error)) {
    50          
    50          
2439 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2440             }
2441            
2442 10 50         XPUSHs(sv_array);
2443 10           XSRETURN(1);
2444             }
2445              
2446             SV*
2447             _xs_new_byte_array_len(...)
2448             PPCODE:
2449             {
2450            
2451 8           SV* sv_self = ST(0);
2452 8           HV* hv_self = (HV*)SvRV(sv_self);
2453            
2454             // Env
2455 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2456 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2457 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2458            
2459             // Stack
2460 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2461 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2462 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2463            
2464 8           SV* sv_length = ST(1);
2465            
2466 8 50         int32_t length = (int32_t)SvIV(sv_length);
2467            
2468 8 100         if (length < 0) {
2469 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2470             }
2471            
2472 6           void* spvm_array = env->new_byte_array_no_mortal(env, stack, length);
2473            
2474 6           SV* sv_byte_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2475            
2476 6 50         XPUSHs(sv_byte_array);
2477 6           XSRETURN(1);
2478             }
2479              
2480             SV*
2481             _xs_new_byte_array_from_bin(...)
2482             PPCODE:
2483             {
2484            
2485 18           SV* sv_self = ST(0);
2486 18           HV* hv_self = (HV*)SvRV(sv_self);
2487            
2488             // Env
2489 18           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2490 18 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2491 18           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2492            
2493             // Stack
2494 18           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2495 18 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2496 18           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2497            
2498 18           SV* sv_binary = ST(1);
2499            
2500 18 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
2501 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2502             }
2503            
2504 14           STRLEN length = -1;
2505 14 50         int8_t* binary = (int8_t*)SvPV(sv_binary, length);
2506            
2507             // New array
2508 14           void* spvm_array = env->new_byte_array_no_mortal(env, stack, (int32_t)length);
2509            
2510 14           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
2511 14           memcpy(elems, binary, length);
2512            
2513 14           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2514            
2515 14 50         XPUSHs(sv_array);
2516 14           XSRETURN(1);
2517             }
2518              
2519             SV*
2520             _xs_new_short_array(...)
2521             PPCODE:
2522             {
2523            
2524 32           SV* sv_self = ST(0);
2525 32           HV* hv_self = (HV*)SvRV(sv_self);
2526            
2527             // Env
2528 32           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2529 32 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2530 32           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2531            
2532             // Stack
2533 32           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2534 32 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2535 32           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2536            
2537 32           SV* sv_array = ST(1);
2538            
2539 32           SV* sv_error = &PL_sv_undef;
2540 32           sv_array = SPVM_XS_UTIL_new_short_array(aTHX_ sv_self, sv_array, &sv_error);
2541            
2542 32 100         if (SvOK(sv_error)) {
    50          
    50          
2543 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2544             }
2545            
2546 28 50         XPUSHs(sv_array);
2547 28           XSRETURN(1);
2548             }
2549              
2550             SV*
2551             _xs_new_short_array_unsigned(...)
2552             PPCODE:
2553             {
2554            
2555 14           SV* sv_self = ST(0);
2556 14           HV* hv_self = (HV*)SvRV(sv_self);
2557            
2558             // Env
2559 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2560 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2561 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2562            
2563             // Stack
2564 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2565 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2566 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2567            
2568 14           SV* sv_array = ST(1);
2569            
2570 14           SV* sv_error = &PL_sv_undef;
2571 14           sv_array = SPVM_XS_UTIL_new_short_array_unsigned(aTHX_ sv_self, sv_array, &sv_error);
2572            
2573 14 100         if (SvOK(sv_error)) {
    50          
    50          
2574 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2575             }
2576            
2577 10 50         XPUSHs(sv_array);
2578 10           XSRETURN(1);
2579             }
2580              
2581             SV*
2582             _xs_new_short_array_len(...)
2583             PPCODE:
2584             {
2585            
2586 8           SV* sv_self = ST(0);
2587 8           HV* hv_self = (HV*)SvRV(sv_self);
2588            
2589             // Env
2590 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2591 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2592 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2593            
2594             // Stack
2595 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2596 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2597 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2598            
2599 8           SV* sv_length = ST(1);
2600            
2601 8 50         int32_t length = (int32_t)SvIV(sv_length);
2602            
2603 8 100         if (length < 0) {
2604 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2605             }
2606            
2607 6           void* spvm_array = env->new_short_array_no_mortal(env, stack, length);
2608            
2609 6           SV* sv_short_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2610            
2611 6 50         XPUSHs(sv_short_array);
2612 6           XSRETURN(1);
2613             }
2614              
2615             SV*
2616             _xs_new_short_array_from_bin(...)
2617             PPCODE:
2618             {
2619            
2620 12           SV* sv_self = ST(0);
2621 12           HV* hv_self = (HV*)SvRV(sv_self);
2622            
2623             // Env
2624 12           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2625 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2626 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2627            
2628             // Stack
2629 12           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2630 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2631 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2632            
2633 12           SV* sv_binary = ST(1);
2634            
2635 12 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
2636 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2637             }
2638            
2639 8           STRLEN binary_length = -1;
2640 8 50         int16_t* binary = (int16_t*)SvPV(sv_binary, binary_length);
2641            
2642 8 100         if (!(binary_length % 2 == 0)) {
2643 2           croak("The length of $binary must be divisible by 2\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2644             }
2645            
2646 6           int32_t array_length = binary_length / sizeof(int16_t);
2647            
2648             // New array
2649 6           void* spvm_array = env->new_short_array_no_mortal(env, stack, array_length);
2650              
2651 6           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
2652 6           memcpy(elems, binary, array_length * sizeof(int16_t));
2653            
2654 6           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2655            
2656 6 50         XPUSHs(sv_array);
2657 6           XSRETURN(1);
2658             }
2659              
2660             SV*
2661             _xs_new_int_array(...)
2662             PPCODE:
2663             {
2664            
2665 42           SV* sv_self = ST(0);
2666 42           HV* hv_self = (HV*)SvRV(sv_self);
2667            
2668             // Env
2669 42           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2670 42 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2671 42           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2672            
2673             // Stack
2674 42           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2675 42 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2676 42           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2677            
2678 42           SV* sv_array = ST(1);
2679            
2680 42           SV* sv_error = &PL_sv_undef;
2681 42           sv_array = SPVM_XS_UTIL_new_int_array(aTHX_ sv_self, sv_array, &sv_error);
2682            
2683 42 100         if (SvOK(sv_error)) {
    50          
    50          
2684 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2685             }
2686            
2687 38 50         XPUSHs(sv_array);
2688 38           XSRETURN(1);
2689             }
2690              
2691             SV*
2692             _xs_new_int_array_unsigned(...)
2693             PPCODE:
2694             {
2695            
2696 14           SV* sv_self = ST(0);
2697 14           HV* hv_self = (HV*)SvRV(sv_self);
2698            
2699             // Env
2700 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2701 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2702 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2703            
2704             // Stack
2705 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2706 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2707 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2708            
2709 14           SV* sv_array = ST(1);
2710            
2711 14           SV* sv_error = &PL_sv_undef;
2712 14           sv_array = SPVM_XS_UTIL_new_int_array_unsigned(aTHX_ sv_self, sv_array, &sv_error);
2713            
2714 14 100         if (SvOK(sv_error)) {
    50          
    50          
2715 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2716             }
2717            
2718 10 50         XPUSHs(sv_array);
2719 10           XSRETURN(1);
2720             }
2721              
2722             SV*
2723             _xs_new_int_array_len(...)
2724             PPCODE:
2725             {
2726            
2727 8           SV* sv_self = ST(0);
2728 8           HV* hv_self = (HV*)SvRV(sv_self);
2729            
2730             // Env
2731 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2732 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2733 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2734            
2735             // Stack
2736 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2737 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2738 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2739            
2740 8           SV* sv_length = ST(1);
2741            
2742 8 50         int32_t length = (int32_t)SvIV(sv_length);
2743            
2744 8 100         if (length < 0) {
2745 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2746             }
2747            
2748 6           void* spvm_array = env->new_int_array_no_mortal(env, stack, length);
2749            
2750 6           SV* sv_int_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2751            
2752 6 50         XPUSHs(sv_int_array);
2753 6           XSRETURN(1);
2754             }
2755              
2756             SV*
2757             _xs_new_int_array_from_bin(...)
2758             PPCODE:
2759             {
2760            
2761 14           SV* sv_self = ST(0);
2762 14           HV* hv_self = (HV*)SvRV(sv_self);
2763            
2764             // Env
2765 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2766 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2767 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2768            
2769             // Stack
2770 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2771 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2772 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2773            
2774 14           SV* sv_binary = ST(1);
2775            
2776 14 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
2777 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2778             }
2779            
2780 10           STRLEN binary_length = -1;
2781 10 50         int32_t* binary = (int32_t*)SvPV(sv_binary, binary_length);
2782            
2783 10 100         if (!(binary_length % 4 == 0)) {
2784 2           croak("The length of $binary must be divisible by 4\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2785             }
2786            
2787 8           int32_t array_length = binary_length / sizeof(int32_t);
2788            
2789 8           void* spvm_array = env->new_int_array_no_mortal(env, stack, array_length);
2790            
2791 8           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
2792 8           memcpy(elems, binary, array_length * sizeof(int32_t));
2793            
2794 8           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2795            
2796 8 50         XPUSHs(sv_array);
2797 8           XSRETURN(1);
2798             }
2799              
2800             SV*
2801             _xs_new_long_array(...)
2802             PPCODE:
2803             {
2804            
2805 32           SV* sv_self = ST(0);
2806 32           HV* hv_self = (HV*)SvRV(sv_self);
2807            
2808             // Env
2809 32           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2810 32 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2811 32           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2812            
2813             // Stack
2814 32           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2815 32 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2816 32           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2817            
2818 32           SV* sv_array = ST(1);
2819            
2820 32           SV* sv_error = &PL_sv_undef;
2821 32           sv_array = SPVM_XS_UTIL_new_long_array(aTHX_ sv_self, sv_array, &sv_error);
2822            
2823 32 100         if (SvOK(sv_error)) {
    50          
    50          
2824 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2825             }
2826            
2827 28 50         XPUSHs(sv_array);
2828 28           XSRETURN(1);
2829             }
2830              
2831             SV*
2832             _xs_new_long_array_unsigned(...)
2833             PPCODE:
2834             {
2835            
2836 14           SV* sv_self = ST(0);
2837 14           HV* hv_self = (HV*)SvRV(sv_self);
2838            
2839             // Env
2840 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2841 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2842 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2843            
2844             // Stack
2845 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2846 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2847 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2848            
2849 14           SV* sv_array = ST(1);
2850            
2851 14           SV* sv_error = &PL_sv_undef;
2852 14           sv_array = SPVM_XS_UTIL_new_long_array_unsigned(aTHX_ sv_self, sv_array, &sv_error);
2853            
2854 14 100         if (SvOK(sv_error)) {
    50          
    50          
2855 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2856             }
2857            
2858 10 50         XPUSHs(sv_array);
2859 10           XSRETURN(1);
2860             }
2861              
2862             SV*
2863             _xs_new_long_array_len(...)
2864             PPCODE:
2865             {
2866            
2867 8           SV* sv_self = ST(0);
2868 8           HV* hv_self = (HV*)SvRV(sv_self);
2869            
2870             // Env
2871 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2872 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2873 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2874            
2875             // Stack
2876 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2877 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2878 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2879            
2880 8           SV* sv_length = ST(1);
2881            
2882 8 50         int32_t length = (int32_t)SvIV(sv_length);
2883            
2884 8 100         if (length < 0) {
2885 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2886             }
2887            
2888 6           void* spvm_array = env->new_long_array_no_mortal(env, stack, length);
2889            
2890 6           SV* sv_long_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2891            
2892 6 50         XPUSHs(sv_long_array);
2893 6           XSRETURN(1);
2894             }
2895              
2896             SV*
2897             _xs_new_long_array_from_bin(...)
2898             PPCODE:
2899             {
2900            
2901 14           SV* sv_self = ST(0);
2902 14           HV* hv_self = (HV*)SvRV(sv_self);
2903            
2904             // Env
2905 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2906 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2907 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2908            
2909             // Stack
2910 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2911 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2912 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2913            
2914 14           SV* sv_binary = ST(1);
2915            
2916 14 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
2917 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2918             }
2919            
2920 10           STRLEN binary_length = -1;
2921 10 50         int64_t* binary = (int64_t*)SvPV(sv_binary, binary_length);
2922            
2923 10 100         if (!(binary_length % 8 == 0)) {
2924 2           croak("The length of $binary must be divisible by 8\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2925             }
2926            
2927 8           int32_t array_length = binary_length / sizeof(int64_t);
2928            
2929             // New array
2930 8           void* spvm_array = env->new_long_array_no_mortal(env, stack, array_length);
2931            
2932 8           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
2933 8           memcpy(elems, binary, array_length * sizeof(int64_t));
2934            
2935 8           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
2936            
2937 8 50         XPUSHs(sv_array);
2938 8           XSRETURN(1);
2939             }
2940              
2941             SV*
2942             _xs_new_float_array(...)
2943             PPCODE:
2944             {
2945            
2946 34           SV* sv_self = ST(0);
2947 34           HV* hv_self = (HV*)SvRV(sv_self);
2948            
2949             // Env
2950 34           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2951 34 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2952 34           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2953            
2954             // Stack
2955 34           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2956 34 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2957 34           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2958            
2959 34           SV* sv_array = ST(1);
2960            
2961 34           SV* sv_error = &PL_sv_undef;
2962 34           sv_array = SPVM_XS_UTIL_new_float_array(aTHX_ sv_self, sv_array, &sv_error);
2963            
2964 34 100         if (SvOK(sv_error)) {
    50          
    50          
2965 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
2966             }
2967            
2968 30 50         XPUSHs(sv_array);
2969 30           XSRETURN(1);
2970             }
2971              
2972             SV*
2973             _xs_new_float_array_len(...)
2974             PPCODE:
2975             {
2976            
2977 8           SV* sv_self = ST(0);
2978 8           HV* hv_self = (HV*)SvRV(sv_self);
2979            
2980             // Env
2981 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
2982 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
2983 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
2984            
2985             // Stack
2986 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
2987 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
2988 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
2989            
2990 8           SV* sv_length = ST(1);
2991            
2992 8 50         int32_t length = (int32_t)SvIV(sv_length);
2993            
2994 8 100         if (length < 0) {
2995 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
2996             }
2997            
2998 6           void* spvm_array = env->new_float_array_no_mortal(env, stack, length);
2999            
3000 6           SV* sv_float_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3001            
3002 6 50         XPUSHs(sv_float_array);
3003 6           XSRETURN(1);
3004             }
3005              
3006             SV*
3007             _xs_new_float_array_from_bin(...)
3008             PPCODE:
3009             {
3010            
3011 14           SV* sv_self = ST(0);
3012 14           HV* hv_self = (HV*)SvRV(sv_self);
3013            
3014             // Env
3015 14           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3016 14 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3017 14           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3018            
3019             // Stack
3020 14           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3021 14 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3022 14           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3023            
3024 14           SV* sv_binary = ST(1);
3025            
3026 14 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
3027 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3028             }
3029            
3030 10           STRLEN binary_length = -1;
3031 10 50         float* binary = (float*)SvPV(sv_binary, binary_length);
3032            
3033 10 100         if (!(binary_length % 4 == 0)) {
3034 2           croak("The length of $binary must be divisible by 4\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3035             }
3036            
3037 8           int32_t array_length = binary_length / sizeof(float);
3038            
3039             // New array
3040 8           void* spvm_array = env->new_float_array_no_mortal(env, stack, array_length);
3041            
3042 8           float* elems = env->get_elems_float(env, stack, spvm_array);
3043 8           memcpy(elems, binary, array_length * sizeof(float));
3044            
3045 8           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3046            
3047 8 50         XPUSHs(sv_array);
3048 8           XSRETURN(1);
3049             }
3050              
3051             SV*
3052             _xs_new_double_array(...)
3053             PPCODE:
3054             {
3055            
3056 32           SV* sv_self = ST(0);
3057 32           HV* hv_self = (HV*)SvRV(sv_self);
3058            
3059             // Env
3060 32           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3061 32 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3062 32           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3063            
3064             // Stack
3065 32           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3066 32 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3067 32           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3068            
3069 32           SV* sv_array = ST(1);
3070            
3071 32           SV* sv_error = &PL_sv_undef;
3072 32           sv_array = SPVM_XS_UTIL_new_double_array(aTHX_ sv_self, sv_array, &sv_error);
3073            
3074 32 100         if (SvOK(sv_error)) {
    50          
    50          
3075 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3076             }
3077            
3078 28 50         XPUSHs(sv_array);
3079 28           XSRETURN(1);
3080             }
3081              
3082             SV*
3083             _xs_new_double_array_len(...)
3084             PPCODE:
3085             {
3086            
3087 8           SV* sv_self = ST(0);
3088 8           HV* hv_self = (HV*)SvRV(sv_self);
3089            
3090             // Env
3091 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3092 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3093 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3094            
3095             // Stack
3096 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3097 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3098 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3099            
3100 8           SV* sv_length = ST(1);
3101            
3102 8 50         int32_t length = (int32_t)SvIV(sv_length);
3103            
3104 8 100         if (length < 0) {
3105 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3106             }
3107            
3108 6           void* spvm_array = env->new_double_array_no_mortal(env, stack, length);
3109            
3110 6           SV* sv_double_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3111            
3112 6 50         XPUSHs(sv_double_array);
3113 6           XSRETURN(1);
3114             }
3115              
3116             SV*
3117             _xs_new_double_array_from_bin(...)
3118             PPCODE:
3119             {
3120            
3121 12           SV* sv_self = ST(0);
3122 12           HV* hv_self = (HV*)SvRV(sv_self);
3123            
3124             // Env
3125 12           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3126 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3127 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3128            
3129             // Stack
3130 12           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3131 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3132 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3133            
3134 12           SV* sv_binary = ST(1);
3135            
3136 12 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
3137 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3138             }
3139            
3140 8           STRLEN binary_length = -1;
3141 8 50         double* binary = (double*)SvPV(sv_binary, binary_length);
3142            
3143 8 100         if (!(binary_length % 8 == 0)) {
3144 2           croak("The length of $binary must be divisible by 8\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3145             }
3146            
3147 6           int32_t array_length = binary_length / sizeof(double);
3148            
3149 6           void* spvm_array = env->new_double_array_no_mortal(env, stack, array_length);
3150            
3151 6           double* elems = env->get_elems_double(env, stack, spvm_array);
3152 6           memcpy(elems, binary, array_length * sizeof(double));
3153            
3154 6           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3155            
3156 6 50         XPUSHs(sv_array);
3157 6           XSRETURN(1);
3158             }
3159              
3160             SV*
3161             _xs_new_string_array(...)
3162             PPCODE:
3163             {
3164            
3165 22           SV* sv_self = ST(0);
3166 22           HV* hv_self = (HV*)SvRV(sv_self);
3167            
3168             // Env
3169 22           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3170 22 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3171 22           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3172            
3173             // Stack
3174 22           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3175 22 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3176 22           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3177            
3178 22           SV* sv_array = ST(1);
3179            
3180 22           SV* sv_error = &PL_sv_undef;
3181 22           sv_array = SPVM_XS_UTIL_new_string_array(aTHX_ sv_self, sv_array, &sv_error);
3182            
3183 22 100         if (SvOK(sv_error)) {
    50          
    50          
3184 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3185             }
3186            
3187 18 50         XPUSHs(sv_array);
3188 18           XSRETURN(1);
3189             }
3190              
3191             SV*
3192             _xs_new_string_array_len(...)
3193             PPCODE:
3194             {
3195            
3196 8           SV* sv_self = ST(0);
3197 8           HV* hv_self = (HV*)SvRV(sv_self);
3198            
3199             // Env
3200 8           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3201 8 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3202 8           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3203            
3204             // Stack
3205 8           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3206 8 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3207 8           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3208            
3209 8           SV* sv_length = ST(1);
3210              
3211 8 50         int32_t length = (int32_t)SvIV(sv_length);
3212            
3213 8 100         if (length < 0) {
3214 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3215             }
3216            
3217 6           void* spvm_array = env->new_string_array_no_mortal(env, stack, length);
3218            
3219 6           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3220            
3221 6 50         XPUSHs(sv_array);
3222 6           XSRETURN(1);
3223             }
3224              
3225             SV*
3226             _xs_new_object_array(...)
3227             PPCODE:
3228             {
3229            
3230 15584           SV* sv_self = ST(0);
3231 15584           HV* hv_self = (HV*)SvRV(sv_self);
3232            
3233             // Env
3234 15584           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3235 15584 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3236 15584           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3237            
3238             // Stack
3239 15584           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3240 15584 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3241 15584           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3242            
3243 15584           SV* sv_basic_type_name = ST(1);
3244 15584           SV* sv_array = ST(2);
3245            
3246 15584 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3247 15584           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3248 15584 100         if (!basic_type) {
3249 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3250             }
3251            
3252 15582           int32_t elem_type_dimension = 0;
3253 15582           int32_t is_object_array = env->api->type->is_object_type(env->runtime, basic_type, elem_type_dimension, 0);
3254 15582 100         if (!is_object_array) {
3255 2           croak("$type_name must be an object array type\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3256             }
3257            
3258 15580           SV* sv_error = &PL_sv_undef;
3259 15580           sv_array = SPVM_XS_UTIL_new_object_array(aTHX_ sv_self, basic_type, sv_array, &sv_error);
3260            
3261 15580 100         if (SvOK(sv_error)) {
    50          
    50          
3262 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3263             }
3264            
3265 15576 50         XPUSHs(sv_array);
3266 15576           XSRETURN(1);
3267             }
3268              
3269             SV*
3270             _xs_new_object_array_len(...)
3271             PPCODE:
3272             {
3273            
3274 16           SV* sv_self = ST(0);
3275 16           HV* hv_self = (HV*)SvRV(sv_self);
3276            
3277             // Env
3278 16           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3279 16 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3280 16           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3281            
3282             // Stack
3283 16           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3284 16 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3285 16           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3286            
3287 16           SV* sv_basic_type_name = ST(1);
3288 16           SV* sv_length = ST(2);
3289            
3290 16 50         int32_t length = (int32_t)SvIV(sv_length);
3291            
3292 16 100         if (length < 0) {
3293 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3294             }
3295            
3296             // Element type id
3297 14 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3298            
3299 14           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3300 14 100         if (!basic_type) {
3301 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3302             }
3303            
3304 12           int32_t elem_type_dimension = 0;
3305 12           int32_t is_object_array = env->api->type->is_object_type(env->runtime, basic_type, elem_type_dimension, 0);
3306 12 100         if (!is_object_array) {
3307 2           croak("$type_name must be an object array type\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3308             }
3309            
3310 10           void* spvm_array = env->new_object_array_no_mortal(env, stack, basic_type, length);
3311            
3312 10           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3313            
3314 10 50         XPUSHs(sv_array);
3315 10           XSRETURN(1);
3316             }
3317              
3318             SV*
3319             _xs_new_mulnum_array(...)
3320             PPCODE:
3321             {
3322            
3323 34           SV* sv_self = ST(0);
3324 34           HV* hv_self = (HV*)SvRV(sv_self);
3325            
3326             // Env
3327 34           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3328 34 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3329 34           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3330            
3331             // Stack
3332 34           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3333 34 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3334 34           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3335            
3336 34           SV* sv_basic_type_name = ST(1);
3337 34           SV* sv_array = ST(2);
3338              
3339 34 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3340              
3341 34           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3342 34 100         if (!basic_type) {
3343 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3344             }
3345 32           int32_t elem_type_dimension = 0;
3346 32           int32_t basic_type_category = env->api->basic_type->get_category(env->runtime, basic_type);
3347 32           int32_t is_mulnum_array = basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM;
3348 32 100         if (!is_mulnum_array) {
3349 2           croak("$type_name must be a multi-numeric array type\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3350             }
3351            
3352 30           SV* sv_error = &PL_sv_undef;
3353 30           sv_array = SPVM_XS_UTIL_new_mulnum_array(aTHX_ sv_self, basic_type, sv_array, &sv_error);
3354            
3355 30 100         if (SvOK(sv_error)) {
    50          
    50          
3356 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3357             }
3358            
3359 26 50         XPUSHs(sv_array);
3360 26           XSRETURN(1);
3361             }
3362              
3363             SV*
3364             _xs_new_mulnum_array_len(...)
3365             PPCODE:
3366             {
3367            
3368 12           SV* sv_self = ST(0);
3369 12           HV* hv_self = (HV*)SvRV(sv_self);
3370            
3371             // Env
3372 12           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3373 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3374 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3375            
3376             // Stack
3377 12           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3378 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3379 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3380            
3381 12           SV* sv_basic_type_name = ST(1);
3382 12           SV* sv_length = ST(2);
3383              
3384 12 50         int32_t length = (int32_t)SvIV(sv_length);
3385            
3386 12 100         if (length < 0) {
3387 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3388             }
3389            
3390 10 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3391            
3392 10           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3393 10 100         if (!basic_type) {
3394 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3395             }
3396            
3397 8           int32_t elem_type_dimension = 0;
3398 8           int32_t basic_type_category = env->api->basic_type->get_category(env->runtime, basic_type);
3399 8           int32_t is_mulnum_array = basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM;
3400 8 100         if (!is_mulnum_array) {
3401 2           croak("$type_name must be a multi-numeric array type\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3402             }
3403            
3404 6           void* spvm_array = env->new_mulnum_array_no_mortal(env, stack, basic_type, length);
3405            
3406 6           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3407            
3408 6 50         XPUSHs(sv_array);
3409 6           XSRETURN(1);
3410             }
3411              
3412             SV*
3413             _xs_new_mulnum_array_from_bin(...)
3414             PPCODE:
3415             {
3416            
3417 24           SV* sv_self = ST(0);
3418 24           HV* hv_self = (HV*)SvRV(sv_self);
3419            
3420             // Env
3421 24           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3422 24 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3423 24           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3424            
3425             // Stack
3426 24           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3427 24 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3428 24           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3429            
3430 24           SV* sv_basic_type_name = ST(1);
3431 24           SV* sv_binary = ST(2);
3432            
3433 24 100         if (!(SvOK(sv_binary) && !SvROK(sv_binary))) {
    50          
    50          
    100          
3434 4           croak("$binary must be a defined non-reference scalar\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3435             }
3436            
3437 20 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3438            
3439 20           STRLEN binary_length = -1;
3440 20 50         void* binary = (void*)SvPV(sv_binary, binary_length);
3441            
3442             // Runtime
3443 20           void* runtime = env->runtime;
3444            
3445 20           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3446 20 100         if (!basic_type) {
3447 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3448             }
3449 18           int32_t basic_type_id = env->api->basic_type->get_id(env->runtime, basic_type);
3450            
3451 18           int32_t elem_type_dimension = 0;
3452 18           int32_t basic_type_category = env->api->basic_type->get_category(env->runtime, basic_type);
3453 18           int32_t is_mulnum_array = basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM;
3454 18 100         if (!is_mulnum_array) {
3455 2           croak("$type_name must be a multi-numeric array type\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3456             }
3457            
3458 16           int32_t basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, basic_type);
3459            
3460 16           int32_t fields_length = basic_type_fields_length;
3461            
3462             int32_t field_size;
3463 16           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, basic_type, 0);
3464 16           void* mulnum_field_basic_type = env->api->field->get_basic_type(env->runtime, mulnum_field);
3465 16           int32_t mulnum_field_basic_type_id = env->api->basic_type->get_id(env->runtime, mulnum_field_basic_type);
3466 16           switch (mulnum_field_basic_type_id) {
3467             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
3468 4           field_size = 1;
3469 4           break;
3470             }
3471             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
3472 2           field_size = 2;
3473 2           break;
3474             }
3475             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
3476 2           field_size = 4;
3477 2           break;
3478             }
3479             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
3480 2           field_size = 8;
3481 2           break;
3482             }
3483             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
3484 2           field_size = 4;
3485 2           break;
3486             }
3487             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
3488 4           field_size = 8;
3489 4           break;
3490             }
3491             default: {
3492             assert(0);
3493             }
3494             }
3495            
3496 16 100         if (binary_length % (field_size * fields_length) != 0) {
3497 2           croak("The length of $binary must be divisible by %d * %d\n %s at %s line %d", field_size, fields_length, __func__, FILE_NAME, __LINE__);
3498             }
3499            
3500 14           int32_t array_length = binary_length / fields_length / field_size;
3501              
3502 14           void* spvm_array = env->new_mulnum_array_no_mortal(env, stack, basic_type, array_length);
3503              
3504 14           int32_t type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
3505            
3506 14           int32_t copy_length = fields_length * array_length * field_size;
3507 14           switch (mulnum_field_basic_type_id) {
3508             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
3509 4           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
3510 4 50         if (array_length > 0) {
3511 4           memcpy(elems, binary, copy_length);
3512             }
3513 4           break;
3514             }
3515             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
3516 2           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
3517 2 50         if (array_length > 0) {
3518 2           memcpy(elems, binary, copy_length);
3519             }
3520 2           break;
3521             }
3522             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
3523 2           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
3524 2 50         if (array_length > 0) {
3525 2           memcpy(elems, binary, copy_length);
3526             }
3527 2           break;
3528             }
3529             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
3530 2           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
3531 2 50         if (array_length > 0) {
3532 2           memcpy(elems, binary, copy_length);
3533             }
3534 2           break;
3535             }
3536             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
3537 2           float* elems = env->get_elems_float(env, stack, spvm_array);
3538 2 50         if (array_length > 0) {
3539 2           memcpy(elems, binary, copy_length);
3540             }
3541 2           break;
3542             }
3543             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
3544 2           double* elems = env->get_elems_double(env, stack, spvm_array);
3545 2 50         if (array_length > 0) {
3546 2           memcpy(elems, binary, copy_length);
3547             }
3548 2           break;
3549             }
3550             default:
3551             assert(0);
3552             }
3553            
3554 14           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3555            
3556 14 50         XPUSHs(sv_array);
3557 14           XSRETURN(1);
3558             }
3559              
3560             SV*
3561             _xs_new_muldim_array(...)
3562             PPCODE:
3563             {
3564            
3565 20           SV* sv_self = ST(0);
3566 20           HV* hv_self = (HV*)SvRV(sv_self);
3567            
3568             // Env
3569 20           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3570 20 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3571 20           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3572            
3573             // Stack
3574 20           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3575 20 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3576 20           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3577            
3578 20           SV* sv_basic_type_name = ST(1);
3579 20           SV* sv_type_dimension = ST(2);
3580 20           SV* sv_array = ST(3);
3581            
3582 20 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3583 20           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3584 20 100         if (!basic_type) {
3585 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3586             }
3587            
3588 18 50         int32_t type_dimension = (int32_t)SvIV(sv_type_dimension);
3589            
3590 18           SV* sv_error = &PL_sv_undef;
3591 18           sv_array = SPVM_XS_UTIL_new_muldim_array(aTHX_ sv_self, basic_type, type_dimension, sv_array, &sv_error);
3592            
3593 18 100         if (SvOK(sv_error)) {
    50          
    50          
3594 4 50         croak("$array%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3595             }
3596            
3597 14 50         XPUSHs(sv_array);
3598 14           XSRETURN(1);
3599             }
3600              
3601             SV*
3602             _xs_new_muldim_array_len(...)
3603             PPCODE:
3604             {
3605            
3606 12           SV* sv_self = ST(0);
3607 12           HV* hv_self = (HV*)SvRV(sv_self);
3608            
3609             // Env
3610 12           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3611 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3612 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3613            
3614             // Stack
3615 12           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3616 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3617 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3618            
3619 12           SV* sv_basic_type_name = ST(1);
3620 12           SV* sv_type_dimension = ST(2);
3621 12           SV* sv_length = ST(3);
3622            
3623 12 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
3624 12           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3625 12 100         if (!basic_type) {
3626 2           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3627             }
3628            
3629 10 50         int32_t type_dimension = (int32_t)SvIV(sv_type_dimension);
3630            
3631 10 50         int32_t length = (int32_t)SvIV(sv_length);
3632            
3633 10 100         if (length < 0) {
3634 2           croak("$length must be greater than or equal to 0\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
3635             }
3636            
3637 8           void* spvm_array = env->new_muldim_array_no_mortal(env, stack, basic_type, type_dimension, length);
3638            
3639 8           SV* sv_array = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, spvm_array, "SPVM::BlessedObject::Array");
3640            
3641 8 50         XPUSHs(sv_array);
3642 8           XSRETURN(1);
3643             }
3644              
3645             SV*
3646             _xs_get_exception(...)
3647             PPCODE:
3648             {
3649            
3650 6           SV* sv_self = ST(0);
3651 6           HV* hv_self = (HV*)SvRV(sv_self);
3652            
3653             // Env
3654 6           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3655 6 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3656 6           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3657            
3658             // Stack
3659 6           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3660 6 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3661 6           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3662            
3663 6           void* str_exception = env->get_exception(env, stack);
3664            
3665             SV* sv_exception;
3666 6 100         if (str_exception) {
3667 4           sv_exception = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_self, str_exception, "SPVM::BlessedObject::String");
3668             }
3669             else {
3670 2           sv_exception = &PL_sv_undef;
3671             }
3672            
3673 6 50         XPUSHs(sv_exception);
3674 6           XSRETURN(1);
3675             }
3676              
3677             SV*
3678             _xs_set_exception(...)
3679             PPCODE:
3680             {
3681            
3682 22           SV* sv_self = ST(0);
3683 22           HV* hv_self = (HV*)SvRV(sv_self);
3684            
3685             // Env
3686 22           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3687 22 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3688 22           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3689            
3690             // Stack
3691 22           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3692 22 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3693 22           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3694            
3695 22           SV* sv_message = ST(1);
3696            
3697 22           SV* sv_error = &PL_sv_undef;
3698 22           sv_message = SPVM_XS_UTIL_new_string(aTHX_ sv_self, sv_message, &sv_error);
3699            
3700 22 100         if (SvOK(sv_error)) {
    50          
    50          
3701 2 50         croak("$message%s\n %s at %s line %d\n", SvPV_nolen(sv_error), __func__, FILE_NAME, __LINE__);
3702             }
3703            
3704 20           void* spvm_message = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_message);
3705            
3706 20           env->set_exception(env, stack, spvm_message);
3707            
3708 20           XSRETURN(0);
3709             }
3710              
3711             SV*
3712             _xs_get_memory_blocks_count(...)
3713             PPCODE:
3714             {
3715            
3716 548           SV* sv_self = ST(0);
3717 548           HV* hv_self = (HV*)SvRV(sv_self);
3718            
3719             // Env
3720 548           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
3721 548 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3722 548           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3723            
3724             // Stack
3725 548           SV** sv_stack_ptr = hv_fetch(hv_self, "stack", strlen("stack"), 0);
3726 548 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3727 548           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3728            
3729 548           int32_t memory_blocks_count = env->get_memory_blocks_count_stack(env, stack);
3730 548           SV* sv_memory_blocks_count = sv_2mortal(newSViv(memory_blocks_count));
3731            
3732 548 50         XPUSHs(sv_memory_blocks_count);
3733 548           XSRETURN(1);
3734             }
3735              
3736             MODULE = SPVM::BlessedObject PACKAGE = SPVM::BlessedObject
3737              
3738             SV*
3739             DESTROY(...)
3740             PPCODE:
3741             {
3742 349347           SV* sv_self = ST(0);
3743 349347           HV* hv_self = (HV*)SvRV(sv_self);
3744            
3745 349347           SV** sv_spvm_object_ptr = hv_fetch(hv_self, "spvm_object", strlen("spvm_object"), 0);
3746 349347 50         SV* sv_spvm_object = sv_spvm_object_ptr ? *sv_spvm_object_ptr : &PL_sv_undef;
3747 349347 50         void** spvm_object_ref = (void**)SvPV_nolen(sv_spvm_object);
3748            
3749 349347           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
3750 349347 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
3751 349347           HV* hv_api = (HV*)SvRV(sv_api);
3752            
3753 349347           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
3754 349347 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3755 349347           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3756            
3757             // Stack
3758 349347           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
3759 349347 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3760 349347           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3761            
3762 349347           env->assign_object(env, stack, spvm_object_ref, NULL);
3763            
3764 349347           XSRETURN(0);
3765             }
3766              
3767             SV*
3768             _xs___get_type_name(...)
3769             PPCODE:
3770             {
3771            
3772 92           SV* sv_self = ST(0);
3773 92           HV* hv_self = (HV*)SvRV(sv_self);
3774              
3775             // API
3776 92           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
3777 92 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
3778 92           HV* hv_api = (HV*)SvRV(sv_api);
3779            
3780             // Env
3781 92           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
3782 92 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3783 92           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3784            
3785             // Stack
3786 92           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
3787 92 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3788 92           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3789            
3790             assert(SvROK(sv_self) && sv_derived_from(sv_self, "SPVM::BlessedObject"));
3791            
3792             // Get object
3793 92           void* spvm_object = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
3794            
3795 92           void* spvm_type_name = env->get_type_name_no_mortal(env, stack, spvm_object);
3796 92           const char* type_name = env->get_chars(env, stack, spvm_type_name);
3797 92           int32_t type_name_length = env->length(env, stack, spvm_type_name);
3798            
3799 92           SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, spvm_type_name, "SPVM::BlessedObject::String");
3800            
3801 92           SV* sv_type_name = sv_2mortal(newSVpv(type_name, type_name_length));
3802            
3803 92 50         XPUSHs(sv_type_name);
3804 92           XSRETURN(1);
3805             }
3806              
3807             MODULE = SPVM::BlessedObject::String PACKAGE = SPVM::BlessedObject::String
3808              
3809             SV*
3810             _xs_to_bin(...)
3811             PPCODE:
3812             {
3813            
3814 96518           SV* sv_self = ST(0);
3815 96518           HV* hv_self = (HV*)SvRV(sv_self);
3816              
3817             // API
3818 96518           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
3819 96518 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
3820 96518           HV* hv_api = (HV*)SvRV(sv_api);
3821            
3822             // Env
3823 96518           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
3824 96518 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3825 96518           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3826            
3827             // Stack
3828 96518           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
3829 96518 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3830 96518           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3831            
3832             assert(SvROK(sv_self) && sv_derived_from(sv_self, "SPVM::BlessedObject::String"));
3833            
3834             // Get object
3835 96518           void* spvm_string = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
3836            
3837 96518           int32_t length = env->length(env, stack, spvm_string);
3838 96518           const char* chars = env->get_chars(env, stack, spvm_string);
3839            
3840 96518           SV* sv_return_value = sv_2mortal(newSVpv(chars, length));
3841            
3842 96518 50         XPUSHs(sv_return_value);
3843 96518           XSRETURN(1);
3844             }
3845              
3846             MODULE = SPVM::BlessedObject::Array PACKAGE = SPVM::BlessedObject::Array
3847              
3848             SV*
3849             _xs_length(...)
3850             PPCODE:
3851             {
3852            
3853 20           SV* sv_self = ST(0);
3854 20           HV* hv_self = (HV*)SvRV(sv_self);
3855            
3856             // API
3857 20           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
3858 20 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
3859 20           HV* hv_api = (HV*)SvRV(sv_api);
3860            
3861             // Env
3862 20           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
3863 20 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3864 20           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3865            
3866             // Stack
3867 20           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
3868 20 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3869 20           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3870            
3871             // Runtime
3872 20           void* runtime = env->runtime;
3873            
3874             assert(SvROK(sv_self) && sv_derived_from(sv_self, "SPVM::BlessedObject::Array"));
3875            
3876             // Get object
3877 20           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
3878            
3879 20           int32_t length = env->length(env, stack, spvm_array);
3880            
3881 20           SV* sv_length = sv_2mortal(newSViv(length));
3882            
3883 20 50         XPUSHs(sv_length);
3884 20           XSRETURN(1);
3885             }
3886              
3887             SV*
3888             _xs_to_elems(...)
3889             PPCODE:
3890             {
3891            
3892 20790           SV* sv_self = ST(0);
3893 20790           HV* hv_self = (HV*)SvRV(sv_self);
3894            
3895             // API
3896 20790           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
3897 20790 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
3898 20790           HV* hv_api = (HV*)SvRV(sv_api);
3899            
3900             // Env
3901 20790           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
3902 20790 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
3903 20790           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
3904            
3905             // Stack
3906 20790           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
3907 20790 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
3908 20790           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
3909            
3910             // Runtime
3911 20790           void* runtime = env->runtime;
3912            
3913             assert(SvROK(sv_self) && sv_derived_from(sv_self, "SPVM::BlessedObject::Array"));
3914            
3915             // Get object
3916 20790           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
3917            
3918 20790           int32_t length = env->length(env, stack, spvm_array);
3919            
3920 20790           const char* basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
3921 20790           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
3922 20790 50         if (!basic_type) {
3923 0           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
3924             }
3925 20790           int32_t basic_type_id = env->api->basic_type->get_id(env->runtime, basic_type);
3926 20790           int32_t type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
3927 20790           int32_t is_array_type = type_dimension > 0;
3928            
3929             assert(is_array_type);
3930            
3931 20790           AV* av_values = (AV*)sv_2mortal((SV*)newAV());
3932 20790 50         if (is_array_type) {
3933 20790           int32_t elem_type_dimension = type_dimension - 1;
3934            
3935 20790           int32_t array_is_mulnum_array = env->is_mulnum_array(env, stack, spvm_array);
3936 20790           int32_t array_is_object_array = env->is_object_array(env, stack, spvm_array);
3937            
3938 20790 100         if (array_is_mulnum_array) {
3939            
3940 112 100         for (int32_t index = 0; index < length; index++) {
3941            
3942 82           int32_t basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, basic_type);
3943 82           void* elems = (void*)env->get_elems_int(env, stack, spvm_array);
3944            
3945 82           HV* hv_value = (HV*)sv_2mortal((SV*)newHV());
3946 82           int32_t fields_length = basic_type_fields_length;
3947 328 100         for (int32_t field_index = 0; field_index < basic_type_fields_length; field_index++) {
3948 246           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, basic_type, field_index);
3949 246           const char* mulnum_field_name = env->api->field->get_name(env->runtime, mulnum_field);
3950            
3951             SV* sv_field_value;
3952 246           void* mulnum_field_basic_type = env->api->field->get_basic_type(env->runtime, mulnum_field);
3953 246           int32_t mulnum_field_basic_type_id = env->api->basic_type->get_id(env->runtime, mulnum_field_basic_type);
3954 246           switch (mulnum_field_basic_type_id) {
3955             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
3956 54           int8_t field_value = ((int8_t*)elems)[(fields_length * index) + field_index];
3957 54           sv_field_value = sv_2mortal(newSViv(field_value));
3958 54           break;
3959             }
3960             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
3961 36           int16_t field_value = ((int16_t*)elems)[(fields_length * index) + field_index];
3962 36           sv_field_value = sv_2mortal(newSViv(field_value));
3963 36           break;
3964             }
3965             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
3966 48           int32_t field_value = ((int32_t*)elems)[(fields_length * index) + field_index];
3967 48           sv_field_value = sv_2mortal(newSViv(field_value));
3968 48           break;
3969             }
3970             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
3971 36           int64_t field_value = ((int64_t*)elems)[(fields_length * index) + field_index];
3972 36           sv_field_value = sv_2mortal(newSViv(field_value));
3973 36           break;
3974             }
3975             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
3976 36           float field_value = ((float*)elems)[(fields_length * index) + field_index];
3977 36           sv_field_value = sv_2mortal(newSVnv(field_value));
3978 36           break;
3979             }
3980             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
3981 36           double field_value = ((double*)elems)[(fields_length * index) + field_index];
3982 36           sv_field_value = sv_2mortal(newSVnv(field_value));
3983 36           break;
3984             }
3985             default: {
3986             assert(0);
3987             }
3988             }
3989 246           SvREFCNT_inc(sv_field_value);
3990 246           (void)hv_store(hv_value, mulnum_field_name, strlen(mulnum_field_name), sv_field_value, 0);
3991             }
3992 82           SV* sv_value = sv_2mortal(newRV_inc((SV*)hv_value));
3993 82           av_push(av_values, SvREFCNT_inc(sv_value));
3994             }
3995             }
3996 20760 100         else if (array_is_object_array) {
3997 20640 100         if (basic_type_id == SPVM_NATIVE_C_BASIC_TYPE_ID_STRING) {
3998 122079 100         for (int32_t i = 0; i < length; i++) {
3999 101479           void* object = env->get_elem_string(env, stack, spvm_array, i);
4000            
4001             SV* sv_value;
4002 101479 100         if (object != NULL) {
4003 101473           sv_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, object, "SPVM::BlessedObject::String");
4004             }
4005             else {
4006 6           sv_value = &PL_sv_undef;
4007             }
4008            
4009 101479           av_push(av_values, SvREFCNT_inc(sv_value));
4010             }
4011             }
4012             else {
4013 20724 100         for (int32_t index = 0; index < length; index++) {
4014             // Index
4015 84           void* value = env->get_elem_object(env, stack, spvm_array, index);
4016 84 100         if (value == NULL) {
4017 18           av_push(av_values, &PL_sv_undef);
4018             }
4019             else {
4020 66           int32_t elem_type_is_array_type = elem_type_dimension > 0;
4021             SV* sv_value;
4022 66 100         if (elem_type_is_array_type) {
4023 24           sv_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, value, "SPVM::BlessedObject::Array");
4024             }
4025             else {
4026 42           sv_value = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, value, "SPVM::BlessedObject::Class");
4027             }
4028 66           av_push(av_values, SvREFCNT_inc(sv_value));
4029             }
4030             }
4031             }
4032             }
4033             else {
4034 120           switch (basic_type_id) {
4035             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
4036 28           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
4037 100 100         for (int32_t i = 0; i < length; i++) {
4038 72           SV* sv_value = sv_2mortal(newSViv(elems[i]));
4039 72           av_push(av_values, SvREFCNT_inc(sv_value));
4040             }
4041 28           break;
4042             }
4043             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
4044 18           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
4045 64 100         for (int32_t i = 0; i < length; i++) {
4046 46           SV* sv_value = sv_2mortal(newSViv(elems[i]));
4047 46           av_push(av_values, SvREFCNT_inc(sv_value));
4048             }
4049 18           break;
4050             }
4051             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
4052 24           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
4053 88 100         for (int32_t i = 0; i < length; i++) {
4054 64           SV* sv_value = sv_2mortal(newSViv(elems[i]));
4055 64           av_push(av_values, SvREFCNT_inc(sv_value));
4056             }
4057 24           break;
4058             }
4059             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
4060 18           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
4061 64 100         for (int32_t i = 0; i < length; i++) {
4062 46           SV* sv_value = sv_2mortal(newSViv(elems[i]));
4063 46           av_push(av_values, SvREFCNT_inc(sv_value));
4064             }
4065 18           break;
4066             }
4067             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
4068 16           float* elems = env->get_elems_float(env, stack, spvm_array);
4069 56 100         for (int32_t i = 0; i < length; i++) {
4070 40           SV* sv_value = sv_2mortal(newSVnv(elems[i]));
4071 40           av_push(av_values, SvREFCNT_inc(sv_value));
4072             }
4073 16           break;
4074             }
4075             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
4076 16           double* elems = env->get_elems_double(env, stack, spvm_array);
4077 56 100         for (int32_t i = 0; i < length; i++) {
4078 40           SV* sv_value = sv_2mortal(newSVnv(elems[i]));
4079 40           av_push(av_values, SvREFCNT_inc(sv_value));
4080             }
4081 16           break;
4082             }
4083             default:
4084             assert(0);
4085             }
4086             }
4087             }
4088              
4089 20790           SV* sv_values = sv_2mortal(newRV_inc((SV*)av_values));
4090            
4091 20790 50         XPUSHs(sv_values);
4092 20790           XSRETURN(1);
4093             }
4094              
4095             SV*
4096             _xs_to_bin(...)
4097             PPCODE:
4098             {
4099            
4100 46           SV* sv_self = ST(0);
4101 46           HV* hv_self = (HV*)SvRV(sv_self);
4102            
4103             // API
4104 46           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
4105 46 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
4106 46           HV* hv_api = (HV*)SvRV(sv_api);
4107            
4108             // Env
4109 46           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
4110 46 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
4111 46           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
4112            
4113             // Stack
4114 46           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
4115 46 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
4116 46           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
4117            
4118             // Runtime
4119 46           void* runtime = env->runtime;
4120            
4121             assert(SvROK(sv_self) && sv_derived_from(sv_self, "SPVM::BlessedObject::Array"));
4122            
4123             // Get object
4124 46           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
4125            
4126 46           int32_t length = env->length(env, stack, spvm_array);
4127            
4128 46           const char* basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
4129 46           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
4130 46 50         if (!basic_type) {
4131 0           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
4132             }
4133 46           int32_t basic_type_id = env->api->basic_type->get_id(env->runtime, basic_type);
4134 46           int32_t type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
4135 46           int32_t is_array_type = type_dimension > 0;
4136             assert(is_array_type);
4137            
4138             SV* sv_binary;
4139 46 50         if (is_array_type) {
4140 46           int32_t elem_type_dimension = type_dimension - 1;
4141            
4142 46           int32_t array_is_mulnum_array = env->is_mulnum_array(env, stack, spvm_array);
4143 46           int32_t array_is_object_array = env->is_object_array(env, stack, spvm_array);
4144            
4145 46 100         if (array_is_mulnum_array) {
4146 12           int32_t basic_type_fields_length = env->api->basic_type->get_fields_length(env->runtime, basic_type);
4147            
4148 12           int32_t fields_length = basic_type_fields_length;
4149            
4150 12           void* mulnum_field = env->api->basic_type->get_field_by_index(runtime, basic_type, 0);
4151 12           void* mulnum_field_basic_type = env->api->field->get_basic_type(env->runtime, mulnum_field);
4152 12           int32_t mulnum_field_basic_type_id = env->api->basic_type->get_id(env->runtime, mulnum_field_basic_type);
4153 12           switch (mulnum_field_basic_type_id) {
4154             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
4155 2           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
4156            
4157 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length));
4158 2           break;
4159             }
4160             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
4161 2           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
4162            
4163 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length * 2));
4164 2           break;
4165             }
4166             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
4167 2           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
4168            
4169 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length * 4));
4170 2           break;
4171             }
4172             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
4173 2           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
4174            
4175 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length * 8));
4176 2           break;
4177             }
4178             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
4179 2           float* elems = env->get_elems_float(env, stack, spvm_array);
4180            
4181 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length * 4));
4182 2           break;
4183             }
4184             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
4185 2           double* elems = env->get_elems_double(env, stack, spvm_array);
4186            
4187 2           sv_binary = sv_2mortal(newSVpvn((char*)elems, fields_length * length * 8));
4188 12           break;
4189             }
4190             default: {
4191             assert(0);
4192             }
4193             }
4194             }
4195 34 50         else if (array_is_object_array) {
4196 0           croak("The object array cannnot be converted to a binary\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
4197             }
4198             else {
4199 34           switch (basic_type_id) {
4200             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
4201 8           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
4202            
4203 8           sv_binary = sv_2mortal(newSVpvn((char*)elems, length));
4204 8           break;
4205             }
4206             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
4207 6           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
4208            
4209 6           sv_binary = sv_2mortal(newSVpvn((char*)elems, length * 2));
4210 6           break;
4211             }
4212             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
4213 6           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
4214            
4215 6           sv_binary = sv_2mortal(newSVpvn((char*)elems, length * 4));
4216 6           break;
4217             }
4218             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
4219 6           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
4220            
4221 6           sv_binary = sv_2mortal(newSVpvn((char*)elems, length * 8));
4222 6           break;
4223             }
4224             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
4225 4           float* elems = env->get_elems_float(env, stack, spvm_array);
4226            
4227 4           sv_binary = sv_2mortal(newSVpvn((char*)elems, length * 4));
4228 4           break;
4229             }
4230             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
4231 4           double* elems = env->get_elems_double(env, stack, spvm_array);
4232            
4233 4           sv_binary = sv_2mortal(newSVpvn((char*)elems, length * 8));
4234 4           break;
4235             }
4236             default: {
4237             assert(0);
4238             }
4239             }
4240             }
4241             }
4242            
4243 46 50         XPUSHs(sv_binary);
4244 46           XSRETURN(1);
4245             }
4246              
4247             SV*
4248             _xs_set(...)
4249             PPCODE:
4250             {
4251            
4252 12           SV* sv_self = ST(0);
4253 12           HV* hv_self = (HV*)SvRV(sv_self);
4254            
4255             // API
4256 12           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
4257 12 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
4258 12           HV* hv_api = (HV*)SvRV(sv_api);
4259            
4260             // Env
4261 12           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
4262 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
4263 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
4264            
4265             // Stack
4266 12           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
4267 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
4268 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
4269            
4270 12           SV* sv_index = ST(1);
4271 12           SV* sv_elem = ST(2);
4272            
4273             // Index
4274 12 50         int32_t index = (int32_t)SvIV(sv_index);
4275            
4276             // Array
4277 12           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
4278            
4279             // Length
4280 12           int32_t length = env->length(env, stack, spvm_array);
4281            
4282             // Check range
4283 12 50         if (!(index >= 0 && index < length)) {
    50          
4284 0           croak("$index must be greatr than or equal to 0 and less than the length of the array\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
4285             }
4286            
4287 12           const char* basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
4288 12           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
4289 12 50         if (!basic_type) {
4290 0           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
4291             }
4292 12           int32_t basic_type_id = env->api->basic_type->get_id(env->runtime, basic_type);
4293 12           int32_t type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
4294            
4295 12 50         if (type_dimension == 1) {
4296 12           switch (basic_type_id) {
4297             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
4298             // Value
4299 2 50         int8_t elem = (int8_t)SvIV(sv_elem);
4300            
4301             // Set element
4302 2           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
4303            
4304 2           elems[index] = elem;
4305            
4306 2           break;
4307             }
4308             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
4309             // Value
4310 2 50         int16_t elem = (int16_t)SvIV(sv_elem);
4311            
4312             // Set element
4313 2           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
4314            
4315 2           elems[index] = elem;
4316 2           break;
4317             }
4318             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
4319             // Value
4320 2 50         int32_t elem = (int32_t)SvIV(sv_elem);
4321            
4322             // Set element
4323 2           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
4324            
4325 2           elems[index] = elem;
4326 2           break;
4327             }
4328             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
4329             // Value
4330 2 50         int64_t elem = (int64_t)SvIV(sv_elem);
4331            
4332             // Set element
4333 2           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
4334            
4335 2           elems[index] = elem;
4336 2           break;
4337             }
4338             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
4339             // Value
4340 2 50         float elem = (float)SvNV(sv_elem);
4341            
4342             // Set element
4343 2           float* elems = env->get_elems_float(env, stack, spvm_array);
4344            
4345 2           elems[index] = elem;
4346 2           break;
4347             }
4348             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
4349             // Value
4350 2 50         double elem = (double)SvNV(sv_elem);
4351            
4352             // Set element
4353 2           double* elems = env->get_elems_double(env, stack, spvm_array);
4354            
4355 2           elems[index] = elem;
4356 2           break;
4357             }
4358             default: {
4359             // Get object
4360 0           void* elem = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_elem);
4361            
4362 12           env->set_elem_object(env, stack, spvm_array, index, elem);
4363             }
4364             }
4365             }
4366 0 0         else if (type_dimension > 1) {
4367            
4368             // Get object
4369 0           void* elem = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_elem);
4370            
4371 0           int32_t elem_isa = env->elem_isa(env, stack, spvm_array, elem);
4372 0 0         if (!elem_isa) {
4373 0           croak("$elem must be assigned to the element of the array\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
4374             }
4375            
4376 0           env->set_elem_object(env, stack, spvm_array, index, elem);
4377             }
4378             else {
4379             assert(0);
4380             }
4381            
4382 12           XSRETURN(0);
4383             }
4384              
4385             SV*
4386             _xs_get(...)
4387             PPCODE:
4388             {
4389            
4390 12           SV* sv_self = ST(0);
4391 12           HV* hv_self = (HV*)SvRV(sv_self);
4392            
4393             // API
4394 12           SV** sv_api_ptr = hv_fetch(hv_self, "__api", strlen("__api"), 0);
4395 12 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
4396 12           HV* hv_api = (HV*)SvRV(sv_api);
4397            
4398             // Env
4399 12           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
4400 12 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
4401 12           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
4402            
4403             // Stack
4404 12           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
4405 12 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
4406 12           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
4407            
4408 12           SV* sv_index = ST(1);
4409            
4410             // Index
4411 12 50         int32_t index = (int32_t)SvIV(sv_index);
4412            
4413             // Array
4414 12           void* spvm_array = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_self);
4415            
4416             // Length
4417 12           int32_t length = env->length(env, stack, spvm_array);
4418            
4419             // Check range
4420 12 50         if (!(index >= 0 && index < length)) {
    50          
4421 0           croak("$index must be greater than or equal to 0 and less than the length of the array\n %s at %s line %d\n", __func__, FILE_NAME, __LINE__);
4422             }
4423            
4424 12           const char* basic_type_name = env->get_object_basic_type_name(env, stack, spvm_array);
4425 12           void* basic_type = env->api->runtime->get_basic_type_by_name(env->runtime, basic_type_name);
4426 12 50         if (!basic_type) {
4427 0           croak("The \"%s\" basic type is not found\n %s at %s line %d\n", basic_type_name, __func__, FILE_NAME, __LINE__);
4428             }
4429 12           int32_t basic_type_id = env->api->basic_type->get_id(env->runtime, basic_type);
4430 12           int32_t type_dimension = env->get_object_type_dimension(env, stack, spvm_array);
4431            
4432             assert(type_dimension >= 1);
4433 12           SV* sv_elem = NULL;
4434 12           int32_t elem_is_object = 0;
4435 12 50         if (type_dimension == 1) {
4436 12           switch (basic_type_id) {
4437             case SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE: {
4438             // Get element
4439 2           int8_t* elems = env->get_elems_byte(env, stack, spvm_array);
4440 2           int8_t elem = elems[index];
4441 2           sv_elem = sv_2mortal(newSViv(elem));
4442 2           break;
4443             }
4444             case SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT: {
4445             // Get element
4446 2           int16_t* elems = env->get_elems_short(env, stack, spvm_array);
4447 2           int16_t elem = elems[index];
4448 2           sv_elem = sv_2mortal(newSViv(elem));
4449 2           break;
4450             }
4451             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
4452             // Get element
4453 2           int32_t* elems = env->get_elems_int(env, stack, spvm_array);
4454 2           int32_t elem = elems[index];
4455 2           sv_elem = sv_2mortal(newSViv(elem));
4456 2           break;
4457             }
4458             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
4459             // Get element
4460 2           int64_t* elems = env->get_elems_long(env, stack, spvm_array);
4461 2           int64_t elem = elems[index];
4462 2           sv_elem = sv_2mortal(newSViv(elem));
4463 2           break;
4464             }
4465             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
4466             // Get element
4467 2           float* elems = env->get_elems_float(env, stack, spvm_array);
4468 2           float elem = elems[index];
4469 2           sv_elem = sv_2mortal(newSVnv(elem));
4470 2           break;
4471             }
4472             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
4473             // Get element
4474 2           double* elems = env->get_elems_double(env, stack, spvm_array);
4475 2           double elem = elems[index];
4476 2           sv_elem = sv_2mortal(newSVnv(elem));
4477 2           break;
4478             }
4479             default: {
4480 12           elem_is_object = 1;
4481             }
4482             }
4483             }
4484 0 0         else if (type_dimension > 1) {
4485 0           elem_is_object = 1;
4486             }
4487            
4488 12 50         if (elem_is_object) {
4489 0           void* runtime = env->runtime;
4490            
4491             // Element type dimension
4492 0           int32_t elem_type_dimension = env->get_object_type_dimension(env, stack, spvm_array) - 1;
4493            
4494             // Index
4495 0           void* elem = env->get_elem_object(env, stack, spvm_array, index);
4496            
4497 0 0         if (elem_type_dimension == 0) {
4498 0           sv_elem = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, elem, "SPVM::BlessedObject::Class");
4499             }
4500 0 0         else if (elem_type_dimension > 0) {
4501 0           sv_elem = SPVM_XS_UTIL_new_sv_blessed_object(aTHX_ sv_api, elem, "SPVM::BlessedObject::Array");
4502             }
4503             }
4504            
4505 12 50         XPUSHs(sv_elem);
4506 12           XSRETURN(1);
4507             }
4508              
4509             MODULE = SPVM::BlessedObject::Class PACKAGE = SPVM::BlessedObject::Class
4510              
4511             SV*
4512             get_basic_type_name(...)
4513             PPCODE:
4514             {
4515            
4516 18           SV* sv_object = ST(0);
4517 18           HV* hv_object = (HV*)SvRV(sv_object);
4518            
4519             assert(SvOK(sv_object));
4520            
4521             // Get object
4522 18           void* object = SPVM_XS_UTIL_get_spvm_object(aTHX_ sv_object);
4523              
4524             // API
4525 18           SV** sv_api_ptr = hv_fetch(hv_object, "__api", strlen("__api"), 0);
4526 18 50         SV* sv_api = sv_api_ptr ? *sv_api_ptr : &PL_sv_undef;
4527 18           HV* hv_api = (HV*)SvRV(sv_api);
4528              
4529             // Env
4530 18           SV** sv_env_ptr = hv_fetch(hv_api, "env", strlen("env"), 0);
4531 18 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
4532 18           SPVM_ENV* env = SPVM_XS_UTIL_get_env(aTHX_ sv_env);
4533            
4534             // Stack
4535 18           SV** sv_stack_ptr = hv_fetch(hv_api, "stack", strlen("stack"), 0);
4536 18 50         SV* sv_stack = sv_stack_ptr ? *sv_stack_ptr : &PL_sv_undef;
4537 18           SPVM_VALUE* stack = SPVM_XS_UTIL_get_stack(aTHX_ sv_stack);
4538            
4539 18           const char* basic_type_name = env->get_object_basic_type_name(env, stack, object);
4540            
4541 18           SV* sv_basic_type_name = sv_2mortal(newSVpv(basic_type_name, 0));
4542            
4543 18 50         XPUSHs(sv_basic_type_name);
4544 18           XSRETURN(1);
4545             }
4546              
4547              
4548             MODULE = SPVM::Builder::Compiler PACKAGE = SPVM::Builder::Compiler
4549              
4550             SV*
4551             DESTROY(...)
4552             PPCODE:
4553             {
4554            
4555 1155           SV* sv_self = ST(0);
4556 1155           HV* hv_self = (HV*)SvRV(sv_self);
4557            
4558 1155           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4559 1155 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4560 1155           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4561            
4562 1155           void* compiler = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4563            
4564             // Free compiler
4565 1155           env_api->api->compiler->free_instance(compiler);
4566            
4567 1155           XSRETURN(0);
4568             }
4569              
4570             SV*
4571             create_native_compiler(...)
4572             PPCODE:
4573             {
4574            
4575 1155           SV* sv_self = ST(0);
4576 1155           HV* hv_self = (HV*)SvRV(sv_self);
4577            
4578 1155           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4579 1155 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4580 1155           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4581            
4582 1155           void* compiler = env_api->api->compiler->new_instance();
4583            
4584 1155           size_t iv_compiler = PTR2IV(compiler);
4585 1155           SV* sviv_compiler = sv_2mortal(newSViv(iv_compiler));
4586 1155           SV* sv_compiler = sv_2mortal(newRV_inc(sviv_compiler));
4587 1155           (void)hv_store(hv_self, "pointer", strlen("pointer"), SvREFCNT_inc(sv_compiler), 0);
4588            
4589 1155           void* runtime = env_api->api->compiler->get_runtime(compiler);
4590            
4591 1155           SV* sv_runtime = SPVM_XS_UTIL_new_sv_pointer_object(aTHX_ runtime, "SPVM::Builder::Runtime");
4592 1155           (void)hv_store(hv_self, "runtime", strlen("runtime"), SvREFCNT_inc(sv_runtime), 0);
4593            
4594 1155           XSRETURN(0);
4595             }
4596              
4597             SV*
4598             get_class_file(...)
4599             PPCODE:
4600             {
4601            
4602 0           SV* sv_self = ST(0);
4603 0           HV* hv_self = (HV*)SvRV(sv_self);
4604            
4605 0           SV* sv_class_name = ST(1);
4606 0 0         const char* class_name = SvPV_nolen(sv_class_name);
4607            
4608 0           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4609 0 0         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4610 0 0         SPVM_ENV* env_api = INT2PTR(SPVM_ENV*, SvIV(SvRV(sv_env_api)));
4611            
4612 0           void* compiler = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4613            
4614 0           void* class_file = env_api->api->compiler->get_class_file(compiler, class_name);
4615 0           SV* sv_class_file = &PL_sv_undef;
4616 0 0         if (class_file) {
4617 0           HV* hv_class_file = (HV*)sv_2mortal((SV*)newHV());
4618            
4619 0           (void)hv_store(hv_class_file, "class_name", strlen("class_name"), SvREFCNT_inc(sv_class_name), 0);
4620            
4621 0           const char* file = env_api->api->class_file->get_file(compiler, class_file);
4622 0 0         if (file) {
4623 0           SV* sv_file = sv_2mortal(newSVpv(file, 0));
4624 0           (void)hv_store(hv_class_file, "file", strlen("file"), SvREFCNT_inc(sv_file), 0);
4625             }
4626            
4627 0           const char* dir = env_api->api->class_file->get_dir(compiler, class_file);
4628 0 0         if (dir) {
4629 0           SV* sv_dir = sv_2mortal(newSVpv(dir, 0));
4630 0           (void)hv_store(hv_class_file, "dir", strlen("dir"), SvREFCNT_inc(sv_dir), 0);
4631             }
4632            
4633 0           const char* rel_file = env_api->api->class_file->get_rel_file(compiler, class_file);
4634 0 0         if (rel_file) {
4635 0           SV* sv_rel_file = sv_2mortal(newSVpv(rel_file, 0));
4636 0           (void)hv_store(hv_class_file, "rel_file", strlen("rel_file"), SvREFCNT_inc(sv_rel_file), 0);
4637             }
4638            
4639 0           const char* content = env_api->api->class_file->get_content(compiler, class_file);
4640 0 0         if (content) {
4641 0           SV* sv_content = sv_2mortal(newSVpv(content, 0));
4642 0           (void)hv_store(hv_class_file, "content", strlen("content"), SvREFCNT_inc(sv_content), 0);
4643             }
4644            
4645 0           int32_t content_length = env_api->api->class_file->get_content_length(compiler, class_file);
4646 0           SV* sv_content_length = sv_2mortal(newSViv(content_length));
4647 0           (void)hv_store(hv_class_file, "content_length", strlen("content_length"), SvREFCNT_inc(sv_content_length), 0);
4648            
4649 0           sv_class_file = sv_2mortal(newRV_inc((SV*)hv_class_file));
4650             }
4651            
4652 0 0         XPUSHs(sv_class_file);
4653            
4654 0           XSRETURN(1);
4655             }
4656              
4657             SV*
4658             compile(...)
4659             PPCODE:
4660             {
4661            
4662 2835           SV* sv_self = ST(0);
4663 2835           SV* sv_basic_type_name = ST(1);
4664 2835           SV* sv_start_file = ST(2);
4665 2835           SV* sv_start_line = ST(3);
4666            
4667 2835           HV* hv_self = (HV*)SvRV(sv_self);
4668            
4669 2835           void* compiler = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4670            
4671             // Include directries
4672 2835           SV** sv_include_dirs_ptr = hv_fetch(hv_self, "include_dirs", strlen("include_dirs"), 0);
4673 2835 50         SV* sv_include_dirs = sv_include_dirs_ptr ? *sv_include_dirs_ptr : &PL_sv_undef;
4674            
4675             // Name
4676 2835 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
4677            
4678             // File
4679 2835 50         const char* start_file = SvPV_nolen(sv_start_file);
4680            
4681             // Line
4682 2835 100         int32_t start_line = (int32_t)SvIV(sv_start_line);
4683            
4684 2835           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4685 2835 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4686 2835           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4687            
4688             // Set starting file
4689 2835           env_api->api->compiler->set_start_file(compiler, start_file);
4690            
4691             // Set starting line
4692 2835           env_api->api->compiler->set_start_line(compiler, start_line);
4693            
4694             // Add include paths
4695             AV* av_include_dirs;
4696 2835 50         if (SvOK(sv_include_dirs)) {
    0          
    0          
4697 2835           av_include_dirs = (AV*)SvRV(sv_include_dirs);
4698             }
4699             else {
4700 0           av_include_dirs = (AV*)sv_2mortal((SV*)newAV());
4701             }
4702 2835           int32_t av_include_dirs_length = (int32_t)av_len(av_include_dirs) + 1;
4703 34660 100         for (int32_t i = 0; i < av_include_dirs_length; i++) {
4704 31825           SV** sv_include_dir_ptr = av_fetch(av_include_dirs, i, 0);
4705 31825 50         SV* sv_include_dir = sv_include_dir_ptr ? *sv_include_dir_ptr : &PL_sv_undef;
4706 31825 50         char* include_dir = SvPV_nolen(sv_include_dir);
4707 31825           env_api->api->compiler->add_include_dir(compiler, include_dir);
4708             }
4709            
4710             // Compile SPVM
4711 2835           int32_t error_id = env_api->api->compiler->compile(compiler, basic_type_name);
4712            
4713 2835           SV* sv_success = &PL_sv_undef;
4714 2835 100         if (error_id == 0) {
4715 2287           sv_success = sv_2mortal(newSViv(1));
4716             }
4717            
4718 2835 50         XPUSHs(sv_success);
4719            
4720 2835           XSRETURN(1);
4721             }
4722              
4723             SV*
4724             get_error_messages(...)
4725             PPCODE:
4726             {
4727            
4728 548           SV* sv_self = ST(0);
4729            
4730 548           HV* hv_self = (HV*)SvRV(sv_self);
4731            
4732 548           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4733 548 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4734 548           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4735            
4736 548           void* compiler = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4737            
4738 548           AV* av_error_messages = (AV*)sv_2mortal((SV*)newAV());
4739 548           SV* sv_error_messages = sv_2mortal(newRV_inc((SV*)av_error_messages));
4740            
4741 548           int32_t error_messages_length = env_api->api->compiler->get_error_messages_length(compiler);
4742            
4743 1163 100         for (int32_t i = 0; i < error_messages_length; i++) {
4744 615           const char* error_message = env_api->api->compiler->get_error_message(compiler, i);
4745 615           SV* sv_error_message = sv_2mortal(newSVpv(error_message, 0));
4746 615           av_push(av_error_messages, SvREFCNT_inc(sv_error_message));
4747             }
4748            
4749 548 50         XPUSHs(sv_error_messages);
4750 548           XSRETURN(1);
4751             }
4752              
4753             MODULE = SPVM::Builder PACKAGE = SPVM::Builder
4754              
4755             MODULE = SPVM::Builder::Runtime PACKAGE = SPVM::Builder::Runtime
4756              
4757             SV*
4758             get_method_names(...)
4759             PPCODE:
4760             {
4761            
4762 2035           SV* sv_self = ST(0);
4763 2035           HV* hv_self = (HV*)SvRV(sv_self);
4764 2035           void* runtime = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4765            
4766 2035           SV* sv_basic_type_name = ST(1);
4767 2035           SV* sv_category = ST(2);
4768            
4769             // Name
4770 2035 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
4771            
4772 2035           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4773 2035 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4774 2035           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4775            
4776 2035           AV* av_method_names = (AV*)sv_2mortal((SV*)newAV());
4777 2035           SV* sv_method_names = sv_2mortal(newRV_inc((SV*)av_method_names));
4778            
4779 2035           void* basic_type = env_api->api->runtime->get_basic_type_by_name(runtime, basic_type_name);
4780            
4781 2035           int32_t methods_length = env_api->api->basic_type->get_methods_length(runtime, basic_type);
4782 27247 100         for (int32_t method_index = 0; method_index < methods_length; method_index++) {
4783 25212           void* method = env_api->api->basic_type->get_method_by_index(runtime, basic_type, method_index);
4784 25212           const char* method_name = env_api->api->method->get_name(runtime, method);
4785 25212           SV* sv_method_name = sv_2mortal(newSVpv(method_name, 0));
4786 25212           int32_t is_push = 0;
4787 25212 50         if (SvOK(sv_category)) {
    0          
    0          
4788 50424 50         if(strEQ(SvPV_nolen(sv_category), "native") && env_api->api->method->is_native(runtime, method)) {
    100          
    100          
4789 21323           av_push(av_method_names, SvREFCNT_inc(sv_method_name));
4790             }
4791 3889 50         else if (strEQ(SvPV_nolen(sv_category), "precompile") && env_api->api->method->is_precompile(runtime, method)) {
    100          
    50          
4792 0           av_push(av_method_names, SvREFCNT_inc(sv_method_name));
4793             }
4794             }
4795             else {
4796 0           av_push(av_method_names, SvREFCNT_inc(sv_method_name));
4797             }
4798             }
4799            
4800 2035 50         XPUSHs(sv_method_names);
4801 2035           XSRETURN(1);
4802             }
4803              
4804             SV*
4805             get_basic_type_names(...)
4806             PPCODE:
4807             {
4808            
4809 0           SV* sv_self = ST(0);
4810 0           HV* hv_self = (HV*)SvRV(sv_self);
4811 0           void* runtime = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4812            
4813 0           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4814 0 0         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4815 0           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4816            
4817 0           AV* av_basic_type_names = (AV*)sv_2mortal((SV*)newAV());
4818 0           SV* sv_basic_type_names = sv_2mortal(newRV_inc((SV*)av_basic_type_names));
4819            
4820 0           int32_t basic_types_length = env_api->api->runtime->get_basic_types_length(runtime);
4821 0 0         for (int32_t basic_type_id = 0; basic_type_id < basic_types_length; basic_type_id++) {
4822 0           void* basic_type = env_api->api->runtime->get_basic_type_by_id(runtime, basic_type_id);
4823 0           int32_t basic_type_category = env_api->api->basic_type->get_category(runtime, basic_type);
4824 0           const char* basic_type_name = env_api->api->basic_type->get_name(runtime, basic_type);
4825 0           SV* sv_basic_type_name = sv_2mortal(newSVpv(basic_type_name, 0));
4826 0           av_push(av_basic_type_names, SvREFCNT_inc(sv_basic_type_name));
4827             }
4828            
4829 0 0         XPUSHs(sv_basic_type_names);
4830 0           XSRETURN(1);
4831             }
4832              
4833             SV*
4834             get_class_file(...)
4835             PPCODE:
4836             {
4837            
4838 2035           SV* sv_self = ST(0);
4839 2035           HV* hv_self = (HV*)SvRV(sv_self);
4840 2035           void* runtime = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4841            
4842 2035           SV* sv_basic_type_name = ST(1);
4843            
4844             // Name
4845 2035 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
4846            
4847 2035           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4848 2035 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4849 2035           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4850            
4851 2035           void* basic_type = env_api->api->runtime->get_basic_type_by_name(runtime, basic_type_name);
4852            
4853             const char* class_file;
4854 2035           SV* sv_class_file = &PL_sv_undef;
4855            
4856 2035 50         if (basic_type) {
4857 2035           int32_t basic_type_category = env_api->api->basic_type->get_category(runtime, basic_type);
4858 2035 50         if (basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS || basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE || basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM) {
    0          
    0          
4859 2035           const char* class_dir = env_api->api->basic_type->get_class_dir(runtime, basic_type);
4860             const char* class_dir_sep;
4861 2035 50         if (class_dir) {
4862 2035           class_dir_sep = "/";
4863             }
4864             else {
4865 0           class_dir_sep = "";
4866 0           class_dir = "";
4867             }
4868 2035           const char* class_rel_file = env_api->api->basic_type->get_class_rel_file(runtime, basic_type);
4869            
4870 2035           sv_class_file = sv_2mortal(newSVpv(class_dir, 0));
4871 2035           sv_catpv(sv_class_file, class_dir_sep);
4872 2035           sv_catpv(sv_class_file, class_rel_file);
4873             }
4874             }
4875            
4876 2035 50         XPUSHs(sv_class_file);
4877 2035           XSRETURN(1);
4878             }
4879              
4880             SV*
4881             set_native_method_address(...)
4882             PPCODE:
4883             {
4884            
4885 21168           SV* sv_self = ST(0);
4886 21168           HV* hv_self = (HV*)SvRV(sv_self);
4887 21168           void* runtime = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4888              
4889 21168           SV* sv_basic_type_name = ST(1);
4890 21168           SV* sv_method_name = ST(2);
4891 21168           SV* sv_native_address = ST(3);
4892            
4893 21168           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4894 21168 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4895 21168           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4896            
4897             // Basic type name
4898 21168 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
4899            
4900 21168           void* basic_type = env_api->api->runtime->get_basic_type_by_name(runtime, basic_type_name);
4901            
4902             // Method name
4903 21168 50         const char* method_name = SvPV_nolen(sv_method_name);
4904            
4905             // Method
4906 21168           void* method = env_api->api->basic_type->get_method_by_name(runtime, basic_type, method_name);
4907            
4908             // Native address
4909 21168 50         void* native_address = INT2PTR(void*, SvIV(sv_native_address));
4910            
4911 21168           env_api->api->method->set_native_address(runtime, method, native_address);
4912            
4913             assert(native_address == env_api->api->method->get_native_address(runtime, method));
4914            
4915 21168           XSRETURN(0);
4916             }
4917              
4918             SV*
4919             build_precompile_module_source(...)
4920             PPCODE:
4921             {
4922 19           SV* sv_self = ST(0);
4923 19           HV* hv_self = (HV*)SvRV(sv_self);
4924 19           void* runtime = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4925            
4926 19           SV* sv_basic_type_name = ST(1);
4927 19 50         const char* basic_type_name = SvPV_nolen(sv_basic_type_name);
4928            
4929 19           SV** sv_env_api_ptr = hv_fetch(hv_self, "env_api", strlen("env_api"), 0);
4930 19 50         SV* sv_env_api = sv_env_api_ptr ? *sv_env_api_ptr : &PL_sv_undef;
4931 19           SPVM_ENV* env_api = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env_api);
4932            
4933             // New allocator
4934 19           void* allocator = env_api->api->allocator->new_instance();
4935            
4936             // New string buffer
4937 19           void* string_buffer = env_api->api->string_buffer->new_instance(allocator, 0);
4938            
4939 19           void* basic_type = env_api->api->runtime->get_basic_type_by_name(runtime, basic_type_name);
4940            
4941 19           env_api->api->runtime->build_precompile_module_source(runtime, string_buffer, basic_type);
4942            
4943 19           const char* string_buffer_value = env_api->api->string_buffer->get_string(string_buffer);
4944 19           int32_t string_buffer_length = env_api->api->string_buffer->get_length(string_buffer);
4945 19           SV* sv_precompile_source = sv_2mortal(newSVpv(string_buffer_value, string_buffer_length));
4946            
4947             // Free string buffer
4948 19           env_api->api->string_buffer->free_instance(string_buffer);
4949            
4950             // Free allocator
4951 19           env_api->api->allocator->free_instance(allocator);
4952            
4953 19 50         XPUSHs(sv_precompile_source);
4954 19           XSRETURN(1);
4955             }
4956              
4957             MODULE = SPVM::Builder::Env PACKAGE = SPVM::Builder::Env
4958              
4959             SV*
4960             new(...)
4961             PPCODE:
4962             {
4963 1491           SV* sv_class = ST(0);
4964            
4965 1491           SV* sv_compiler = ST(1);
4966            
4967 1491           SPVM_ENV* new_env = SPVM_API_new_env();
4968            
4969 1491           SV* sv_self = SPVM_XS_UTIL_new_sv_pointer_object(aTHX_ new_env, "SPVM::Builder::Env");
4970 1491           HV* hv_self = (HV*)SvRV(sv_self);
4971            
4972 1491 100         if (SvOK(sv_compiler)) {
    50          
    50          
4973 336           void* compiler = SPVM_XS_UTIL_get_pointer(aTHX_ sv_compiler);
4974 336           void* runtime = new_env->api->compiler->get_runtime(compiler);
4975 336           new_env->runtime = runtime;
4976 336           new_env->api->runtime->set_compiler(runtime, compiler);
4977 336           (void)hv_store(hv_self, "compiler", strlen("compiler"), SvREFCNT_inc(sv_compiler), 0);
4978             }
4979            
4980 1491 50         XPUSHs(sv_self);
4981 1491           XSRETURN(1);
4982             }
4983              
4984             SV*
4985             DESTROY(...)
4986             PPCODE:
4987             {
4988            
4989 1491           SV* sv_self = ST(0);
4990 1491           HV* hv_self = (HV*)SvRV(sv_self);
4991            
4992             // Env
4993 1491           SPVM_ENV* env = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
4994            
4995 1491           env->free_env(env);
4996            
4997 1491           XSRETURN(0);
4998             }
4999              
5000             SV*
5001             new_stack(...)
5002             PPCODE:
5003             {
5004            
5005             // Env
5006 336           SV* sv_env = ST(0);
5007 336           SPVM_ENV* env = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env);
5008              
5009             // Create native_stack
5010 336           SPVM_VALUE* stack = env->new_stack(env);
5011 336           SV* sv_stack = SPVM_XS_UTIL_new_sv_pointer_object(aTHX_ stack, "SPVM::Builder::Stack");
5012 336           HV* hv_stack = (HV*)SvRV(sv_stack);
5013              
5014 336           (void)hv_store(hv_stack, "env", strlen("env"), SvREFCNT_inc(sv_env), 0);
5015              
5016 336 50         XPUSHs(sv_stack);
5017 336           XSRETURN(1);
5018             }
5019              
5020             MODULE = SPVM::Builder::Stack PACKAGE = SPVM::Builder::Stack
5021              
5022             SV*
5023             DESTROY(...)
5024             PPCODE:
5025             {
5026            
5027 336           SV* sv_self = ST(0);
5028 336           HV* hv_self = (HV*)SvRV(sv_self);
5029            
5030             // Stack
5031 336           SPVM_VALUE* stack = SPVM_XS_UTIL_get_pointer(aTHX_ sv_self);
5032            
5033             // Env
5034 336           SV** sv_env_ptr = hv_fetch(hv_self, "env", strlen("env"), 0);
5035 336 50         SV* sv_env = sv_env_ptr ? *sv_env_ptr : &PL_sv_undef;
5036 336           SPVM_ENV* env = SPVM_XS_UTIL_get_pointer(aTHX_ sv_env);
5037            
5038             // Free native_stack
5039 336           env->free_stack(env, stack);
5040            
5041 336           XSRETURN(0);
5042             }
5043              
5044             MODULE = SPVM PACKAGE = SPVM