#include "spvm_native.h"
#include <assert.h>
static
const
char
* FILE_NAME =
"Native/MethodCall.c"
;
int32_t SPVM__Native__MethodCall__new_method_with_env_stack_common(SPVM_ENV* env, SPVM_VALUE* stack, int32_t method_call_type) {
int32_t error_id = 0;
void
* obj_self_env = stack[0].oval;
void
* obj_self_stack = stack[1].oval;
void
* obj_instance = stack[2].oval;
void
* obj_basic_type_name = stack[2].oval;
void
* obj_method_name = stack[3].oval;
SPVM_ENV* self_env = NULL;
if
(obj_self_env) {
self_env = env->get_pointer(env, stack, obj_self_env);
}
else
{
self_env = env;
void
* obj_address_self_env = env->new_pointer_object_by_name(env, stack,
"Address"
, self_env, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
stack[0].oval = obj_address_self_env;
env->call_class_method_by_name(env, stack,
"Native::Env"
,
"new_with_pointer"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
obj_self_env = stack[0].oval;
env->set_no_free(env, stack, obj_self_env, 1);
}
SPVM_VALUE* self_stack = NULL;
if
(obj_self_stack) {
self_stack = env->get_pointer(env, stack, obj_self_stack);
}
else
{
self_stack = stack;
void
* obj_address_self_stack = env->new_pointer_object_by_name(env, stack,
"Address"
, self_stack, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
stack[0].oval = obj_address_self_stack;
env->call_class_method_by_name(env, stack,
"Native::Stack"
,
"new_with_pointer"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
obj_self_stack = stack[0].oval;
env->set_no_free(env, stack, obj_self_stack, 1);
}
int32_t is_binary_compatible_stack = env->is_binary_compatible_stack(self_env, self_stack);
if
(!is_binary_compatible_stack) {
return
env->die(env, stack,
"The runtime stack $stack is not compatible with the runtime environemnt $env."
, __func__, __FILE__, __LINE__);
}
void
* method = NULL;
const
char
* method_disp = NULL;
if
(method_call_type == 0) {
if
(!obj_basic_type_name) {
return
env->die(env, stack,
"The basic type name $basic_type_name must be defined."
, __func__, FILE_NAME, __LINE__);
}
const
char
* basic_type_name = env->get_chars(env, stack, obj_basic_type_name);
if
(!obj_method_name) {
return
env->die(env, stack,
"The method name $method_name must be defined."
, __func__, FILE_NAME, __LINE__);
}
const
char
* method_name = env->get_chars(env, stack, obj_method_name);
method = self_env->get_class_method(self_env, self_stack, basic_type_name, method_name);
if
(!method) {
return
env->die(env, stack,
"The \"%s\" class method in the \"%s\" class cannot be found."
, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
}
}
else
if
(method_call_type == 1) {
if
(!obj_basic_type_name) {
return
env->die(env, stack,
"The basic type name $basic_type_name must be defined."
, __func__, FILE_NAME, __LINE__);
}
const
char
* basic_type_name = env->get_chars(env, stack, obj_basic_type_name);
if
(!obj_method_name) {
return
env->die(env, stack,
"The method name $method_name must be defined."
, __func__, FILE_NAME, __LINE__);
}
const
char
* method_name = env->get_chars(env, stack, obj_method_name);
method = self_env->get_instance_method_static(self_env, self_stack, basic_type_name, method_name);
if
(!method) {
return
env->die(env, stack,
"The \"%s\" instance method in the \"%s\" class cannot be found."
, method_name, basic_type_name, __func__, FILE_NAME, __LINE__);
}
}
else
if
(method_call_type == 2) {
if
(!obj_instance) {
return
env->die(env, stack,
"The instance $instance must be defined."
, __func__, FILE_NAME, __LINE__);
}
if
(!obj_method_name) {
return
env->die(env, stack,
"The method name $method_name must be defined."
, __func__, FILE_NAME, __LINE__);
}
const
char
* method_name = env->get_chars(env, stack, obj_method_name);
method = self_env->get_instance_method(self_env, self_stack, obj_instance, method_name);
if
(!method) {
return
env->die(env, stack,
"The \"%s\" instance method cannot be found."
, method_name, __func__, FILE_NAME, __LINE__);
}
}
void
* obj_address_method = env->new_pointer_object_by_name(env, stack,
"Address"
, method, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
stack[0].oval = obj_address_method;
env->call_class_method_by_name(env, stack,
"Native::Method"
,
"new_with_pointer"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
void
* obj_method = stack[0].oval;
env->set_no_free(env, stack, obj_method, 1);
void
* obj_self = env->new_pointer_object_by_name(env, stack,
"Native::MethodCall"
, method, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
env->set_field_object_by_name(env, stack, obj_self,
"method"
, obj_method, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
env->set_field_object_by_name(env, stack, obj_self,
"env"
, obj_self_env, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
env->set_field_object_by_name(env, stack, obj_self,
"stack"
, obj_self_stack, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
stack[0].oval = obj_self;
return
0;
}
int32_t SPVM__Native__MethodCall__new_class_method_with_env_stack(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = SPVM__Native__MethodCall__new_method_with_env_stack_common(env, stack, 0);
return
error_id;
}
int32_t SPVM__Native__MethodCall__new_instance_method_static_with_env_stack(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = SPVM__Native__MethodCall__new_method_with_env_stack_common(env, stack, 1);
return
error_id;
}
int32_t SPVM__Native__MethodCall__new_instance_method_with_env_stack(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = SPVM__Native__MethodCall__new_method_with_env_stack_common(env, stack, 2);
return
error_id;
}
int32_t SPVM__Native__MethodCall__call(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = 0;
void
* obj_self = stack[0].oval;
void
* obj_args = stack[1].oval;
void
* obj_error_id_ref = stack[2].oval;
if
(obj_error_id_ref) {
int32_t error_id_ref_length = env->length(env, stack, obj_error_id_ref);
if
(!(error_id_ref_length == 1)) {
return
env->die(env, stack,
"If the reference to an error id $error_id_ref exists, the length of it must be 1."
, __func__, FILE_NAME, __LINE__);
}
}
if
(!obj_args) {
obj_args = env->new_object_array_by_name(env, stack,
"object"
, 0, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
}
int32_t args_length = env->length(env, stack, obj_args);
void
* obj_method = env->get_field_object_by_name(env, stack, obj_self,
"method"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
void
* runtime = env->runtime;
void
* method = env->get_pointer(env, stack, obj_method);
const
char
* method_name = env->api->method->get_name(runtime, method);
void
* basic_type = env->api->method->get_current_basic_type(runtime, method);
const
char
* class_name = env->api->basic_type->get_name(runtime, basic_type);
int32_t method_required_args_length = env->api->method->get_required_args_length(runtime, method);
if
(!(args_length >= method_required_args_length)) {
return
env->die(env, stack,
"%s#%s method failed to execute. Too few arguments."
, class_name, method_name, __func__, FILE_NAME, __LINE__);
}
int32_t method_args_length = env->api->method->get_args_length(runtime, method);
if
(!(args_length <= method_args_length)) {
return
env->die(env, stack,
"%s#%s method failed to execute. Too many arguments."
, class_name, method_name, __func__, FILE_NAME, __LINE__);
}
void
* obj_self_env = env->get_field_object_by_name(env, stack, obj_self,
"env"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_ENV* self_env = env->get_pointer(env, stack, obj_self_env);
void
* obj_self_stack = env->get_field_object_by_name(env, stack, obj_self,
"stack"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_VALUE* self_stack = env->get_pointer(env, stack, obj_self_stack);
int32_t stack_index = 0;
for
(int32_t arg_index = 0; arg_index < args_length; arg_index++) {
void
* obj_arg = env->get_elem_object(env, stack, obj_args, arg_index);
void
* method_arg = env->api->method->get_arg_by_index(runtime, method, arg_index);
void
* method_arg_basic_type = env->api->arg->get_basic_type(runtime, method_arg);
int32_t method_arg_basic_type_id = env->api->basic_type->get_id(runtime, method_arg_basic_type);
int32_t method_arg_type_dimension = env->api->arg->get_type_dimension(runtime, method_arg);
int32_t method_arg_type_flag = env->api->arg->get_type_flag(runtime, method_arg);
int32_t method_arg_basic_type_category = env->api->basic_type->get_category(runtime, method_arg_basic_type);
int32_t method_arg_is_object_type = env->api->type->is_object_type(runtime, method_arg_basic_type, method_arg_type_dimension, method_arg_type_flag);
if
(method_arg_is_object_type) {
if
(obj_arg) {
void
* arg_basic_type = env->get_object_basic_type(env, stack, obj_arg);
const
char
* arg_basic_type_name = env->api->basic_type->get_name(runtime, arg_basic_type);
int32_t arg_type_dimension = env->get_object_type_dimension(env, stack, obj_arg);
int32_t can_assign = env->api->type->can_assign(
runtime,
method_arg_basic_type, method_arg_type_dimension, method_arg_type_flag,
arg_basic_type, method_arg_type_dimension, 0
);
if
(!can_assign) {
return
env->die(env, stack,
"%s#%s method failed to execute. The %dth argument cannot be assigned."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t is_binary_compatible_object = self_env->is_binary_compatible_object(self_env, self_stack, obj_arg);
if
(!is_binary_compatible_object) {
return
env->die(env, stack,
"%s#%s method failed to execute. The object of the %dth argument is not binary compatible."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
}
self_stack[stack_index].oval = obj_arg;
stack_index++;
}
else
{
if
(!obj_arg) {
return
env->die(env, stack,
"%s#%s method failed to execute. The %dth argument must be defined."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t method_arg_type_is_ref = method_arg_type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF;
if
(!method_arg_type_is_ref) {
if
(method_arg_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC) {
switch
(method_arg_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Byte"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Byte class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int8_t value = env->get_field_byte_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].bval = value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Short"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Short class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int16_t value = env->get_field_short_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].sval = value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Int"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Int class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t value = env->get_field_int_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].ival = value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Long"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Long class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int64_t value = env->get_field_long_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].lval = value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Float"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Float class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
float
value = env->get_field_float_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].fval = value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"Double"
, 0)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the Double class."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
double
value = env->get_field_double_by_name(env, stack, obj_arg,
"value"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
self_stack[stack_index].dval = value;
break
;
}
default
: {
assert
(0);
}
}
stack_index++;
}
else
if
(method_arg_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM) {
int32_t method_arg_width = env->api->type->get_type_width(runtime, method_arg_basic_type, method_arg_type_dimension, method_arg_type_flag);
int32_t arg_array_length = env->length(env, stack, obj_arg);
if
(!(arg_array_length == method_arg_width)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The array length of the %dth argument must be %d."
, class_name, method_name, arg_index + 1, method_arg_width, __func__, FILE_NAME, __LINE__);
}
void
* method_arg_mulnum_field = env->api->basic_type->get_field_by_index(runtime, method_arg_basic_type, 0);
void
* method_arg_mulnum_field_basic_type = env->api->field->get_basic_type(runtime, method_arg_mulnum_field);
int32_t method_arg_mulnum_field_basic_type_id = env->api->basic_type->get_id(runtime, method_arg_mulnum_field_basic_type);
switch
(method_arg_mulnum_field_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"byte"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the byte[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int8_t* value_ref = env->get_elems_byte(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].bval = value_ref[i];
}
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"short"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the short[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int16_t* value_ref = env->get_elems_short(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].sval = value_ref[i];
}
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"int"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the int[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t* value_ref = env->get_elems_int(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].ival = value_ref[i];
}
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"long"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the long[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int64_t* value_ref = env->get_elems_long(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].lval = value_ref[i];
}
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"float"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the float[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
float
* value_ref = env->get_elems_float(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].fval = value_ref[i];
}
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"double"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the double[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
double
* value_ref = env->get_elems_double(env, stack, obj_arg);
for
(int32_t i = 0; i < method_arg_width; i++) {
self_stack[stack_index + i].dval = value_ref[i];
}
break
;
}
default
: {
assert
(0);
}
}
stack_index += method_arg_width;
}
else
{
assert
(0);
}
}
else
{
if
(method_arg_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC) {
int32_t arg_array_length = env->length(env, stack, obj_arg);
if
(!(arg_array_length == 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The array length of the %dth argument must be 1."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
switch
(method_arg_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"byte"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the byte[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int8_t* value_ref = env->get_elems_byte(env, stack, obj_arg);
self_stack[stack_index].bref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"short"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the short[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int16_t* value_ref = env->get_elems_short(env, stack, obj_arg);
self_stack[stack_index].sref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"int"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the int[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t* value_ref = env->get_elems_int(env, stack, obj_arg);
self_stack[stack_index].iref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"long"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the long[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int64_t* value_ref = env->get_elems_long(env, stack, obj_arg);
self_stack[stack_index].lref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"float"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the float[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
float
* value_ref = env->get_elems_float(env, stack, obj_arg);
self_stack[stack_index].fref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"double"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the double[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
double
* value_ref = env->get_elems_double(env, stack, obj_arg);
self_stack[stack_index].dref = value_ref;
break
;
}
default
: {
assert
(0);
}
}
}
else
if
(method_arg_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM) {
int32_t method_arg_width = env->api->basic_type->get_fields_length(runtime, method_arg_basic_type);
int32_t arg_array_length = env->length(env, stack, obj_arg);
if
(!(arg_array_length == method_arg_width)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The array length of the %dth argument must be %d."
, class_name, method_name, arg_index + 1, method_arg_width, __func__, FILE_NAME, __LINE__);
}
void
* method_arg_mulnum_field = env->api->basic_type->get_field_by_index(runtime, method_arg_basic_type, 0);
void
* method_arg_mulnum_field_basic_type = env->api->field->get_basic_type(runtime, method_arg_mulnum_field);
int32_t method_arg_mulnum_field_basic_type_id = env->api->basic_type->get_id(runtime, method_arg_mulnum_field_basic_type);
switch
(method_arg_mulnum_field_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"byte"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the byte[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int8_t* value_ref = env->get_elems_byte(env, stack, obj_arg);
self_stack[stack_index].bref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"short"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the short[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int16_t* value_ref = env->get_elems_short(env, stack, obj_arg);
self_stack[stack_index].sref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"int"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the int[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int32_t* value_ref = env->get_elems_int(env, stack, obj_arg);
self_stack[stack_index].iref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"long"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the long[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
int64_t* value_ref = env->get_elems_long(env, stack, obj_arg);
self_stack[stack_index].lref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"float"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the float[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
float
* value_ref = env->get_elems_float(env, stack, obj_arg);
self_stack[stack_index].fref = value_ref;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
if
(!env->is_type_by_name(env, stack, obj_arg,
"double"
, 1)) {
return
env->die(env, stack,
"%s#%s method failed to execute. The type of the %dth argument must be the double[] type."
, class_name, method_name, arg_index + 1, __func__, FILE_NAME, __LINE__);
}
double
* value_ref = env->get_elems_double(env, stack, obj_arg);
self_stack[stack_index].dref = value_ref;
break
;
}
default
: {
assert
(0);
}
}
}
else
{
assert
(0);
}
stack_index++;
}
}
}
int32_t stack_length = stack_index;
int32_t error_id_exception_thrown = env->get_basic_type_id_by_name(env, stack,
"Native::MethodCall::Error::ExceptionThrown"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
int32_t self_error_id = self_env->call_method(self_env, self_stack, method, stack_length);
if
(obj_error_id_ref) {
int32_t* error_id_ref = env->get_elems_int(env, stack, obj_error_id_ref);
*error_id_ref = self_error_id;
}
if
(self_error_id) {
env->set_exception(env, stack, env->get_exception(env, self_stack));
return
error_id_exception_thrown;
}
void
* method_return_basic_type = env->api->method->get_return_basic_type(runtime, method);
int32_t method_return_basic_type_id = env->api->basic_type->get_id(runtime, method_return_basic_type);
int32_t method_return_type_dimension = env->api->method->get_return_type_dimension(runtime, method);
int32_t method_return_type_flag = env->api->method->get_return_type_flag(runtime, method);
int32_t method_return_basic_type_category = env->api->basic_type->get_category(runtime, method_return_basic_type);
int32_t method_return_is_object_type = env->api->type->is_object_type(runtime, method_return_basic_type, method_return_type_dimension, method_return_type_flag);
if
(method_return_is_object_type) {
int32_t is_binary_compatible_object = env->is_binary_compatible_object(env, stack, self_stack[0].oval);
if
(!is_binary_compatible_object) {
return
env->die(env, stack,
"The return object is not binary compatible."
, __func__, FILE_NAME, __LINE__);
}
}
else
{
int32_t method_return_type_is_ref = method_return_type_flag & SPVM_NATIVE_C_TYPE_FLAG_REF;
assert
(!method_return_type_is_ref);
if
(method_return_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC) {
switch
(method_return_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
self_stack[0].ival = self_stack[0].bval;
env->call_class_method_by_name(env, stack,
"Byte"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
self_stack[0].ival = self_stack[0].sval;
env->call_class_method_by_name(env, stack,
"Short"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
env->call_class_method_by_name(env, stack,
"Int"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
env->call_class_method_by_name(env, stack,
"Long"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
env->call_class_method_by_name(env, stack,
"Float"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
env->call_class_method_by_name(env, stack,
"Double"
,
"new"
, 1, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
break
;
}
default
: {
assert
(0);
}
}
}
else
if
(method_return_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM) {
int32_t method_return_width = env->api->type->get_type_width(runtime, method_return_basic_type, method_return_type_dimension, method_return_type_flag);
void
* method_return_mulnum_field = env->api->basic_type->get_field_by_index(runtime, method_return_basic_type, 0);
void
* method_return_mulnum_field_basic_type = env->api->field->get_basic_type(runtime, method_return_mulnum_field);
int32_t method_return_mulnum_field_basic_type_id = env->api->basic_type->get_id(runtime, method_return_mulnum_field_basic_type);
switch
(method_return_mulnum_field_basic_type_id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE : {
void
* obj_return_value = env->new_byte_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
int8_t* return_value_ref = env->get_elems_byte(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].bval;
}
self_stack[0].oval = obj_return_value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT : {
void
* obj_return_value = env->new_short_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
int16_t* return_value_ref = env->get_elems_short(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].sval;
}
self_stack[0].oval = obj_return_value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT : {
void
* obj_return_value = env->new_int_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
int32_t* return_value_ref = env->get_elems_int(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].ival;
}
self_stack[0].oval = obj_return_value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG : {
void
* obj_return_value = env->new_long_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
int64_t* return_value_ref = env->get_elems_long(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].lval;
}
self_stack[0].oval = obj_return_value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT : {
void
* obj_return_value = env->new_float_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
float
* return_value_ref = env->get_elems_float(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].fval;
}
self_stack[0].oval = obj_return_value;
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE : {
void
* obj_return_value = env->new_double_array(env, stack, method_return_width);
if
(error_id) {
return
error_id; }
double
* return_value_ref = env->get_elems_double(env, stack, obj_return_value);
for
(int32_t i = 0; i < method_return_width; i++) {
return_value_ref[i] = self_stack[i].dval;
}
self_stack[0].oval = obj_return_value;
break
;
}
default
: {
assert
(0);
}
}
}
else
if
(method_return_basic_type_category == SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_VOID) {
self_stack[0].oval = NULL;
}
else
{
assert
(0);
}
}
return
0;
}
int32_t SPVM__Native__MethodCall__get_exception(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = 0;
void
* obj_self = stack[0].oval;
void
* obj_self_env = env->get_field_object_by_name(env, stack, obj_self,
"env"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_ENV* self_env = env->get_pointer(env, stack, obj_self_env);
void
* obj_self_stack = env->get_field_object_by_name(env, stack, obj_self,
"stack"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_VALUE* self_stack = env->get_pointer(env, stack, obj_self_stack);
void
* obj_exception = self_env->get_exception(self_env, self_stack);
stack[0].oval = obj_exception;
return
0;
}
int32_t SPVM__Native__MethodCall__set_exception(SPVM_ENV* env, SPVM_VALUE* stack) {
int32_t error_id = 0;
void
* obj_self = stack[0].oval;
void
* obj_exception = stack[1].oval;
void
* obj_self_env = env->get_field_object_by_name(env, stack, obj_self,
"env"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_ENV* self_env = env->get_pointer(env, stack, obj_self_env);
void
* obj_self_stack = env->get_field_object_by_name(env, stack, obj_self,
"stack"
, &error_id, __func__, FILE_NAME, __LINE__);
if
(error_id) {
return
error_id; }
SPVM_VALUE* self_stack = env->get_pointer(env, stack, obj_self_stack);
self_env->set_exception(self_env, self_stack, obj_exception);
return
0;
}