// Copyright (c) 2023 Yuki Kimoto
// MIT License
#include "spvm_native.h"
#include <assert.h>
static const char* FILE_NAME = "Runtime.c";
int32_t SPVM__Runtime__DESTROY(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
env->api->runtime->free_object(runtime);
return 0;
}
int32_t SPVM__Runtime__set_native_method_address(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* obj_method_name = stack[2].oval;
const char* method_name = env->get_chars(env, stack, obj_method_name);
void* obj_address = stack[3].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// Method id
int32_t method_id = env->api->runtime->get_method_id_by_name(runtime, class_name, method_name);
// Native address
void* address = env->get_pointer(env, stack, obj_address);
env->api->runtime->set_native_method_address(runtime, method_id, address);
return 0;
}
int32_t SPVM__Runtime__get_native_method_address(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
void* obj_method_name = stack[2].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// Class name
const char* class_name = env->get_chars(env, stack, obj_class_name);
// Method name
const char* method_name = env->get_chars(env, stack, obj_method_name);
// Method id
int32_t method_id = env->api->runtime->get_method_id_by_name(runtime, class_name, method_name);
void* address = env->api->runtime->get_native_method_address(runtime, method_id);
// Native address
void* obj_address = env->new_pointer_object_by_name(env, stack, "Native::Address", address, &e, __func__, FILE_NAME, __LINE__);
stack[0].oval = obj_address;
return 0;
}
int32_t SPVM__Runtime__get_method_is_class_method(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
void* obj_method_name = stack[2].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// Class name
const char* class_name = env->get_chars(env, stack, obj_class_name);
// Method name
const char* method_name = env->get_chars(env, stack, obj_method_name);
// Method id
int32_t method_id = env->api->runtime->get_method_id_by_name(runtime, class_name, method_name);
int32_t is_class_method = env->api->runtime->get_method_is_class_method(runtime, method_id);
stack[0].ival = is_class_method;
return 0;
}
int32_t SPVM__Runtime__get_precompile_method_address(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
void* obj_method_name = stack[2].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// Class name
const char* class_name = env->get_chars(env, stack, obj_class_name);
// Method name
const char* method_name = env->get_chars(env, stack, obj_method_name);
// Method id
int32_t method_id = env->api->runtime->get_method_id_by_name(runtime, class_name, method_name);
void* address = env->api->runtime->get_precompile_method_address(runtime, method_id);
// Native address
void* obj_address = env->new_pointer_object_by_name(env, stack, "Native::Address", address, &e, __func__, FILE_NAME, __LINE__);
stack[0].oval = obj_address;
return 0;
}
int32_t SPVM__Runtime__set_precompile_method_address(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* obj_method_name = stack[2].oval;
const char* method_name = env->get_chars(env, stack, obj_method_name);
void* obj_address = stack[3].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// Method id
int32_t method_id = env->api->runtime->get_method_id_by_name(runtime, class_name, method_name);
// Native address
void* address = env->get_pointer(env, stack, obj_address);
env->api->runtime->set_precompile_method_address(runtime, method_id, address);
return 0;
}
int32_t SPVM__Runtime__build_precompile_class_source(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* runtime = env->get_pointer(env, stack, obj_self);
// New allocator
void* allocator = env->api->allocator->new_object();
// New string buffer
void* string_buffer = env->api->string_buffer->new_object(allocator, 0);
void* precompile = env->api->precompile->new_object();
env->api->precompile->set_runtime(precompile, runtime);
env->api->precompile->build_class_source(precompile, string_buffer, class_name);
env->api->precompile->free_object(precompile);
const char* string_buffer_value = env->api->string_buffer->get_value(string_buffer);
int32_t string_buffer_length = env->api->string_buffer->get_length(string_buffer);
void* obj_precompile_class_source = env->new_string(env, stack, string_buffer_value, string_buffer_length);
// Free string buffer
env->api->string_buffer->free_object(string_buffer);
// Free allocator
env->api->allocator->free_object(allocator);
stack[0].oval = obj_precompile_class_source;
return 0;
}
int32_t SPVM__Runtime__build_precompile_method_source(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* obj_method_name = stack[2].oval;
const char* method_name = env->get_chars(env, stack, obj_method_name);
void* runtime = env->get_pointer(env, stack, obj_self);
// New allocator
void* allocator = env->api->allocator->new_object();
// New string buffer
void* string_buffer = env->api->string_buffer->new_object(allocator, 0);
void* precompile = env->api->precompile->new_object();
env->api->precompile->set_runtime(precompile, runtime);
env->api->precompile->build_method_source(precompile, string_buffer, class_name, method_name);
env->api->precompile->free_object(precompile);
const char* string_buffer_value = env->api->string_buffer->get_value(string_buffer);
int32_t string_buffer_length = env->api->string_buffer->get_length(string_buffer);
void* obj_precompile_method_source = env->new_string(env, stack, string_buffer_value, string_buffer_length);
// Free string buffer
env->api->string_buffer->free_object(string_buffer);
// Free allocator
env->api->allocator->free_object(allocator);
stack[0].oval = obj_precompile_method_source;
return 0;
}
int32_t SPVM__Runtime__get_runtime_codes(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
// SPVM 32bit codes
int32_t* runtime_runtime_codes = env->api->runtime->get_runtime_codes(runtime);
int32_t runtime_codes_length = env->api->runtime->get_runtime_codes_length(runtime);
void* obj_runtime_codes = env->new_int_array(env, stack, runtime_codes_length);
int32_t* runtime_codes = env->get_elems_int(env, stack, obj_runtime_codes);
memcpy(runtime_codes, runtime_runtime_codes, sizeof(int32_t) * runtime_codes_length);
stack[0].oval = obj_runtime_codes;
return 0;
}
int32_t SPVM__Runtime__get_classes_length(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
int32_t classes_length = env->api->runtime->get_classes_length(runtime);
stack[0].ival = classes_length;
return 0;
}
int32_t SPVM__Runtime__get_class_names(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* runtime = env->get_pointer(env, stack, obj_self);
int32_t classes_length = env->api->runtime->get_classes_length(runtime);
void* obj_class_names = env->new_string_array(env, stack, classes_length);
for (int32_t class_id = 0; class_id < classes_length; class_id++) {
const char* class_name = env->api->runtime->get_name(runtime, env->api->runtime->get_class_name_id(runtime, class_id));
void* obj_class_name = env->new_string_nolen(env, stack, class_name);
env->set_elem_object(env, stack, obj_class_names, class_id, obj_class_name);
}
stack[0].oval = obj_class_names;
return 0;
}
int32_t SPVM__Runtime__get_module_file(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* runtime = env->get_pointer(env, stack, obj_self);
// Copy class load path to builder
int32_t class_id = env->api->runtime->get_class_id_by_name(runtime, class_name);
const char* module_file;
void* sv_module_file;
void* obj_module_file = NULL;
if (class_id >= 0) {
int32_t module_rel_file_id = env->api->runtime->get_class_module_rel_file_id(runtime, class_id);
int32_t module_dir_id = env->api->runtime->get_class_module_dir_id(runtime, class_id);
const char* module_dir = NULL;
const char* module_dir_sep;
if (module_dir_id >= 0) {
module_dir_sep = "/";
module_dir = env->api->runtime->get_constant_string_value(runtime, module_dir_id, NULL);
}
else {
module_dir_sep = "";
module_dir = "";
}
const char* module_rel_file = env->api->runtime->get_constant_string_value(runtime, module_rel_file_id, NULL);
int32_t module_file_length = strlen(module_dir) + strlen(module_dir_sep) + strlen(module_rel_file);
obj_module_file = env->new_string(env, stack, NULL, module_file_length);
char* module_file = (char*)env->get_chars(env, stack, obj_module_file);
memcpy(module_file, module_dir, strlen(module_dir));
memcpy(module_file + strlen(module_dir), module_dir_sep, strlen(module_dir_sep));
memcpy(module_file + strlen(module_dir) + strlen(module_dir_sep), module_rel_file, strlen(module_rel_file));
}
stack[0].oval = obj_module_file;
return 0;
}
int32_t SPVM__Runtime__get_parent_class_name(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* runtime = env->get_pointer(env, stack, obj_self);
int32_t class_id = env->api->runtime->get_class_id_by_name(runtime, class_name);
int32_t parent_class_id = env->api->runtime->get_class_parent_class_id(runtime, class_id);
void* obj_parent_class_name = NULL;
if (parent_class_id >= 0) {
int32_t parent_class_name_id = env->api->runtime->get_class_name_id(runtime, parent_class_id);
const char* parent_class_name = env->api->runtime->get_name(runtime, parent_class_name_id);
obj_parent_class_name = env->new_string_nolen(env, stack, parent_class_name);
}
stack[0].oval = obj_parent_class_name;
return 0;
}
int32_t SPVM__Runtime__get_anon_class_names(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
void* runtime = env->get_pointer(env, stack, obj_self);
int32_t class_id = env->api->runtime->get_class_id_by_name(runtime, class_name);
int32_t methods_length = env->api->runtime->get_class_methods_length(runtime, class_id);
int32_t anon_classes_length = 0;
for (int32_t method_index = 0; method_index < methods_length; method_index++) {
int32_t method_id = env->api->runtime->get_method_id_by_index(runtime, class_id, method_index);
int32_t is_anon_method = env->api->runtime->get_method_is_anon(runtime, method_id);
if (is_anon_method) {
anon_classes_length++;
}
}
void* obj_anon_class_names = env->new_string_array(env, stack, anon_classes_length);
int32_t anon_class_index = 0;
for (int32_t method_index = 0; method_index < methods_length; method_index++) {
int32_t method_id = env->api->runtime->get_method_id_by_index(runtime, class_id, method_index);
int32_t is_anon_method = env->api->runtime->get_method_is_anon(runtime, method_id);
if (is_anon_method) {
int32_t anon_class_id = env->api->runtime->get_method_class_id(runtime, method_id);
const char* anon_class_name = env->api->runtime->get_name(runtime, env->api->runtime->get_class_name_id(runtime, anon_class_id));
void* obj_anon_class_name = env->new_string_nolen(env, stack, anon_class_name);
env->set_elem_object(env, stack, obj_anon_class_names, anon_class_index, obj_anon_class_name);
anon_class_index++;
}
}
stack[0].oval = obj_anon_class_names;
return 0;
}
int32_t SPVM__Runtime___get_method_names(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_self = stack[0].oval;
void* obj_class_name = stack[1].oval;
const char* class_name = env->get_chars(env, stack, obj_class_name);
int32_t native_flag = stack[2].ival;
int32_t precompile_flag = stack[3].ival;
int32_t enum_flag = stack[4].ival;
void* runtime = env->get_pointer(env, stack, obj_self);
int32_t class_id = env->api->runtime->get_class_id_by_name(runtime, class_name);
int32_t methods_length = env->api->runtime->get_class_methods_length(runtime, class_id);
int32_t match_methodes_length = 0;
for (int32_t method_index = 0; method_index < methods_length; method_index++) {
int32_t method_id = env->api->runtime->get_method_id_by_index(runtime, class_id, method_index);
int32_t match = 0;
if (native_flag) {
if (env->api->runtime->get_method_is_native(runtime, method_id)) {
match = 1;
}
}
else if (precompile_flag) {
if (env->api->runtime->get_method_is_precompile(runtime, method_id)) {
match = 1;
}
}
else if (enum_flag) {
if (env->api->runtime->get_method_is_enum(runtime, method_id)) {
match = 1;
}
}
else {
match = 1;
}
if (match) {
match_methodes_length++;
}
}
void* obj_method_names = env->new_string_array(env, stack, match_methodes_length);
int32_t match_method_index = 0;
for (int32_t method_index = 0; method_index < methods_length; method_index++) {
int32_t method_id = env->api->runtime->get_method_id_by_index(runtime, class_id, method_index);
int32_t match = 0;
if (native_flag) {
if (env->api->runtime->get_method_is_native(runtime, method_id)) {
match = 1;
}
}
else if (precompile_flag) {
if (env->api->runtime->get_method_is_precompile(runtime, method_id)) {
match = 1;
}
}
else if (enum_flag) {
if (env->api->runtime->get_method_is_enum(runtime, method_id)) {
match = 1;
}
}
else {
match = 1;
}
if (match) {
const char* method_name = env->api->runtime->get_name(runtime, env->api->runtime->get_method_name_id(runtime, method_id));
void* obj_method_name = env->new_string_nolen(env, stack, method_name);
env->set_elem_object(env, stack, obj_method_names, match_method_index, obj_method_name);
match_method_index++;
}
}
stack[0].oval = obj_method_names;
return 0;
}
int32_t SPVM__Runtime__build_env(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t e = 0;
void* obj_runtime = stack[0].oval;
void* runtime = env->get_pointer(env, stack, obj_runtime);
SPVM_ENV* my_env = env->new_env_raw(env);
// Set runtime information
my_env->runtime = runtime;
// Initialize env
my_env->init_env(my_env);
void* obj_self= env->new_pointer_object_by_name(env, stack, "Env", my_env, &e, __func__, FILE_NAME, __LINE__);
if (e) { return e; }
env->set_field_object_by_name(env, stack, obj_self, "runtime", obj_runtime, &e, __func__, FILE_NAME, __LINE__);
if (e) { return e; }
stack[0].oval = obj_self;
return 0;
}