Compare commits
No commits in common. "3f3835839061bc1d9c67f19ed18d1532f47fbd83" and "9ab09e85f60e1a6c50a7cedaf8811c14e4807b76" have entirely different histories.
3f38358390
...
9ab09e85f6
180
src/compiler.c
180
src/compiler.c
|
@ -11,9 +11,6 @@ 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)
|
||||||
|
@ -24,17 +21,6 @@ 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]);
|
||||||
|
@ -48,39 +34,6 @@ 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);
|
||||||
|
@ -214,32 +167,6 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
||||||
}
|
}
|
||||||
// Variables stuff
|
// Variables stuff
|
||||||
else if (root->type == NODE_FUNDECL)
|
|
||||||
{
|
|
||||||
cstatic cs;
|
|
||||||
cstatic_init(&cs);
|
|
||||||
type* ty = cstatic_resolve_new(&cs,
|
|
||||||
self->sym,
|
|
||||||
root->children.data[1]);
|
|
||||||
|
|
||||||
size_t id = symtable_declare(
|
|
||||||
self->sym,
|
|
||||||
root->children.data[0]->value,
|
|
||||||
ty,
|
|
||||||
root->children.data[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
compiler_push_fun(self, root->children.data[0]->value);
|
|
||||||
compile_node(self, root->children.data[1], prog);
|
|
||||||
compiler_pop_fun(self);
|
|
||||||
|
|
||||||
program_add_instr(prog, OP_STORE, id);
|
|
||||||
|
|
||||||
type_free(ty);
|
|
||||||
free(ty);
|
|
||||||
cstatic_free(&cs);
|
|
||||||
}
|
|
||||||
else if (root->type == NODE_CONSTDECL)
|
else if (root->type == NODE_CONSTDECL)
|
||||||
{
|
{
|
||||||
cstatic cs;
|
cstatic cs;
|
||||||
|
@ -256,20 +183,7 @@ 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);
|
||||||
|
@ -297,20 +211,7 @@ 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);
|
||||||
|
@ -369,7 +270,6 @@ 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]);
|
||||||
|
|
||||||
|
@ -443,70 +343,64 @@ 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];
|
||||||
|
|
||||||
// prepare program
|
// add params
|
||||||
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; }
|
|
||||||
|
|
||||||
char* name = param->children.data[0]->value;
|
if (param->type == NODE_FUN_PARAM)
|
||||||
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(
|
symtable_declare(comp.sym, param_name
|
||||||
comp.sym,
|
, param_ty
|
||||||
name,
|
, param->children.data[0]);
|
||||||
ty,
|
|
||||||
param
|
|
||||||
);
|
|
||||||
|
|
||||||
type_free(ty); free(ty);
|
type_free(param_ty); free(param_ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* fun_name = compiler_top_fun(self);
|
|
||||||
|
|
||||||
symtable_declare(
|
// compile body
|
||||||
comp.sym,
|
compile_node(&comp, block, fun_prog);
|
||||||
fun_name,
|
compiler_free(&comp);
|
||||||
fn_ty,
|
|
||||||
root
|
|
||||||
);
|
|
||||||
|
|
||||||
// compile fun block
|
// init fun object
|
||||||
node* fun_block = root->children.data[root->children.size - 1];
|
cstatic cs;
|
||||||
compile_node(&comp, fun_block, &local_prog);
|
cstatic_init(&cs);
|
||||||
//char c[1024]; node_str(root, c, 1024); printf("%s\n", c);
|
|
||||||
|
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
|
// create value
|
||||||
fun* fn = malloc(sizeof(fun));
|
|
||||||
fun_init(fn, fn_ty, (struct program*) &local_prog);
|
|
||||||
value* val = malloc(sizeof(value));
|
value* val = malloc(sizeof(value));
|
||||||
value_init_fun(val, fn, root->lineno);
|
value_init_fun(val, fn, root->lineno);
|
||||||
cstatic_free(&cs);
|
|
||||||
|
|
||||||
// push value
|
// push it
|
||||||
program_add_instr(prog, OP_PUSH, program_add_pool(prog, val));
|
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,20 +16,11 @@ 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);
|
||||||
|
|
217
src/cstatic.c
217
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(fun_info*) * self->fun_types.capacity);
|
self->fun_types.data = malloc(sizeof(type*) * 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]->ty);
|
type_free(self->fun_types.data[i]);
|
||||||
free(self->fun_types.data[i]->ty);
|
free(self->fun_types.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(self->fun_types.data);
|
free(self->fun_types.data);
|
||||||
|
@ -63,6 +63,7 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
type_new_from_node(
|
type_new_from_node(
|
||||||
ast->children.data[i]->children.data[1]
|
ast->children.data[i]->children.data[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
type_add_sub_type(ty, param_ty);
|
type_add_sub_type(ty, param_ty);
|
||||||
type_free(param_ty); free(param_ty);
|
type_free(param_ty); free(param_ty);
|
||||||
|
|
||||||
|
@ -89,44 +90,18 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
if (ast->type == NODE_CALL)
|
if (ast->type == NODE_CALL)
|
||||||
{
|
{
|
||||||
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);
|
||||||
fun_info* info = NULL;
|
assert(entry);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
if (ret_count > 0)
|
if (ret_count > 0)
|
||||||
{
|
{
|
||||||
type* ret_type =
|
type* ret_type = fun_type->sub_types.data[ret_count - 1];
|
||||||
fun_type->sub_types.data[ret_count - 1];
|
|
||||||
|
|
||||||
assert(ret_type);
|
assert(ret_type);
|
||||||
|
|
||||||
if (ret_type->kind == KIND_RETURN)
|
if (ret_type->kind == KIND_RETURN)
|
||||||
|
@ -185,9 +160,7 @@ 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)
|
|
||||||
{
|
{
|
||||||
type* ty = cstatic_resolve_new(self,
|
type* ty = cstatic_resolve_new(self,
|
||||||
sym,
|
sym,
|
||||||
|
@ -393,6 +366,8 @@ 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);
|
||||||
|
@ -419,7 +394,9 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
msg,
|
msg,
|
||||||
size
|
size
|
||||||
);
|
);
|
||||||
|
|
||||||
symtable_free(inner_table); free(inner_table);
|
symtable_free(inner_table); free(inner_table);
|
||||||
|
cstatic_pop_fun(self);
|
||||||
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -429,12 +406,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);
|
||||||
int status_inner = cstatic_check_children(self, ast, sym, msg, size);
|
|
||||||
|
|
||||||
if (!status_inner) { return status_inner; }
|
|
||||||
|
|
||||||
type* fun_ty = cstatic_top_fun(self)->ty;
|
|
||||||
|
|
||||||
type* fun_res = NULL;
|
type* fun_res = NULL;
|
||||||
|
|
||||||
|
@ -449,7 +421,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(fun_res);
|
assert(fun_res);
|
||||||
assert(ret_ty);
|
|
||||||
int status = cstatic_check_same_type_ptr(
|
int status = cstatic_check_same_type_ptr(
|
||||||
self,
|
self,
|
||||||
ast,
|
ast,
|
||||||
|
@ -477,24 +449,9 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
type* fun_type = NULL;
|
type* fun_type = entry->ty;
|
||||||
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
fun_type = entry->ty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fun_info* info = cstatic_top_fun(self);
|
|
||||||
|
|
||||||
if (info && info->name)
|
|
||||||
{
|
|
||||||
fun_type = info->ty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(fun_type);
|
|
||||||
|
|
||||||
node* args = ast->children.data[1];
|
node* args = ast->children.data[1];
|
||||||
size_t arity = 0;
|
size_t arity = 0;
|
||||||
|
@ -502,7 +459,6 @@ 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++;
|
||||||
|
@ -557,7 +513,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,
|
||||||
|
@ -568,59 +524,6 @@ 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
|
||||||
|
@ -822,6 +725,36 @@ 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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
@ -1063,36 +996,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1265,7 +1168,7 @@ int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cstatic_push_fun(cstatic* self, char* name, type* fun_ty)
|
void cstatic_push_fun(cstatic* self, type* fun_ty)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(fun_ty);
|
assert(fun_ty);
|
||||||
|
@ -1275,18 +1178,11 @@ void cstatic_push_fun(cstatic* self, char* name, 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(fun_info*) * self->fun_types.capacity
|
sizeof(type*) * self->fun_types.capacity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->fun_types.data[self->fun_types.size] = malloc(sizeof(fun_info));
|
self->fun_types.data[self->fun_types.size] = type_new_clone(fun_ty);
|
||||||
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++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1295,20 +1191,13 @@ 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]->ty);
|
type_free(self->fun_types.data[self->fun_types.size - 1]);
|
||||||
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--;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun_info* cstatic_top_fun(cstatic* self)
|
type* 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,16 +7,11 @@
|
||||||
|
|
||||||
#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;
|
||||||
fun_info** data;
|
type** data;
|
||||||
} fun_types;
|
} fun_types;
|
||||||
} cstatic;
|
} cstatic;
|
||||||
|
|
||||||
|
@ -29,8 +24,6 @@ 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, ...);
|
||||||
|
|
||||||
|
@ -44,7 +37,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, char* name, type* fun_ty);
|
void cstatic_push_fun(cstatic* self, type* fun_ty);
|
||||||
void cstatic_pop_fun(cstatic* self);
|
void cstatic_pop_fun(cstatic* self);
|
||||||
fun_info* cstatic_top_fun(cstatic* self);
|
type* cstatic_top_fun(cstatic* self);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
G(NODE_IF), G(NODE_ELSE), G(NODE_BLOCK), \
|
G(NODE_IF), G(NODE_ELSE), G(NODE_BLOCK), \
|
||||||
G(NODE_WHILE), G(NODE_CONTINUE), G(NODE_BREAK), \
|
G(NODE_WHILE), G(NODE_CONTINUE), G(NODE_BREAK), \
|
||||||
G(NODE_COLON), G(NODE_FUN_TYPE), G(NODE_RETURN), G(NODE_FUN), \
|
G(NODE_COLON), G(NODE_FUN_TYPE), G(NODE_RETURN), G(NODE_FUN), \
|
||||||
G(NODE_FUN_PARAM), G(NODE_FUN_RET), G(NODE_CALL), G(NODE_ARGS), \
|
G(NODE_FUN_PARAM), G(NODE_FUN_RET), G(NODE_CALL), G(NODE_ARGS)
|
||||||
G(NODE_FUNDECL)
|
|
||||||
|
|
||||||
|
|
||||||
#include "mutils.h"
|
#include "mutils.h"
|
||||||
|
|
56
src/parser.y
56
src/parser.y
|
@ -29,7 +29,7 @@
|
||||||
%token BREAK
|
%token BREAK
|
||||||
%left ASSERT
|
%left ASSERT
|
||||||
%token <str> TYPE BOOLEAN INTEGER FLOAT STRING IDENT
|
%token <str> TYPE BOOLEAN INTEGER FLOAT STRING IDENT
|
||||||
%type <n_children> expr exprs prog array builtins fun_body
|
%type <n_children> expr exprs prog array builtins
|
||||||
%type <n_children> expr_list type type_list ident if
|
%type <n_children> expr_list type type_list ident if
|
||||||
%type <n_children> fun_rets fun_params fun_param fun
|
%type <n_children> fun_rets fun_params fun_param fun
|
||||||
%type <n_children> fun_ret_list fun_call fun_args any instr
|
%type <n_children> fun_ret_list fun_call fun_args any instr
|
||||||
|
@ -595,49 +595,33 @@ fun_rets:
|
||||||
;
|
;
|
||||||
|
|
||||||
fun:
|
fun:
|
||||||
FUN ident fun_body {
|
FUN OPAR fun_params CPAR fun_rets block END {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_FUN, "", line);
|
node_init(n, NODE_FUN, "", line);
|
||||||
size_t const SZ = $3;
|
|
||||||
node* all[SZ];
|
|
||||||
|
|
||||||
for (size_t i=0; i<SZ; i++)
|
node* block_node = stack_pop();
|
||||||
|
assert(block_node);
|
||||||
|
|
||||||
|
node* ret_node = stack_pop();
|
||||||
|
assert(ret_node);
|
||||||
|
|
||||||
|
if ($3 > 0)
|
||||||
{
|
{
|
||||||
all[SZ - 1 - i] = stack_pop();
|
node* params[$3];
|
||||||
}
|
|
||||||
|
|
||||||
node* ident_node = stack_pop();
|
for (size_t i=0; i<$3; i++)
|
||||||
|
|
||||||
for (size_t i=0; i<SZ; i++)
|
|
||||||
{
|
{
|
||||||
node_add_child(n, all[i]);
|
params[i] = stack_pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
node* fdecl = malloc(sizeof(node));
|
for (size_t i=0; i<$3; i++)
|
||||||
node_init(fdecl, NODE_FUNDECL, "", line);
|
|
||||||
|
|
||||||
node_add_child(fdecl, ident_node);
|
|
||||||
node_add_child(fdecl, n);
|
|
||||||
|
|
||||||
stack_push(fdecl);
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| FUN fun_body {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_FUN, "", line);
|
|
||||||
size_t const SZ = $2;
|
|
||||||
node* all[SZ];
|
|
||||||
|
|
||||||
for (size_t i=0; i<SZ; i++)
|
|
||||||
{
|
{
|
||||||
all[SZ - 1 - i] = stack_pop();
|
node_add_child(n, params[$3 - 1 - i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i=0; i<SZ; i++)
|
node_add_child(n, ret_node);
|
||||||
{
|
node_add_child(n, block_node);
|
||||||
node_add_child(n, all[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
stack_push(n);
|
stack_push(n);
|
||||||
|
|
||||||
|
@ -645,12 +629,6 @@ fun:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
fun_body:
|
|
||||||
OPAR fun_params CPAR fun_rets block END {
|
|
||||||
$$ = $2 + $4 + $5;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
fun_args:
|
fun_args:
|
||||||
expr_list {
|
expr_list {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
|
|
|
@ -35,7 +35,6 @@ type* type_init_from_node(node* root)
|
||||||
for (size_t i=0; i< rets->children.size; i++)
|
for (size_t i=0; i< rets->children.size; i++)
|
||||||
{
|
{
|
||||||
type* t = type_new_from_node(rets->children.data[i]);
|
type* t = type_new_from_node(rets->children.data[i]);
|
||||||
t->kind = KIND_RETURN;
|
|
||||||
type_add_sub_type(ty, t);
|
type_add_sub_type(ty, t);
|
||||||
type_free(t); free(t);
|
type_free(t); free(t);
|
||||||
}
|
}
|
||||||
|
|
31
src/vm.c
31
src/vm.c
|
@ -1150,11 +1150,7 @@ void vm_call(vm* self, int param)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
vm v;
|
// get function and parameters
|
||||||
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++)
|
||||||
|
@ -1162,30 +1158,33 @@ 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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get calling function
|
// execute function
|
||||||
value* function_val = vm_pop_value(self);
|
vm_exec(&v, (program*) f->prog);
|
||||||
fun* function = function_val->val.fun_val;
|
|
||||||
vm_set(&v, param, function_val);
|
|
||||||
|
|
||||||
// execute and finalize
|
value* ret = value_new_clone(v.stack.data[v.stack.size - 1]);
|
||||||
|
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,38 +30,3 @@ end
|
||||||
|
|
||||||
assert 43 == *d
|
assert 43 == *d
|
||||||
|
|
||||||
fun e (n as int) as int
|
|
||||||
return n * 2
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
fun h (n as int, m as fun<int:int>) as int
|
|
||||||
return (m (m n))
|
|
||||||
end
|
|
||||||
|
|
||||||
fun i (n as int) as int
|
|
||||||
return n * 3
|
|
||||||
end
|
|
||||||
|
|
||||||
assert 27 == h 3, i
|
|
||||||
|
|
||||||
fun j (n as int) as int
|
|
||||||
fun j_inner (n as int) as int
|
|
||||||
return n * 2
|
|
||||||
end
|
|
||||||
|
|
||||||
return j_inner (j_inner n)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert 32 == j 8
|
|
||||||
|
|
Loading…
Reference in New Issue