Compare commits
4 Commits
9ab09e85f6
...
3f38358390
Author | SHA1 | Date |
---|---|---|
bog | 3f38358390 | |
bog | bc869aa6e8 | |
bog | 9b31a14723 | |
bog | 5825f5b316 |
196
src/compiler.c
196
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);
|
||||||
|
@ -167,6 +214,32 @@ 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;
|
||||||
|
@ -183,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);
|
||||||
|
@ -211,9 +297,22 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
root->children.data[1]
|
root->children.data[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
compile_node(self, root->children.data[1], prog);
|
int is_fn = root->children.data[1]->type == NODE_FUN;
|
||||||
program_add_instr(prog, OP_STORE, id);
|
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_push_fun(self, root->children.data[0]->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
|
||||||
|
if (is_fn)
|
||||||
|
{
|
||||||
|
compiler_pop_fun(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
program_add_instr(prog, OP_STORE, id);
|
||||||
|
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
free(ty);
|
free(ty);
|
||||||
cstatic_free(&cs);
|
cstatic_free(&cs);
|
||||||
|
@ -270,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]);
|
||||||
|
|
||||||
|
@ -343,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 =
|
symtable_declare(
|
||||||
type_new_from_node(param->children.data[1]);
|
comp.sym,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
param
|
||||||
|
);
|
||||||
|
|
||||||
symtable_declare(comp.sym, param_name
|
type_free(ty); free(ty);
|
||||||
, param_ty
|
|
||||||
, param->children.data[0]);
|
|
||||||
|
|
||||||
type_free(param_ty); free(param_ty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// compile body
|
char* fun_name = compiler_top_fun(self);
|
||||||
compile_node(&comp, block, fun_prog);
|
|
||||||
compiler_free(&comp);
|
|
||||||
|
|
||||||
// init fun object
|
symtable_declare(
|
||||||
cstatic cs;
|
comp.sym,
|
||||||
cstatic_init(&cs);
|
fun_name,
|
||||||
|
fn_ty,
|
||||||
fun* fn = malloc(sizeof(fun));
|
root
|
||||||
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)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
229
src/cstatic.c
229
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);
|
||||||
|
@ -63,7 +63,6 @@ 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);
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
&& ast->children.data[i]->type == NODE_FUN_RET)
|
&& ast->children.data[i]->type == NODE_FUN_RET)
|
||||||
{
|
{
|
||||||
node* ret = ast->children.data[i];
|
node* ret = ast->children.data[i];
|
||||||
|
|
||||||
for (size_t i=0; i<ret->children.size; i++)
|
for (size_t i=0; i<ret->children.size; i++)
|
||||||
{
|
{
|
||||||
type* r = type_new_from_node(ret->children.data[i]);
|
type* r = type_new_from_node(ret->children.data[i]);
|
||||||
|
@ -90,20 +89,46 @@ 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);
|
||||||
assert(entry);
|
fun_info* info = NULL;
|
||||||
|
|
||||||
type* fun_type = entry->ty;
|
|
||||||
assert(fun_type);
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 = fun_type->sub_types.data[ret_count - 1];
|
type* ret_type =
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
type* res = type_new_clone(ret_type);
|
type* res = type_new_clone(ret_type);
|
||||||
|
@ -160,7 +185,9 @@ 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,
|
||||||
|
@ -338,7 +365,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
|
||||||
// BLOCK
|
// BLOCK
|
||||||
if (ast->type == NODE_BLOCK)
|
if (ast->type == NODE_BLOCK)
|
||||||
{
|
{
|
||||||
|
@ -365,9 +392,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
if (ast->type == NODE_FUN)
|
if (ast->type == NODE_FUN)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
@ -394,9 +419,7 @@ 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;
|
||||||
|
@ -406,7 +429,12 @@ 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;
|
||||||
|
|
||||||
|
@ -421,7 +449,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,
|
||||||
|
@ -449,16 +477,32 @@ 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 = entry->ty;
|
type* fun_type = NULL;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
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 +557,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 +568,59 @@ 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,36 +822,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)
|
|
||||||
{
|
|
||||||
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)
|
||||||
|
@ -996,6 +1063,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1265,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);
|
||||||
|
@ -1178,11 +1275,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] = 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.data[self->fun_types.size] = type_new_clone(fun_ty);
|
|
||||||
self->fun_types.size++;
|
self->fun_types.size++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1191,13 +1295,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
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
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"
|
||||||
|
|
62
src/parser.y
62
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
|
%type <n_children> expr exprs prog array builtins fun_body
|
||||||
%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,33 +595,49 @@ fun_rets:
|
||||||
;
|
;
|
||||||
|
|
||||||
fun:
|
fun:
|
||||||
FUN OPAR fun_params CPAR fun_rets block END {
|
FUN ident fun_body {
|
||||||
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* block_node = stack_pop();
|
node* all[SZ];
|
||||||
assert(block_node);
|
|
||||||
|
|
||||||
node* ret_node = stack_pop();
|
for (size_t i=0; i<SZ; i++)
|
||||||
assert(ret_node);
|
|
||||||
|
|
||||||
if ($3 > 0)
|
|
||||||
{
|
{
|
||||||
node* params[$3];
|
all[SZ - 1 - i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
node* ident_node = stack_pop();
|
||||||
|
|
||||||
for (size_t i=0; i<$3; i++)
|
for (size_t i=0; i<SZ; i++)
|
||||||
{
|
{
|
||||||
params[i] = stack_pop();
|
node_add_child(n, all[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node* fdecl = malloc(sizeof(node));
|
||||||
|
node_init(fdecl, NODE_FUNDECL, "", line);
|
||||||
|
|
||||||
|
node_add_child(fdecl, ident_node);
|
||||||
|
node_add_child(fdecl, n);
|
||||||
|
|
||||||
|
stack_push(fdecl);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i=0; i<$3; i++)
|
| FUN fun_body {
|
||||||
{
|
node* n = malloc(sizeof(node));
|
||||||
node_add_child(n, params[$3 - 1 - i]);
|
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, ret_node);
|
for (size_t i=0; i<SZ; i++)
|
||||||
node_add_child(n, block_node);
|
{
|
||||||
|
node_add_child(n, all[i]);
|
||||||
|
}
|
||||||
|
|
||||||
stack_push(n);
|
stack_push(n);
|
||||||
|
|
||||||
|
@ -629,6 +645,12 @@ 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,6 +35,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
37
src/vm.c
37
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
|
|
||||||
vm_exec(&v, (program*) f->prog);
|
|
||||||
|
|
||||||
value* ret = value_new_clone(v.stack.data[v.stack.size - 1]);
|
// get calling function
|
||||||
vm_push_value(self, ret);
|
value* function_val = vm_pop_value(self);
|
||||||
|
fun* function = function_val->val.fun_val;
|
||||||
|
vm_set(&v, param, function_val);
|
||||||
|
|
||||||
|
// execute and finalize
|
||||||
|
|
||||||
|
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,3 +30,38 @@ 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