SPVM
view release on metacpan or search on metacpan
lib/SPVM/Builder/src/spvm_op.c view on Meta::CPAN
break;
}
default: {
SPVM_COMPILER_error(compiler, "Invalid method attribute \"%s\".\n at %s line %d", SPVM_ATTRIBUTE_get_name(compiler, attribute->id), op_attributes->file, op_attributes->line);
}
}
}
if (method->is_native && method->is_precompile) {
SPVM_COMPILER_error(compiler, "Only one of method attributes \"native\" and \"precompile\" can be specified.\n at %s line %d", op_attributes->file, op_attributes->line);
}
if (access_control_attributes_count > 1) {
SPVM_COMPILER_error(compiler, "Only one of method attributes \"private\", \"protected\" or \"public\" can be specified.\n at %s line %d", op_method->file, op_method->line);
}
}
// The default of the access controll of the method is publice.
if (method->access_control_type == SPVM_ATTRIBUTE_C_ID_UNKNOWN) {
method->access_control_type = SPVM_ATTRIBUTE_C_ID_PUBLIC;
}
// Native method cannnot have block
if ((method->is_native) && op_block) {
SPVM_COMPILER_error(compiler, "A native method cannnot have its block.\n at %s line %d", op_block->file, op_block->line);
}
// method args
if (!op_args) {
op_args = SPVM_OP_new_op_list(compiler, op_method->file, op_method->line);
}
// Add $self : self before the first argument
if (!method->is_class_method) {
SPVM_OP* op_arg_var_name_self = SPVM_OP_new_op_name(compiler, "$self", op_method->file, op_method->line);
SPVM_OP* op_arg_var_self = SPVM_OP_new_op_var(compiler, op_arg_var_name_self);
SPVM_OP* op_self_type = SPVM_OP_new_op_unresolved_type(compiler, NULL, 0, 0, op_method->file, op_method->line);
SPVM_TYPE* self_type = op_self_type->uv.type;
SPVM_OP* op_arg_self = SPVM_OP_build_arg(compiler, op_arg_var_self, op_self_type, NULL, NULL);
SPVM_OP_insert_child(compiler, op_args, op_args->first, op_arg_self);
}
// Add method arguments
{
int32_t found_optional_arg = 0;
int32_t required_args_length = 0;
int32_t args_length = 0;
SPVM_OP* op_arg = op_args->first;
while ((op_arg = SPVM_OP_sibling(compiler, op_arg))) {
SPVM_VAR_DECL* arg_var_decl = op_arg->uv.var->var_decl;
if (!found_optional_arg) {
if (arg_var_decl->op_arg_default) {
found_optional_arg = 1;
}
else {
required_args_length++;
}
}
args_length++;
}
method->args_length = args_length;
method->required_args_length = required_args_length;
}
// Variable declarations of arguments
SPVM_OP* op_arg = op_args->first;
while ((op_arg = SPVM_OP_sibling(compiler, op_arg))) {
SPVM_LIST_push(method->var_decls, op_arg->uv.var->var_decl);
}
// return type
method->return_type = op_return_type->uv.type;
if (strcmp(method->op_name->uv.name, "DESTROY") == 0) {
method->is_destroy_method = 1;
// DESTROY return type must be void
if (!(method->return_type->dimension == 0 && method->return_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_VOID)) {
SPVM_COMPILER_error(compiler, "The return type of DESTROY method must be the void type.\n at %s line %d", op_method->file, op_method->line);
}
// DESTROY is instance method
if (method->is_class_method) {
SPVM_COMPILER_error(compiler, "DESTROY method must be an instance method.\n at %s line %d", op_method->file, op_method->line);
}
// DESTROY doesn't have arguments without invocant
if (method->args_length != 1) {
SPVM_COMPILER_error(compiler, "DESTROY method cannnot have arguments.\n at %s line %d", op_method->file, op_method->line);
}
}
SPVM_OP* op_anon_method_field_var_decl_start = NULL;
if (op_block) {
SPVM_OP* op_list_statement = op_block->first;
op_anon_method_field_var_decl_start = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING, op_list_statement->file, op_list_statement->last->line + 1);
SPVM_OP_insert_child(compiler, op_list_statement, op_list_statement->first, op_anon_method_field_var_decl_start);
method->op_anon_method_field_var_decl_start = op_anon_method_field_var_decl_start;
// Add variable declarations before the first of the statements
for (int32_t i = method->args_length - 1; i >= 0; i--) {
SPVM_VAR_DECL* arg_var_decl = SPVM_LIST_get(method->var_decls, i);
assert(arg_var_decl);
SPVM_OP* op_name_var = SPVM_OP_new_op_name(compiler, arg_var_decl->var->name, arg_var_decl->op_var_decl->file, arg_var_decl->op_var_decl->line);
SPVM_OP* op_var = SPVM_OP_new_op_var(compiler, op_name_var);
op_var->uv.var->var_decl = arg_var_decl;
op_var->uv.var->is_declaration = 1;
op_var->uv.var->var_decl = arg_var_decl;
SPVM_OP_insert_child(compiler, op_list_statement, op_list_statement->first, op_var);
}
// Add condition_flag variable to first of block
{
SPVM_OP* op_var = SPVM_OP_new_op_var_condition_flag(compiler, op_list_statement->file, op_list_statement->last->line + 1);
SPVM_OP* op_var_decl = SPVM_OP_new_op_var_decl(compiler, op_list_statement->file, op_list_statement->last->line + 1);
SPVM_OP* op_type = SPVM_OP_new_op_int_type(compiler, op_list_statement->file, op_list_statement->line);
op_var = SPVM_OP_build_var_decl(compiler, op_var_decl, op_var, op_type, NULL);
( run in 3.344 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )