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

#ifndef SPVM_NATIVE_H
#define SPVM_NATIVE_H

#ifndef SPVM_NATIVE_NO_INCLUDE_HEADERS
/*
  This header file must not include any headers other than standard C headers to ensure it can be used standalone.
  
  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).
  
  If you need to use new types in function definitions, 
  consider using typedefs for pointer abstract types
  or using integer types (e.g., using int to represent errno_t). 
  
  Example of a pointer abstract type for strunct tm:
  
  struct spvm_native_ctype_tm;
  typedef struct spvm_native_ctype_tm SPVM_NATIVE_CTYPE_TM;
*/

  #include <stdint.h>
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <inttypes.h>
  #include <assert.h>
#endif

#ifndef SPVM_NATIVE_NO_VERSION_UTILITIES
  #define SPVM_NATIVE_VERSION_NUMBER 0.990196
  
  #define SPVM_NATIVE_CREATE_VERSION_STRING_STRINGIFY(x) #x
  
  #define SPVM_NATIVE_CREATE_VERSION_STRING(x) SPVM_NATIVE_CREATE_VERSION_STRING_STRINGIFY(x)
  
  #define SPVM_NATIVE_VERSION_STRING SPVM_NATIVE_CREATE_VERSION_STRING(SPVM_NATIVE_VERSION_NUMBER)
#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__)
#define spvm_diag(format, ...) spvm_warn(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;

struct spvm_api_cfunc;
typedef struct spvm_api_cfunc SPVM_API_CFUNC;

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);
  void (*push_caller_stack)(SPVM_ENV* env, SPVM_VALUE* stack, const char* func_name, const char* file, int32_t line);
  void (*pop_caller_stack)(SPVM_ENV* env, SPVM_VALUE* stack);
  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);
  void* reserved231;
  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 start_call_depth);
  SPVM_OBJ* (*build_exception_message)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t start_call_depth);
  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);
  const char* (*get_exception_chars)(SPVM_ENV* env, SPVM_VALUE* stack);
  int32_t (*get_error_id)(SPVM_ENV* env, SPVM_VALUE* stack);
  void (*set_error_id)(SPVM_ENV* env, SPVM_VALUE* stack, int32_t error_id);
  int32_t (*no_close)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object);
  void (*set_no_close)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* object, int32_t no_close);
  SPVM_OBJ* (*longmess_no_mortal)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_message, int32_t start_call_depth, int32_t end_call_depth);
  SPVM_OBJ* (*longmess)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* obj_message, int32_t start_call_depth, int32_t end_call_depth);
  void (*diag)(SPVM_ENV* env, SPVM_VALUE* stack, SPVM_OBJ* string, const char* func_name, const char* file, int32_t line);
};

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;
  SPVM_API_CFUNC* cfunc;
};

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_class_search_dirs_length )(SPVM_NATIVE_COMPILER* compiler);
  const char* (*get_class_search_dir)(SPVM_NATIVE_COMPILER* compiler, int32_t index);
  void (*add_class_search_dir)(SPVM_NATIVE_COMPILER* compiler, const char* class_search_dir);
  void (*clear_class_search_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_class_search_dir)(SPVM_NATIVE_COMPILER* compiler, const char* class_search_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);
};

struct spvm_api_cfunc {
  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,
  SPVM_NATIVE_C_BASIC_TYPE_ID_ERROR_FIELD_NOT_SPECIFIED_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,
};

SPVM_ENV* SPVM_NATIVE_new_env(void);

#endif
