raw pointers.

main
bog 2024-02-20 22:23:58 +01:00
parent bf91985e00
commit d1286c008b
24 changed files with 597 additions and 79 deletions

View File

@ -17,13 +17,14 @@ 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
@ -34,7 +35,7 @@ WHILE ::= while EXPR BLOCK
FUN ::= fun PARAMS (rarrow TYPE) BLOCK FUN ::= fun PARAMS (rarrow TYPE) BLOCK
PARAMS ::= PARAMS ::=
| opar ident colon TYPE (comma ident colon type)* cpar | opar var? ident colon TYPE (comma var? 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
@ -67,3 +68,4 @@ BUILTIN ::= bool | int | float | string
TYPE ::= TYPE ::=
| type | type
| opar TYPE+ rarrow TYPE+ cpar | opar TYPE+ rarrow TYPE+ cpar
| rawptr TYPE

View File

@ -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] %s\n", fprintf(stderr, "[%s:%d] type check error, %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] %s\n", fprintf(stderr, "[%s:%d] compile error, %s\n",
path, path,
compiler.error_line, compiler.error_line,
compiler.error_msg); compiler.error_msg);

View File

@ -18,6 +18,7 @@ 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)
@ -38,6 +39,21 @@ 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)
{ {
@ -65,7 +81,11 @@ int compiler_compile(struct compiler* self,
{ {
struct node* param = params->children.data[i]; struct node* param = params->children.data[i];
if (param->type != NODE_TYPE) if (param->type == NODE_VAR)
{
continue;
}
else if (param->type != NODE_TYPE)
{ {
vec_push(&idents, param); vec_push(&idents, param);
} }
@ -76,8 +96,7 @@ 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(ty, TYPE_VOID); type_init_from_node(ty, param);
compiler_get_type(self, param, ty);
sym_table_declare_const(&compiler.sym_table, sym_table_declare_const(&compiler.sym_table,
ident->value, ident->value,
@ -255,13 +274,32 @@ 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 = sym_table_fetch(&self->sym_table, struct sym* entry;
if (is_ptr)
{
entry = sym_table_fetch(&self->sym_table,
ident->value,
&lhs_ty);
}
else
{
entry = sym_table_fetch(&self->sym_table,
ident->value, ident->value,
&type); &type);
}
type_free(&lhs_ty);
type_free(&type); type_free(&type);
assert(entry); assert(entry);
@ -271,7 +309,8 @@ int compiler_compile(struct compiler* self,
return 1; return 1;
} }
compiler_gen_instr(self, program, OP_STORE, entry->addr); compiler_gen_instr(self, program, is_ptr ? OP_REFSTORE : OP_STORE,
entry->addr);
} break; } break;
case NODE_IDENT: { case NODE_IDENT: {
@ -299,11 +338,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
int err = compiler_compile(self, node->children.size == 1
? node->children.data[0] ? node->children.data[0]
: node->children.data[1], : node->children.data[1];
program);
int err = compiler_compile(self, rhs, program);
if (err != 0) if (err != 0)
{ {
@ -312,7 +351,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, node->children.data[0], ty); compiler_get_type(self, rhs, 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);
@ -320,10 +359,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));
@ -637,6 +676,7 @@ 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:
@ -654,12 +694,17 @@ 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: break; case OP_STORE:
case OP_REFSTORE:break;
default: assert(0);
} }
return addr; return addr;

View File

@ -17,6 +17,7 @@ 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);

View File

@ -26,11 +26,14 @@ 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);

View File

@ -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_ARGS), G(NODE_RAWPTR), G(NODE_PTR), G(NODE_FREE), G(NODE_NEW)
GUX_ENUM_H(NodeType, NODE_TYPE); GUX_ENUM_H(NodeType, NODE_TYPE);

View File

@ -6,7 +6,8 @@
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_SWAP), G(OP_CALL), G(OP_RET), G(OP_GLOAD), G(OP_NEW), \
G(OP_FREE), G(OP_DEREF), G(OP_REFSTORE)
#include <commons.h> #include <commons.h>

View File

@ -149,7 +149,8 @@ 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)
@ -232,11 +233,29 @@ 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));
@ -425,7 +444,8 @@ 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);
@ -434,6 +454,14 @@ 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));
@ -564,14 +592,9 @@ 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));
} }
@ -953,6 +976,14 @@ 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

View File

@ -13,11 +13,14 @@ void program_free(struct program* self)
assert(self); assert(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);

View File

@ -233,7 +233,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->is_var = is_var; sym->type->is_var = is_var;
sym->addr = self->addr_counter; sym->addr = self->addr_counter;
vec_push(&table->syms, sym); vec_push(&table->syms, sym);
@ -264,7 +264,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->is_var = 0; sym->type->is_var = 0;
sym->addr = addr; sym->addr = addr;
vec_push(&table->syms, sym); vec_push(&table->syms, sym);

View File

@ -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;

View File

@ -8,6 +8,7 @@ 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);
} }
@ -15,9 +16,17 @@ 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, "fun") == 0) if (node->type == NODE_TYPE && strcmp(node->value, "rawptr") == 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;
@ -68,14 +77,23 @@ 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);
} }
} }
@ -94,6 +112,8 @@ 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);
@ -149,6 +169,25 @@ 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);
@ -164,6 +203,11 @@ 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_"));

View File

@ -7,13 +7,15 @@
#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);
@ -24,6 +26,8 @@ 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);

View File

@ -44,7 +44,7 @@ int type_checker_check(struct type_checker* self,
return 1; return 1;
} }
if (!type_equals(&fun_ty, &ret_ty)) if (!type_equiv(&fun_ty, &ret_ty))
{ {
type_checker_error_msg(self, node, &fun_ty, &ret_ty); type_checker_error_msg(self, node, &fun_ty, &ret_ty);
@ -109,7 +109,6 @@ int type_checker_check(struct type_checker* self,
{ {
struct type* sub = ty->subtypes.data[i + 1]; struct type* sub = ty->subtypes.data[i + 1];
struct node* sub_node = args->children.data[i]; struct node* sub_node = args->children.data[i];
struct type t; struct type t;
type_init(&t, TYPE_VOID); type_init(&t, TYPE_VOID);
@ -127,13 +126,22 @@ int type_checker_check(struct type_checker* self,
return 1; return 1;
} }
if (!type_equals(&t, sub)) 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);
} }
@ -149,6 +157,9 @@ 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];
@ -161,16 +172,34 @@ 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);
sym_table_declare_const(&self->sym_table, int* var = vars.data[j];
ty->is_var = *var;
sym_table_declare(&self->sym_table,
n->value, n->value,
ty); 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 else if (param->type == NODE_VAR)
{ {
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);
} }
} }
@ -220,6 +249,8 @@ 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);
} }
@ -235,7 +266,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_equals(&have, &want)) if (!type_equiv(&have, &want))
{ {
type_checker_error_msg(self, node, &want, &have); type_checker_error_msg(self, node, &want, &have);
type_free(&have); type_free(&have);
@ -301,7 +332,7 @@ int type_checker_check(struct type_checker* self,
return 1; return 1;
} }
if (!entry->is_var) if (!entry->type->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);
@ -317,7 +348,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_equals(var_type, &expr_type)) if (!type_equiv(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);
@ -331,8 +362,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,
type_resolver_resolve(&self->resolver, node->children.data[0], &type); 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,
@ -370,6 +401,11 @@ 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;
@ -479,7 +515,7 @@ int type_checker_check(struct type_checker* self,
lhs_msg); lhs_msg);
} }
} }
else if (!type_equals(&lhs_type, &rhs_type)) else if (!type_equiv(&lhs_type, &rhs_type))
{ {
snprintf(self->error_msg, MSG_SZ, snprintf(self->error_msg, MSG_SZ,
"type mismatch (<%s>, <%s>)", "type mismatch (<%s>, <%s>)",
@ -489,7 +525,7 @@ int type_checker_check(struct type_checker* self,
if (solve_lhs != 0 if (solve_lhs != 0
|| solve_rhs != 0 || solve_rhs != 0
|| !type_equals(&lhs_type, &rhs_type) || !type_equiv(&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)
@ -549,7 +585,7 @@ int type_checker_check(struct type_checker* self,
node->children.data[i], node->children.data[i],
&node_type); &node_type);
if (!type_equals(&type, &node_type)) if (!type_equiv(&type, &node_type))
{ {
self->error_line = node->line; self->error_line = node->line;
snprintf(self->error_msg, snprintf(self->error_msg,

View File

@ -1,4 +1,5 @@
#include "type_resolver.h" #include "type_resolver.h"
#include "commons.h"
#include "node.h" #include "node.h"
#include "sym_table.h" #include "sym_table.h"
#include "type.h" #include "type.h"
@ -27,6 +28,14 @@ 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)
{ {
@ -99,8 +108,8 @@ int type_resolver_resolve(struct type_resolver* self,
type_copy(ty, type); type_copy(ty, type);
//sym_table_declare(self->sym_table, node->value, ty, type_free(ty);
// node->type == NODE_VARDECL); free(ty);
} return 0; } return 0;
@ -167,7 +176,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_equals(&lhs, &rhs); int equals = type_equiv(&lhs, &rhs);
if (type_is(&lhs, "INT") && equals) if (type_is(&lhs, "INT") && equals)
{ {
@ -191,6 +200,16 @@ 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);

View File

@ -1,4 +1,5 @@
#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"
@ -66,6 +67,18 @@ 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);
@ -114,6 +127,13 @@ 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>");

View File

@ -13,6 +13,7 @@ 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;
}; };
@ -31,6 +32,8 @@ 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);

View File

@ -127,8 +127,10 @@ Test(lexer, ident) {
} }
Test(lexer, var_types) { Test(lexer, var_types) {
test_lexer("int float bool string", 4, test_lexer("int float bool string ^", 5,
"TYPE[int]", "TYPE[float]", "TYPE[bool]", "TYPE[string]"); "TYPE[int]", "TYPE[float]",
"TYPE[bool]", "TYPE[string]",
"PTR");
} }
Test(lexer, blocks) { Test(lexer, blocks) {
@ -143,3 +145,7 @@ 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");
}

View File

@ -174,6 +174,9 @@ 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) {
@ -194,6 +197,15 @@ 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) {
@ -202,3 +214,11 @@ 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;");
}

View File

@ -44,6 +44,20 @@ 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);

View File

@ -14,6 +14,7 @@ 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);

15
tests/mem.gux Normal file
View File

@ -0,0 +1,15 @@
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;

View File

@ -17,6 +17,7 @@ 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)
@ -31,6 +32,16 @@ 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)
@ -131,6 +142,99 @@ 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];
@ -202,7 +306,12 @@ 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;
vm_exec(self, &fun->program); if (vm_exec(self, &fun->program) != 0)
{
vec_free_elements(&args);
vec_free(&args);
return 1;
}
vec_free_elements(&args); vec_free_elements(&args);
vec_free(&args); vec_free(&args);
@ -327,8 +436,11 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val =
struct value* rhs_val = program->constant_pool.data[rhs]; vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -371,8 +483,11 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val =
struct value* rhs_val = program->constant_pool.data[rhs]; vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -384,8 +499,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val =
struct value* rhs_val = program->constant_pool.data[rhs]; vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -397,8 +514,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -410,8 +529,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -423,8 +544,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -436,8 +559,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -449,8 +574,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -462,8 +589,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -475,8 +604,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -488,8 +619,10 @@ 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 = program->constant_pool.data[lhs]; struct value* lhs_val
struct value* rhs_val = program->constant_pool.data[rhs]; = vm_try_get_val(self, program->constant_pool.data[lhs]);
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));
@ -512,6 +645,8 @@ 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];
@ -529,5 +664,108 @@ 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;
}
}

View File

@ -12,6 +12,11 @@ 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;
@ -26,6 +31,7 @@ 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);
@ -44,4 +50,10 @@ 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