ADD: recursive functions.
parent
5825f5b316
commit
9b31a14723
176
src/compiler.c
176
src/compiler.c
|
@ -11,6 +11,9 @@ void compiler_init(compiler* self)
|
||||||
self->binfo.capacity = 1;
|
self->binfo.capacity = 1;
|
||||||
self->binfo.data = malloc(sizeof(block_info*) * self->binfo.capacity);
|
self->binfo.data = malloc(sizeof(block_info*) * self->binfo.capacity);
|
||||||
|
|
||||||
|
self->fun_stack.size = 0;
|
||||||
|
self->fun_stack.capacity = 1;
|
||||||
|
self->fun_stack.data = malloc(sizeof(char*) * self->fun_stack.capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_free(compiler* self)
|
void compiler_free(compiler* self)
|
||||||
|
@ -21,6 +24,17 @@ void compiler_free(compiler* self)
|
||||||
free(self->sym);
|
free(self->sym);
|
||||||
self->sym = NULL;
|
self->sym = NULL;
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->fun_stack.size; i++)
|
||||||
|
{
|
||||||
|
free(self->fun_stack.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->fun_stack.data);
|
||||||
|
|
||||||
|
self->fun_stack.size = 0;
|
||||||
|
self->fun_stack.capacity = 0;
|
||||||
|
self->fun_stack.data = NULL;
|
||||||
|
|
||||||
for (size_t i=0; i<self->binfo.size; i++)
|
for (size_t i=0; i<self->binfo.size; i++)
|
||||||
{
|
{
|
||||||
block_info_free(self->binfo.data[i]);
|
block_info_free(self->binfo.data[i]);
|
||||||
|
@ -34,6 +48,39 @@ void compiler_free(compiler* self)
|
||||||
self->binfo.data = NULL;
|
self->binfo.data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compiler_push_fun(compiler* self, char* fun_name)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if (self->fun_stack.size >= self->fun_stack.capacity)
|
||||||
|
{
|
||||||
|
self->fun_stack.capacity *= 2;
|
||||||
|
self->fun_stack.data = realloc(
|
||||||
|
self->fun_stack.data,
|
||||||
|
sizeof(char*) * self->fun_stack.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->fun_stack.data[self->fun_stack.size] = str_new(fun_name);
|
||||||
|
self->fun_stack.size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compiler_pop_fun(compiler* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(self->fun_stack.size > 0);
|
||||||
|
|
||||||
|
free(self->fun_stack.data[self->fun_stack.size - 1]);
|
||||||
|
self->fun_stack.size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* compiler_top_fun(compiler* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(self->fun_stack.size > 0);
|
||||||
|
return self->fun_stack.data[self->fun_stack.size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
block_info* compiler_current_info(compiler* self)
|
block_info* compiler_current_info(compiler* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -182,7 +229,11 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
root->children.data[1]
|
root->children.data[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
compiler_push_fun(self, root->children.data[0]->value);
|
||||||
compile_node(self, root->children.data[1], prog);
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
compiler_pop_fun(self);
|
||||||
|
|
||||||
program_add_instr(prog, OP_STORE, id);
|
program_add_instr(prog, OP_STORE, id);
|
||||||
|
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
|
@ -205,7 +256,20 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
root->children.data[1]
|
root->children.data[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int is_fn = root->children.data[1]->type == NODE_FUN;
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_push_fun(self, root->children.data[0]->value);
|
||||||
|
}
|
||||||
|
|
||||||
compile_node(self, root->children.data[1], prog);
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_pop_fun(self);
|
||||||
|
}
|
||||||
|
|
||||||
program_add_instr(prog, OP_STORE, id);
|
program_add_instr(prog, OP_STORE, id);
|
||||||
|
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
|
@ -233,7 +297,20 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
root->children.data[1]
|
root->children.data[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int is_fn = root->children.data[1]->type == NODE_FUN;
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_push_fun(self, root->children.data[0]->value);
|
||||||
|
}
|
||||||
|
|
||||||
compile_node(self, root->children.data[1], prog);
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_pop_fun(self);
|
||||||
|
}
|
||||||
|
|
||||||
program_add_instr(prog, OP_STORE, id);
|
program_add_instr(prog, OP_STORE, id);
|
||||||
|
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
|
@ -292,6 +369,7 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
int lhs = cstatic_resolve_base_type(&cs,
|
int lhs = cstatic_resolve_base_type(&cs,
|
||||||
self->sym,
|
self->sym,
|
||||||
root->children.data[0]);
|
root->children.data[0]);
|
||||||
|
|
||||||
int rhs = cstatic_resolve_base_type(&cs, self->sym,
|
int rhs = cstatic_resolve_base_type(&cs, self->sym,
|
||||||
root->children.data[1]);
|
root->children.data[1]);
|
||||||
|
|
||||||
|
@ -365,64 +443,70 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_FUN)
|
else if (root->type == NODE_FUN)
|
||||||
{
|
{
|
||||||
// init body
|
|
||||||
|
// prepare compiler
|
||||||
compiler comp;
|
compiler comp;
|
||||||
compiler_init(&comp);
|
compiler_init(&comp);
|
||||||
program* fun_prog = malloc(sizeof(program));
|
|
||||||
program_init(fun_prog);
|
|
||||||
node* block = root->children.data[root->children.size - 1];
|
|
||||||
|
|
||||||
// add params
|
// prepare program
|
||||||
|
program local_prog;
|
||||||
|
program_init(&local_prog);
|
||||||
|
|
||||||
|
// resolve function type
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
type* fn_ty = cstatic_resolve_new(&cs, self->sym, root);
|
||||||
|
|
||||||
|
// prepare environment (parameters and function)
|
||||||
|
|
||||||
for (size_t i=0; i<root->children.size; i++)
|
for (size_t i=0; i<root->children.size; i++)
|
||||||
{
|
{
|
||||||
node* param = root->children.data[i];
|
node* param = root->children.data[i];
|
||||||
|
if (param->type != NODE_FUN_PARAM) { continue; }
|
||||||
|
|
||||||
if (param->type == NODE_FUN_PARAM)
|
char* name = param->children.data[0]->value;
|
||||||
{
|
type* ty = type_new_from_node(param->children.data[1]);
|
||||||
char const* param_name = param->children.data[0]->value;
|
|
||||||
type* param_ty =
|
|
||||||
type_new_from_node(param->children.data[1]);
|
|
||||||
|
|
||||||
symtable_declare(comp.sym, param_name
|
symtable_declare(
|
||||||
, param_ty
|
comp.sym,
|
||||||
, param->children.data[0]);
|
name,
|
||||||
|
ty,
|
||||||
type_free(param_ty); free(param_ty);
|
param
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// compile body
|
|
||||||
compile_node(&comp, block, fun_prog);
|
|
||||||
compiler_free(&comp);
|
|
||||||
|
|
||||||
// init fun object
|
|
||||||
cstatic cs;
|
|
||||||
cstatic_init(&cs);
|
|
||||||
|
|
||||||
fun* fn = malloc(sizeof(fun));
|
|
||||||
type* ty = cstatic_resolve_new(&cs, self->sym, root);
|
|
||||||
|
|
||||||
fun_init(fn, ty, (struct program*) fun_prog);
|
|
||||||
program_free(fun_prog); free(fun_prog); fun_prog = NULL;
|
|
||||||
|
|
||||||
type_free(ty); free(ty);
|
|
||||||
|
|
||||||
// create value
|
|
||||||
value* val = malloc(sizeof(value));
|
|
||||||
value_init_fun(val, fn, root->lineno);
|
|
||||||
|
|
||||||
// push it
|
|
||||||
program_add_instr(
|
|
||||||
prog,
|
|
||||||
OP_PUSH,
|
|
||||||
program_add_pool(prog, val)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
type_free(ty); free(ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* fun_name = compiler_top_fun(self);
|
||||||
|
|
||||||
|
symtable_declare(
|
||||||
|
comp.sym,
|
||||||
|
fun_name,
|
||||||
|
fn_ty,
|
||||||
|
root
|
||||||
|
);
|
||||||
|
|
||||||
|
// compile fun block
|
||||||
|
node* fun_block = root->children.data[root->children.size - 1];
|
||||||
|
compile_node(&comp, fun_block, &local_prog);
|
||||||
|
//char c[1024]; node_str(root, c, 1024); printf("%s\n", c);
|
||||||
|
|
||||||
|
// create value
|
||||||
|
fun* fn = malloc(sizeof(fun));
|
||||||
|
fun_init(fn, fn_ty, (struct program*) &local_prog);
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_fun(val, fn, root->lineno);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
// push value
|
||||||
|
program_add_instr(prog, OP_PUSH, program_add_pool(prog, val));
|
||||||
|
|
||||||
|
// free stuff
|
||||||
|
program_free(&local_prog);
|
||||||
|
compiler_free(&comp);
|
||||||
|
type_free(fn_ty); free(fn_ty);
|
||||||
value_free(val); free(val);
|
value_free(val); free(val);
|
||||||
fun_free(fn); free(fn);
|
fun_free(fn); free(fn);
|
||||||
|
|
||||||
cstatic_free(&cs);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_CALL)
|
else if (root->type == NODE_CALL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,11 +16,20 @@ typedef struct {
|
||||||
block_info** data;
|
block_info** data;
|
||||||
} binfo;
|
} binfo;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
char** data;
|
||||||
|
} fun_stack;
|
||||||
|
|
||||||
} compiler;
|
} compiler;
|
||||||
|
|
||||||
void compiler_init(compiler* self);
|
void compiler_init(compiler* self);
|
||||||
void compiler_free(compiler* self);
|
void compiler_free(compiler* self);
|
||||||
|
|
||||||
|
void compiler_push_fun(compiler* self, char* fun_name);
|
||||||
|
void compiler_pop_fun(compiler* self);
|
||||||
|
char* compiler_top_fun(compiler* self);
|
||||||
|
|
||||||
block_info* compiler_current_info(compiler* self);
|
block_info* compiler_current_info(compiler* self);
|
||||||
block_info* compiler_find_info(compiler* self, int kind);
|
block_info* compiler_find_info(compiler* self, int kind);
|
||||||
|
|
187
src/cstatic.c
187
src/cstatic.c
|
@ -7,7 +7,7 @@ void cstatic_init(cstatic* self)
|
||||||
|
|
||||||
self->fun_types.size = 0;
|
self->fun_types.size = 0;
|
||||||
self->fun_types.capacity = 1;
|
self->fun_types.capacity = 1;
|
||||||
self->fun_types.data = malloc(sizeof(type*) * self->fun_types.capacity);
|
self->fun_types.data = malloc(sizeof(fun_info*) * self->fun_types.capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cstatic_free(cstatic* self)
|
void cstatic_free(cstatic* self)
|
||||||
|
@ -16,8 +16,8 @@ void cstatic_free(cstatic* self)
|
||||||
|
|
||||||
for (size_t i=0; i<self->fun_types.size; i++)
|
for (size_t i=0; i<self->fun_types.size; i++)
|
||||||
{
|
{
|
||||||
type_free(self->fun_types.data[i]);
|
type_free(self->fun_types.data[i]->ty);
|
||||||
free(self->fun_types.data[i]);
|
free(self->fun_types.data[i]->ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(self->fun_types.data);
|
free(self->fun_types.data);
|
||||||
|
@ -92,9 +92,34 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
char const* fun_name = ast->children.data[0]->value;
|
char const* fun_name = ast->children.data[0]->value;
|
||||||
|
|
||||||
symentry* entry = symtable_find(sym, fun_name);
|
symentry* entry = symtable_find(sym, fun_name);
|
||||||
assert(entry);
|
fun_info* info = NULL;
|
||||||
|
|
||||||
|
if (self->fun_types.size > 0)
|
||||||
|
{
|
||||||
|
info = cstatic_top_fun(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
type* fun_type = NULL;
|
||||||
|
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
fun_type = entry->ty;
|
||||||
|
}
|
||||||
|
else if (info && info->name && strcmp(info->name, fun_name) == 0)
|
||||||
|
{
|
||||||
|
fun_type = info->ty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr
|
||||||
|
, "E(%d): cannot call unknown function '%s'.\n"
|
||||||
|
, ast->children.data[0]->lineno
|
||||||
|
, fun_name);
|
||||||
|
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type* fun_type = entry->ty;
|
|
||||||
assert(fun_type);
|
assert(fun_type);
|
||||||
|
|
||||||
size_t ret_count = fun_type->sub_types.size;
|
size_t ret_count = fun_type->sub_types.size;
|
||||||
|
@ -106,6 +131,7 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
|
|
||||||
if (ret_type->kind == KIND_RETURN)
|
if (ret_type->kind == KIND_RETURN)
|
||||||
{
|
{
|
||||||
|
|
||||||
type* res = type_new_clone(ret_type);
|
type* res = type_new_clone(ret_type);
|
||||||
res->kind = KIND_CONJUNCTION;
|
res->kind = KIND_CONJUNCTION;
|
||||||
return res;
|
return res;
|
||||||
|
@ -160,8 +186,12 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast->type == NODE_VARDECL)
|
if (ast->type == NODE_VARDECL
|
||||||
|
|| ast->type == NODE_CONSTDECL
|
||||||
|
|| ast->type == NODE_FUNDECL)
|
||||||
{
|
{
|
||||||
|
char* name = ast->children.data[0]->value;
|
||||||
|
printf("-> %s\n", name);
|
||||||
type* ty = cstatic_resolve_new(self,
|
type* ty = cstatic_resolve_new(self,
|
||||||
sym,
|
sym,
|
||||||
ast->children.data[1]);
|
ast->children.data[1]);
|
||||||
|
@ -366,8 +396,6 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
{
|
{
|
||||||
type* ty = cstatic_resolve_new(self, sym, ast);
|
type* ty = cstatic_resolve_new(self, sym, ast);
|
||||||
|
|
||||||
cstatic_push_fun(self, ty);
|
|
||||||
|
|
||||||
type_free(ty); free(ty);
|
type_free(ty); free(ty);
|
||||||
|
|
||||||
symtable* inner_table = symtable_new_clone(sym);
|
symtable* inner_table = symtable_new_clone(sym);
|
||||||
|
@ -396,7 +424,6 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
);
|
);
|
||||||
|
|
||||||
symtable_free(inner_table); free(inner_table);
|
symtable_free(inner_table); free(inner_table);
|
||||||
cstatic_pop_fun(self);
|
|
||||||
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -406,7 +433,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
if (ast->type == NODE_RETURN)
|
if (ast->type == NODE_RETURN)
|
||||||
{
|
{
|
||||||
type* ret_ty = cstatic_resolve_new(self, sym, ast);
|
type* ret_ty = cstatic_resolve_new(self, sym, ast);
|
||||||
type* fun_ty = cstatic_top_fun(self);
|
type* fun_ty = cstatic_top_fun(self)->ty;
|
||||||
|
|
||||||
type* fun_res = NULL;
|
type* fun_res = NULL;
|
||||||
|
|
||||||
|
@ -459,6 +486,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
for (size_t i=0; i<fun_type->sub_types.size; i++)
|
for (size_t i=0; i<fun_type->sub_types.size; i++)
|
||||||
{
|
{
|
||||||
type* ty = fun_type->sub_types.data[i];
|
type* ty = fun_type->sub_types.data[i];
|
||||||
|
|
||||||
if (ty->kind != KIND_RETURN)
|
if (ty->kind != KIND_RETURN)
|
||||||
{
|
{
|
||||||
arity++;
|
arity++;
|
||||||
|
@ -513,7 +541,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
for (size_t i=0; i<ast->children.size; i++)
|
/*for (size_t i=0; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
int status = cstatic_check(self, ast->children.data[i],
|
int status = cstatic_check(self, ast->children.data[i],
|
||||||
sym,
|
sym,
|
||||||
|
@ -524,6 +552,58 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (ast->type == NODE_VARDECL
|
||||||
|
|| ast->type == NODE_CONSTDECL
|
||||||
|
|| ast->type == NODE_FUNDECL)
|
||||||
|
{
|
||||||
|
char const* name = ast->children.data[0]->value;
|
||||||
|
symentry* entry = symtable_find(sym, name);
|
||||||
|
if (entry && entry->scope >= sym->scope)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E(%d): '%s' is already defined.\n",
|
||||||
|
ast->lineno,
|
||||||
|
name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
type* ty = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
|
if (ty->base_type == TY_FUNCTION)
|
||||||
|
{
|
||||||
|
cstatic_push_fun(self, ast->children.data[0]->value, ty);
|
||||||
|
int status =
|
||||||
|
cstatic_check(self, ast->children.data[1], sym, msg, size);
|
||||||
|
cstatic_pop_fun(self);
|
||||||
|
|
||||||
|
if (!status) { return status; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int status =
|
||||||
|
cstatic_check(self, ast->children.data[1], sym, msg, size);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ty);
|
||||||
|
|
||||||
|
if (ast->type == NODE_VARDECL)
|
||||||
|
{
|
||||||
|
symtable_declare_mut(sym, name, ty, ast->children.data[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
symtable_declare(sym, name, ty, ast->children.data[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_free(ty);
|
||||||
|
free(ty);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arrays
|
// Arrays
|
||||||
|
@ -725,37 +805,6 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (ast->type == NODE_VARDECL
|
|
||||||
|| ast->type == NODE_CONSTDECL
|
|
||||||
|| ast->type == NODE_FUNDECL)
|
|
||||||
{
|
|
||||||
char const* name = ast->children.data[0]->value;
|
|
||||||
symentry* entry = symtable_find(sym, name);
|
|
||||||
|
|
||||||
if (entry && entry->scope >= sym->scope)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "E(%d): '%s' is already defined.\n",
|
|
||||||
ast->lineno,
|
|
||||||
name);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
type* ty = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
|
||||||
assert(ty);
|
|
||||||
|
|
||||||
if (ast->type == NODE_VARDECL)
|
|
||||||
{
|
|
||||||
symtable_declare_mut(sym, name, ty, ast->children.data[1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
symtable_declare(sym, name, ty, ast->children.data[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
type_free(ty);
|
|
||||||
free(ty);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Types Operations
|
// Types Operations
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
|
@ -997,6 +1046,36 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
|
{
|
||||||
|
int status = cstatic_check(self, ast->children.data[i],
|
||||||
|
sym,
|
||||||
|
msg, size);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cstatic_check_children(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size)
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<lhs->children.size; i++)
|
||||||
|
{
|
||||||
|
int status = cstatic_check(self, lhs->children.data[i],
|
||||||
|
sym,
|
||||||
|
msg, size);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1169,7 +1248,7 @@ int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cstatic_push_fun(cstatic* self, type* fun_ty)
|
void cstatic_push_fun(cstatic* self, char* name, type* fun_ty)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(fun_ty);
|
assert(fun_ty);
|
||||||
|
@ -1179,11 +1258,18 @@ void cstatic_push_fun(cstatic* self, type* fun_ty)
|
||||||
self->fun_types.capacity *= 2;
|
self->fun_types.capacity *= 2;
|
||||||
self->fun_types.data = realloc(
|
self->fun_types.data = realloc(
|
||||||
self->fun_types.data,
|
self->fun_types.data,
|
||||||
sizeof(type*) * self->fun_types.capacity
|
sizeof(fun_info*) * self->fun_types.capacity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->fun_types.data[self->fun_types.size] = type_new_clone(fun_ty);
|
self->fun_types.data[self->fun_types.size] = malloc(sizeof(fun_info));
|
||||||
|
self->fun_types.data[self->fun_types.size]->ty = type_new_clone(fun_ty);
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
self->fun_types.data[self->fun_types.size]->name = str_new(name);
|
||||||
|
}
|
||||||
|
|
||||||
self->fun_types.size++;
|
self->fun_types.size++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1192,13 +1278,20 @@ void cstatic_pop_fun(cstatic* self)
|
||||||
{
|
{
|
||||||
assert(self->fun_types.size > 0);
|
assert(self->fun_types.size > 0);
|
||||||
|
|
||||||
type_free(self->fun_types.data[self->fun_types.size - 1]);
|
type_free(self->fun_types.data[self->fun_types.size - 1]->ty);
|
||||||
|
free(self->fun_types.data[self->fun_types.size - 1]->ty);
|
||||||
|
|
||||||
|
if (self->fun_types.data[self->fun_types.size - 1]->name)
|
||||||
|
{
|
||||||
|
free(self->fun_types.data[self->fun_types.size - 1]->name);
|
||||||
|
}
|
||||||
|
|
||||||
free(self->fun_types.data[self->fun_types.size - 1]);
|
free(self->fun_types.data[self->fun_types.size - 1]);
|
||||||
|
|
||||||
self->fun_types.size--;
|
self->fun_types.size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
type* cstatic_top_fun(cstatic* self)
|
fun_info* cstatic_top_fun(cstatic* self)
|
||||||
{
|
{
|
||||||
assert(self->fun_types.size > 0);
|
assert(self->fun_types.size > 0);
|
||||||
return self->fun_types.data[self->fun_types.size - 1];
|
return self->fun_types.data[self->fun_types.size - 1];
|
||||||
|
|
|
@ -7,11 +7,16 @@
|
||||||
|
|
||||||
#define TYPE_END (-1)
|
#define TYPE_END (-1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
type* ty;
|
||||||
|
char* name;
|
||||||
|
} fun_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct {
|
struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
type** data;
|
fun_info** data;
|
||||||
} fun_types;
|
} fun_types;
|
||||||
} cstatic;
|
} cstatic;
|
||||||
|
|
||||||
|
@ -24,6 +29,8 @@ int cstatic_resolve_base_type(cstatic* self, symtable* sym, node* ast);
|
||||||
type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast);
|
type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast);
|
||||||
int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size);
|
int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size);
|
||||||
|
|
||||||
|
int cstatic_check_children(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size);
|
||||||
|
|
||||||
int cstatic_check_type(cstatic* self, node* lhs, symtable* sym,
|
int cstatic_check_type(cstatic* self, node* lhs, symtable* sym,
|
||||||
char* msg, size_t size, type* types, ...);
|
char* msg, size_t size, type* types, ...);
|
||||||
|
|
||||||
|
@ -37,7 +44,7 @@ int cstatic_check_same_type_ptr(cstatic* self,
|
||||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
||||||
char* msg, size_t size);
|
char* msg, size_t size);
|
||||||
|
|
||||||
void cstatic_push_fun(cstatic* self, type* fun_ty);
|
void cstatic_push_fun(cstatic* self, char* name, type* fun_ty);
|
||||||
void cstatic_pop_fun(cstatic* self);
|
void cstatic_pop_fun(cstatic* self);
|
||||||
type* cstatic_top_fun(cstatic* self);
|
fun_info* cstatic_top_fun(cstatic* self);
|
||||||
#endif
|
#endif
|
||||||
|
|
31
src/vm.c
31
src/vm.c
|
@ -1150,7 +1150,11 @@ void vm_call(vm* self, int param)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
// get function and parameters
|
vm v;
|
||||||
|
vm_init(&v);
|
||||||
|
|
||||||
|
|
||||||
|
// get arguments
|
||||||
value* args[param];
|
value* args[param];
|
||||||
|
|
||||||
for (int i=0; i<param; i++)
|
for (int i=0; i<param; i++)
|
||||||
|
@ -1158,33 +1162,30 @@ void vm_call(vm* self, int param)
|
||||||
args[param - 1 - i] = vm_pop_value(self);
|
args[param - 1 - i] = vm_pop_value(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
value* fun_val = vm_pop_value(self);
|
|
||||||
fun* f = fun_val->val.fun_val;
|
|
||||||
|
|
||||||
// create new ecxecution environment
|
|
||||||
vm v;
|
|
||||||
vm_init(&v);
|
|
||||||
|
|
||||||
for (int i=0; i<param; i++)
|
for (int i=0; i<param; i++)
|
||||||
{
|
{
|
||||||
vm_set(&v, i, args[i]);
|
vm_set(&v, i, args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute function
|
// get calling function
|
||||||
vm_exec(&v, (program*) f->prog);
|
value* function_val = vm_pop_value(self);
|
||||||
|
fun* function = function_val->val.fun_val;
|
||||||
|
vm_set(&v, param, function_val);
|
||||||
|
|
||||||
value* ret = value_new_clone(v.stack.data[v.stack.size - 1]);
|
// execute and finalize
|
||||||
vm_push_value(self, ret);
|
|
||||||
|
|
||||||
|
vm_exec(&v, (program*) function->prog);
|
||||||
|
vm_push_value(self, value_new_clone(v.stack.data[v.stack.size - 1]));
|
||||||
|
|
||||||
|
|
||||||
|
// cleanup
|
||||||
vm_free(&v);
|
vm_free(&v);
|
||||||
|
value_free(function_val); free(function_val);
|
||||||
|
|
||||||
for (int i=0; i<param; i++)
|
for (int i=0; i<param; i++)
|
||||||
{
|
{
|
||||||
value_free(args[i]); free(args[i]);
|
value_free(args[i]); free(args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_free(fun_val); free(fun_val);
|
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,3 +36,13 @@ end
|
||||||
|
|
||||||
assert 14 == e 7
|
assert 14 == e 7
|
||||||
|
|
||||||
|
fun f (n as int) as int
|
||||||
|
if n == 0
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return n * f(n - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 120 == f 5
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue