#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include "spvm_compiler.h"
#include "spvm_type.h"
#include "spvm_class.h"
#include "spvm_type.h"
#include "spvm_op.h"
#include "spvm_hash.h"
#include "spvm_list.h"
#include "spvm_allocator.h"
#include "spvm_yacc_util.h"
#include "spvm_list.h"
#include "spvm_opcode_array.h"
#include "spvm_method.h"
#include "spvm_method.h"
#include "spvm_field.h"
#include "spvm_class_var.h"
#include "spvm_native.h"
#include "spvm_opcode.h"
#include "spvm_basic_type.h"
#include "spvm_use.h"
#include "spvm_op_checker.h"
#include "spvm_opcode_builder.h"
#include "spvm_object.h"
#include "spvm_my.h"
#include "spvm_string_buffer.h"
#include "spvm_allow.h"
#include "spvm_implement.h"
#include "spvm_class_var_access.h"
#include "spvm_constant.h"
#include "spvm_array_field_access.h"
#include "spvm_field_access.h"
#include "spvm_call_method.h"
#include "spvm_var.h"
#include "spvm_string.h"
#include "spvm_runtime_basic_type.h"
#include "spvm_runtime_class.h"
#include "spvm_runtime_class_var.h"
#include "spvm_runtime_field.h"
#include "spvm_runtime_info.h"
#include "spvm_runtime_manager.h"
#include "spvm_runtime_method.h"
#include "spvm_runtime_string.h"
#include "spvm_runtime_type.h"
SPVM_COMPILER* SPVM_COMPILER_new() {
SPVM_COMPILER* compiler = SPVM_ALLOCATOR_alloc_memory_block_unmanaged(
sizeof
(SPVM_COMPILER));
SPVM_ALLOCATOR* allocator = SPVM_ALLOCATOR_new();
compiler->allocator = allocator;
compiler->bufptr =
""
;
compiler->strings = SPVM_LIST_new_list_permanent(compiler->allocator, 128);
compiler->string_symtable = SPVM_HASH_new_hash_permanent(compiler->allocator, 128);
compiler->string_buffer = SPVM_STRING_BUFFER_new(compiler->allocator, 8192, SPVM_ALLOCATOR_C_ALLOC_TYPE_PERMANENT);
compiler->module_dirs = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->types = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->type_symtable = SPVM_HASH_new_hash_permanent(compiler->allocator, 0);
compiler->basic_types = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->basic_type_symtable = SPVM_HASH_new_hash_permanent(compiler->allocator, 0);
compiler->methods = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->args = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->fields = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->classes = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->class_symtable = SPVM_HASH_new_hash_permanent(compiler->allocator, 0);
compiler->class_vars = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
compiler->opcode_array = SPVM_OPCODE_ARRAY_new(compiler);
compiler->module_source_symtable = SPVM_HASH_new_hash_permanent(compiler->allocator, 0);
compiler->switch_infos = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
SPVM_COMPILER_add_basic_types(compiler);
const
char
* spvm_bool_module_source =
"class Bool {\n INIT {\n $TRUE = new Bool;\n $TRUE->{value} = 1;\n $FALSE = new Bool;\n $FALSE->{value} = 0;\n }\n \n our $TRUE : ro Bool;\n our $FALSE : ro Bool;\n has value : ro int;\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Bool"
,
strlen
(
"Bool"
), (
void
*)spvm_bool_module_source);
const
char
* spvm_byte_module_source =
"class Byte {\n has value : ro byte;\n static method new : Byte ($value : byte) {\n my $self = new Byte;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Byte"
,
strlen
(
"Byte"
), (
void
*)spvm_byte_module_source);
const
char
* spvm_short_module_source =
"class Short {\n has value : ro short;\n static method new : Short ($value : short) {\n my $self = new Short;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Short"
,
strlen
(
"Short"
), (
void
*)spvm_short_module_source);
const
char
* spvm_int_module_source =
"class Int {\n has value : ro int;\n static method new : Int ($value : int) {\n my $self = new Int;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Int"
,
strlen
(
"Int"
), (
void
*)spvm_int_module_source);
const
char
* spvm_long_module_source =
"class Long {\n has value : ro long;\n static method new : Long ($value : long) {\n my $self = new Long;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Long"
,
strlen
(
"Long"
), (
void
*)spvm_long_module_source);
const
char
* spvm_float_module_source =
"class Float {\n has value : ro float;\n static method new : Float ($value : float) {\n my $self = new Float;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Float"
,
strlen
(
"Float"
), (
void
*)spvm_float_module_source);
const
char
* spvm_double_module_source =
"class Double {\n has value : ro double;\n static method new : Double ($value : double) {\n my $self = new Double;\n $self->{value} = $value;\n return $self;\n }\n}"
;
SPVM_HASH_insert(compiler->module_source_symtable,
"Double"
,
strlen
(
"Double"
), (
void
*)spvm_double_module_source);
return
compiler;
}
void
SPVM_COMPILER_add_basic_type(SPVM_COMPILER* compiler, int32_t basic_type_id) {
SPVM_BASIC_TYPE* basic_type = SPVM_BASIC_TYPE_new(compiler);
basic_type->id = basic_type_id;
const
char
* basic_type_name_tmp = (SPVM_BASIC_TYPE_C_ID_NAMES())[basic_type->id];
SPVM_STRING* basic_type_name_string = SPVM_STRING_new(compiler, basic_type_name_tmp,
strlen
(basic_type_name_tmp));
basic_type->name = basic_type_name_string->value;
SPVM_LIST_push(compiler->basic_types, basic_type);
SPVM_HASH_insert(compiler->basic_type_symtable, basic_type->name,
strlen
(basic_type->name), basic_type);
}
void
SPVM_COMPILER_add_basic_types(SPVM_COMPILER* compiler) {
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_UNKNOWN);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_UNDEF);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_VOID);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_BYTE);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_SHORT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_INT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_LONG);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_FLOAT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_DOUBLE);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_STRING);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_ANY_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_OARRAY);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_BYTE_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_SHORT_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_INT_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_LONG_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_FLOAT_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_DOUBLE_OBJECT);
SPVM_COMPILER_add_basic_type(compiler, SPVM_BASIC_TYPE_C_ID_BOOL_OBJECT);
}
int32_t SPVM_COMPILER_get_error_messages_length(SPVM_COMPILER* compiler) {
return
compiler->error_messages->length;
}
const
char
* SPVM_COMPILER_get_error_message(SPVM_COMPILER* compiler, int32_t index) {
const
char
* error_message = (
const
char
*)SPVM_LIST_fetch(compiler->error_messages, index);
return
error_message;
}
void
SPVM_COMPILER_print_error_messages(SPVM_COMPILER* compiler,
FILE
* fh) {
for
(int32_t i = 0; i < compiler->error_messages->length; i++) {
const
char
* error_message = (
const
char
*)SPVM_LIST_fetch(compiler->error_messages, i);
fprintf
(fh,
"[CompileError]%s\n"
, error_message);
}
}
void
SPVM_COMPILER_use(SPVM_COMPILER* compiler,
const
char
* class_name,
const
char
* file, int32_t line) {
SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, class_name, file, line);
SPVM_OP* op_type = SPVM_OP_build_basic_type(compiler, op_name);
SPVM_OP* op_use = SPVM_OP_new_op_use(compiler, op_name->file, op_name->line);
SPVM_OP_build_use(compiler, op_use, op_type, NULL, 0);
SPVM_LIST_push(compiler->op_use_stack, op_use);
}
const
char
* SPVM_COMPILER_get_runtime_name(SPVM_HASH* runtime_string_symtable,
const
char
* name) {
SPVM_RUNTIME_STRING* string = SPVM_HASH_fetch(runtime_string_symtable, name,
strlen
(name));
const
char
* new_name = string->value;
return
new_name;
}
int32_t SPVM_COMPILER_compile_spvm(SPVM_COMPILER* compiler,
const
char
* class_name) {
compiler->cur_class_base = compiler->classes->length;
int32_t cur_basic_type_base = compiler->basic_types->length;
const
char
* start_file = compiler->start_file;
int32_t start_line = compiler->start_line;
SPVM_yydebug = 0;
#ifdef SPVM_DEBUG_YACC
SPVM_yydebug = 1;
#endif
compiler->parse_start = 1;
compiler->error_messages = SPVM_LIST_new_list_permanent(compiler->allocator, 0);
int32_t error_code = 0;
int32_t compile_start_memory_blocks_count_tmp = compiler->allocator->memory_blocks_count_tmp;
compiler->ops = SPVM_LIST_new(compiler->allocator, 0, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
compiler->op_use_stack = SPVM_LIST_new(compiler->allocator, 0, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
compiler->op_types = SPVM_LIST_new(compiler->allocator, 0, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
compiler->used_class_symtable = SPVM_HASH_new(compiler->allocator, 0, SPVM_ALLOCATOR_C_ALLOC_TYPE_TMP);
for
(int32_t i = 0; i < compiler->classes->length; i++) {
SPVM_CLASS*
class
= SPVM_LIST_fetch(compiler->classes, i);
const
char
* class_name =
class
->name;
SPVM_HASH_insert(compiler->used_class_symtable, class_name,
strlen
(class_name), (
void
*)class_name);
}
SPVM_COMPILER_use(compiler,
"Bool"
,
"Bool"
, 0);
SPVM_COMPILER_use(compiler,
"Byte"
,
"Byte"
, 0);
SPVM_COMPILER_use(compiler,
"Short"
,
"Short"
, 0);
SPVM_COMPILER_use(compiler,
"Int"
,
"Int"
, 0);
SPVM_COMPILER_use(compiler,
"Long"
,
"Long"
, 0);
SPVM_COMPILER_use(compiler,
"Float"
,
"Float"
, 0);
SPVM_COMPILER_use(compiler,
"Double"
,
"Double"
, 0);
SPVM_COMPILER_use(compiler, class_name, start_file, start_line);
int32_t parse_error_flag = SPVM_yyparse(compiler);
if
(parse_error_flag) {
error_code = 1;
}
else
{
if
(SPVM_COMPILER_get_error_messages_length(compiler) > 0) {
error_code = 2;
}
else
{
SPVM_OP_CHECKER_check(compiler);
if
(SPVM_COMPILER_get_error_messages_length(compiler) > 0) {
error_code = 3;
}
else
{
int32_t build_opcode_array_start_memory_blocks_count_tmp = compiler->allocator->memory_blocks_count_tmp;
SPVM_OPCODE_BUILDER_build_opcode_array(compiler);
assert
(compiler->allocator->memory_blocks_count_tmp == build_opcode_array_start_memory_blocks_count_tmp);
if
(SPVM_COMPILER_get_error_messages_length(compiler) > 0) {
error_code = 4;
}
}
}
}
for
(int32_t i = 0; i < compiler->ops->length; i++) {
SPVM_OP* op = SPVM_LIST_fetch(compiler->ops, i);
int32_t op_id = op->id;
switch
(op_id) {
case
SPVM_OP_C_ID_BLOCK: {
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, op->uv.block);
break
;
}
case
SPVM_OP_C_ID_DESCRIPTOR: {
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, op->uv.descriptor);
break
;
}
case
SPVM_OP_C_ID_USE: {
SPVM_USE* use = op->uv.use;
use->op_type = NULL;
use->class_alias_name = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, use);
break
;
}
case
SPVM_OP_C_ID_ALLOW: {
SPVM_ALLOW* allow = op->uv.allow;
allow->op_type = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, allow);
break
;
}
case
SPVM_OP_C_ID_IMPLEMENT: {
SPVM_IMPLEMENT* implement = op->uv.implement;
implement->op_type = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, implement);
break
;
}
case
SPVM_OP_C_ID_CLASS_VAR_ACCESS: {
SPVM_CLASS_VAR_ACCESS* class_var_access = op->uv.class_var_access;
class_var_access->op_name = NULL;
class_var_access->class_var = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, class_var_access);
break
;
}
case
SPVM_OP_C_ID_CONSTANT: {
SPVM_CONSTANT* constant = op->uv.constant;
constant->op_constant = NULL;
constant->type = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, constant);
break
;
}
case
SPVM_OP_C_ID_ARRAY_FIELD_ACCESS: {
SPVM_ARRAY_FIELD_ACCESS* array_field_access = op->uv.array_field_access;
array_field_access->field = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, array_field_access);
break
;
}
case
SPVM_OP_C_ID_FIELD_ACCESS: {
SPVM_FIELD_ACCESS* field_access = op->uv.field_access;
field_access->op_term = NULL;
field_access->op_name = NULL;
field_access->field = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, field_access);
break
;
}
case
SPVM_OP_C_ID_CALL_METHOD: {
SPVM_CALL_METHOD* call_method = op->uv.call_method;
call_method->op_invocant = NULL;
call_method->op_name = NULL;
call_method->method = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, call_method);
break
;
}
case
SPVM_OP_C_ID_VAR: {
SPVM_VAR* var = op->uv.var;
var->op_name = NULL;
var->name = NULL;
var->my = NULL;
var->call_method = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, var);
break
;
}
case
SPVM_OP_C_ID_MY: {
SPVM_MY* my = op->uv.my;
if
(!my->is_eternal) {
my->op_my = NULL;
my->type = NULL;
my->var = NULL;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, my);
}
break
;
}
}
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->allocator, op);
}
for
(int32_t class_index = compiler->cur_class_base; class_index < compiler->classes->length; class_index++) {
SPVM_CLASS*
class
= SPVM_LIST_fetch(compiler->classes, class_index);
class
->op_class = NULL;
class
->op_name = NULL;
SPVM_LIST_free(
class
->allows);
SPVM_LIST* methods =
class
->methods;
{
int32_t method_index;
for
(method_index = 0; method_index < methods->length; method_index++) {
SPVM_METHOD* method = SPVM_LIST_fetch(methods, method_index);
method->op_method = NULL;
method->op_name = NULL;
method->op_block = NULL;
method->op_inline = NULL;
}
}
}
SPVM_LIST_free(compiler->op_use_stack);
compiler->op_use_stack = NULL;
SPVM_LIST_free(compiler->op_types);
compiler->op_types = NULL;
SPVM_HASH_free(compiler->used_class_symtable);
compiler->used_class_symtable = NULL;
SPVM_LIST_free(compiler->ops);
compiler->ops = NULL;
assert
(compiler->allocator->memory_blocks_count_tmp == compile_start_memory_blocks_count_tmp);
return
error_code;
}
SPVM_RUNTIME_INFO* SPVM_COMPILER_build_runtime_info(SPVM_COMPILER* compiler) {
SPVM_ALLOCATOR* allocator = SPVM_ALLOCATOR_new();
SPVM_RUNTIME_INFO* runtime_info = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_INFO));
runtime_info->allocator = allocator;
runtime_info->opcodes = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_OPCODE) * compiler->opcode_array->length);
memcpy
(runtime_info->opcodes, compiler->opcode_array->values,
sizeof
(SPVM_OPCODE) * compiler->opcode_array->length);
runtime_info->string_buffer_length = compiler->string_buffer->length;
runtime_info->string_buffer = (
const
char
*)SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator, compiler->string_buffer->length);
memcpy
((
char
*)runtime_info->string_buffer, compiler->string_buffer->buffer, compiler->string_buffer->length);
runtime_info->strings_length = compiler->strings->length;
runtime_info->strings = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_STRING) * compiler->strings->length);
for
(int32_t string_id = 0; string_id < compiler->strings->length; string_id++) {
SPVM_STRING* string = SPVM_LIST_fetch(compiler->strings, string_id);
SPVM_RUNTIME_STRING* runtime_string = &runtime_info->strings[string_id];
runtime_string->id = string->id;
runtime_string->length = string->length;
runtime_string->string_buffer_id = string->string_buffer_id;
}
runtime_info->string_symtable = SPVM_HASH_new_hash_permanent(allocator, 0);
for
(int32_t string_id = 0; string_id < runtime_info->strings_length; string_id++) {
SPVM_RUNTIME_STRING* runtime_string = &runtime_info->strings[string_id];
runtime_string->value = &runtime_info->string_buffer[runtime_string->string_buffer_id];
SPVM_HASH_insert(runtime_info->string_symtable, runtime_string->value,
strlen
(runtime_string->value), runtime_string);
}
runtime_info->classes_length = compiler->classes->length;
runtime_info->classes = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_CLASS) * compiler->classes->length);
runtime_info->class_symtable = SPVM_HASH_new_hash_permanent(allocator, 0);
for
(int32_t class_id = 0; class_id < compiler->classes->length; class_id++) {
SPVM_CLASS*
class
= SPVM_LIST_fetch(compiler->classes, class_id);
SPVM_RUNTIME_CLASS* runtime_class = &runtime_info->classes[class_id];
runtime_class->type_id =
class
->type->id;
runtime_class->id =
class
->id;
if
(
class
->module_file) {
SPVM_STRING* class_module_file_string = SPVM_HASH_fetch(compiler->string_symtable,
class
->module_file,
strlen
(
class
->module_file));
runtime_class->module_file_id = class_module_file_string->id;
}
else
{
runtime_class->name_id = -1;
}
runtime_class->flag =
class
->flag;
runtime_class->object_fields_length =
class
->object_fields_length;
runtime_class->object_fields_offset =
class
->object_fields_offset;
runtime_class->has_init_block =
class
->has_init_block;
runtime_class->is_anon =
class
->is_anon;
SPVM_STRING* class_string = SPVM_HASH_fetch(compiler->string_symtable,
class
->name,
strlen
(
class
->name));
runtime_class->name_id = class_string->id;
if
(
class
->method_destructor) {
runtime_class->method_destructor_id =
class
->method_destructor->id;
}
else
{
runtime_class->method_destructor_id = -1;
}
runtime_class->method_ids_length =
class
->methods->length;
if
(
class
->methods->length > 0) {
SPVM_METHOD* method = SPVM_LIST_fetch(
class
->methods, 0);
runtime_class->method_ids_base = method->id;
}
else
{
runtime_class->method_ids_base = -1;
}
runtime_class->field_ids_length =
class
->fields->length;
if
(
class
->fields->length > 0) {
SPVM_FIELD* field = SPVM_LIST_fetch(
class
->fields, 0);
runtime_class->field_ids_base = field->id;
}
else
{
runtime_class->field_ids_base = -1;
}
runtime_class->class_var_ids_length =
class
->class_vars->length;
if
(
class
->class_vars->length > 0) {
SPVM_CLASS_VAR* class_var = SPVM_LIST_fetch(
class
->class_vars, 0);
runtime_class->class_var_ids_base = class_var->id;
}
else
{
runtime_class->class_var_ids_base = -1;
}
runtime_class->interface_class_ids_length =
class
->interface_classes->length;
if
(
class
->interface_classes->length > 0) {
SPVM_CLASS* interface_class = SPVM_LIST_fetch(
class
->interface_classes, 0);
runtime_class->interface_class_ids_base = interface_class->id;
}
else
{
runtime_class->interface_class_ids_base = -1;
}
SPVM_RUNTIME_STRING* class_name_string = (SPVM_RUNTIME_STRING*)&runtime_info->strings[runtime_class->name_id];
const
char
* runtime_class_name = (
const
char
*)&runtime_info->string_buffer[class_name_string->string_buffer_id];
SPVM_HASH_insert(runtime_info->class_symtable, runtime_class_name,
strlen
(runtime_class_name), runtime_class);
}
runtime_info->basic_types_length = compiler->basic_types->length;
runtime_info->basic_types = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_BASIC_TYPE) * compiler->basic_types->length);
for
(int32_t basic_type_id = 0; basic_type_id < compiler->basic_types->length; basic_type_id++) {
SPVM_BASIC_TYPE* basic_type = SPVM_LIST_fetch(compiler->basic_types, basic_type_id);
SPVM_RUNTIME_BASIC_TYPE* runtime_basic_type = &runtime_info->basic_types[basic_type_id];
runtime_basic_type->id = basic_type->id;
if
(basic_type->
class
) {
runtime_basic_type->class_id = basic_type->
class
->id;
}
else
{
runtime_basic_type->class_id = -1;
}
SPVM_STRING* basic_type_string = SPVM_HASH_fetch(compiler->string_symtable, basic_type->name,
strlen
(basic_type->name));
runtime_basic_type->name_id = basic_type_string->id;
}
runtime_info->basic_type_symtable = SPVM_HASH_new_hash_permanent(allocator, runtime_info->basic_types_length);
for
(int32_t basic_type_id = 0; basic_type_id < runtime_info->basic_types_length; basic_type_id++) {
SPVM_RUNTIME_BASIC_TYPE* runtime_basic_type = &runtime_info->basic_types[basic_type_id];
SPVM_RUNTIME_STRING* basic_type_name_string = (SPVM_RUNTIME_STRING*)&runtime_info->strings[runtime_basic_type->name_id];
const
char
* runtime_basic_type_name = (
const
char
*)&runtime_info->string_buffer[basic_type_name_string->string_buffer_id];
SPVM_HASH_insert(runtime_info->basic_type_symtable, runtime_basic_type_name,
strlen
(runtime_basic_type_name), runtime_basic_type);
}
runtime_info->types_length = compiler->types->length;
runtime_info->types = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_TYPE) * compiler->types->length);
for
(int32_t type_id = 0; type_id < compiler->types->length; type_id++) {
SPVM_TYPE* type = SPVM_LIST_fetch(compiler->types, type_id);
SPVM_RUNTIME_TYPE* runtime_type = &runtime_info->types[type_id];
runtime_type->basic_type_id = type->basic_type->id;
runtime_type->dimension = type->dimension;
runtime_type->flag = type->flag;
runtime_type->category = type->category;
runtime_type->width = type->width;
}
runtime_info->class_vars_length = compiler->class_vars->length;
runtime_info->class_vars = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_CLASS_VAR) * compiler->class_vars->length);
for
(int32_t class_var_id = 0; class_var_id < compiler->class_vars->length; class_var_id++) {
SPVM_CLASS_VAR* class_var = SPVM_LIST_fetch(compiler->class_vars, class_var_id);
SPVM_RUNTIME_CLASS_VAR* runtime_class_var = &runtime_info->class_vars[class_var_id];
runtime_class_var->id = class_var->id;
runtime_class_var->type_id = class_var->type->id;
runtime_class_var->class_id = class_var->
class
->id;
SPVM_STRING* class_var_name_string = SPVM_HASH_fetch(compiler->string_symtable, class_var->name,
strlen
(class_var->name));
runtime_class_var->name_id = class_var_name_string->id;
SPVM_STRING* class_var_signature_string = SPVM_HASH_fetch(compiler->string_symtable, class_var->signature,
strlen
(class_var->signature));
runtime_class_var->signature_id = class_var_signature_string->id;
}
runtime_info->methods_length = compiler->methods->length;
runtime_info->methods = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_METHOD) * compiler->methods->length);
for
(int32_t method_id = 0; method_id < compiler->methods->length; method_id++) {
SPVM_METHOD* method = SPVM_LIST_fetch(compiler->methods, method_id);
SPVM_RUNTIME_METHOD* runtime_method = &runtime_info->methods[method_id];
runtime_method->opcodes_base = method->opcodes_base;
runtime_method->opcodes_length = method->opcodes_length;
runtime_method->id = method->id;
runtime_method->class_id = method->
class
->id;
runtime_method->flag = method->flag;
runtime_method->is_class_method = method->is_class_method;
runtime_method->is_init = method->is_init;
runtime_method->call_stack_byte_vars_legnth = method->call_stack_byte_vars_legnth;
runtime_method->call_stack_short_vars_legnth = method->call_stack_short_vars_legnth;
runtime_method->call_stack_int_vars_legnth = method->call_stack_int_vars_legnth;
runtime_method->call_stack_long_vars_legnth = method->call_stack_long_vars_legnth;
runtime_method->call_stack_float_vars_legnth = method->call_stack_float_vars_legnth;
runtime_method->call_stack_double_vars_legnth = method->call_stack_double_vars_legnth;
runtime_method->call_stack_object_vars_legnth = method->call_stack_object_vars_legnth;
runtime_method->call_stack_ref_vars_legnth = method->call_stack_ref_vars_legnth;
runtime_method->mortal_stack_length = method->mortal_stack_length;
runtime_method->return_type_id = method->return_type->id;
SPVM_STRING* method_name_string = SPVM_HASH_fetch(compiler->string_symtable, method->name,
strlen
(method->name));
runtime_method->name_id = method_name_string->id;
SPVM_STRING* method_signature_string = SPVM_HASH_fetch(compiler->string_symtable, method->signature,
strlen
(method->signature));
runtime_method->signature_id = method_signature_string->id;
runtime_method->arg_type_ids_length = method->args_length;
if
(method->args_length > 0) {
SPVM_MY* arg = SPVM_LIST_fetch(method->mys, 0);
runtime_method->arg_type_ids_base = arg->arg_id;
}
else
{
runtime_method->arg_type_ids_base = -1;
}
}
runtime_info->method_native_addresses = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(
void
*) * runtime_info->methods_length);
runtime_info->method_precompile_addresses = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(
void
*) * runtime_info->methods_length);
runtime_info->arg_type_ids_length = compiler->args->length;
runtime_info->arg_type_ids = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(int32_t) * compiler->args->length);
for
(int32_t arg_id = 0; arg_id < compiler->args->length; arg_id++) {
SPVM_MY* arg_my = SPVM_LIST_fetch(compiler->args, arg_id);
int32_t arg_type_id = arg_my->type->id;
runtime_info->arg_type_ids[arg_id] = arg_type_id;
}
runtime_info->fields_length = compiler->fields->length;
runtime_info->fields = SPVM_ALLOCATOR_alloc_memory_block_permanent(allocator,
sizeof
(SPVM_RUNTIME_FIELD) * compiler->fields->length);
for
(int32_t field_id = 0; field_id < compiler->fields->length; field_id++) {
SPVM_FIELD* field = SPVM_LIST_fetch(compiler->fields, field_id);
SPVM_RUNTIME_FIELD* runtime_field = &runtime_info->fields[field_id];
runtime_field->id = field->id;
runtime_field->index = field->index;
runtime_field->offset = field->offset;
runtime_field->type_id = field->type->id;
SPVM_STRING* field_name_string = SPVM_HASH_fetch(compiler->string_symtable, field->name,
strlen
(field->name));
runtime_field->name_id = field_name_string->id;
SPVM_STRING* field_signature_string = SPVM_HASH_fetch(compiler->string_symtable, field->signature,
strlen
(field->signature));
runtime_field->signature_id = field_signature_string->id;
}
return
runtime_info;
}
void
SPVM_COMPILER_error(SPVM_COMPILER* compiler,
const
char
* message_template, ...) {
int32_t message_length = 0;
int32_t message_template_length = (int32_t)
strlen
(message_template);
va_list
args;
va_start
(args, message_template);
message_length += message_template_length;
char
* found_ptr = (
char
*)message_template;
while
(1) {
found_ptr =
strchr
(found_ptr,
'%'
);
if
(found_ptr) {
if
(*(found_ptr + 1) ==
'c'
) {
int
arg =
va_arg
(args,
int
);
message_length++;
}
else
if
(*(found_ptr + 1) ==
's'
) {
char
* arg =
va_arg
(args,
char
*);
message_length +=
strlen
(arg);
}
else
if
(*(found_ptr + 1) ==
'd'
) {
(
void
)
va_arg
(args,
int
);
message_length += 30;
}
else
if
(*(found_ptr + 1) ==
'%'
) {
found_ptr++;
}
else
{
assert
(0);
}
found_ptr++;
}
else
{
break
;
}
}
va_end
(args);
char
* message = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->allocator, message_length + 1);
va_start
(args, message_template);
vsprintf
(message, message_template, args);
va_end
(args);
SPVM_LIST_push(compiler->error_messages, message);
}
const
char
* SPVM_COMPILER_create_method_signature(SPVM_COMPILER* compiler, SPVM_METHOD* method) {
int32_t length = 0;
{
length +=
strlen
(method->return_type->basic_type->name);
length += method->return_type->dimension * 2;
length += 1;
int32_t arg_index;
for
(arg_index = 0; arg_index < method->args_length; arg_index++) {
if
(!method->is_class_method && arg_index == 0) {
length += 4;
}
else
{
SPVM_MY* arg_my_method = SPVM_LIST_fetch(method->mys, arg_index);
SPVM_TYPE* type_arg_method = arg_my_method->type;
if
(SPVM_TYPE_is_ref_type(compiler, type_arg_method->basic_type->id, type_arg_method->dimension, type_arg_method->flag)) {
length += 1;
}
length +=
strlen
(type_arg_method->basic_type->name);
length += type_arg_method->dimension * 2;
}
if
(arg_index != method->args_length - 1) {
length += 1;
}
}
length += 1;
}
char
* method_signature_tmp = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->allocator, length + 1);
char
* bufptr = method_signature_tmp;
{
memcpy
(bufptr, method->return_type->basic_type->name,
strlen
(method->return_type->basic_type->name));
bufptr +=
strlen
(method->return_type->basic_type->name);
int32_t dim_index;
for
(dim_index = 0; dim_index < method->return_type->dimension; dim_index++) {
memcpy
(bufptr,
"[]"
, 2);
bufptr += 2;
}
*bufptr =
'('
;
bufptr += 1;
int32_t arg_index;
for
(arg_index = 0; arg_index < method->args_length; arg_index++) {
if
(!method->is_class_method && arg_index == 0) {
memcpy
(bufptr,
"self"
, 4);
bufptr += 4;
}
else
{
SPVM_MY* arg_my_method = SPVM_LIST_fetch(method->mys, arg_index);
SPVM_TYPE* type_arg_method = arg_my_method->type;
if
(SPVM_TYPE_is_ref_type(compiler, type_arg_method->basic_type->id, type_arg_method->dimension, type_arg_method->flag)) {
*bufptr =
'&'
;
bufptr += 1;
}
memcpy
(bufptr, type_arg_method->basic_type->name,
strlen
(type_arg_method->basic_type->name));
bufptr +=
strlen
(type_arg_method->basic_type->name);
int32_t dim_index;
for
(dim_index = 0; dim_index < type_arg_method->dimension; dim_index++) {
memcpy
(bufptr,
"[]"
, 2);
bufptr += 2;
}
}
if
(arg_index != method->args_length - 1) {
memcpy
(bufptr,
","
, 1);
bufptr += 1;
}
}
memcpy
(bufptr,
")"
, 1);
bufptr += 1;
}
SPVM_STRING* method_signature_string = SPVM_STRING_new(compiler, method_signature_tmp,
strlen
(method_signature_tmp));
const
char
* method_signature = method_signature_string->value;
return
method_signature;
}
const
char
* SPVM_COMPILER_create_field_signature(SPVM_COMPILER* compiler, SPVM_FIELD* field) {
int32_t length = 0;
{
length +=
strlen
(field->type->basic_type->name);
length += field->type->dimension * 2;
}
char
* field_signature_tmp = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->allocator, length + 1);
char
* bufptr = field_signature_tmp;
{
memcpy
(bufptr, field->type->basic_type->name,
strlen
(field->type->basic_type->name));
bufptr +=
strlen
(field->type->basic_type->name);
int32_t dim_index;
for
(dim_index = 0; dim_index < field->type->dimension; dim_index++) {
memcpy
(bufptr,
"[]"
, 2);
bufptr += 2;
}
}
SPVM_STRING* field_signature_string = SPVM_STRING_new(compiler, field_signature_tmp,
strlen
(field_signature_tmp));
const
char
* field_signature = field_signature_string->value;
return
field_signature;
}
const
char
* SPVM_COMPILER_create_class_var_signature(SPVM_COMPILER* compiler, SPVM_CLASS_VAR* class_var) {
int32_t length = 0;
{
length +=
strlen
(class_var->type->basic_type->name);
length += class_var->type->dimension * 2;
}
char
* class_var_signature_tmp = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->allocator, length + 1);
char
* bufptr = class_var_signature_tmp;
{
memcpy
(bufptr, class_var->type->basic_type->name,
strlen
(class_var->type->basic_type->name));
bufptr +=
strlen
(class_var->type->basic_type->name);
int32_t dim_index;
for
(dim_index = 0; dim_index < class_var->type->dimension; dim_index++) {
memcpy
(bufptr,
"[]"
, 2);
bufptr += 2;
}
}
SPVM_STRING* class_var_signature_string = SPVM_STRING_new(compiler, class_var_signature_tmp,
strlen
(class_var_signature_tmp));
const
char
* class_var_signature = class_var_signature_string->value;
return
class_var_signature;
}
void
SPVM_COMPILER_free(SPVM_COMPILER* compiler) {
SPVM_OPCODE_ARRAY_free(compiler, compiler->opcode_array);
SPVM_ALLOCATOR_free(compiler->allocator);
compiler->allocator = NULL;
}