Compare commits
No commits in common. "d1286c008bf6a147d20b2d0af7a280244eee35ae" and "85875d2d946b8c139d5a7b78242cf91cbe0c997f" have entirely different histories.
d1286c008b
...
85875d2d94
|
@ -17,14 +17,13 @@ LEXPR ::=
|
||||||
| continue
|
| continue
|
||||||
| return EXPR?
|
| return EXPR?
|
||||||
| FUN
|
| FUN
|
||||||
| new EXPR
|
|
||||||
| free EXPR
|
|
||||||
|
|
||||||
BEXPR ::=
|
BEXPR ::=
|
||||||
| BLOCK
|
| BLOCK
|
||||||
| IF
|
| IF
|
||||||
| WHILE
|
| WHILE
|
||||||
|
|
||||||
|
|
||||||
IF ::=
|
IF ::=
|
||||||
| if EXPR BLOCK
|
| if EXPR BLOCK
|
||||||
| if EXPR BLOCK else BLOCK
|
| if EXPR BLOCK else BLOCK
|
||||||
|
@ -35,7 +34,7 @@ WHILE ::= while EXPR BLOCK
|
||||||
FUN ::= fun PARAMS (rarrow TYPE) BLOCK
|
FUN ::= fun PARAMS (rarrow TYPE) BLOCK
|
||||||
|
|
||||||
PARAMS ::=
|
PARAMS ::=
|
||||||
| opar var? ident colon TYPE (comma var? ident colon type)* cpar
|
| opar ident colon TYPE (comma ident colon type)* cpar
|
||||||
|
|
||||||
BLOCK ::= obrace INSTR* cbrace
|
BLOCK ::= obrace INSTR* cbrace
|
||||||
VARDECL ::= var ident colon TYPE? assign EXPR
|
VARDECL ::= var ident colon TYPE? assign EXPR
|
||||||
|
@ -68,4 +67,3 @@ BUILTIN ::= bool | int | float | string
|
||||||
TYPE ::=
|
TYPE ::=
|
||||||
| type
|
| type
|
||||||
| opar TYPE+ rarrow TYPE+ cpar
|
| opar TYPE+ rarrow TYPE+ cpar
|
||||||
| rawptr TYPE
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if (type_checker_check(&checker, ast) != 0)
|
if (type_checker_check(&checker, ast) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[%s:%d] type check error, %s\n",
|
fprintf(stderr, "[%s:%d] %s\n",
|
||||||
path,
|
path,
|
||||||
checker.error_line,
|
checker.error_line,
|
||||||
checker.error_msg);
|
checker.error_msg);
|
||||||
|
@ -215,7 +215,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if (compiler_compile(&compiler, ast, &program) != 0)
|
if (compiler_compile(&compiler, ast, &program) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[%s:%d] compile error, %s\n",
|
fprintf(stderr, "[%s:%d] %s\n",
|
||||||
path,
|
path,
|
||||||
compiler.error_line,
|
compiler.error_line,
|
||||||
compiler.error_msg);
|
compiler.error_msg);
|
||||||
|
|
|
@ -18,7 +18,6 @@ void compiler_init(struct compiler* self, struct sym_table* global)
|
||||||
memset(self->error_msg, 0, GUX_STR_SIZE);
|
memset(self->error_msg, 0, GUX_STR_SIZE);
|
||||||
self->stack_size = 0;
|
self->stack_size = 0;
|
||||||
vec_init(&self->loops, 1);
|
vec_init(&self->loops, 1);
|
||||||
self->heap_addr_counter = 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_free(struct compiler* self)
|
void compiler_free(struct compiler* self)
|
||||||
|
@ -39,21 +38,6 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case NODE_NEW: {
|
|
||||||
compiler_compile(self, node->children.data[0], program);
|
|
||||||
compiler_gen_instr(self, program, OP_NEW, self->heap_addr_counter++);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_FREE: {
|
|
||||||
struct node* ident = node->children.data[0];
|
|
||||||
|
|
||||||
struct sym* entry = sym_table_fetch(&self->sym_table,
|
|
||||||
ident->value,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
compiler_gen_instr(self, program, OP_FREE, entry->addr);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_RETURN: {
|
case NODE_RETURN: {
|
||||||
if (node->children.size > 0)
|
if (node->children.size > 0)
|
||||||
{
|
{
|
||||||
|
@ -81,11 +65,7 @@ int compiler_compile(struct compiler* self,
|
||||||
{
|
{
|
||||||
struct node* param = params->children.data[i];
|
struct node* param = params->children.data[i];
|
||||||
|
|
||||||
if (param->type == NODE_VAR)
|
if (param->type != NODE_TYPE)
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (param->type != NODE_TYPE)
|
|
||||||
{
|
{
|
||||||
vec_push(&idents, param);
|
vec_push(&idents, param);
|
||||||
}
|
}
|
||||||
|
@ -96,7 +76,8 @@ int compiler_compile(struct compiler* self,
|
||||||
struct node* ident = idents.data[j];
|
struct node* ident = idents.data[j];
|
||||||
|
|
||||||
struct type* ty = malloc(sizeof(struct type));
|
struct type* ty = malloc(sizeof(struct type));
|
||||||
type_init_from_node(ty, param);
|
type_init(ty, TYPE_VOID);
|
||||||
|
compiler_get_type(self, param, ty);
|
||||||
|
|
||||||
sym_table_declare_const(&compiler.sym_table,
|
sym_table_declare_const(&compiler.sym_table,
|
||||||
ident->value,
|
ident->value,
|
||||||
|
@ -274,32 +255,13 @@ int compiler_compile(struct compiler* self,
|
||||||
struct node* ident = node->children.data[0];
|
struct node* ident = node->children.data[0];
|
||||||
struct node* expr = node->children.data[1];
|
struct node* expr = node->children.data[1];
|
||||||
|
|
||||||
struct type lhs_ty;
|
|
||||||
type_init(&lhs_ty, TYPE_VOID);
|
|
||||||
compiler_get_type(self, ident, &lhs_ty);
|
|
||||||
|
|
||||||
int is_ptr = lhs_ty.kind == TYPE_RAW_PTR;
|
|
||||||
|
|
||||||
struct type type;
|
struct type type;
|
||||||
type_init(&type, TYPE_VOID);
|
type_init(&type, TYPE_VOID);
|
||||||
compiler_get_type(self, expr, &type);
|
compiler_get_type(self, expr, &type);
|
||||||
|
|
||||||
struct sym* entry;
|
struct sym* entry = sym_table_fetch(&self->sym_table,
|
||||||
|
ident->value,
|
||||||
if (is_ptr)
|
&type);
|
||||||
{
|
|
||||||
entry = sym_table_fetch(&self->sym_table,
|
|
||||||
ident->value,
|
|
||||||
&lhs_ty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry = sym_table_fetch(&self->sym_table,
|
|
||||||
ident->value,
|
|
||||||
&type);
|
|
||||||
}
|
|
||||||
|
|
||||||
type_free(&lhs_ty);
|
|
||||||
type_free(&type);
|
type_free(&type);
|
||||||
|
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
@ -309,8 +271,7 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_gen_instr(self, program, is_ptr ? OP_REFSTORE : OP_STORE,
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
||||||
entry->addr);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
|
@ -338,11 +299,11 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
case NODE_CONSTDECL:
|
case NODE_CONSTDECL:
|
||||||
case NODE_VARDECL: {
|
case NODE_VARDECL: {
|
||||||
struct node* rhs = node->children.size == 1
|
|
||||||
? node->children.data[0]
|
|
||||||
: node->children.data[1];
|
|
||||||
|
|
||||||
int err = compiler_compile(self, rhs, program);
|
int err = compiler_compile(self, node->children.size == 1
|
||||||
|
? node->children.data[0]
|
||||||
|
: node->children.data[1],
|
||||||
|
program);
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +312,7 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
struct type* ty = malloc(sizeof(struct type));
|
struct type* ty = malloc(sizeof(struct type));
|
||||||
type_init(ty, TYPE_VOID);
|
type_init(ty, TYPE_VOID);
|
||||||
compiler_get_type(self, rhs, ty);
|
compiler_get_type(self, node->children.data[0], ty);
|
||||||
|
|
||||||
sym_table_declare(&self->sym_table, node->value, ty,
|
sym_table_declare(&self->sym_table, node->value, ty,
|
||||||
node->type == NODE_VARDECL);
|
node->type == NODE_VARDECL);
|
||||||
|
@ -359,10 +320,10 @@ int compiler_compile(struct compiler* self,
|
||||||
struct sym* entry = sym_table_fetch(&self->sym_table,
|
struct sym* entry = sym_table_fetch(&self->sym_table,
|
||||||
node->value,
|
node->value,
|
||||||
ty);
|
ty);
|
||||||
|
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
|
||||||
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NODE_BOOL: {
|
case NODE_BOOL: {
|
||||||
struct value* val = malloc(sizeof(struct value));
|
struct value* val = malloc(sizeof(struct value));
|
||||||
|
@ -676,7 +637,6 @@ size_t compiler_gen_instr(struct compiler* self,
|
||||||
case OP_GLOAD:
|
case OP_GLOAD:
|
||||||
case OP_PUSH: self->stack_size += 1; break;
|
case OP_PUSH: self->stack_size += 1; break;
|
||||||
|
|
||||||
case OP_FREE:
|
|
||||||
case OP_LT:
|
case OP_LT:
|
||||||
case OP_LE:
|
case OP_LE:
|
||||||
case OP_GT:
|
case OP_GT:
|
||||||
|
@ -694,17 +654,12 @@ size_t compiler_gen_instr(struct compiler* self,
|
||||||
case OP_BRT:
|
case OP_BRT:
|
||||||
self->stack_size -= 1; break;
|
self->stack_size -= 1; break;
|
||||||
|
|
||||||
case OP_DEREF:
|
|
||||||
case OP_NEW:
|
|
||||||
case OP_RET:
|
case OP_RET:
|
||||||
case OP_SWAP:
|
case OP_SWAP:
|
||||||
case OP_BR:
|
case OP_BR:
|
||||||
case OP_NOT:
|
case OP_NOT:
|
||||||
case OP_NOP:
|
case OP_NOP:
|
||||||
case OP_STORE:
|
case OP_STORE: break;
|
||||||
case OP_REFSTORE:break;
|
|
||||||
|
|
||||||
default: assert(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
|
|
|
@ -17,7 +17,6 @@ struct compiler {
|
||||||
int error_line;
|
int error_line;
|
||||||
int stack_size;
|
int stack_size;
|
||||||
struct vec loops;
|
struct vec loops;
|
||||||
int heap_addr_counter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void compiler_init(struct compiler* self, struct sym_table* global);
|
void compiler_init(struct compiler* self, struct sym_table* global);
|
||||||
|
|
|
@ -26,14 +26,11 @@ void lexer_init(struct lexer* self, char const* source)
|
||||||
|
|
||||||
lexer_add_tok(self, "var", NODE_VAR, "", 1);
|
lexer_add_tok(self, "var", NODE_VAR, "", 1);
|
||||||
|
|
||||||
lexer_add_tok(self, "new", NODE_NEW, "", 1);
|
|
||||||
lexer_add_tok(self, "free", NODE_FREE, "", 1);
|
|
||||||
lexer_add_tok(self, "int", NODE_TYPE, "int", 1);
|
lexer_add_tok(self, "int", NODE_TYPE, "int", 1);
|
||||||
lexer_add_tok(self, "float", NODE_TYPE, "float", 1);
|
lexer_add_tok(self, "float", NODE_TYPE, "float", 1);
|
||||||
lexer_add_tok(self, "bool", NODE_TYPE, "bool", 1);
|
lexer_add_tok(self, "bool", NODE_TYPE, "bool", 1);
|
||||||
lexer_add_tok(self, "string", NODE_TYPE, "string", 1);
|
lexer_add_tok(self, "string", NODE_TYPE, "string", 1);
|
||||||
|
|
||||||
lexer_add_tok(self, "^", NODE_PTR, "", 0);
|
|
||||||
lexer_add_tok(self, ",", NODE_COMMA, "", 0);
|
lexer_add_tok(self, ",", NODE_COMMA, "", 0);
|
||||||
lexer_add_tok(self, "{", NODE_OBRACE, "", 0);
|
lexer_add_tok(self, "{", NODE_OBRACE, "", 0);
|
||||||
lexer_add_tok(self, "}", NODE_CBRACE, "", 0);
|
lexer_add_tok(self, "}", NODE_CBRACE, "", 0);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
G(NODE_IF), G(NODE_ELSE), G(NODE_COND), G(NODE_WHILE), G(NODE_FOR), \
|
G(NODE_IF), G(NODE_ELSE), G(NODE_COND), G(NODE_WHILE), G(NODE_FOR), \
|
||||||
G(NODE_CONTINUE), G(NODE_BREAK), G(NODE_RARROW), G(NODE_FUN), \
|
G(NODE_CONTINUE), G(NODE_BREAK), G(NODE_RARROW), G(NODE_FUN), \
|
||||||
G(NODE_RETURN), G(NODE_PARAMS), G(NODE_COMMA), G(NODE_CALL), \
|
G(NODE_RETURN), G(NODE_PARAMS), G(NODE_COMMA), G(NODE_CALL), \
|
||||||
G(NODE_ARGS), G(NODE_RAWPTR), G(NODE_PTR), G(NODE_FREE), G(NODE_NEW)
|
G(NODE_ARGS)
|
||||||
|
|
||||||
|
|
||||||
GUX_ENUM_H(NodeType, NODE_TYPE);
|
GUX_ENUM_H(NodeType, NODE_TYPE);
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
G(OP_BRT), G(OP_NOP), G(OP_NOT), G(OP_EQ), \
|
G(OP_BRT), G(OP_NOP), G(OP_NOT), G(OP_EQ), \
|
||||||
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
||||||
G(OP_LT), G(OP_LE), G(OP_GT),G(OP_GE), G(OP_LOAD), G(OP_STORE), \
|
G(OP_LT), G(OP_LE), G(OP_GT),G(OP_GE), G(OP_LOAD), G(OP_STORE), \
|
||||||
G(OP_SWAP), G(OP_CALL), G(OP_RET), G(OP_GLOAD), G(OP_NEW), \
|
G(OP_SWAP), G(OP_CALL), G(OP_RET), G(OP_GLOAD)
|
||||||
G(OP_FREE), G(OP_DEREF), G(OP_REFSTORE)
|
|
||||||
|
|
||||||
#include <commons.h>
|
#include <commons.h>
|
||||||
|
|
||||||
|
|
|
@ -149,8 +149,7 @@ int parser_start_type(struct parser* self)
|
||||||
struct node* tok = self->tokens.data[self->cursor];
|
struct node* tok = self->tokens.data[self->cursor];
|
||||||
|
|
||||||
return tok->type == NODE_OPAR
|
return tok->type == NODE_OPAR
|
||||||
|| tok->type == NODE_TYPE
|
|| tok->type == NODE_TYPE;
|
||||||
|| tok->type == NODE_PTR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node* parser_try_new_root(struct parser* self, char const* source)
|
struct node* parser_try_new_root(struct parser* self, char const* source)
|
||||||
|
@ -233,29 +232,11 @@ struct node* parser_try_new_lexpr(struct parser* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if (parser_try_consume(self, NODE_FREE) == 0)
|
|
||||||
{
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_FREE, "", parser_current_line(self));
|
|
||||||
node_add_child(node, parser_try_new_expr(self));
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser_type_is(self, NODE_FUN, 0))
|
if (parser_type_is(self, NODE_FUN, 0))
|
||||||
{
|
{
|
||||||
return parser_try_new_fun(self);
|
return parser_try_new_fun(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser_try_consume(self, NODE_NEW) == 0)
|
|
||||||
{
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_NEW, "", parser_current_line(self));
|
|
||||||
|
|
||||||
node_add_child(node, parser_try_new_expr(self));
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser_try_consume(self, NODE_RETURN) == 0)
|
if (parser_try_consume(self, NODE_RETURN) == 0)
|
||||||
{
|
{
|
||||||
struct node* node = malloc(sizeof(struct node));
|
struct node* node = malloc(sizeof(struct node));
|
||||||
|
@ -444,8 +425,7 @@ struct node* parser_try_new_params(struct parser* self)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (!parser_type_is(self, NODE_IDENT, 0)
|
if (!parser_type_is(self, NODE_IDENT, 0))
|
||||||
&& !parser_type_is(self, NODE_VAR, 0))
|
|
||||||
{
|
{
|
||||||
vec_free_elements(&types);
|
vec_free_elements(&types);
|
||||||
vec_free(&types);
|
vec_free(&types);
|
||||||
|
@ -454,14 +434,6 @@ struct node* parser_try_new_params(struct parser* self)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser_try_consume(self, NODE_VAR) == 0)
|
|
||||||
{
|
|
||||||
struct node* var = malloc(sizeof(struct node));
|
|
||||||
node_init(var, NODE_VAR, "",
|
|
||||||
parser_current_line(self));
|
|
||||||
node_add_child(node, var);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ident
|
// ident
|
||||||
struct node* current = self->tokens.data[self->cursor];
|
struct node* current = self->tokens.data[self->cursor];
|
||||||
struct node* ident = malloc(sizeof(struct node));
|
struct node* ident = malloc(sizeof(struct node));
|
||||||
|
@ -592,9 +564,14 @@ struct node* parser_try_new_vardecl(struct parser* self)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser_type_is(self, NODE_TYPE, 0)
|
if (parser_type_is(self, NODE_TYPE, 0))
|
||||||
|| parser_type_is(self, NODE_PTR, 0))
|
|
||||||
{
|
{
|
||||||
|
/*current = self->tokens.data[self->cursor];
|
||||||
|
struct node* ty = malloc(sizeof(struct node));
|
||||||
|
node_init(ty, NODE_TYPE, current->value, parser_current_line(self));
|
||||||
|
|
||||||
|
node_add_child(node, ty);
|
||||||
|
self->cursor++;*/
|
||||||
node_add_child(node, parser_try_new_type(self));
|
node_add_child(node, parser_try_new_type(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,14 +953,6 @@ struct node* parser_try_new_type(struct parser* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if (parser_try_consume(self, NODE_PTR) == 0)
|
|
||||||
{
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_TYPE, "rawptr", parser_current_line(self));
|
|
||||||
node_add_child(node, parser_try_new_type(self));
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser_type_is(self, NODE_OPAR, 0))
|
if (parser_type_is(self, NODE_OPAR, 0))
|
||||||
{
|
{
|
||||||
self->cursor++; // opar
|
self->cursor++; // opar
|
||||||
|
|
|
@ -14,13 +14,10 @@ void program_free(struct program* self)
|
||||||
|
|
||||||
for (size_t i=0; i<self->constant_pool.size; i++)
|
for (size_t i=0; i<self->constant_pool.size; i++)
|
||||||
{
|
{
|
||||||
if (self->constant_pool.data[i] != NULL)
|
value_free(self->constant_pool.data[i]);
|
||||||
{
|
|
||||||
value_free(self->constant_pool.data[i]);
|
|
||||||
free(self->constant_pool.data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec_free_elements(&self->constant_pool);
|
||||||
vec_free(&self->constant_pool);
|
vec_free(&self->constant_pool);
|
||||||
|
|
||||||
vec_free_elements(&self->instructions);
|
vec_free_elements(&self->instructions);
|
||||||
|
|
|
@ -12,12 +12,6 @@ void sym_table_init(struct sym_table* self, struct sym_table* prev)
|
||||||
self->addr_counter = 0;
|
self->addr_counter = 0;
|
||||||
|
|
||||||
self->prev = prev;
|
self->prev = prev;
|
||||||
self->next = NULL;
|
|
||||||
|
|
||||||
if (self->prev && self->prev->next == NULL)
|
|
||||||
{
|
|
||||||
self->prev->next = self;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sym_table_free(struct sym_table* self)
|
void sym_table_free(struct sym_table* self)
|
||||||
|
@ -102,7 +96,7 @@ struct sym* sym_table_fetch(struct sym_table* self,
|
||||||
|
|
||||||
if (self->prev)
|
if (self->prev)
|
||||||
{
|
{
|
||||||
return sym_table_fetch(self->prev, name, type);
|
return sym_table_fetch(self->prev, name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -115,15 +109,8 @@ struct sym* sym_table_fetch_fun(struct sym_table* self,
|
||||||
struct vec args_ty;
|
struct vec args_ty;
|
||||||
vec_init(&args_ty, 1);
|
vec_init(&args_ty, 1);
|
||||||
|
|
||||||
struct sym_table* itr = self;
|
|
||||||
|
|
||||||
while (itr->next)
|
|
||||||
{
|
|
||||||
itr = itr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct type_resolver resolver;
|
struct type_resolver resolver;
|
||||||
type_resolver_init(&resolver, itr);
|
type_resolver_init(&resolver, self);
|
||||||
|
|
||||||
for (size_t i=0; i < args->children.size; i++)
|
for (size_t i=0; i < args->children.size; i++)
|
||||||
{
|
{
|
||||||
|
@ -132,7 +119,6 @@ struct sym* sym_table_fetch_fun(struct sym_table* self,
|
||||||
type_init(arg_type, TYPE_VOID);
|
type_init(arg_type, TYPE_VOID);
|
||||||
|
|
||||||
type_resolver_resolve(&resolver, child, arg_type);
|
type_resolver_resolve(&resolver, child, arg_type);
|
||||||
|
|
||||||
vec_push(&args_ty, arg_type);
|
vec_push(&args_ty, arg_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +177,7 @@ struct sym* sym_table_fetch_fun(struct sym_table* self,
|
||||||
|
|
||||||
if (self->prev)
|
if (self->prev)
|
||||||
{
|
{
|
||||||
return sym_table_fetch_fun(self->prev, name, args);
|
return sym_table_fetch(self->prev, name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -219,7 +205,7 @@ int sym_table_declare(struct sym_table* self,
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(strcmp(name, "") != 0);
|
assert(strcmp(name, "") != 0);
|
||||||
|
|
||||||
struct sym* s = sym_table_fetch(self, name, new_type);
|
struct sym* s = sym_table_fetch(self, name, NULL);
|
||||||
|
|
||||||
if (s && s->parent == self->root
|
if (s && s->parent == self->root
|
||||||
&& type_equals(s->type, new_type))
|
&& type_equals(s->type, new_type))
|
||||||
|
@ -233,7 +219,7 @@ int sym_table_declare(struct sym_table* self,
|
||||||
sym->type = new_type;
|
sym->type = new_type;
|
||||||
sym->parent = self->root;
|
sym->parent = self->root;
|
||||||
sym->is_global = 0;
|
sym->is_global = 0;
|
||||||
sym->type->is_var = is_var;
|
sym->is_var = is_var;
|
||||||
sym->addr = self->addr_counter;
|
sym->addr = self->addr_counter;
|
||||||
vec_push(&table->syms, sym);
|
vec_push(&table->syms, sym);
|
||||||
|
|
||||||
|
@ -250,7 +236,7 @@ int sym_table_declare_global(struct sym_table* self,
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(strcmp(name, "") != 0);
|
assert(strcmp(name, "") != 0);
|
||||||
|
|
||||||
struct sym* s = sym_table_fetch(self, name, new_type);
|
struct sym* s = sym_table_fetch(self, name, NULL);
|
||||||
|
|
||||||
if (s && s->parent == self->root && s->is_global
|
if (s && s->parent == self->root && s->is_global
|
||||||
&& type_equals(s->type, new_type))
|
&& type_equals(s->type, new_type))
|
||||||
|
@ -264,7 +250,7 @@ int sym_table_declare_global(struct sym_table* self,
|
||||||
sym->type = new_type;
|
sym->type = new_type;
|
||||||
sym->parent = self->root;
|
sym->parent = self->root;
|
||||||
sym->is_global = 1;
|
sym->is_global = 1;
|
||||||
sym->type->is_var = 0;
|
sym->is_var = 0;
|
||||||
sym->addr = addr;
|
sym->addr = addr;
|
||||||
vec_push(&table->syms, sym);
|
vec_push(&table->syms, sym);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
struct sym {
|
struct sym {
|
||||||
struct table* parent;
|
struct table* parent;
|
||||||
char* name;
|
char* name;
|
||||||
//int is_var;
|
int is_var;
|
||||||
int is_global;
|
int is_global;
|
||||||
int addr;
|
int addr;
|
||||||
struct type* type;
|
struct type* type;
|
||||||
|
@ -20,7 +20,6 @@ struct table {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sym_table {
|
struct sym_table {
|
||||||
struct sym_table* next;
|
|
||||||
struct sym_table* prev;
|
struct sym_table* prev;
|
||||||
struct table* root;
|
struct table* root;
|
||||||
int addr_counter;
|
int addr_counter;
|
||||||
|
|
|
@ -8,7 +8,6 @@ void type_init(struct type* self, enum TypeKind kind)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
self->kind = kind;
|
self->kind = kind;
|
||||||
self->is_var = 0;
|
|
||||||
vec_init(&self->subtypes, 1);
|
vec_init(&self->subtypes, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,17 +15,9 @@ void type_init_from_node(struct type* self, struct node* node)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
self->is_var = 0;
|
|
||||||
vec_init(&self->subtypes, 1);
|
vec_init(&self->subtypes, 1);
|
||||||
|
|
||||||
if (node->type == NODE_TYPE && strcmp(node->value, "rawptr") == 0)
|
if (node->type == NODE_TYPE && strcmp(node->value, "fun") == 0)
|
||||||
{
|
|
||||||
self->kind = TYPE_RAW_PTR;
|
|
||||||
type_add_subtype(self, TYPE_VOID);
|
|
||||||
type_free(self->subtypes.data[0]);
|
|
||||||
type_init_from_node(self->subtypes.data[0], node->children.data[0]);
|
|
||||||
}
|
|
||||||
else if (node->type == NODE_TYPE && strcmp(node->value, "fun") == 0)
|
|
||||||
{
|
{
|
||||||
self->kind = TYPE_FUN;
|
self->kind = TYPE_FUN;
|
||||||
int input = 1;
|
int input = 1;
|
||||||
|
@ -77,23 +68,14 @@ void type_init_from_node(struct type* self, struct node* node)
|
||||||
type_init_from_node(ret_ty, ret);
|
type_init_from_node(ret_ty, ret);
|
||||||
vec_push(&self->subtypes, ret_ty);
|
vec_push(&self->subtypes, ret_ty);
|
||||||
|
|
||||||
int is_var = 0;
|
|
||||||
|
|
||||||
for (size_t i=0; i<params->children.size; i++)
|
for (size_t i=0; i<params->children.size; i++)
|
||||||
{
|
{
|
||||||
struct node* child = params->children.data[i];
|
struct node* child = params->children.data[i];
|
||||||
|
|
||||||
if (child->type == NODE_VAR)
|
|
||||||
{
|
|
||||||
is_var = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child->type == NODE_TYPE)
|
if (child->type == NODE_TYPE)
|
||||||
{
|
{
|
||||||
struct type* param_ty = malloc(sizeof(struct type));
|
struct type* param_ty = malloc(sizeof(struct type));
|
||||||
type_init_from_node(param_ty, child);
|
type_init_from_node(param_ty, child);
|
||||||
param_ty->is_var = is_var;
|
|
||||||
is_var = 0;
|
|
||||||
vec_push(&self->subtypes, param_ty);
|
vec_push(&self->subtypes, param_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,8 +94,6 @@ void type_copy(struct type* self, struct type* dest)
|
||||||
type_free(dest);
|
type_free(dest);
|
||||||
type_init(dest, self->kind);
|
type_init(dest, self->kind);
|
||||||
|
|
||||||
dest->is_var = self->is_var;
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->subtypes.size; i++)
|
for (size_t i=0; i<self->subtypes.size; i++)
|
||||||
{
|
{
|
||||||
type_add_subtype(dest, TYPE_VOID);
|
type_add_subtype(dest, TYPE_VOID);
|
||||||
|
@ -169,25 +149,6 @@ int type_equals(struct type* self, struct type* rhs)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int type_equiv(struct type* self, struct type* rhs)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(rhs);
|
|
||||||
|
|
||||||
if (type_equals(self, rhs))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->kind == TYPE_RAW_PTR
|
|
||||||
&& type_equals(self->subtypes.data[0], rhs))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_add_subtype(struct type* self, enum TypeKind kind)
|
void type_add_subtype(struct type* self, enum TypeKind kind)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -203,11 +164,6 @@ size_t type_str(struct type* self, char* buffer, size_t size)
|
||||||
assert(buffer);
|
assert(buffer);
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
|
|
||||||
if (0 && self->is_var)
|
|
||||||
{
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "VAR_");
|
|
||||||
}
|
|
||||||
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "%s",
|
sz += snprintf(buffer + sz, size - sz, "%s",
|
||||||
TypeKindStr[self->kind] + strlen("TYPE_"));
|
TypeKindStr[self->kind] + strlen("TYPE_"));
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,13 @@
|
||||||
|
|
||||||
#define TYPE_KIND(G) \
|
#define TYPE_KIND(G) \
|
||||||
G(TYPE_VOID), G(TYPE_BOOL), G(TYPE_INT), \
|
G(TYPE_VOID), G(TYPE_BOOL), G(TYPE_INT), \
|
||||||
G(TYPE_FLOAT), G(TYPE_STRING), G(TYPE_FUN), \
|
G(TYPE_FLOAT), G(TYPE_STRING), G(TYPE_FUN)
|
||||||
G(TYPE_RAW_PTR)
|
|
||||||
|
|
||||||
GUX_ENUM_H(TypeKind, TYPE_KIND);
|
GUX_ENUM_H(TypeKind, TYPE_KIND);
|
||||||
|
|
||||||
struct type {
|
struct type {
|
||||||
enum TypeKind kind;
|
enum TypeKind kind;
|
||||||
struct vec subtypes;
|
struct vec subtypes;
|
||||||
int is_var;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void type_init(struct type* self, enum TypeKind kind);
|
void type_init(struct type* self, enum TypeKind kind);
|
||||||
|
@ -26,8 +24,6 @@ void type_copy(struct type* self, struct type* dest);
|
||||||
void type_clear(struct type* self);
|
void type_clear(struct type* self);
|
||||||
|
|
||||||
int type_equals(struct type* self, struct type* rhs);
|
int type_equals(struct type* self, struct type* rhs);
|
||||||
int type_equiv(struct type* self, struct type* rhs);
|
|
||||||
|
|
||||||
void type_add_subtype(struct type* self, enum TypeKind kind);
|
void type_add_subtype(struct type* self, enum TypeKind kind);
|
||||||
size_t type_str(struct type* self, char* buffer, size_t size);
|
size_t type_str(struct type* self, char* buffer, size_t size);
|
||||||
int type_is(struct type* self, char const* repr);
|
int type_is(struct type* self, char const* repr);
|
||||||
|
|
|
@ -44,7 +44,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type_equiv(&fun_ty, &ret_ty))
|
if (!type_equals(&fun_ty, &ret_ty))
|
||||||
{
|
{
|
||||||
type_checker_error_msg(self, node, &fun_ty, &ret_ty);
|
type_checker_error_msg(self, node, &fun_ty, &ret_ty);
|
||||||
|
|
||||||
|
@ -83,8 +83,8 @@ int type_checker_check(struct type_checker* self,
|
||||||
struct node* args = node->children.data[1];
|
struct node* args = node->children.data[1];
|
||||||
|
|
||||||
struct sym* entry = sym_table_fetch_fun(&self->sym_table,
|
struct sym* entry = sym_table_fetch_fun(&self->sym_table,
|
||||||
target->value,
|
target->value,
|
||||||
args);
|
args);
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
|
@ -118,30 +118,13 @@ int type_checker_check(struct type_checker* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_checker_check(self, sub_node) != 0)
|
if (!type_equals(&t, sub))
|
||||||
{
|
|
||||||
self->error_line = sub_node->line;
|
|
||||||
|
|
||||||
type_free(&t);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type_equiv(&t, sub))
|
|
||||||
{
|
{
|
||||||
type_checker_error_msg(self, sub_node, sub, &t);
|
type_checker_error_msg(self, sub_node, sub, &t);
|
||||||
type_free(&t);
|
type_free(&t);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t.is_var && sub->is_var)
|
|
||||||
{
|
|
||||||
snprintf(self->error_msg, GUX_STR_SIZE,
|
|
||||||
"<%s> is not mutable", sub_node->value);
|
|
||||||
self->error_line = sub_node->line;
|
|
||||||
type_free(&t);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_free(&t);
|
type_free(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +140,6 @@ int type_checker_check(struct type_checker* self,
|
||||||
struct vec names;
|
struct vec names;
|
||||||
vec_init(&names, 1);
|
vec_init(&names, 1);
|
||||||
|
|
||||||
struct vec vars;
|
|
||||||
vec_init(&vars, 1);
|
|
||||||
|
|
||||||
for (size_t i=0; i<params->children.size; i++)
|
for (size_t i=0; i<params->children.size; i++)
|
||||||
{
|
{
|
||||||
struct node* param = params->children.data[i];
|
struct node* param = params->children.data[i];
|
||||||
|
@ -172,34 +152,16 @@ int type_checker_check(struct type_checker* self,
|
||||||
struct type* ty = malloc(sizeof(struct type));
|
struct type* ty = malloc(sizeof(struct type));
|
||||||
type_init_from_node(ty, param);
|
type_init_from_node(ty, param);
|
||||||
|
|
||||||
int* var = vars.data[j];
|
sym_table_declare_const(&self->sym_table,
|
||||||
ty->is_var = *var;
|
n->value,
|
||||||
|
ty);
|
||||||
sym_table_declare(&self->sym_table,
|
|
||||||
n->value,
|
|
||||||
ty,
|
|
||||||
*var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec_free(&names);
|
vec_free(&names);
|
||||||
vec_init(&names, 1);
|
vec_init(&names, 1);
|
||||||
vec_free_elements(&vars);
|
|
||||||
vec_free(&vars);
|
|
||||||
vec_init(&vars, 1);
|
|
||||||
}
|
}
|
||||||
else if (param->type == NODE_VAR)
|
else
|
||||||
{
|
{
|
||||||
int* var = malloc(sizeof(int));
|
|
||||||
*var = 1;
|
|
||||||
vec_push(&vars, var);
|
|
||||||
vec_push(&names, params->children.data[i + 1]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (param->type == NODE_IDENT)
|
|
||||||
{
|
|
||||||
int* var = malloc(sizeof(int));
|
|
||||||
*var = 0;
|
|
||||||
vec_push(&vars, var);
|
|
||||||
vec_push(&names, param);
|
vec_push(&names, param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,8 +211,6 @@ int type_checker_check(struct type_checker* self,
|
||||||
type_free(&ret_ty);
|
type_free(&ret_ty);
|
||||||
vec_free(&ret_instrs);
|
vec_free(&ret_instrs);
|
||||||
vec_free(&names);
|
vec_free(&names);
|
||||||
vec_free_elements(&vars);
|
|
||||||
vec_free(&vars);
|
|
||||||
|
|
||||||
sym_table_pop_table(&self->sym_table);
|
sym_table_pop_table(&self->sym_table);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +226,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
struct type want;
|
struct type want;
|
||||||
type_init(&want, TYPE_BOOL);
|
type_init(&want, TYPE_BOOL);
|
||||||
|
|
||||||
if (!type_equiv(&have, &want))
|
if (!type_equals(&have, &want))
|
||||||
{
|
{
|
||||||
type_checker_error_msg(self, node, &want, &have);
|
type_checker_error_msg(self, node, &want, &have);
|
||||||
type_free(&have);
|
type_free(&have);
|
||||||
|
@ -332,7 +292,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry->type->is_var)
|
if (!entry->is_var)
|
||||||
{
|
{
|
||||||
snprintf(self->error_msg, GUX_STR_SIZE, "<%s> is not mutable",
|
snprintf(self->error_msg, GUX_STR_SIZE, "<%s> is not mutable",
|
||||||
ident->value);
|
ident->value);
|
||||||
|
@ -348,7 +308,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
|
|
||||||
type_resolver_resolve(&self->resolver, expr, &expr_type);
|
type_resolver_resolve(&self->resolver, expr, &expr_type);
|
||||||
|
|
||||||
if (!type_equiv(var_type, &expr_type))
|
if (!type_equals(var_type, &expr_type))
|
||||||
{
|
{
|
||||||
type_checker_error_msg(self, node, var_type, &expr_type);
|
type_checker_error_msg(self, node, var_type, &expr_type);
|
||||||
type_free(&expr_type);
|
type_free(&expr_type);
|
||||||
|
@ -362,8 +322,8 @@ int type_checker_check(struct type_checker* self,
|
||||||
case NODE_CONSTDECL:{
|
case NODE_CONSTDECL:{
|
||||||
struct type type;
|
struct type type;
|
||||||
type_init(&type, TYPE_VOID);
|
type_init(&type, TYPE_VOID);
|
||||||
type_resolver_resolve(&self->resolver,
|
|
||||||
node->children.data[0], &type);
|
type_resolver_resolve(&self->resolver, node->children.data[0], &type);
|
||||||
|
|
||||||
struct sym* entry = sym_table_fetch(&self->sym_table,
|
struct sym* entry = sym_table_fetch(&self->sym_table,
|
||||||
node->value,
|
node->value,
|
||||||
|
@ -401,11 +361,6 @@ int type_checker_check(struct type_checker* self,
|
||||||
|
|
||||||
if (type_resolver_resolve(&self->resolver, expr, ty) != 0)
|
if (type_resolver_resolve(&self->resolver, expr, ty) != 0)
|
||||||
{
|
{
|
||||||
char expr_str[GUX_STR_SIZE];
|
|
||||||
node_str(expr, expr_str, GUX_STR_SIZE);
|
|
||||||
snprintf(self->error_msg, GUX_STR_SIZE * 2,
|
|
||||||
"cannot find type of <%s>.", expr_str);
|
|
||||||
self->error_line = expr->line;
|
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
free(ty);
|
free(ty);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -515,7 +470,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
lhs_msg);
|
lhs_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!type_equiv(&lhs_type, &rhs_type))
|
else if (!type_equals(&lhs_type, &rhs_type))
|
||||||
{
|
{
|
||||||
snprintf(self->error_msg, MSG_SZ,
|
snprintf(self->error_msg, MSG_SZ,
|
||||||
"type mismatch (<%s>, <%s>)",
|
"type mismatch (<%s>, <%s>)",
|
||||||
|
@ -525,7 +480,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
|
|
||||||
if (solve_lhs != 0
|
if (solve_lhs != 0
|
||||||
|| solve_rhs != 0
|
|| solve_rhs != 0
|
||||||
|| !type_equiv(&lhs_type, &rhs_type)
|
|| !type_equals(&lhs_type, &rhs_type)
|
||||||
|| lhs_type.subtypes.size > 0
|
|| lhs_type.subtypes.size > 0
|
||||||
|| rhs_type.subtypes.size > 0
|
|| rhs_type.subtypes.size > 0
|
||||||
|| (lhs_type.kind != TYPE_INT && lhs_type.kind != TYPE_FLOAT)
|
|| (lhs_type.kind != TYPE_INT && lhs_type.kind != TYPE_FLOAT)
|
||||||
|
@ -585,7 +540,7 @@ int type_checker_check(struct type_checker* self,
|
||||||
node->children.data[i],
|
node->children.data[i],
|
||||||
&node_type);
|
&node_type);
|
||||||
|
|
||||||
if (!type_equiv(&type, &node_type))
|
if (!type_equals(&type, &node_type))
|
||||||
{
|
{
|
||||||
self->error_line = node->line;
|
self->error_line = node->line;
|
||||||
snprintf(self->error_msg,
|
snprintf(self->error_msg,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "type_resolver.h"
|
#include "type_resolver.h"
|
||||||
#include "commons.h"
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "sym_table.h"
|
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
void type_resolver_init(struct type_resolver* self,
|
void type_resolver_init(struct type_resolver* self,
|
||||||
|
@ -28,14 +26,6 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case NODE_NEW: {
|
|
||||||
type->kind = TYPE_RAW_PTR;
|
|
||||||
type_add_subtype(type, TYPE_VOID);
|
|
||||||
type_resolver_resolve(self, node->children.data[0],
|
|
||||||
type->subtypes.data[0]);
|
|
||||||
|
|
||||||
} return 0;
|
|
||||||
|
|
||||||
case NODE_RETURN: {
|
case NODE_RETURN: {
|
||||||
if (node->children.size == 0)
|
if (node->children.size == 0)
|
||||||
{
|
{
|
||||||
|
@ -50,22 +40,9 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
};
|
};
|
||||||
|
|
||||||
case NODE_CALL: {
|
case NODE_CALL: {
|
||||||
struct node* target = node->children.data[0];
|
|
||||||
struct node* args = node->children.data[1];
|
|
||||||
struct sym* entry = sym_table_fetch_fun(self->sym_table,
|
|
||||||
target->value,
|
|
||||||
args);
|
|
||||||
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
type_copy(entry->type->subtypes.data[0], type);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct type call_type;
|
struct type call_type;
|
||||||
type_init(&call_type, TYPE_VOID);
|
type_init(&call_type, TYPE_VOID);
|
||||||
|
|
||||||
|
|
||||||
if (type_resolver_resolve(self, node->children.data[0], &call_type) == 0
|
if (type_resolver_resolve(self, node->children.data[0], &call_type) == 0
|
||||||
&& call_type.subtypes.size > 0)
|
&& call_type.subtypes.size > 0)
|
||||||
{
|
{
|
||||||
|
@ -108,8 +85,8 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
|
|
||||||
type_copy(ty, type);
|
type_copy(ty, type);
|
||||||
|
|
||||||
type_free(ty);
|
//sym_table_declare(self->sym_table, node->value, ty,
|
||||||
free(ty);
|
// node->type == NODE_VARDECL);
|
||||||
|
|
||||||
} return 0;
|
} return 0;
|
||||||
|
|
||||||
|
@ -176,7 +153,7 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
type_init(&rhs, TYPE_VOID);
|
type_init(&rhs, TYPE_VOID);
|
||||||
type_resolver_resolve(self, node->children.data[1], &rhs);
|
type_resolver_resolve(self, node->children.data[1], &rhs);
|
||||||
|
|
||||||
int equals = type_equiv(&lhs, &rhs);
|
int equals = type_equals(&lhs, &rhs);
|
||||||
|
|
||||||
if (type_is(&lhs, "INT") && equals)
|
if (type_is(&lhs, "INT") && equals)
|
||||||
{
|
{
|
||||||
|
@ -200,16 +177,6 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
{
|
{
|
||||||
type->kind = TYPE_STRING;
|
type->kind = TYPE_STRING;
|
||||||
}
|
}
|
||||||
else if (lhs.kind == TYPE_RAW_PTR)
|
|
||||||
{
|
|
||||||
struct type* sub = lhs.subtypes.data[0];
|
|
||||||
type->kind = sub->kind;
|
|
||||||
}
|
|
||||||
else if (rhs.kind == TYPE_RAW_PTR)
|
|
||||||
{
|
|
||||||
struct type* sub = rhs.subtypes.data[0];
|
|
||||||
type->kind = sub->kind;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type_free(&lhs);
|
type_free(&lhs);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "commons.h"
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "fun.h"
|
#include "fun.h"
|
||||||
|
@ -67,18 +66,6 @@ void value_init_new_native(struct value* self, native_fun_t native,
|
||||||
self->is_native = 1;
|
self->is_native = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void value_init_new_rawptr(struct value* self, int addr,
|
|
||||||
struct type* type, int line)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
type_init(&self->type, TYPE_VOID);
|
|
||||||
type_copy(type, &self->type);
|
|
||||||
self->data.addr = addr;
|
|
||||||
self->line = line;
|
|
||||||
self->is_native = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void value_free(struct value* self)
|
void value_free(struct value* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -127,13 +114,6 @@ size_t value_str(struct value* self, char* buffer, size_t size)
|
||||||
|
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
|
|
||||||
if (self->type.kind == TYPE_RAW_PTR)
|
|
||||||
{
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "<raw ptr: %d>",
|
|
||||||
self->data.addr);
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->type.kind == TYPE_FUN)
|
if (self->type.kind == TYPE_FUN)
|
||||||
{
|
{
|
||||||
sz += snprintf(buffer + sz, size - sz, "<function>");
|
sz += snprintf(buffer + sz, size - sz, "<function>");
|
||||||
|
|
|
@ -13,7 +13,6 @@ union value_data {
|
||||||
char* s;
|
char* s;
|
||||||
float f;
|
float f;
|
||||||
int i;
|
int i;
|
||||||
int addr;
|
|
||||||
struct fun* fun;
|
struct fun* fun;
|
||||||
native_fun_t native;
|
native_fun_t native;
|
||||||
};
|
};
|
||||||
|
@ -32,8 +31,6 @@ void value_init_string(struct value* self, char* value, int line);
|
||||||
void value_init_new_fun(struct value* self, struct fun* value, int line);
|
void value_init_new_fun(struct value* self, struct fun* value, int line);
|
||||||
void value_init_new_native(struct value* self, native_fun_t native,
|
void value_init_new_native(struct value* self, native_fun_t native,
|
||||||
struct type* type, int line);
|
struct type* type, int line);
|
||||||
void value_init_new_rawptr(struct value* self, int addr,
|
|
||||||
struct type* type, int line);
|
|
||||||
|
|
||||||
void value_free(struct value* self);
|
void value_free(struct value* self);
|
||||||
|
|
||||||
|
|
|
@ -127,10 +127,8 @@ Test(lexer, ident) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(lexer, var_types) {
|
Test(lexer, var_types) {
|
||||||
test_lexer("int float bool string ^", 5,
|
test_lexer("int float bool string", 4,
|
||||||
"TYPE[int]", "TYPE[float]",
|
"TYPE[int]", "TYPE[float]", "TYPE[bool]", "TYPE[string]");
|
||||||
"TYPE[bool]", "TYPE[string]",
|
|
||||||
"PTR");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(lexer, blocks) {
|
Test(lexer, blocks) {
|
||||||
|
@ -145,7 +143,3 @@ Test(lexer, flow_control) {
|
||||||
Test(lexer, fun) {
|
Test(lexer, fun) {
|
||||||
test_lexer("-> fun return,", 4, "RARROW", "FUN", "RETURN", "COMMA");
|
test_lexer("-> fun return,", 4, "RARROW", "FUN", "RETURN", "COMMA");
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(lexer, mem) {
|
|
||||||
test_lexer("new free", 2, "NEW", "FREE");
|
|
||||||
}
|
|
||||||
|
|
|
@ -174,9 +174,6 @@ Test(parser, types) {
|
||||||
test_parser("ROOT(CONSTDECL[x]("
|
test_parser("ROOT(CONSTDECL[x]("
|
||||||
"TYPE[fun](TYPE[int],TYPE[int],RARROW,TYPE[float]),INT[0]))",
|
"TYPE[fun](TYPE[int],TYPE[int],RARROW,TYPE[float]),INT[0]))",
|
||||||
"x : (int int -> float) = 0;");
|
"x : (int int -> float) = 0;");
|
||||||
|
|
||||||
test_parser("ROOT(CONSTDECL[x](TYPE[rawptr](TYPE[float]),INT[0]))",
|
|
||||||
"x : ^float = 0;");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(parser, fun_call) {
|
Test(parser, fun_call) {
|
||||||
|
@ -197,15 +194,6 @@ Test(parser, fun_decl) {
|
||||||
test_parser("ROOT(CONSTDECL[hello](FUN(PARAMS(IDENT[n],TYPE[int]),"
|
test_parser("ROOT(CONSTDECL[hello](FUN(PARAMS(IDENT[n],TYPE[int]),"
|
||||||
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
||||||
"fun hello (n: int) -> int { return n; }");
|
"fun hello (n: int) -> int { return n; }");
|
||||||
|
|
||||||
test_parser("ROOT(CONSTDECL[hello](FUN(PARAMS(VAR,IDENT[n],TYPE[int]),"
|
|
||||||
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
|
||||||
"fun hello (var n: int) -> int { return n; }");
|
|
||||||
|
|
||||||
test_parser("ROOT(CONSTDECL[hello](FUN(PARAMS(IDENT[m],TYPE[float],"
|
|
||||||
"VAR,IDENT[n],TYPE[int]),"
|
|
||||||
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
|
||||||
"fun hello (m: float, var n: int) -> int { return n; }");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(parser, param_sugar) {
|
Test(parser, param_sugar) {
|
||||||
|
@ -214,11 +202,3 @@ Test(parser, param_sugar) {
|
||||||
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
"TYPE[int],BLOCK(RETURN(IDENT[n])))))",
|
||||||
"fun hello (n, m, k: int) -> int { return n; }");
|
"fun hello (n, m, k: int) -> int { return n; }");
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(parser, mem) {
|
|
||||||
test_parser("ROOT(CONSTDECL[x](NEW(INT[32])))",
|
|
||||||
"x := new 32;");
|
|
||||||
|
|
||||||
test_parser("ROOT(FREE(IDENT[hello]))",
|
|
||||||
"free hello;");
|
|
||||||
}
|
|
||||||
|
|
|
@ -44,20 +44,6 @@ void* vec_pop(struct vec* self)
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* vec_remove(struct vec* self, size_t index)
|
|
||||||
{
|
|
||||||
assert(index < self->size);
|
|
||||||
void* to_remove = self->data[index];
|
|
||||||
void* tmp = self->data[self->size - 1];
|
|
||||||
|
|
||||||
self->data[self->size - 1] = to_remove;
|
|
||||||
to_remove = tmp;
|
|
||||||
|
|
||||||
vec_pop(self);
|
|
||||||
|
|
||||||
return to_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vec_free_elements(struct vec* self)
|
void vec_free_elements(struct vec* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
|
@ -14,7 +14,6 @@ void vec_free(struct vec* self);
|
||||||
|
|
||||||
void vec_push(struct vec* self, void* element);
|
void vec_push(struct vec* self, void* element);
|
||||||
void* vec_pop(struct vec* self);
|
void* vec_pop(struct vec* self);
|
||||||
void* vec_remove(struct vec* self, size_t index);
|
|
||||||
|
|
||||||
void vec_free_elements(struct vec* self);
|
void vec_free_elements(struct vec* self);
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
fun incr(var n: ^int) {
|
|
||||||
n = n + 1;
|
|
||||||
n = n * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a : ^int = new 43;
|
|
||||||
|
|
||||||
assert a == 43;
|
|
||||||
|
|
||||||
incr(a);
|
|
||||||
a = a + 1;
|
|
||||||
|
|
||||||
assert a == 89;
|
|
||||||
|
|
||||||
free a;
|
|
284
vm/src/vm.c
284
vm/src/vm.c
|
@ -17,7 +17,6 @@ void vm_init(struct vm* self, struct vec* natives)
|
||||||
memset(self->error_msg, 0, GUX_STR_SIZE);
|
memset(self->error_msg, 0, GUX_STR_SIZE);
|
||||||
|
|
||||||
vm_add_frame(self);
|
vm_add_frame(self);
|
||||||
vec_init(&self->heap, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_free(struct vm* self)
|
void vm_free(struct vm* self)
|
||||||
|
@ -32,16 +31,6 @@ void vm_free(struct vm* self)
|
||||||
}
|
}
|
||||||
|
|
||||||
self->fp = 0;
|
self->fp = 0;
|
||||||
|
|
||||||
for (size_t i=0; i<self->heap.size; i++)
|
|
||||||
{
|
|
||||||
struct heap_item* item = self->heap.data[i];
|
|
||||||
value_free(item->value);
|
|
||||||
free(item->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec_free_elements(&self->heap);
|
|
||||||
vec_free(&self->heap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_add_frame(struct vm* self)
|
void vm_add_frame(struct vm* self)
|
||||||
|
@ -142,99 +131,6 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case OP_FREE: {
|
|
||||||
int ref_val = vm_load(self, param);
|
|
||||||
int stack_addr = frame->stack[ref_val];
|
|
||||||
|
|
||||||
struct value* ref = program->constant_pool.data[stack_addr];
|
|
||||||
int addr = ref->data.addr;
|
|
||||||
|
|
||||||
ssize_t value_idx = vm_heap_try_find(self, addr);
|
|
||||||
|
|
||||||
if (value_idx == -1)
|
|
||||||
{
|
|
||||||
snprintf(self->error_msg, GUX_STR_SIZE, "wrong address");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stack_val = vm_pop(self);
|
|
||||||
struct value* stack = program->constant_pool.data[stack_val];
|
|
||||||
assert(stack);
|
|
||||||
|
|
||||||
struct heap_item* item = vec_remove(&self->heap, value_idx);
|
|
||||||
|
|
||||||
value_free(item->value);
|
|
||||||
free(item->value);
|
|
||||||
free(item);
|
|
||||||
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_REFSTORE: {
|
|
||||||
int ref_val = vm_load(self, param);
|
|
||||||
int stack_addr = frame->stack[ref_val];
|
|
||||||
|
|
||||||
struct value* ref = program->constant_pool.data[stack_addr];
|
|
||||||
|
|
||||||
int addr = ref->data.addr;
|
|
||||||
|
|
||||||
ssize_t value_idx = vm_heap_try_find(self, addr);
|
|
||||||
|
|
||||||
if (value_idx == -1)
|
|
||||||
{
|
|
||||||
snprintf(self->error_msg, GUX_STR_SIZE, "wrong address");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stack_val = vm_pop(self);
|
|
||||||
struct value* stack = program->constant_pool.data[stack_val];
|
|
||||||
assert(stack);
|
|
||||||
|
|
||||||
struct heap_item* item = self->heap.data[value_idx];
|
|
||||||
|
|
||||||
value_free(item->value);
|
|
||||||
free(item->value);
|
|
||||||
item->value = value_new_clone(stack);
|
|
||||||
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_DEREF: {
|
|
||||||
int val = vm_pop(self);
|
|
||||||
struct value* ref = program->constant_pool.data[val];
|
|
||||||
|
|
||||||
struct value* value = value_new_clone
|
|
||||||
(vm_heap_try_load(self, ref->data.addr));
|
|
||||||
assert(value);
|
|
||||||
|
|
||||||
vm_push(self,
|
|
||||||
program_push_constant(program, value));
|
|
||||||
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_NEW: {
|
|
||||||
int val = vm_pop(self);
|
|
||||||
struct value* value =
|
|
||||||
value_new_clone(program->constant_pool.data[val]);
|
|
||||||
|
|
||||||
vm_heap_store_new(self, param, value);
|
|
||||||
|
|
||||||
struct type type;
|
|
||||||
type_init(&type, TYPE_RAW_PTR);
|
|
||||||
type_add_subtype(&type, TYPE_VOID);
|
|
||||||
type_copy(&value->type, type.subtypes.data[0]);
|
|
||||||
|
|
||||||
struct value* ref = malloc(sizeof(struct value));
|
|
||||||
value_init_new_rawptr(ref, param, &type, value->line);
|
|
||||||
type_free(&type);
|
|
||||||
|
|
||||||
vm_push(self,
|
|
||||||
program_push_constant(program, ref));
|
|
||||||
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
int fun_addr = vm_pop(self);
|
int fun_addr = vm_pop(self);
|
||||||
struct value* fun_val = program->constant_pool.data[fun_addr];
|
struct value* fun_val = program->constant_pool.data[fun_addr];
|
||||||
|
@ -306,12 +202,7 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
size_t ret_addr = self->pc;
|
size_t ret_addr = self->pc;
|
||||||
self->pc = 0;
|
self->pc = 0;
|
||||||
|
|
||||||
if (vm_exec(self, &fun->program) != 0)
|
vm_exec(self, &fun->program);
|
||||||
{
|
|
||||||
vec_free_elements(&args);
|
|
||||||
vec_free(&args);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec_free_elements(&args);
|
vec_free_elements(&args);
|
||||||
vec_free(&args);
|
vec_free(&args);
|
||||||
|
@ -436,11 +327,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val =
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
|
|
||||||
struct value* rhs_val =
|
|
||||||
vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = malloc(sizeof(struct value));
|
struct value* res = malloc(sizeof(struct value));
|
||||||
|
|
||||||
|
@ -483,11 +371,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val =
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
|
|
||||||
struct value* rhs_val =
|
|
||||||
vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_add(lhs_val, rhs_val);
|
struct value* res = value_try_new_add(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -499,10 +384,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val =
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val =
|
|
||||||
vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_sub(lhs_val, rhs_val);
|
struct value* res = value_try_new_sub(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -514,10 +397,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_mul(lhs_val, rhs_val);
|
struct value* res = value_try_new_mul(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -529,10 +410,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_div(lhs_val, rhs_val);
|
struct value* res = value_try_new_div(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -544,10 +423,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_mod(lhs_val, rhs_val);
|
struct value* res = value_try_new_mod(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -559,10 +436,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_pow(lhs_val, rhs_val);
|
struct value* res = value_try_new_pow(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -574,10 +449,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_lt(lhs_val, rhs_val);
|
struct value* res = value_try_new_lt(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -589,10 +462,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_le(lhs_val, rhs_val);
|
struct value* res = value_try_new_le(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -604,10 +475,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_gt(lhs_val, rhs_val);
|
struct value* res = value_try_new_gt(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -619,10 +488,8 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
int rhs = vm_pop(self);
|
int rhs = vm_pop(self);
|
||||||
int lhs = vm_pop(self);
|
int lhs = vm_pop(self);
|
||||||
|
|
||||||
struct value* lhs_val
|
struct value* lhs_val = program->constant_pool.data[lhs];
|
||||||
= vm_try_get_val(self, program->constant_pool.data[lhs]);
|
struct value* rhs_val = program->constant_pool.data[rhs];
|
||||||
struct value* rhs_val
|
|
||||||
= vm_try_get_val(self, program->constant_pool.data[rhs]);
|
|
||||||
|
|
||||||
struct value* res = value_try_new_ge(lhs_val, rhs_val);
|
struct value* res = value_try_new_ge(lhs_val, rhs_val);
|
||||||
vm_push(self, program_push_constant(program, res));
|
vm_push(self, program_push_constant(program, res));
|
||||||
|
@ -645,8 +512,6 @@ size_t vm_str(struct vm* self, struct program* program,
|
||||||
|
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "--- STACKS ---\n");
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->fp; i++)
|
for (size_t i=0; i<self->fp; i++)
|
||||||
{
|
{
|
||||||
struct frame* frame = self->stack[i];
|
struct frame* frame = self->stack[i];
|
||||||
|
@ -664,108 +529,5 @@ size_t vm_str(struct vm* self, struct program* program,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "--- HEAP ---\n");
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->heap.size; i++)
|
|
||||||
{
|
|
||||||
struct heap_item* item = self->heap.data[i];
|
|
||||||
char val_str[GUX_STR_SIZE];
|
|
||||||
value_str(item->value, val_str, GUX_STR_SIZE);
|
|
||||||
|
|
||||||
sz += snprintf(buffer + sz, size - sz, "%i %s\n",
|
|
||||||
item->addr,
|
|
||||||
val_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_heap_store_new(struct vm* self, int addr, struct value* value)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
struct heap_item* item = malloc(sizeof(struct heap_item));
|
|
||||||
item->addr = addr;
|
|
||||||
item->value = value;
|
|
||||||
vec_push(&self->heap, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct value* vm_heap_try_load(struct vm* self, int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->heap.size; i++)
|
|
||||||
{
|
|
||||||
struct heap_item* item = self->heap.data[i];
|
|
||||||
|
|
||||||
if (item->addr == addr)
|
|
||||||
{
|
|
||||||
return item->value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t vm_heap_try_find(struct vm* self, int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->heap.size; i++)
|
|
||||||
{
|
|
||||||
struct heap_item* item = self->heap.data[i];
|
|
||||||
|
|
||||||
if (item->addr == addr)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vm_heap_free(struct vm* self, int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
size_t idx = 0;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->heap.size; i++)
|
|
||||||
{
|
|
||||||
struct heap_item* item = self->heap.data[i];
|
|
||||||
|
|
||||||
if (item->addr == addr)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
idx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) { return 1; }
|
|
||||||
|
|
||||||
struct heap_item* tmp = self->heap.data[self->heap.size - 1];
|
|
||||||
self->heap.data[self->heap.size - 1] = self->heap.data[idx];
|
|
||||||
self->heap.data[idx] = tmp;
|
|
||||||
|
|
||||||
vec_pop(&self->heap);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct value* vm_try_get_val(struct vm* self, struct value* value)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(value);
|
|
||||||
|
|
||||||
if (value->type.kind == TYPE_RAW_PTR)
|
|
||||||
{
|
|
||||||
struct value* v = vm_heap_try_load(self, value->data.addr);
|
|
||||||
assert(v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
12
vm/src/vm.h
12
vm/src/vm.h
|
@ -12,11 +12,6 @@ struct local {
|
||||||
int stack_addr;
|
int stack_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct heap_item {
|
|
||||||
int addr;
|
|
||||||
struct value* value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct frame {
|
struct frame {
|
||||||
int stack[STACK_DEPTH];
|
int stack[STACK_DEPTH];
|
||||||
size_t sp;
|
size_t sp;
|
||||||
|
@ -31,7 +26,6 @@ struct vm {
|
||||||
size_t fp;
|
size_t fp;
|
||||||
struct frame* stack[FRAME_DEPTH];
|
struct frame* stack[FRAME_DEPTH];
|
||||||
struct vec* natives;
|
struct vec* natives;
|
||||||
struct vec heap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void vm_init(struct vm* self, struct vec* natives);
|
void vm_init(struct vm* self, struct vec* natives);
|
||||||
|
@ -50,10 +44,4 @@ int vm_exec(struct vm* self, struct program* program);
|
||||||
size_t vm_str(struct vm* self, struct program* program,
|
size_t vm_str(struct vm* self, struct program* program,
|
||||||
char* buffer, size_t size);
|
char* buffer, size_t size);
|
||||||
|
|
||||||
void vm_heap_store_new(struct vm* self, int addr, struct value* value);
|
|
||||||
struct value* vm_heap_try_load(struct vm* self, int addr);
|
|
||||||
ssize_t vm_heap_try_find(struct vm* self, int addr);
|
|
||||||
int vm_heap_free(struct vm* self, int addr);
|
|
||||||
struct value* vm_try_get_val(struct vm* self, struct value* value);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue