ADD: simple functions.
parent
84b0af8090
commit
9ab09e85f6
|
@ -51,6 +51,7 @@ executable(
|
||||||
'src/vm.c',
|
'src/vm.c',
|
||||||
|
|
||||||
'src/symtable.c',
|
'src/symtable.c',
|
||||||
|
'src/fun.c',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
m_dep
|
m_dep
|
||||||
|
|
197
src/compiler.c
197
src/compiler.c
|
@ -341,9 +341,139 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (root->type == NODE_FUN)
|
||||||
|
{
|
||||||
|
// init body
|
||||||
|
compiler 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
|
||||||
|
for (size_t i=0; i<root->children.size; i++)
|
||||||
|
{
|
||||||
|
node* param = root->children.data[i];
|
||||||
|
|
||||||
|
if (param->type == NODE_FUN_PARAM)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
, param_ty
|
||||||
|
, param->children.data[0]);
|
||||||
|
|
||||||
|
type_free(param_ty); free(param_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
value_free(val); free(val);
|
||||||
|
fun_free(fn); free(fn);
|
||||||
|
|
||||||
|
cstatic_free(&cs);
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_CALL)
|
||||||
|
{
|
||||||
|
//{char c[512]; node_str(root, c, 512); printf("%s\n", c);}
|
||||||
|
char const* fun_name = root->children.data[0]->value;
|
||||||
|
node* args = root->children.data[1];
|
||||||
|
|
||||||
|
symentry* entry = symtable_find(self->sym, fun_name);
|
||||||
|
assert(entry);
|
||||||
|
|
||||||
|
program_add_instr(prog, OP_LOAD, entry->id);
|
||||||
|
|
||||||
|
for (size_t i=0; i<args->children.size; i++)
|
||||||
|
{
|
||||||
|
node* arg = args->children.data[i];
|
||||||
|
compile_node(self, arg, prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
program_add_instr(prog, OP_CALL, args->children.size);
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_RETURN)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
program_add_instr(prog, OP_RET, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_FUN_TYPE)
|
||||||
|
{
|
||||||
|
type* ty = malloc(sizeof(type));
|
||||||
|
type_init(ty, TY_FUNCTION);
|
||||||
|
|
||||||
|
node* lhs = root->children.data[0];
|
||||||
|
|
||||||
|
size_t lhs_sz = lhs->children.size;
|
||||||
|
|
||||||
|
for (size_t i=0; i<lhs_sz; i++)
|
||||||
|
{
|
||||||
|
type* sub = type_new_from_node(
|
||||||
|
lhs->children.data[lhs_sz - 1 - i]);
|
||||||
|
type_add_sub_type(ty, sub);
|
||||||
|
type_free(sub); free(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root->children.data[1]->children.size > 0)
|
||||||
|
{
|
||||||
|
node* rhs = root->children.data[1];
|
||||||
|
size_t rhs_sz = rhs->children.size;
|
||||||
|
for (size_t i=0; i<rhs_sz; i++)
|
||||||
|
{
|
||||||
|
type* sub = type_new_from_node(
|
||||||
|
rhs->children.data[rhs_sz - 1 - i]);
|
||||||
|
sub->kind = KIND_RETURN;
|
||||||
|
type_add_sub_type(ty, sub);
|
||||||
|
type_free(sub); free(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value val;
|
||||||
|
value_init_type(&val,
|
||||||
|
ty,
|
||||||
|
root->lineno);
|
||||||
|
|
||||||
|
size_t idx = program_add_pool(prog, &val);
|
||||||
|
program_add_instr(prog, OP_PUSH, idx);
|
||||||
|
|
||||||
|
|
||||||
|
type_free(ty);
|
||||||
|
free(ty);
|
||||||
|
|
||||||
|
value_free(&val);
|
||||||
|
}
|
||||||
else if (root->type == NODE_TYPE)
|
else if (root->type == NODE_TYPE)
|
||||||
{
|
{
|
||||||
type* ty = compile_get_type(self, root);
|
type* ty = type_new_from_node(root);
|
||||||
|
|
||||||
value val;
|
value val;
|
||||||
value_init_type(&val,
|
value_init_type(&val,
|
||||||
|
@ -572,71 +702,6 @@ void compile_children(compiler* self, node* root, program* prog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type* compile_get_type(compiler* self, node* root)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(root);
|
|
||||||
type* ty = malloc(sizeof(type));
|
|
||||||
|
|
||||||
if (strcmp(root->value, "int") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_INTEGER);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (strcmp(root->value, "float") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_FLOAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (strcmp(root->value, "str") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_STRING);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (strcmp(root->value, "bool") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_BOOLEAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (strcmp(root->value, "type") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (strcmp(root->value, "array") == 0)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_ARRAY);
|
|
||||||
ty->kind = KIND_SEQUENTIAL;
|
|
||||||
}
|
|
||||||
else if (root->type == NODE_ADD)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_TYPE);
|
|
||||||
ty->kind = KIND_DISJUNCTION;
|
|
||||||
}
|
|
||||||
else if (root->type == NODE_MUL)
|
|
||||||
{
|
|
||||||
type_init(ty, TY_TYPE);
|
|
||||||
ty->kind = KIND_CONJUNCTION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"E(%d): cannot compile unknown type '%s'.\n",
|
|
||||||
root->lineno,
|
|
||||||
NodeTypeStr[root->type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<root->children.size; i++)
|
|
||||||
{
|
|
||||||
type* sub = compile_get_type(self, root->children.data[i]);
|
|
||||||
type_add_sub_type(ty, sub);
|
|
||||||
type_free(sub);
|
|
||||||
free(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void compile_if(compiler* self, node* root, program* prog)
|
void compile_if(compiler* self, node* root, program* prog)
|
||||||
{
|
{
|
||||||
if (root->children.size == 1)
|
if (root->children.size == 1)
|
||||||
|
|
|
@ -30,8 +30,6 @@ void compiler_pop_info(compiler* self);
|
||||||
void compile_node(compiler* self, node* root, program* prog);
|
void compile_node(compiler* self, node* root, program* prog);
|
||||||
void compile_children(compiler* self, node* root, program* prog);
|
void compile_children(compiler* self, node* root, program* prog);
|
||||||
|
|
||||||
type* compile_get_type(compiler* self, node* root);
|
|
||||||
|
|
||||||
void compile_number(compiler* self, node* root, program* prog,
|
void compile_number(compiler* self, node* root, program* prog,
|
||||||
int integer_op,
|
int integer_op,
|
||||||
int float_op);
|
int float_op);
|
||||||
|
|
292
src/cstatic.c
292
src/cstatic.c
|
@ -4,11 +4,26 @@
|
||||||
void cstatic_init(cstatic* self)
|
void cstatic_init(cstatic* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
self->fun_types.size = 0;
|
||||||
|
self->fun_types.capacity = 1;
|
||||||
|
self->fun_types.data = malloc(sizeof(type*) * self->fun_types.capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cstatic_free(cstatic* self)
|
void cstatic_free(cstatic* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->fun_types.size; i++)
|
||||||
|
{
|
||||||
|
type_free(self->fun_types.data[i]);
|
||||||
|
free(self->fun_types.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->fun_types.data);
|
||||||
|
self->fun_types.size = 0;
|
||||||
|
self->fun_types.capacity = 0;
|
||||||
|
self->fun_types.data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
type* cstatic_new_type(cstatic* self, int base_type)
|
type* cstatic_new_type(cstatic* self, int base_type)
|
||||||
|
@ -35,10 +50,96 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
|
||||||
|
if (ast->type == NODE_FUN)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_new_type(self, TY_FUNCTION);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while (i < ast->children.size
|
||||||
|
&& ast->children.data[i]->type == NODE_FUN_PARAM)
|
||||||
|
{
|
||||||
|
type* param_ty =
|
||||||
|
type_new_from_node(
|
||||||
|
ast->children.data[i]->children.data[1]
|
||||||
|
);
|
||||||
|
|
||||||
|
type_add_sub_type(ty, param_ty);
|
||||||
|
type_free(param_ty); free(param_ty);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < ast->children.size
|
||||||
|
&& ast->children.data[i]->type == NODE_FUN_RET)
|
||||||
|
{
|
||||||
|
node* ret = ast->children.data[i];
|
||||||
|
|
||||||
|
for (size_t i=0; i<ret->children.size; i++)
|
||||||
|
{
|
||||||
|
type* r = type_new_from_node(ret->children.data[i]);
|
||||||
|
r->kind = KIND_RETURN;
|
||||||
|
type_add_sub_type(ty, r);
|
||||||
|
type_free(r); free(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_CALL)
|
||||||
|
{
|
||||||
|
char const* fun_name = ast->children.data[0]->value;
|
||||||
|
|
||||||
|
symentry* entry = symtable_find(sym, fun_name);
|
||||||
|
assert(entry);
|
||||||
|
|
||||||
|
type* fun_type = entry->ty;
|
||||||
|
assert(fun_type);
|
||||||
|
|
||||||
|
size_t ret_count = fun_type->sub_types.size;
|
||||||
|
|
||||||
|
if (ret_count > 0)
|
||||||
|
{
|
||||||
|
type* ret_type = fun_type->sub_types.data[ret_count - 1];
|
||||||
|
assert(ret_type);
|
||||||
|
|
||||||
|
if (ret_type->kind == KIND_RETURN)
|
||||||
|
{
|
||||||
|
type* res = type_new_clone(ret_type);
|
||||||
|
res->kind = KIND_CONJUNCTION;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_RETURN)
|
||||||
|
{
|
||||||
|
return cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_IF)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_resolve_new(self,
|
||||||
|
sym,
|
||||||
|
ast->children.data[1]);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_DO)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_resolve_new(self,
|
||||||
|
sym,
|
||||||
|
ast->children.data[0]);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
if (ast->type == NODE_IDENT)
|
if (ast->type == NODE_IDENT)
|
||||||
{
|
{
|
||||||
symentry* entry = symtable_find(sym,
|
symentry* entry = symtable_find(sym,
|
||||||
ast->value);
|
ast->value);
|
||||||
|
assert(entry);
|
||||||
type* ty = type_new_clone(entry->ty);
|
type* ty = type_new_clone(entry->ty);
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -184,7 +285,8 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
return cstatic_new_type(self, TY_STRING);
|
return cstatic_new_type(self, TY_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ast->type == NODE_TYPE)
|
else if (ast->type == NODE_TYPE
|
||||||
|
|| ast->type == NODE_FUN_TYPE)
|
||||||
{
|
{
|
||||||
return cstatic_new_type(self, TY_TYPE);
|
return cstatic_new_type(self, TY_TYPE);
|
||||||
}
|
}
|
||||||
|
@ -250,7 +352,7 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +361,157 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function Stuff
|
||||||
|
if (ast->type == NODE_FUN)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_resolve_new(self, sym, ast);
|
||||||
|
|
||||||
|
cstatic_push_fun(self, ty);
|
||||||
|
|
||||||
|
type_free(ty); free(ty);
|
||||||
|
|
||||||
|
symtable* inner_table = symtable_new_clone(sym);
|
||||||
|
|
||||||
|
// function args
|
||||||
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
|
{
|
||||||
|
node* child = ast->children.data[i];
|
||||||
|
|
||||||
|
if (child->type == NODE_FUN_PARAM)
|
||||||
|
{
|
||||||
|
char const* name = child->children.data[0]->value;
|
||||||
|
type* t = type_new_from_node(child->children.data[1]);
|
||||||
|
|
||||||
|
symtable_declare_mut(inner_table, name, t, child);
|
||||||
|
|
||||||
|
type_free(t); free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = cstatic_check(self,
|
||||||
|
ast->children.data[ast->children.size - 1],
|
||||||
|
inner_table,
|
||||||
|
msg,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
|
||||||
|
symtable_free(inner_table); free(inner_table);
|
||||||
|
cstatic_pop_fun(self);
|
||||||
|
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function Stuff
|
||||||
|
if (ast->type == NODE_RETURN)
|
||||||
|
{
|
||||||
|
type* ret_ty = cstatic_resolve_new(self, sym, ast);
|
||||||
|
type* fun_ty = cstatic_top_fun(self);
|
||||||
|
|
||||||
|
type* fun_res = NULL;
|
||||||
|
|
||||||
|
for (size_t i=0; i<fun_ty->sub_types.size; i++)
|
||||||
|
{
|
||||||
|
if (fun_ty->sub_types.data[i]->kind == KIND_RETURN)
|
||||||
|
{
|
||||||
|
fun_res = type_new_clone(fun_ty->sub_types.data[i]);
|
||||||
|
fun_res->kind = KIND_CONJUNCTION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(fun_res);
|
||||||
|
|
||||||
|
int status = cstatic_check_same_type_ptr(
|
||||||
|
self,
|
||||||
|
ast,
|
||||||
|
fun_res,
|
||||||
|
ret_ty,
|
||||||
|
sym,
|
||||||
|
msg,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
if (fun_res)
|
||||||
|
{
|
||||||
|
type_free(fun_res); free(fun_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_free(ret_ty); free(ret_ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_CALL)
|
||||||
|
{
|
||||||
|
char const* fun_name = ast->children.data[0]->value;
|
||||||
|
symentry* entry = symtable_find(sym, fun_name);
|
||||||
|
assert(entry);
|
||||||
|
|
||||||
|
type* fun_type = entry->ty;
|
||||||
|
|
||||||
|
node* args = ast->children.data[1];
|
||||||
|
size_t arity = 0;
|
||||||
|
|
||||||
|
for (size_t i=0; i<fun_type->sub_types.size; i++)
|
||||||
|
{
|
||||||
|
type* ty = fun_type->sub_types.data[i];
|
||||||
|
if (ty->kind != KIND_RETURN)
|
||||||
|
{
|
||||||
|
arity++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arity != args->children.size)
|
||||||
|
{
|
||||||
|
snprintf(msg, size, "E(%d): function arity mismatch: "
|
||||||
|
"expected '%ld', got '%ld'.\n",
|
||||||
|
args->lineno,
|
||||||
|
arity,
|
||||||
|
args->children.size
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<args->children.size; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
type* sub = type_new_clone(fun_type->sub_types.data[i]);
|
||||||
|
assert(sub);
|
||||||
|
|
||||||
|
type* arg_type = cstatic_resolve_new(
|
||||||
|
self,
|
||||||
|
sym,
|
||||||
|
args->children.data[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
int status = cstatic_check_same_type_ptr(
|
||||||
|
self,
|
||||||
|
args->children.data[i],
|
||||||
|
sub,
|
||||||
|
arg_type,
|
||||||
|
sym,
|
||||||
|
msg,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_free(sub); free(sub);
|
||||||
|
type_free(arg_type); free(arg_type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
for (size_t i=0; i<ast->children.size; i++)
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
|
@ -914,3 +1167,38 @@ 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)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(fun_ty);
|
||||||
|
|
||||||
|
if (self->fun_types.size >= self->fun_types.capacity)
|
||||||
|
{
|
||||||
|
self->fun_types.capacity *= 2;
|
||||||
|
self->fun_types.data = realloc(
|
||||||
|
self->fun_types.data,
|
||||||
|
sizeof(type*) * self->fun_types.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->fun_types.data[self->fun_types.size] = type_new_clone(fun_ty);
|
||||||
|
self->fun_types.size++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cstatic_pop_fun(cstatic* self)
|
||||||
|
{
|
||||||
|
assert(self->fun_types.size > 0);
|
||||||
|
|
||||||
|
type_free(self->fun_types.data[self->fun_types.size - 1]);
|
||||||
|
free(self->fun_types.data[self->fun_types.size - 1]);
|
||||||
|
|
||||||
|
self->fun_types.size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
type* cstatic_top_fun(cstatic* self)
|
||||||
|
{
|
||||||
|
assert(self->fun_types.size > 0);
|
||||||
|
return self->fun_types.data[self->fun_types.size - 1];
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,11 @@
|
||||||
#define TYPE_END (-1)
|
#define TYPE_END (-1)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int _unused;
|
struct {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
type** data;
|
||||||
|
} fun_types;
|
||||||
} cstatic;
|
} cstatic;
|
||||||
|
|
||||||
void cstatic_init(cstatic* self);
|
void cstatic_init(cstatic* self);
|
||||||
|
@ -33,4 +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, type* fun_ty);
|
||||||
|
void cstatic_pop_fun(cstatic* self);
|
||||||
|
type* cstatic_top_fun(cstatic* self);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "fun.h"
|
||||||
|
#include "program.h"
|
||||||
|
|
||||||
|
void fun_init(fun* self, type* ty, struct program* prog)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->ty = type_new_clone(ty);
|
||||||
|
self->prog = program_new_clone(prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fun_free(fun* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
type_free(self->ty); free(self->ty);
|
||||||
|
|
||||||
|
program_free(self->prog);
|
||||||
|
free(self->prog);
|
||||||
|
self->prog = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun* fun_new_clone(fun* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
fun* clone = malloc(sizeof(fun));
|
||||||
|
fun_init(clone, self->ty, self->prog);
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fun_str(fun* self, char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(buffer);
|
||||||
|
size_t sz = 0;
|
||||||
|
|
||||||
|
sz += snprintf(buffer + sz, size - sz, "function");
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fun_equals(fun* self, fun* lhs)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(lhs);
|
||||||
|
return 0; // TODO to impl
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef FUN_H
|
||||||
|
#define FUN_H
|
||||||
|
|
||||||
|
#include "commons.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
struct program;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
type* ty;
|
||||||
|
struct program* prog;
|
||||||
|
} fun;
|
||||||
|
|
||||||
|
void fun_init(fun* self, type* ty, struct program* prog);
|
||||||
|
void fun_free(fun* self);
|
||||||
|
|
||||||
|
fun* fun_new_clone(fun* self);
|
||||||
|
size_t fun_str(fun* self, char* buffer, size_t size);
|
||||||
|
int fun_equals(fun* self, fun* lhs);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,5 @@
|
||||||
%{
|
%{
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "src/utils.h"
|
#include "src/utils.h"
|
||||||
int line = 1;
|
int line = 1;
|
||||||
|
@ -15,9 +16,11 @@ FLOAT -?[0-9]+\.[0-9]+
|
||||||
STRING \"[^"]*\"
|
STRING \"[^"]*\"
|
||||||
TYPE (int|float|bool|str|array|type)
|
TYPE (int|float|bool|str|array|type)
|
||||||
IDENT [_A-Za-z][_A-Za-z0-9]*
|
IDENT [_A-Za-z][_A-Za-z0-9]*
|
||||||
|
SEP [\n]|[;]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
{COMMENT} {}
|
{COMMENT} {}
|
||||||
|
{SEP} { line++; return SEP; }
|
||||||
"\n" { line++; }
|
"\n" { line++; }
|
||||||
{WHITESPACES} {}
|
{WHITESPACES} {}
|
||||||
|
|
||||||
|
@ -26,6 +29,9 @@ IDENT [_A-Za-z][_A-Za-z0-9]*
|
||||||
return TYPE;
|
return TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"fun" { return FUN; }
|
||||||
|
"as" { return AS; }
|
||||||
|
"return" { return RETURN; }
|
||||||
"while" { return WHILE; }
|
"while" { return WHILE; }
|
||||||
"break" { return BREAK; }
|
"break" { return BREAK; }
|
||||||
"continue" { return CONTINUE; }
|
"continue" { return CONTINUE; }
|
||||||
|
@ -42,6 +48,7 @@ IDENT [_A-Za-z][_A-Za-z0-9]*
|
||||||
"<" { return LT; }
|
"<" { return LT; }
|
||||||
">" { return GT; }
|
">" { return GT; }
|
||||||
"," { return COMMA; }
|
"," { return COMMA; }
|
||||||
|
":" { return COLON; }
|
||||||
"+" { return ADD; }
|
"+" { return ADD; }
|
||||||
"-" { return SUB; }
|
"-" { return SUB; }
|
||||||
"*" { return MUL; }
|
"*" { return MUL; }
|
||||||
|
|
32
src/main.c
32
src/main.c
|
@ -5,6 +5,7 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "cstatic.h"
|
#include "cstatic.h"
|
||||||
|
|
||||||
|
|
||||||
extern FILE* yyin;
|
extern FILE* yyin;
|
||||||
extern node* ast;
|
extern node* ast;
|
||||||
extern void stack_push(node*);
|
extern void stack_push(node*);
|
||||||
|
@ -13,6 +14,8 @@ extern void stack_free();
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
int DEBUG = argc > 2;
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
yyin = fopen(argv[1], "r");
|
yyin = fopen(argv[1], "r");
|
||||||
|
@ -27,6 +30,16 @@ int main(int argc, char** argv)
|
||||||
ast = stack_pop();
|
ast = stack_pop();
|
||||||
stack_free();
|
stack_free();
|
||||||
|
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
size_t const BUF = 1024;
|
||||||
|
char buffer[BUF];
|
||||||
|
memset(buffer, 0, BUF);
|
||||||
|
node_str(ast, buffer, BUF);
|
||||||
|
printf("-- ast ---\n%s\n\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
// Static checking
|
// Static checking
|
||||||
symtable sym;
|
symtable sym;
|
||||||
symtable_init(&sym);
|
symtable_init(&sym);
|
||||||
|
@ -52,24 +65,25 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
compile_node(&comp, ast, &prog);
|
compile_node(&comp, ast, &prog);
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
size_t const BUF = 1024;
|
||||||
|
char buffer[BUF];
|
||||||
|
memset(buffer, 0, BUF);
|
||||||
|
program_str(&prog, buffer, BUF);
|
||||||
|
printf("--- program ---\n%s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
// Execution
|
// Execution
|
||||||
vm v;
|
vm v;
|
||||||
vm_init(&v);
|
vm_init(&v);
|
||||||
|
|
||||||
vm_exec(&v, &prog);
|
vm_exec(&v, &prog);
|
||||||
|
|
||||||
if (0) // DEBUG
|
if (DEBUG)
|
||||||
{
|
{
|
||||||
size_t const BUF = 1024;
|
size_t const BUF = 1024;
|
||||||
char buffer[BUF];
|
char buffer[BUF];
|
||||||
memset(buffer, 0, BUF);
|
|
||||||
node_str(ast, buffer, BUF);
|
|
||||||
printf("-- ast ---\n%s\n\n", buffer);
|
|
||||||
|
|
||||||
memset(buffer, 0, BUF);
|
|
||||||
program_str(&prog, buffer, BUF);
|
|
||||||
printf("--- program ---\n%s\n", buffer);
|
|
||||||
|
|
||||||
memset(buffer, 0, BUF);
|
memset(buffer, 0, BUF);
|
||||||
vm_str(&v, buffer, BUF);
|
vm_str(&v, buffer, BUF);
|
||||||
printf("--- stack ---\n%s\n", buffer);
|
printf("--- stack ---\n%s\n", buffer);
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT), \
|
G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT), \
|
||||||
G(NODE_CONSTDECL), G(NODE_ASSIGN), G(NODE_DO), G(NODE_IS), \
|
G(NODE_CONSTDECL), G(NODE_ASSIGN), G(NODE_DO), G(NODE_IS), \
|
||||||
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_FUN_PARAM), G(NODE_FUN_RET), G(NODE_CALL), G(NODE_ARGS)
|
||||||
|
|
||||||
|
|
||||||
#include "mutils.h"
|
#include "mutils.h"
|
||||||
|
|
|
@ -47,7 +47,9 @@
|
||||||
G(OP_ASTORE), \
|
G(OP_ASTORE), \
|
||||||
G(OP_TEQ), \
|
G(OP_TEQ), \
|
||||||
G(OP_BRF), \
|
G(OP_BRF), \
|
||||||
G(OP_BR)
|
G(OP_BR), \
|
||||||
|
G(OP_CALL), \
|
||||||
|
G(OP_RET)
|
||||||
|
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
|
|
431
src/parser.y
431
src/parser.y
|
@ -2,7 +2,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "src/node.h"
|
#include "src/node.h"
|
||||||
|
|
||||||
extern int line;
|
extern int line;
|
||||||
void yyerror(char const*);
|
void yyerror(char const*);
|
||||||
node* ast = NULL;
|
node* ast = NULL;
|
||||||
|
@ -16,11 +15,13 @@
|
||||||
void stack_free();
|
void stack_free();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%define parse.error verbose
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
char* str;
|
char* str;
|
||||||
size_t n_children;
|
size_t n_children;
|
||||||
};
|
};
|
||||||
|
%token SEP
|
||||||
%token IF_COND
|
%token IF_COND
|
||||||
%token ELSE_COND
|
%token ELSE_COND
|
||||||
%token WHILE
|
%token WHILE
|
||||||
|
@ -30,6 +31,8 @@
|
||||||
%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
|
||||||
%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_ret_list fun_call fun_args any instr
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left LT GT LE GE
|
%left LT GT LE GE
|
||||||
%left AND
|
%left AND
|
||||||
|
@ -39,11 +42,11 @@
|
||||||
%left POW
|
%left POW
|
||||||
%left NOT
|
%left NOT
|
||||||
%token OPAR CPAR
|
%token OPAR CPAR
|
||||||
%token OSQUARE CSQUARE COMMA
|
%token OSQUARE CSQUARE COMMA COLON
|
||||||
%token LET LET_MUT ASSIGN DO END
|
%token LET LET_MUT ASSIGN DO END
|
||||||
%type <n_children> expr_unop block if_rec
|
%type <n_children> expr_unop block if_rec
|
||||||
%left IS
|
%left IS
|
||||||
|
%token RETURN FUN AS
|
||||||
%%
|
%%
|
||||||
|
|
||||||
prog:
|
prog:
|
||||||
|
@ -76,30 +79,19 @@ prog:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
exprs:
|
sep: SEP | sep SEP;
|
||||||
exprs expr { $$ = $1 + $2; }
|
optsep: | sep;
|
||||||
|
|
||||||
| expr { $$ = $1; }
|
exprs:
|
||||||
|
exprs optsep instr sep { $$ = $1 + $3; }
|
||||||
|
| optsep instr sep { $$ = $2; }
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
any: expr { $$ = $1; } | instr { $$ = $1; };
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
CONTINUE {
|
WHILE expr block END {
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_CONTINUE, "", line);
|
|
||||||
stack_push(n);
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| BREAK {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_BREAK, "", line);
|
|
||||||
stack_push(n);
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| WHILE expr block END {
|
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_WHILE, "", line);
|
node_init(n, NODE_WHILE, "", line);
|
||||||
|
|
||||||
|
@ -144,24 +136,6 @@ expr:
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INDEX
|
|
||||||
| expr array ASSIGN expr {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_ASSIGN, "", line);
|
|
||||||
|
|
||||||
node* expr_node = stack_pop();
|
|
||||||
node* array_node = stack_pop();
|
|
||||||
node* ident_node = stack_pop();
|
|
||||||
|
|
||||||
node_add_child(n, ident_node);
|
|
||||||
node_add_child(n, array_node);
|
|
||||||
node_add_child(n, expr_node);
|
|
||||||
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| expr array {
|
| expr array {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_INDEX, "", line);
|
node_init(n, NODE_INDEX, "", line);
|
||||||
|
@ -185,51 +159,6 @@ expr:
|
||||||
| ident {
|
| ident {
|
||||||
}
|
}
|
||||||
|
|
||||||
| LET_MUT ident ASSIGN expr {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_VARDECL, "", line);
|
|
||||||
|
|
||||||
node* rhs = stack_pop();
|
|
||||||
node* lhs = stack_pop();
|
|
||||||
|
|
||||||
node_add_child(n, lhs);
|
|
||||||
node_add_child(n, rhs);
|
|
||||||
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| LET ident ASSIGN expr {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_CONSTDECL, "", line);
|
|
||||||
|
|
||||||
node* rhs = stack_pop();
|
|
||||||
node* lhs = stack_pop();
|
|
||||||
|
|
||||||
node_add_child(n, lhs);
|
|
||||||
node_add_child(n, rhs);
|
|
||||||
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
| ident ASSIGN expr {
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_ASSIGN, "", line);
|
|
||||||
|
|
||||||
node* rhs = stack_pop();
|
|
||||||
node* lhs = stack_pop();
|
|
||||||
|
|
||||||
node_add_child(n, lhs);
|
|
||||||
node_add_child(n, rhs);
|
|
||||||
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXPRESSIONS
|
// EXPRESSIONS
|
||||||
| array {
|
| array {
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
|
@ -239,16 +168,6 @@ expr:
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| ASSERT expr {
|
|
||||||
node *n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_ASSERT, "", line);
|
|
||||||
node_add_child(n, stack_pop());
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
$$ = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
| expr LT expr {
|
| expr LT expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_LT, "", line);
|
node_init(n, NODE_LT, "", line);
|
||||||
|
@ -415,10 +334,112 @@ expr:
|
||||||
|
|
||||||
| expr_unop {}
|
| expr_unop {}
|
||||||
|
|
||||||
|
| fun_call { $$ = $1; }
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
instr:
|
||||||
|
expr
|
||||||
|
|
||||||
|
| RETURN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_RETURN, "", line);
|
||||||
|
|
||||||
|
node_add_child(n, stack_pop());
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| ident ASSIGN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_ASSIGN, "", line);
|
||||||
|
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| LET_MUT ident ASSIGN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_VARDECL, "", line);
|
||||||
|
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| LET ident ASSIGN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_CONSTDECL, "", line);
|
||||||
|
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| CONTINUE {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_CONTINUE, "", line);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| BREAK {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_BREAK, "", line);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// INDEX
|
||||||
|
| expr array ASSIGN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_ASSIGN, "", line);
|
||||||
|
|
||||||
|
node* expr_node = stack_pop();
|
||||||
|
node* array_node = stack_pop();
|
||||||
|
node* ident_node = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, ident_node);
|
||||||
|
node_add_child(n, array_node);
|
||||||
|
node_add_child(n, expr_node);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| ASSERT expr {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_ASSERT, "", line);
|
||||||
|
node_add_child(n, stack_pop());
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
if_rec:
|
if_rec:
|
||||||
ELSE_COND IF_COND expr block if_rec {
|
ELSE_COND IF_COND expr block_or_expr if_rec {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_IF, "", line);
|
node_init(n, NODE_IF, "", line);
|
||||||
|
|
||||||
|
@ -435,7 +456,7 @@ if_rec:
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| ELSE_COND expr END {
|
| ELSE_COND block_or_expr END {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_IF, "", line);
|
node_init(n, NODE_IF, "", line);
|
||||||
|
|
||||||
|
@ -449,8 +470,10 @@ if_rec:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
block_or_expr: block | expr;
|
||||||
|
|
||||||
if:
|
if:
|
||||||
IF_COND expr block if_rec {
|
IF_COND expr block_or_expr if_rec {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_IF, "", line);
|
node_init(n, NODE_IF, "", line);
|
||||||
|
|
||||||
|
@ -467,7 +490,7 @@ if:
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| IF_COND expr block END {
|
| IF_COND expr block_or_expr END {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_IF, "", line);
|
node_init(n, NODE_IF, "", line);
|
||||||
|
|
||||||
|
@ -502,8 +525,168 @@ expr_unop:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
type_list:
|
fun_param:
|
||||||
|
ident AS type {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FUN_PARAM, "", line);
|
||||||
|
|
||||||
|
node* type_node = stack_pop();
|
||||||
|
node* ident_node = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, ident_node);
|
||||||
|
node_add_child(n, type_node);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun_param:
|
||||||
|
ident AS type
|
||||||
|
;
|
||||||
|
|
||||||
|
fun_params:
|
||||||
|
{ $$ = 0; }
|
||||||
|
| fun_param {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| fun_params COMMA fun_param {
|
||||||
|
$$ = $1 + $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
fun_ret_list:
|
||||||
type { $$ = $1; }
|
type { $$ = $1; }
|
||||||
|
| fun_ret_list COMMA type {
|
||||||
|
$$ = $1 + $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
fun_rets:
|
||||||
|
{
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FUN_RET, "", line);
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| AS fun_ret_list {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FUN_RET, "", line);
|
||||||
|
|
||||||
|
node* rets[$2];
|
||||||
|
|
||||||
|
for (size_t i=0; i<$2; i++)
|
||||||
|
{
|
||||||
|
rets[$2 - 1 - i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<$2; i++)
|
||||||
|
{
|
||||||
|
node_add_child(n, rets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
fun:
|
||||||
|
FUN OPAR fun_params CPAR fun_rets block END {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FUN, "", line);
|
||||||
|
|
||||||
|
node* block_node = stack_pop();
|
||||||
|
assert(block_node);
|
||||||
|
|
||||||
|
node* ret_node = stack_pop();
|
||||||
|
assert(ret_node);
|
||||||
|
|
||||||
|
if ($3 > 0)
|
||||||
|
{
|
||||||
|
node* params[$3];
|
||||||
|
|
||||||
|
for (size_t i=0; i<$3; i++)
|
||||||
|
{
|
||||||
|
params[i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<$3; i++)
|
||||||
|
{
|
||||||
|
node_add_child(n, params[$3 - 1 - i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node_add_child(n, ret_node);
|
||||||
|
node_add_child(n, block_node);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
fun_args:
|
||||||
|
expr_list {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_ARGS, "", line);
|
||||||
|
size_t const SZ = $1;
|
||||||
|
|
||||||
|
node* args[SZ];
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
args[$1 - 1 - i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
node_add_child(n, args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
fun_call:
|
||||||
|
MUL expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_CALL, "", line);
|
||||||
|
|
||||||
|
node* args = malloc(sizeof(node));
|
||||||
|
node_init(args, NODE_ARGS, "", line);
|
||||||
|
|
||||||
|
node* fn_expr = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, fn_expr);
|
||||||
|
node_add_child(n, args);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| expr fun_args {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_CALL, "", line);
|
||||||
|
|
||||||
|
node* args = stack_pop();
|
||||||
|
node* fn_expr = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, fn_expr);
|
||||||
|
node_add_child(n, args);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
type_list: { $$ = 0; }
|
||||||
|
| type { $$ = $1; }
|
||||||
| type_list COMMA type { $$ = $1 + $3; }
|
| type_list COMMA type { $$ = $1 + $3; }
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -533,10 +716,55 @@ block:
|
||||||
;
|
;
|
||||||
|
|
||||||
type:
|
type:
|
||||||
TYPE LT type_list GT {
|
FUN LT type_list COLON type_list GT {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FUN_TYPE, "", line);
|
||||||
|
|
||||||
|
node* right = malloc(sizeof(node));
|
||||||
|
node_init(right, NODE_TYPE, "", line);
|
||||||
|
|
||||||
|
size_t SZ = $5;
|
||||||
|
node* all_right[SZ];
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
all_right[i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
node_add_child(right, all_right[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
node* left = malloc(sizeof(node));
|
||||||
|
node_init(left, NODE_TYPE, "", line);
|
||||||
|
|
||||||
|
SZ = $3;
|
||||||
|
node* all_left[SZ];
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
all_left[i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
node_add_child(left, all_left[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_add_child(n, left);
|
||||||
|
node_add_child(n, right);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| TYPE LT type_list GT {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_TYPE, $1, line);
|
node_init(n, NODE_TYPE, $1, line);
|
||||||
free($1);
|
free($1);
|
||||||
|
|
||||||
size_t const SZ = $3;
|
size_t const SZ = $3;
|
||||||
node* all[SZ];
|
node* all[SZ];
|
||||||
|
|
||||||
|
@ -595,6 +823,7 @@ ident: IDENT {
|
||||||
|
|
||||||
builtins:
|
builtins:
|
||||||
type {}
|
type {}
|
||||||
|
| fun {}
|
||||||
|
|
||||||
| STRING {
|
| STRING {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
|
|
|
@ -37,6 +37,27 @@ void program_free(program* self)
|
||||||
self->pool.capacity = 0;
|
self->pool.capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program* program_new_clone(program* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
program* clone = malloc(sizeof(program));
|
||||||
|
program_init(clone);
|
||||||
|
|
||||||
|
for (size_t i=0; i < self->instrs.size; i++)
|
||||||
|
{
|
||||||
|
program_add_instr(clone, self->instrs.data[i]->opcode
|
||||||
|
, self->instrs.data[i]->param);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i < self->pool.size; i++)
|
||||||
|
{
|
||||||
|
assert(self->pool.data[i]);
|
||||||
|
program_add_pool(clone, self->pool.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
void program_set_instr(program* self, size_t index, int opcode, int param)
|
void program_set_instr(program* self, size_t index, int opcode, int param)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -99,11 +120,14 @@ size_t program_add_pool(program* self, value* val)
|
||||||
self->pool.capacity *= 2;
|
self->pool.capacity *= 2;
|
||||||
self->pool.data = realloc(
|
self->pool.data = realloc(
|
||||||
self->pool.data,
|
self->pool.data,
|
||||||
sizeof(value) * self->pool.capacity
|
sizeof(value*) * self->pool.capacity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t idx = self->pool.size;
|
size_t idx = self->pool.size;
|
||||||
self->pool.data[idx] = value_new_clone(val);
|
value* new_val = value_new_clone(val);
|
||||||
|
assert(new_val);
|
||||||
|
self->pool.data[idx] = new_val;
|
||||||
|
|
||||||
self->pool.size++;
|
self->pool.size++;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ typedef struct {
|
||||||
void program_init(program* self);
|
void program_init(program* self);
|
||||||
void program_free(program* self);
|
void program_free(program* self);
|
||||||
|
|
||||||
|
program* program_new_clone(program* self);
|
||||||
|
|
||||||
size_t program_add_instr(program* self, int opcode, int param);
|
size_t program_add_instr(program* self, int opcode, int param);
|
||||||
void program_set_instr(program* self, size_t index, int opcode, int param);
|
void program_set_instr(program* self, size_t index, int opcode, int param);
|
||||||
void program_set_param(program* self, size_t index, int param);
|
void program_set_param(program* self, size_t index, int param);
|
||||||
|
|
|
@ -42,6 +42,36 @@ void symentry_free(symentry* self)
|
||||||
free(self->ty);
|
free(self->ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symtable* symtable_new_clone(symtable* self)
|
||||||
|
{
|
||||||
|
symtable* clone = malloc(sizeof(symtable));
|
||||||
|
symtable_init(clone);
|
||||||
|
|
||||||
|
clone->entries.capacity = self->entries.capacity;
|
||||||
|
clone->entries.data = realloc(clone->entries.data,
|
||||||
|
sizeof(symentry*) * clone->entries.capacity);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
|
{
|
||||||
|
symentry* entry = self->entries.data[i];
|
||||||
|
symentry* clone_entry = malloc(sizeof(symentry));
|
||||||
|
|
||||||
|
clone_entry->id = entry->id;
|
||||||
|
clone_entry->name = str_new(entry->name);
|
||||||
|
clone_entry->is_mut = entry->is_mut;
|
||||||
|
clone_entry->scope = entry->scope;
|
||||||
|
clone_entry->ty = type_new_clone(entry->ty);
|
||||||
|
clone_entry->sym_node = node_new_clone(entry->sym_node);
|
||||||
|
clone->entries.data[i] = clone_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone->entries.size = self->entries.size;
|
||||||
|
clone->id = self->id;
|
||||||
|
clone->scope = self->scope;
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node)
|
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
|
@ -29,6 +29,7 @@ void symtable_init(symtable* self);
|
||||||
void symtable_free(symtable* self);
|
void symtable_free(symtable* self);
|
||||||
void symentry_free(symentry* self);
|
void symentry_free(symentry* self);
|
||||||
|
|
||||||
|
symtable* symtable_new_clone(symtable* self);
|
||||||
size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_node);
|
size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_node);
|
||||||
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node);
|
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node);
|
||||||
symentry* symtable_find(symtable* self, char const* name);
|
symentry* symtable_find(symtable* self, char const* name);
|
||||||
|
|
113
src/type.c
113
src/type.c
|
@ -12,6 +12,103 @@ void type_init(type* self, int base_type)
|
||||||
self->sub_types.data = malloc(sizeof(type*));
|
self->sub_types.data = malloc(sizeof(type*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type* type_init_from_node(node* root)
|
||||||
|
{
|
||||||
|
assert(root);
|
||||||
|
type* ty = malloc(sizeof(type));
|
||||||
|
|
||||||
|
if (root->type == NODE_FUN_TYPE)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_FUNCTION);
|
||||||
|
|
||||||
|
node* params = root->children.data[0];
|
||||||
|
|
||||||
|
for (size_t i=0; i< params->children.size; i++)
|
||||||
|
{
|
||||||
|
type* t = type_new_from_node(params->children.data[i]);
|
||||||
|
type_add_sub_type(ty, t);
|
||||||
|
type_free(t); free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
node* rets = root->children.data[1];
|
||||||
|
|
||||||
|
for (size_t i=0; i< rets->children.size; i++)
|
||||||
|
{
|
||||||
|
type* t = type_new_from_node(rets->children.data[i]);
|
||||||
|
type_add_sub_type(ty, t);
|
||||||
|
type_free(t); free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "fun") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_FUNCTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "int") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_INTEGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "float") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "str") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "bool") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_BOOLEAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "type") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(root->value, "array") == 0)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_ARRAY);
|
||||||
|
ty->kind = KIND_SEQUENTIAL;
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_ADD)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_TYPE);
|
||||||
|
ty->kind = KIND_DISJUNCTION;
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_MUL)
|
||||||
|
{
|
||||||
|
type_init(ty, TY_TYPE);
|
||||||
|
ty->kind = KIND_CONJUNCTION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char c[512];
|
||||||
|
node_str(root, c, 512);
|
||||||
|
printf("errnode = %s\n", c);
|
||||||
|
fprintf(stderr,
|
||||||
|
"E(%d): cannot compile unknown type '%s').\n",
|
||||||
|
root->lineno,
|
||||||
|
NodeTypeStr[root->type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<root->children.size; i++)
|
||||||
|
{
|
||||||
|
type* sub = type_new_from_node(root->children.data[i]);
|
||||||
|
type_add_sub_type(ty, sub);
|
||||||
|
type_free(sub);
|
||||||
|
free(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
void type_init_array(type* self, type* array_type)
|
void type_init_array(type* self, type* array_type)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -35,7 +132,12 @@ void type_free(type* self)
|
||||||
self->sub_types.size = 0;
|
self->sub_types.size = 0;
|
||||||
self->sub_types.capacity = 0;
|
self->sub_types.capacity = 0;
|
||||||
self->sub_types.data = NULL;
|
self->sub_types.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
type* type_new_from_node(node* root)
|
||||||
|
{
|
||||||
|
assert(root);
|
||||||
|
return type_init_from_node(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_add_sub_type(type* self, type* rhs)
|
void type_add_sub_type(type* self, type* rhs)
|
||||||
|
@ -92,7 +194,8 @@ int type_equals(type* self, type* rhs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->kind != KIND_SEQUENTIAL)
|
if (self->kind == KIND_CONJUNCTION
|
||||||
|
|| self->kind == KIND_DISJUNCTION)
|
||||||
{
|
{
|
||||||
for (int i=0; i<TY_TYPE_COUNT; i++)
|
for (int i=0; i<TY_TYPE_COUNT; i++)
|
||||||
{
|
{
|
||||||
|
@ -141,7 +244,13 @@ size_t type_str(type* self, char* buffer, size_t size)
|
||||||
|
|
||||||
for (size_t i=0; i<self->sub_types.size; i++)
|
for (size_t i=0; i<self->sub_types.size; i++)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
|
||||||
|
if ((i == 0 || self->sub_types.data[i - 1 ]->kind != KIND_RETURN)
|
||||||
|
&& self->sub_types.data[i]->kind == KIND_RETURN)
|
||||||
|
{
|
||||||
|
sz += snprintf(buffer + sz, size - sz, " : ");
|
||||||
|
}
|
||||||
|
else if (i > 0)
|
||||||
{
|
{
|
||||||
sz += snprintf(buffer + sz, size - sz, ", ");
|
sz += snprintf(buffer + sz, size - sz, ", ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define TYPE_H
|
#define TYPE_H
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
#define TYPES(G) \
|
#define TYPES(G) \
|
||||||
G(TY_NIL), \
|
G(TY_NIL), \
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
G(TY_STRING), \
|
G(TY_STRING), \
|
||||||
G(TY_ARRAY), \
|
G(TY_ARRAY), \
|
||||||
G(TY_TYPE), \
|
G(TY_TYPE), \
|
||||||
|
G(TY_FUNCTION), \
|
||||||
G(TY_TYPE_COUNT)
|
G(TY_TYPE_COUNT)
|
||||||
|
|
||||||
enum Types {
|
enum Types {
|
||||||
|
@ -22,7 +24,8 @@ extern char const* TypesStr[];
|
||||||
enum TypeKind {
|
enum TypeKind {
|
||||||
KIND_DISJUNCTION,
|
KIND_DISJUNCTION,
|
||||||
KIND_CONJUNCTION,
|
KIND_CONJUNCTION,
|
||||||
KIND_SEQUENTIAL
|
KIND_SEQUENTIAL,
|
||||||
|
KIND_RETURN
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct type {
|
typedef struct type {
|
||||||
|
@ -37,9 +40,11 @@ typedef struct type {
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
void type_init(type* self, int base_type);
|
void type_init(type* self, int base_type);
|
||||||
|
type* type_init_from_node(node* root);
|
||||||
void type_init_array(type* self, type* array_type);
|
void type_init_array(type* self, type* array_type);
|
||||||
void type_free(type* self);
|
void type_free(type* self);
|
||||||
|
|
||||||
|
type* type_new_from_node(node* root);
|
||||||
void type_add_sub_type(type* self, type* rhs);
|
void type_add_sub_type(type* self, type* rhs);
|
||||||
|
|
||||||
type* type_new_clone(type* self);
|
type* type_new_clone(type* self);
|
||||||
|
|
35
src/value.c
35
src/value.c
|
@ -67,6 +67,17 @@ void value_init_type(value* self, type* ty, int lineno)
|
||||||
type_init(self->type, TY_TYPE);
|
type_init(self->type, TY_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value_init_fun(value* self, fun* f, int lineno)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(f);
|
||||||
|
|
||||||
|
self->val.fun_val = fun_new_clone(f);
|
||||||
|
|
||||||
|
self->lineno = lineno;
|
||||||
|
self->type = type_new_clone(f->ty);
|
||||||
|
}
|
||||||
|
|
||||||
void value_free(value* self)
|
void value_free(value* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -94,6 +105,14 @@ void value_free(value* self)
|
||||||
self->val.array_val = NULL;
|
self->val.array_val = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_FUNCTION
|
||||||
|
&& self->val.fun_val != NULL)
|
||||||
|
{
|
||||||
|
fun_free(self->val.fun_val);
|
||||||
|
free(self->val.fun_val);
|
||||||
|
self->val.fun_val = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
type_free(self->type);
|
type_free(self->type);
|
||||||
free(self->type);
|
free(self->type);
|
||||||
self->type = NULL;
|
self->type = NULL;
|
||||||
|
@ -121,6 +140,11 @@ value* value_new_clone(value* self)
|
||||||
clone->val.array_val = array_new_clone(self->val.array_val);
|
clone->val.array_val = array_new_clone(self->val.array_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_FUNCTION)
|
||||||
|
{
|
||||||
|
clone->val.fun_val = fun_new_clone(self->val.fun_val);
|
||||||
|
}
|
||||||
|
|
||||||
clone->lineno = self->lineno;
|
clone->lineno = self->lineno;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
@ -167,6 +191,11 @@ int value_equals(value* self, value* rhs)
|
||||||
return array_equals(self->val.array_val, rhs->val.array_val);
|
return array_equals(self->val.array_val, rhs->val.array_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_FUNCTION)
|
||||||
|
{
|
||||||
|
return fun_equals(self->val.fun_val, rhs->val.fun_val);
|
||||||
|
}
|
||||||
|
|
||||||
size_t const SZ = 512;
|
size_t const SZ = 512;
|
||||||
char ty_str[SZ];
|
char ty_str[SZ];
|
||||||
|
|
||||||
|
@ -190,6 +219,12 @@ size_t value_str(value* self, char* buffer, size_t size)
|
||||||
case TY_ARRAY:
|
case TY_ARRAY:
|
||||||
return array_str(self->val.array_val, buffer, size);
|
return array_str(self->val.array_val, buffer, size);
|
||||||
|
|
||||||
|
case TY_FUNCTION:
|
||||||
|
return fun_str(self->val.fun_val, buffer, size);
|
||||||
|
|
||||||
|
case TY_FLOAT:
|
||||||
|
return snprintf(buffer, size, "%f",
|
||||||
|
self->val.real_float);
|
||||||
case TY_STRING:
|
case TY_STRING:
|
||||||
return snprintf(buffer, size, "%s",
|
return snprintf(buffer, size, "%s",
|
||||||
self->val.string);
|
self->val.string);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
#include "fun.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
type* type;
|
type* type;
|
||||||
|
@ -15,6 +16,8 @@ typedef struct {
|
||||||
char* string;
|
char* string;
|
||||||
array* array_val;
|
array* array_val;
|
||||||
type* type_val;
|
type* type_val;
|
||||||
|
fun* fun_val;
|
||||||
|
|
||||||
} val;
|
} val;
|
||||||
} value;
|
} value;
|
||||||
|
|
||||||
|
@ -24,6 +27,7 @@ void value_init_float(value* self, float real_float, int lineno);
|
||||||
void value_init_string(value* self, char* string, int lineno);
|
void value_init_string(value* self, char* string, int lineno);
|
||||||
void value_init_array(value* self, array* arr, int lineno);
|
void value_init_array(value* self, array* arr, int lineno);
|
||||||
void value_init_type(value* self, type* ty, int lineno);
|
void value_init_type(value* self, type* ty, int lineno);
|
||||||
|
void value_init_fun(value* self, fun* f, int lineno);
|
||||||
|
|
||||||
void value_free(value* self);
|
void value_free(value* self);
|
||||||
|
|
||||||
|
|
51
src/vm.c
51
src/vm.c
|
@ -109,6 +109,9 @@ void vm_exec(vm* self, program* prog)
|
||||||
|
|
||||||
case OP_TEQ: vm_teq(self); break;
|
case OP_TEQ: vm_teq(self); break;
|
||||||
|
|
||||||
|
case OP_CALL: vm_call(self, param); break;
|
||||||
|
case OP_RET: vm_ret(self); break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
OpcodesStr[opcode]);
|
OpcodesStr[opcode]);
|
||||||
|
@ -1142,3 +1145,51 @@ void vm_br(vm* self, int param)
|
||||||
assert(self);
|
assert(self);
|
||||||
self->pc = param;
|
self->pc = param;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_call(vm* self, int param)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
// get function and parameters
|
||||||
|
value* args[param];
|
||||||
|
|
||||||
|
for (int i=0; i<param; i++)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
vm_push_value(self, ret);
|
||||||
|
|
||||||
|
vm_free(&v);
|
||||||
|
|
||||||
|
for (int i=0; i<param; i++)
|
||||||
|
{
|
||||||
|
value_free(args[i]); free(args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_free(fun_val); free(fun_val);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_ret(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->pc = self->prog->instrs.size;
|
||||||
|
}
|
||||||
|
|
3
src/vm.h
3
src/vm.h
|
@ -95,4 +95,7 @@ void vm_teq(vm* self);
|
||||||
void vm_brf(vm* self, int param);
|
void vm_brf(vm* self, int param);
|
||||||
void vm_br(vm* self, int param);
|
void vm_br(vm* self, int param);
|
||||||
|
|
||||||
|
void vm_call(vm* self, int param);
|
||||||
|
void vm_ret(vm* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
let f = fun () as int return 1.2; end ; f
|
|
@ -1,8 +1,8 @@
|
||||||
let x = 0 x + 1.2
|
let x = 0 ; x + 1.2
|
||||||
let x = false x + "false"
|
let x = false ; x + "false"
|
||||||
let x=0 let x=7
|
let x=0 ; let x=7
|
||||||
let x=[1, 2] x[7, 9]
|
let x=[1, 2] ; x[7, 9]
|
||||||
let x = 0 x = 3.2
|
let x = 0 ; x = 3.2
|
||||||
let x = 0 x = 7
|
let x = 0 ; x = 7
|
||||||
let x=[1, 2] x[0] = 3.2
|
let x=[1, 2] ; x[0] = 3.2
|
||||||
let x=[3, 4] x[0] = 7
|
let x=[3, 4] ; x[0] = 7
|
||||||
|
|
|
@ -9,7 +9,6 @@ echo -e "\e[34m=== Error Testing ===\e[0m"
|
||||||
for file in $(find . -name "err_*.wuz")
|
for file in $(find . -name "err_*.wuz")
|
||||||
do
|
do
|
||||||
LINE=1
|
LINE=1
|
||||||
|
|
||||||
while read line;
|
while read line;
|
||||||
do
|
do
|
||||||
echo "$line" | wuz &> /dev/null
|
echo "$line" | wuz &> /dev/null
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
assert fun<int:int> is type
|
||||||
|
assert fun<int:> is type
|
||||||
|
assert fun<:int> is type
|
||||||
|
assert fun<int, int: float, str> is type
|
||||||
|
assert fun< fun<:> : int> is type
|
||||||
|
|
||||||
|
let a = fun (x as int, y as int) as int
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
assert a is fun<int, int: int>
|
||||||
|
assert !(a is fun<:>)
|
||||||
|
|
||||||
|
let b = fun (x as int) as int
|
||||||
|
return x * 7
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 42 == b 6
|
||||||
|
|
||||||
|
let c = fun () as int
|
||||||
|
return 3 * 6
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 18 == *c
|
||||||
|
|
||||||
|
let d = fun () as int
|
||||||
|
return 43
|
||||||
|
27
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 43 == *d
|
||||||
|
|
|
@ -20,3 +20,4 @@ assert 64 == 2^(3+3)
|
||||||
assert 1 == -2 - -3
|
assert 1 == -2 - -3
|
||||||
|
|
||||||
assert 5 + 7 == 12
|
assert 5 + 7 == 12
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue