// Copyright (c) 2023 Yuki Kimoto
// MIT License

#ifndef SPVM_NATIVE_H
#define SPVM_NATIVE_H

#ifndef SPVM_NATIVE_NO_INCLUDE_HEADERS
/*
    Do not reduce these headers. 
    When adding new headers, exercise extreme caution and ensure they are absolutely necessary.
    
    SPVM_NATIVE_NO_INCLUDE_HEADERS is defined in precompiled code
    because precompiled code cannnot contain #include and export for generating portable JIT code(LLVM, tcc, Mir, etc).
*/
  #include <stdint.h>
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <inttypes.h>
  #include <assert.h>
  #include "spvm_version.h"
  #include "spvm_builtin_expect.h"
#endif

struct spvm_native_allocator;
typedef struct spvm_native_allocator SPVM_NATIVE_ALLOCATOR;

struct spvm_native_string_buffer;
typedef struct spvm_native_string_buffer SPVM_NATIVE_STRING_BUFFER;

struct spvm_native_compiler;
typedef struct spvm_native_compiler SPVM_NATIVE_COMPILER;

struct spvm_native_class_file;
typedef struct spvm_native_class_file SPVM_NATIVE_CLASS_FILE;

struct spvm_native_runtime;
typedef struct spvm_native_runtime SPVM_NATIVE_RUNTIME;

struct spvm_native_basic_type;
typedef struct spvm_native_basic_type SPVM_NATIVE_BASIC_TYPE;

struct spvm_native_class_var;
typedef struct spvm_native_class_var SPVM_NATIVE_CLASS_VAR;

struct spvm_native_field;
typedef struct spvm_native_field SPVM_NATIVE_FIELD;

struct spvm_native_method;
typedef struct spvm_native_method SPVM_NATIVE_METHOD;

struct spvm_native_arg;
typedef struct spvm_native_arg SPVM_NATIVE_ARG;

struct spvm_native_mutex;
typedef struct spvm_native_mutex SPVM_NATIVE_MUTEX;

struct spvm_native_opcode;
typedef struct spvm_native_opcode SPVM_NATIVE_OPCODE;

struct spvm_obj;
typedef struct spvm_obj SPVM_OBJ;

struct spvm_ref;
typedef struct spvm_ref SPVM_REF;

#define SPVM_NATIVE_GET_POINTER(object) (*(void**)object)

#define SPVM_NATIVE_SET_POINTER(object, pointer) (*(void**)object = pointer)

/*
 * spvm_warnf and spvm_warn macros
 * * These macros provide a way to print formatted warning messages to a stream (or stderr),
 * including the function name, file name, and line number.
 * * Special care is taken for MSVC's traditional preprocessor which handles __VA_ARGS__ 
 * as a single token. The SPVM_EXPAND macro forces a rescan of arguments to correctly
 * separate them for fprintf.
 */

#if defined(_MSC_VER) && defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL
  /* Support for MSVC Traditional Preprocessor (without -Zc:preprocessor) */
  #define SPVM_EXPAND(x) x
  #define spvm_warnf(stream, format, ...) \
    SPVM_EXPAND(fprintf(stream, format "\n  %s at %s line %d\n", __VA_ARGS__, __func__, __FILE__, __LINE__))
#else
  /* Support for GCC, Clang, and Modern MSVC (with -Zc:preprocessor) */
  /* The ##__VA_ARGS__ extension handles cases where the variable arguments are empty. */
  #define spvm_warnf(stream, format, ...) fprintf(stream, format "\n  %s at %s line %d\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__)
#endif

/* Standard warning macro pointing to stderr */
#define spvm_warn(format, ...) spvm_warnf(stderr, format, ##__VA_ARGS__)

typedef union spvm_value SPVM_VALUE;

struct spvm_env;
typedef struct spvm_env SPVM_ENV;

struct spvm_env_api;
typedef struct spvm_env_api SPVM_ENV_API;

struct spvm_api_allocator;
typedef struct spvm_api_allocator SPVM_API_ALLOCATOR;

struct spvm_api_string_buffer;
typedef struct spvm_api_string_buffer SPVM_API_STRING_BUFFER;

struct spvm_api_compiler;
typedef struct spvm_api_compiler SPVM_API_COMPILER;

struct spvm_api_class_file;
typedef struct spvm_api_class_file SPVM_API_CLASS_FILE;

struct spvm_api_runtime;
typedef struct spvm_api_runtime SPVM_API_RUNTIME;

struct spvm_api_basic_type;
typedef struct spvm_api_basic_type SPVM_API_BASIC_TYPE;

struct spvm_api_class_var;
typedef struct spvm_api_class_var SPVM_API_CLASS_VAR;

struct spvm_api_field;
typedef struct spvm_api_field SPVM_API_FIELD;

struct spvm_api_method;
typedef struct spvm_api_method SPVM_API_METHOD;

struct spvm_api_arg;
typedef struct spvm_api_arg SPVM_API_ARG;

struct spvm_api_mutex;
typedef struct spvm_api_mutex SPVM_API_MUTEX;

struct spvm_api_type;
typedef struct spvm_api_type SPVM_API_TYPE;

struct spvm_api_internal;
typedef struct spvm_api_internal SPVM_API_INTERNAL;

union spvm_value {
  int8_t bval;
  int16_t sval;
  int32_t ival;
  int64_t lval;
  float fval;
  double dval;
  SPVM_OBJ* oval;
  SPVM_REF* ref;
  void* address;
  int8_t* bref;
  int16_t* sref;
  int32_t* iref;
  int64_t* lref;
  float* fref;
  double* dref;
};







struct spvm_env {
  SPVM_NATIVE_RUNTIME* runtime;
  SPVM_ENV_API* api;
  SPVM_ENV* (*new_env)(void);
  void (*free_env)(SPVM_ENV* env);
  int32_t (*call_init_methods)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*set_command_info_program_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_program_name);
  int32_t (*set_command_info_argv)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_argv);
  int32_t (*set_command_info_basetime)(SPVM_ENV* env, SPVM_VALUE* stack, int64_t base_time);
  void (*destroy_class_vars)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*args_width)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_NATIVE_BASIC_TYPE* (*get_object_basic_type)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*get_object_basic_type_id)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  const char* (*get_object_basic_type_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*get_object_type_dimension)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type_by_id)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t basic_type_id);
  int32_t (*get_basic_type_id)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name);
  int32_t (*get_basic_type_id_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_NATIVE_CLASS_VAR* (*get_class_var)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name);
  int8_t (*get_class_var_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  int16_t (*get_class_var_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  int32_t (*get_class_var_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  int64_t (*get_class_var_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  float (*get_class_var_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  double (*get_class_var_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  SPVM_OBJ* (*get_class_var_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  SPVM_OBJ* (*get_class_var_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  void (*set_class_var_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, int8_t value);
  void (*set_class_var_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, int16_t value);
  void (*set_class_var_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, int32_t value);
  void (*set_class_var_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, int64_t value);
  void (*set_class_var_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, float value);
  void (*set_class_var_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, double value);
  void (*set_class_var_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, SPVM_OBJ* value);
  void (*set_class_var_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var, SPVM_OBJ* value);
  SPVM_OBJ** (*get_class_var_object_ref)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_CLASS_VAR* class_var);
  int8_t (*get_class_var_byte_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int16_t (*get_class_var_short_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int32_t (*get_class_var_int_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int64_t (*get_class_var_long_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  float (*get_class_var_float_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  double (*get_class_var_double_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*get_class_var_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*get_class_var_string_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_byte_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int8_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_short_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int16_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_int_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int32_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_long_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, int64_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_float_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, float value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_double_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, double value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, SPVM_OBJ* value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_class_var_string_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* class_var_name, SPVM_OBJ* value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_NATIVE_FIELD* (*get_field)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name);
  SPVM_NATIVE_FIELD* (*get_field_static)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* field_name);
  int8_t (*get_field_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  int16_t (*get_field_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  int32_t (*get_field_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  int64_t (*get_field_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  float (*get_field_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  double (*get_field_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  SPVM_OBJ* (*get_field_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  SPVM_OBJ* (*get_field_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  void (*set_field_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, int8_t value);
  void (*set_field_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, int16_t value);
  void (*set_field_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, int32_t value);
  void (*set_field_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, int64_t value);
  void (*set_field_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, float value);
  void (*set_field_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, double value);
  void (*set_field_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, SPVM_OBJ* value);
  void (*set_field_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field, SPVM_OBJ* value);
  int8_t (*get_field_byte_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int16_t (*get_field_short_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int32_t (*get_field_int_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int64_t (*get_field_long_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  float (*get_field_float_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  double (*get_field_double_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*get_field_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*get_field_string_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_byte_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int8_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_short_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int16_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_int_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_long_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int64_t value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_float_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, float value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_double_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, double value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, SPVM_OBJ* value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*set_field_string_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, SPVM_OBJ* value, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  const char* (*get_field_string_chars_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_NATIVE_METHOD* (*get_method)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name);
  SPVM_NATIVE_METHOD* (*get_class_method)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name);
  SPVM_NATIVE_METHOD* (*get_instance_method_static)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name);
  SPVM_NATIVE_METHOD* (*get_instance_method)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* method_name);
  int32_t (*call_method_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_METHOD* method, int32_t args_width, const char* func_name, const char* file, int32_t line);
  int32_t (*call_method)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_METHOD* method, int32_t args_width, const char* func_name, const char* file, int32_t line);
  void (*call_class_method_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*call_instance_method_static_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*call_instance_method_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* method_name, int32_t args_width, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*new_object_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_OBJ* (*new_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_OBJ* (*new_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*new_pointer_object_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, void* pointer);
  SPVM_OBJ* (*new_pointer_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, void* pointer);
  SPVM_OBJ* (*new_pointer_object_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, void* pointer, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void* (*get_pointer)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*set_pointer)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, void* pointer);
  SPVM_OBJ* (*new_string_nolen_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes);
  SPVM_OBJ* (*new_string_nolen)(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes);
  SPVM_OBJ* (*new_string_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes, int32_t length);
  SPVM_OBJ* (*new_string)(SPVM_ENV* env, SPVM_VALUE* stack, const char* bytes, int32_t length);
  SPVM_OBJ* (*new_byte_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_byte_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_short_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_short_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_int_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_int_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_long_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_long_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_float_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_float_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_double_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_double_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_object_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t length);
  SPVM_OBJ* (*new_object_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t length);
  SPVM_OBJ* (*new_object_array_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*new_string_array)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  SPVM_OBJ* (*new_muldim_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t length);
  SPVM_OBJ* (*new_muldim_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t length);
  SPVM_OBJ* (*new_muldim_array_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*new_mulnum_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t length);
  SPVM_OBJ* (*new_mulnum_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t length);
  SPVM_OBJ* (*new_mulnum_array_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t length, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*new_array_proto_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t length);
  SPVM_OBJ* (*new_array_proto)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t length);
  int32_t (*length)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int8_t* (*get_elems_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  int16_t* (*get_elems_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  int32_t* (*get_elems_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  int64_t* (*get_elems_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  float* (*get_elems_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  double* (*get_elems_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  SPVM_OBJ* (*get_elem_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t index);
  SPVM_OBJ* (*get_elem_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t index);
  void (*set_elem_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t index, SPVM_OBJ* object);
  void (*set_elem_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, int32_t index, SPVM_OBJ* string);
  const char* (*get_chars)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string_object);
  int32_t (*get_bool_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* bool_object);
  SPVM_OBJ* (*concat_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string1, SPVM_OBJ* string2);
  SPVM_OBJ* (*concat)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string1, SPVM_OBJ* string2);
  void (*shorten)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string, int32_t new_length);
  void (*make_read_only)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  int32_t (*is_read_only)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  void (*print)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  void (*print_stderr)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  SPVM_OBJ* (*dump_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_OBJ* (*dump)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  const char* (*dumpc)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_OBJ* (*copy_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_OBJ* (*copy)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  const char* (*get_spvm_version_string)(SPVM_ENV* env, SPVM_VALUE* stack);
  double (*get_spvm_version_number)(SPVM_ENV* env, SPVM_VALUE* stack);
  const char* (*get_version_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type);
  double (*get_version_number)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*die)(SPVM_ENV* env, SPVM_VALUE* stack, const char* exception_format, const char* func_name, const char* file, int32_t line, ...);
  SPVM_OBJ* (*get_exception)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*set_exception)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* exception);
  SPVM_OBJ* (*new_stack_trace_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* exception, SPVM_NATIVE_METHOD* method, int32_t line);
  SPVM_OBJ* (*new_stack_trace)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* exception, SPVM_NATIVE_METHOD* method, int32_t line);
  int32_t (*is_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_class)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_pointer_class)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_object_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_numeric_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_mulnum_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*isa)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension);
  int32_t (*isa_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* basic_type_name, int32_t type_dimension);
  int32_t (*is_type)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension);
  int32_t (*is_type_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* basic_type_name, int32_t type_dimension);
  int32_t (*elem_isa)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array, SPVM_OBJ* element);
  int32_t (*get_elem_size)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* array);
  SPVM_OBJ* (*get_type_name_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_OBJ* (*get_type_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  SPVM_OBJ* (*get_compile_type_name_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t type_flag);
  SPVM_OBJ* (*get_compile_type_name)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name, int32_t type_dimension, int32_t type_flag);
  int32_t (*enter_scope)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*leave_scope)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t mortal_stack_top);
  int32_t (*push_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*weaken)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ** object_address);
  int32_t (*isweak)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ** object);
  void (*unweaken)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ** object_address);
  SPVM_OBJ* (*strerror_string)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value, int32_t length);
  SPVM_OBJ* (*strerror_string_nolen)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value);
  const char* (*strerror)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value, int32_t length);
  const char* (*strerror_nolen)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t errno_value);
  int32_t (*is_binary_compatible_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_binary_compatible_stack)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_VALUE* (*new_stack)(SPVM_ENV* env);
  void (*free_stack)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_OBJ* (*get_field_object_defined_and_has_pointer_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file_name, int32_t line);
  SPVM_OBJ** (*get_field_object_ref)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  SPVM_OBJ** (*get_field_object_ref_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  int32_t (*check_bootstrap_method)(SPVM_ENV* env, SPVM_VALUE* stack, const char* basic_type_name);
  void (*assign_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ** dist_ref, SPVM_OBJ* object);
  SPVM_OBJ* (*new_string_array_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t length);
  void* (*new_memory_block)(SPVM_ENV* env, SPVM_VALUE* stack, size_t size);
  void (*free_memory_block)(SPVM_ENV* env, SPVM_VALUE* stack, void* block);
  int32_t (*get_memory_blocks_count)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*say)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  void (*warn)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string, const char* func_name, const char* file, int32_t line);
  FILE* (*spvm_stdin)(SPVM_ENV* env, SPVM_VALUE* stack);
  FILE* (*spvm_stdout)(SPVM_ENV* env, SPVM_VALUE* stack);
  FILE* (*spvm_stderr)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_OBJ* (*new_array_proto_element_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* element, int32_t length);
  SPVM_OBJ* (*new_array_proto_element)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* element, int32_t length);
  int32_t (*get_byte_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* byte_object);
  int32_t (*get_short_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* short_object);
  int32_t (*get_int_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* int_object);
  int64_t (*get_long_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* long_object);
  float (*get_float_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* float_object);
  double (*get_double_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* double_object);
  int32_t (*no_free)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*set_no_free)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t no_free);
  char* (*get_stack_tmp_buffer)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*print_exception_to_stderr)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_OBJ* (*dump_object_internal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*get_seed)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*set_seed)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t seed);
  int32_t (*seed_initialized)(SPVM_ENV* env, SPVM_VALUE* stack);
  const char* (*get_basic_type_name_in_version_from)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*set_command_info_warning)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t warning);
  void (*destroy_cache_class_vars)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_VALUE* (*new_stack_with_all_method_call_permitted)(SPVM_ENV* env);
  int32_t (*call_instance_method_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, const char* method_name, int32_t args_width);
  int32_t (*call_instance_method)(SPVM_ENV* env, SPVM_VALUE* stack, const char* method_name, int32_t args_width);
  int32_t (*call_method_no_mortal_no_check_args)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_METHOD* method, int32_t args_width, const char* func_name, const char* file_name, int32_t line);
  int32_t (*call_instance_method_no_mortal_less_check_args)(SPVM_ENV* env, SPVM_VALUE* stack, const char* method_name, int32_t args_width, const char* decl_args_signature, const char* func_name, const char* file_name, int32_t line);
  void (*enable_options)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*disable_options)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_options)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_any_object_array)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*exists_field)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  int32_t (*exists_field_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*delete_field)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, SPVM_NATIVE_FIELD* field);
  void (*delete_field_by_name)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, const char* field_name, int32_t* error_id, const char* func_name, const char* file, int32_t line);
  void (*make_fixed_length)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*is_fixed_length)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*set_length)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t length);
  int32_t (*capacity)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  int32_t (*set_capacity)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t capacity);
  int8_t (*numeric_object_to_byte)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  int16_t (*numeric_object_to_short)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  int32_t (*numeric_object_to_int)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  int64_t (*numeric_object_to_long)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  float (*numeric_object_to_float)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  double (*numeric_object_to_double)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  SPVM_OBJ* (*numeric_object_to_string_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  SPVM_OBJ* (*numeric_object_to_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t* error_id);
  int32_t (*is_numeric_object)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*say_stderr)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string);
  int32_t (*get_call_depth)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_VALUE* (*get_caller_info_stack)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*get_caller_info_stack_record_size)(SPVM_ENV* env, SPVM_VALUE* stack);
  SPVM_NATIVE_METHOD* (*get_current_method)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t level, int32_t* error_id);
  SPVM_OBJ* (*caller_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t level, int32_t* error_id);
  SPVM_OBJ* (*caller)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t level, int32_t* error_id);
  int32_t (*die_with_string)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_exception, const char* func_name, const char* file, int32_t line);
  SPVM_OBJ* (*build_exception_message_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t level);
  SPVM_OBJ* (*build_exception_message)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t level);
  int32_t (*call_end_methods)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*is_utf8)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_string, int32_t* error_id);
  void (*set_byte_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* byte_object, int8_t value);
  void (*set_short_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* short_object, int16_t value);
  void (*set_int_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* int_object, int32_t value);
  void (*set_long_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* long_object, int64_t value);
  void (*set_float_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* float_object, float value);
  void (*set_double_object_value)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* double_object, double value);
};

struct spvm_env_api {
  SPVM_API_ALLOCATOR* allocator;
  SPVM_API_STRING_BUFFER* string_buffer;
  SPVM_API_COMPILER* compiler;
  SPVM_API_CLASS_FILE* class_file;
  SPVM_API_RUNTIME* runtime;
  SPVM_API_BASIC_TYPE* basic_type;
  SPVM_API_CLASS_VAR* class_var;
  SPVM_API_FIELD* field;
  SPVM_API_METHOD* method;
  SPVM_API_ARG* arg;
  SPVM_API_TYPE* type;
  SPVM_API_INTERNAL* internal;
  SPVM_API_MUTEX* mutex;
};

struct spvm_api_allocator {
  SPVM_NATIVE_ALLOCATOR* (*new_instance)(void);
  void (*free_instance)(SPVM_NATIVE_ALLOCATOR* allocator);
};

struct spvm_api_arg {
  const char* (*get_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  int32_t (*get_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  int32_t (*get_type_dimension)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  int32_t (*get_type_flag)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  int32_t (*get_stack_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  SPVM_NATIVE_METHOD* (*get_current_method)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  int32_t (*is_optional)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
  SPVM_VALUE (*get_default_value)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_ARG* arg);
};

struct spvm_api_basic_type {
  const char* (*get_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*get_id)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*get_category)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_BASIC_TYPE* (*get_parent)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  const char* (*get_version_string)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  const char* (*get_class_dir)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  const char* (*get_class_rel_file)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*is_pointer)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*is_anon)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_CLASS_VAR* (*get_class_var_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t class_var_index);
  SPVM_NATIVE_CLASS_VAR* (*get_class_var_by_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, const char* class_var_name);
  int32_t (*get_class_vars_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_FIELD* (*get_field_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t field_index);
  SPVM_NATIVE_FIELD* (*get_field_by_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, const char* field_name);
  int32_t (*get_fields_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_METHOD* (*get_method_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t method_index);
  SPVM_NATIVE_METHOD* (*get_method_by_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, const char* method_name);
  int32_t (*get_methods_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_BASIC_TYPE* (*get_anon_basic_type_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t anon_basic_type_index);
  int32_t (*get_anon_basic_types_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*has_interface)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, SPVM_NATIVE_BASIC_TYPE* interface_basic_type);
  int32_t (*is_super_class)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* dist_basic_type, SPVM_NATIVE_BASIC_TYPE* src_basic_type);
  const char* (*get_file)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_RUNTIME* (*get_current_runtime)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type_in_version_from)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*get_fields_size)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*get_monitor_var_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t* ret_basic_type_id, int32_t* ret_dimension, int32_t* ret_flag);
  int32_t (*has_monitor_var)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
  int32_t (*is_generated_from_anon_method)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type);
};

struct spvm_api_class_file {
  const char* (*get_class_name)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  const char* (*get_file)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  void (*set_file)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file, const char* file);
  const char* (*get_dir)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  void (*set_dir)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file, const char* dir);
  const char* (*get_rel_file)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  void (*set_rel_file)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file, const char* rel_file);
  const char* (*get_content)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  void (*set_content)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file, const char* content);
  int32_t (*get_content_length)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file);
  void (*set_content_length)(SPVM_NATIVE_COMPILER* compiler, SPVM_NATIVE_CLASS_FILE* class_file, int32_t content_length);
};

struct spvm_api_class_var {
  const char* (*get_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  int32_t (*get_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  int32_t (*get_type_dimension)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  int32_t (*get_type_flag)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  SPVM_NATIVE_BASIC_TYPE* (*get_current_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
  int32_t (*is_cache)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_CLASS_VAR* class_var);
};

struct spvm_api_compiler {
  SPVM_NATIVE_COMPILER* (*new_instance)(void);
  void (*free_instance)(SPVM_NATIVE_COMPILER* compiler);
  int32_t (*get_start_line)(SPVM_NATIVE_COMPILER* compiler);
  void (*set_start_line)(SPVM_NATIVE_COMPILER* compiler, int32_t start_line);
  const char* (*get_start_file)(SPVM_NATIVE_COMPILER* compiler);
  void (*set_start_file)(SPVM_NATIVE_COMPILER* compiler, const char* start_file);
  int32_t (*get_include_dirs_length )(SPVM_NATIVE_COMPILER* compiler);
  const char* (*get_include_dir )(SPVM_NATIVE_COMPILER* compiler, int32_t index);
  void (*add_include_dir)(SPVM_NATIVE_COMPILER* compiler, const char* include_dir);
  void (*clear_include_dirs)(SPVM_NATIVE_COMPILER* compiler);
  void (*add_class_file)(SPVM_NATIVE_COMPILER* compiler, const char* class_name);
  void (*delete_class_file)(SPVM_NATIVE_COMPILER* compiler, const char* class_name);
  SPVM_NATIVE_CLASS_FILE* (*get_class_file)(SPVM_NATIVE_COMPILER* compiler, const char* class_name);
  int32_t (*compile)(SPVM_NATIVE_COMPILER* compiler, const char* basic_type_name);
  const char* (*get_error_message)(SPVM_NATIVE_COMPILER* compiler, int32_t index);
  int32_t (*get_error_messages_length)(SPVM_NATIVE_COMPILER* compiler);
  SPVM_NATIVE_RUNTIME* (*get_runtime)(SPVM_NATIVE_COMPILER* compiler);
  void (*prepend_include_dir)(SPVM_NATIVE_COMPILER* compiler, const char* include_dir);
  int32_t (*compile_anon_class)(SPVM_NATIVE_COMPILER* compiler, const char* source, const char** anon_basic_type_name_ptr);
  int32_t (*compile_script)(SPVM_NATIVE_COMPILER* compiler, const char* source, const char** anon_basic_type_name_ptr);
};

struct spvm_api_field {
  const char* (*get_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_offset)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_type_dimension)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_type_flag)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  SPVM_NATIVE_BASIC_TYPE* (*get_current_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_exists_offset)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
  int32_t (*get_exists_bit)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_FIELD* field);
};

struct spvm_api_method {
  const char* (*get_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  SPVM_NATIVE_BASIC_TYPE* (*get_return_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_return_type_dimension)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_return_type_flag)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  SPVM_NATIVE_ARG* (*get_arg_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method, int32_t arg_index);
  int32_t (*get_args_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_required_args_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  SPVM_NATIVE_BASIC_TYPE* (*get_current_basic_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  SPVM_NATIVE_OPCODE* (*get_opcode_by_index)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method, int32_t opcode_index);
  int32_t (*get_opcodes_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*is_class_method)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*is_anon)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*is_native)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*is_precompile)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*is_enum)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_byte_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_short_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_int_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_long_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_float_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_double_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_object_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_ref_vars_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  int32_t (*get_mortal_stack_length)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  void* (*get_native_address)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  void (*set_native_address)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method, void* address);
  void* (*get_precompile_address)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  void (*set_precompile_address)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method, void* address);
  int32_t (*is_precompile_fallback)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  void (*set_is_precompile_fallback)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method, int32_t is_precompile_fallback);
  const char* (*get_args_signature)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
  const char* (*get_abs_name)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_METHOD* method);
};

struct spvm_api_runtime {
  int32_t (*get_object_data_offset)(SPVM_NATIVE_RUNTIME* runtime);
  int32_t (*get_object_ref_count_offset)(SPVM_NATIVE_RUNTIME* runtime);
  int32_t (*get_object_length_offset)(SPVM_NATIVE_RUNTIME* runtime);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type_by_id)(SPVM_NATIVE_RUNTIME* runtime, int32_t basic_type_id);
  SPVM_NATIVE_BASIC_TYPE* (*get_basic_type_by_name)(SPVM_NATIVE_RUNTIME* runtime, const char* basic_type_name);
  int32_t (*get_basic_types_length)(SPVM_NATIVE_RUNTIME* runtime);
  void (*build_precompile_class_source)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_STRING_BUFFER* string_buffer, SPVM_NATIVE_BASIC_TYPE* module_basic_type);
  void (*build_precompile_method_source)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_STRING_BUFFER* string_buffer, SPVM_NATIVE_METHOD* method);
  SPVM_NATIVE_COMPILER* (*get_compiler)(SPVM_NATIVE_RUNTIME* runtime);
  void (*set_compiler)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_COMPILER* compiler);
  FILE* (*get_spvm_stdin)(SPVM_NATIVE_RUNTIME* runtime);
  FILE* (*get_spvm_stdout)(SPVM_NATIVE_RUNTIME* runtime);
  FILE* (*get_spvm_stderr)(SPVM_NATIVE_RUNTIME* runtime);
  SPVM_ENV* (*get_env)(SPVM_NATIVE_RUNTIME* runtime);
  int32_t (*get_object_capacity_offset)(SPVM_NATIVE_RUNTIME* runtime);
  void* method_begin_cb;
  void* method_end_cb;
  void* object_data_offset;
  void* object_length_offset;
  void* object_capacity_offset;
  void* stack_index_call_depth;
  void* stack_index_caller_info_stack;
  void* stack_index_caller_info_stack_record_size;
};

struct spvm_api_mutex {
  SPVM_NATIVE_MUTEX* (*new_instance)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*free_instance)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_MUTEX* mutex);
  void (*lock)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_MUTEX* mutex);
  void (*unlock)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_MUTEX* mutex);
  void (*reader_lock)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_MUTEX* mutex);
  void (*reader_unlock)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_NATIVE_MUTEX* mutex);
};

struct spvm_api_string_buffer {
  SPVM_NATIVE_STRING_BUFFER* (*new_instance)(SPVM_NATIVE_ALLOCATOR* allocator, int32_t capacity);
  void (*free_instance)(SPVM_NATIVE_STRING_BUFFER* string_buffer);
  const char* (*get_string)(SPVM_NATIVE_STRING_BUFFER* string_buffer);
  int32_t (*get_length)(SPVM_NATIVE_STRING_BUFFER* string_buffer);
};

struct spvm_api_internal {
  int32_t (*get_ref_count)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*inc_ref_count)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*dec_ref_count)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  char* (*get_stack_tmp_buffer)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*leave_scope_local)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ** object_vars, int32_t* mortal_stack_typed_var_index, int32_t* mortal_stack_top_ptr, int32_t* mortal_stack_tops, int32_t mortal_stack_tops_index);
  size_t (*c_strlen)(SPVM_ENV* env, SPVM_VALUE* stack, const char* str);
  void* (*c_memcpy)(SPVM_ENV* env, SPVM_VALUE* stack, void* dest, const void* src, size_t n);
  void* (*c_memset)(SPVM_ENV* env, SPVM_VALUE* stack, void* s, int c, size_t n);
  int (*c_memcmp)(SPVM_ENV* env, SPVM_VALUE* stack, const void* s1, const void* s2, size_t n);
  long long (*c_strtoll)(SPVM_ENV* env, SPVM_VALUE* stack, const char* str, char** endptr, int base);
  float (*c_strtof)(SPVM_ENV* env, SPVM_VALUE* stack, const char* str, char** endptr);
  double (*c_strtod)(SPVM_ENV* env, SPVM_VALUE* stack, const char* str, char** endptr);
  int (*c_fputs)(SPVM_ENV* env, SPVM_VALUE* stack, const char* s, void* stream);
  int (*c_fgetc)(SPVM_ENV* env, SPVM_VALUE* stack, void* stream);
  int (*c_snprintf_len)(SPVM_ENV* env, SPVM_VALUE* stack, char* str, size_t size, const char* format, SPVM_VALUE* args, int32_t args_length);
};

struct spvm_api_type {
  int32_t (*can_assign)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* dist_basic_type, int32_t dist_type_dimension, int32_t dist_type_flag, SPVM_NATIVE_BASIC_TYPE* src_basic_type, int32_t src_type_dimension, int32_t src_type_flag);
  int32_t (*get_type_width)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_object_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_any_object_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_object_array_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_any_object_array_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_numeric_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
  int32_t (*is_class_type)(SPVM_NATIVE_RUNTIME* runtime, SPVM_NATIVE_BASIC_TYPE* basic_type, int32_t type_dimension, int32_t type_flag);
};

enum {
  SPVM_NATIVE_C_BASIC_TYPE_ID_UNKNOWN,
  SPVM_NATIVE_C_BASIC_TYPE_ID_UNDEF,
  SPVM_NATIVE_C_BASIC_TYPE_ID_VOID,
  SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE,
  SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT,
  SPVM_NATIVE_C_BASIC_TYPE_ID_INT,
  SPVM_NATIVE_C_BASIC_TYPE_ID_LONG,
  SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT,
  SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE,
  SPVM_NATIVE_C_BASIC_TYPE_ID_STRING,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ANY_OBJECT,
  SPVM_NATIVE_C_BASIC_TYPE_ID_BYTE_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_SHORT_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_INT_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_LONG_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_BOOL_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_SYSTEM_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_NOT_SUPPORTED_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_COMMAND_INFO_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ADDRESS_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_COMPILE_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_SPVM_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_METHOD_CALL_NOT_PERMITTED_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_STRINGABLE_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_COUNTABLE_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_CALLER_INFO_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_ID_CLONEABLE_CLASS,
};

enum {
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_UNKNOWN,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_UNDEF,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_VOID,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_NUMERIC,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_STRING,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE,
  SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_ANY_OBJECT,
};

enum {
  SPVM_NATIVE_C_TYPE_FLAG_REF = 1,
  SPVM_NATIVE_C_TYPE_FLAG_MUTABLE = 2,
  SPVM_NATIVE_C_TYPE_FLAG_VARARGS = 4,
};

enum {
  SPVM_NATIVE_C_STACK_TMP_BUFFER_SIZE = 512,
};

// These functions are linked only by SPVM itself,
// so native classes cannot use these functions.
SPVM_ENV* SPVM_NATIVE_new_env(void);

#endif
