improved println 🎨 better global support 🐛 string duplication with clone.

main
bog 2024-04-07 05:23:59 +02:00
parent 88aad1ee75
commit b5f0713fee
15 changed files with 140 additions and 55 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
*\#* *\#*
build build
.cache .cache
vgcore*

View File

@ -10,7 +10,7 @@ void natives_decl(struct state* state,
struct sym* sym, struct sym* sym,
char* name, char* name,
nfun_body fun, nfun_body fun,
size_t arity); int arity);
SK native_println(struct state* state, struct vec* args); SK native_println(struct state* state, struct vec* args);

View File

@ -9,10 +9,10 @@ typedef SK (*nfun_body)(struct state*, struct vec*);
struct nfun struct nfun
{ {
nfun_body body; nfun_body body;
size_t arity; int arity;
}; };
void nfun_init(struct nfun* self, nfun_body body, size_t arity); void nfun_init(struct nfun* self, nfun_body body, int arity);
void nfun_free(struct nfun* self); void nfun_free(struct nfun* self);
SK nfun_call(struct nfun* self, SK nfun_call(struct nfun* self,

View File

@ -14,7 +14,8 @@ G(OP_NOT), G(OP_AND), G(OP_OR), \
G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \ G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \
G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \ G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \
G(OP_CALL), G(OP_RET), G(OP_MAKE_REF), \ G(OP_CALL), G(OP_RET), G(OP_MAKE_REF), \
G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE) G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE), \
G(OP_GLOBAL_LOAD)
SK_ENUM_H(Opcode, OPCODE); SK_ENUM_H(Opcode, OPCODE);

View File

@ -26,11 +26,19 @@ struct frame
struct fun* fun; struct fun* fun;
}; };
struct global
{
int id;
size_t addr;
};
struct state struct state
{ {
struct vec frames; struct vec frames;
size_t addr; size_t addr;
int global_id;
struct vec globals; struct vec globals;
struct vec global_values;
}; };
typedef SK (*nfun_body)(struct state*, struct vec*); typedef SK (*nfun_body)(struct state*, struct vec*);
@ -83,6 +91,9 @@ void state_closure_store(struct state* self,
void state_local_load(struct state* self, void state_local_load(struct state* self,
int id); int id);
void state_global_load(struct state* self,
int id);
void state_closure_load(struct state* self, void state_closure_load(struct state* self,
int id); int id);
@ -107,9 +118,12 @@ SK state_lt(struct state* self);
SK state_gt(struct state* self); SK state_gt(struct state* self);
SK state_eq(struct state* self); SK state_eq(struct state* self);
int state_add_global(struct state* self,
struct value* value);
void state_call(struct state* self, struct fun* fun); void state_call(struct state* self, struct fun* fun);
void state_ret(struct state* self); void state_ret(struct state* self);
SK state_add_nfun(struct state* self, SK state_add_nfun(struct state* self,
nfun_body body, nfun_body body,
size_t arity); int arity);
#endif #endif

View File

@ -12,6 +12,7 @@ struct symbol
int native_id; int native_id;
char* name; char* name;
bool is_const; bool is_const;
bool is_global;
struct env* env; struct env* env;
}; };
@ -26,6 +27,7 @@ struct sym
int id_counter; int id_counter;
int closure_counter; int closure_counter;
int native_counter; int native_counter;
int global_counter;
struct env* env; struct env* env;
}; };
@ -49,7 +51,7 @@ void sym_free(struct sym* self);
int sym_decl_var(struct sym* self, char const* name); int sym_decl_var(struct sym* self, char const* name);
int sym_decl_const(struct sym* self, char const* name); int sym_decl_const(struct sym* self, char const* name);
int sym_decl_closure(struct sym* self, int id, char const* name); int sym_decl_closure(struct sym* self, int id, char const* name);
int sym_decl_native(struct sym* self, char const* name, int addr); int sym_decl_global(struct sym* self, int id, char const* name);
void sym_open_scope(struct sym* self); void sym_open_scope(struct sym* self);
void sym_close_scope(struct sym* self); void sym_close_scope(struct sym* self);

View File

@ -189,14 +189,9 @@ void compiler_compile(struct compiler* self,
itr = itr->parent; itr = itr->parent;
} }
if (symbol->native_id != SK_NO_NATIVE) if (symbol->is_global)
{ {
struct value* value = malloc(sizeof(struct value)); prog_add_instr(prog, OP_GLOBAL_LOAD, symbol->id);
union val val;
val.ref = symbol->native_id;
value_init(value, TYPE_REF, val, node->token->line);
size_t idx = prog_add_constant(prog, value);
prog_add_instr(prog, OP_PUSH, idx);
} }
else if (symbol->closure_id != SK_NO_CLOSURE) else if (symbol->closure_id != SK_NO_CLOSURE)
{ {
@ -265,6 +260,7 @@ void compiler_compile(struct compiler* self,
} }
} }
} }
compiler_compile(self, body, p, fun->sym, state); compiler_compile(self, body, p, fun->sym, state);
union val val; union val val;

View File

@ -40,6 +40,11 @@ void exec_execute(struct exec* self,
self->pc++; self->pc++;
} break; } break;
case OP_GLOBAL_LOAD: {
state_global_load(state, param);
self->pc++;
} break;
case OP_LOCAL_LOAD: { case OP_LOCAL_LOAD: {
state_local_load(state, param); state_local_load(state, param);
self->pc++; self->pc++;
@ -98,6 +103,7 @@ void exec_execute(struct exec* self,
vec_init(&pvalues); vec_init(&pvalues);
SK function = state_pop(state); SK function = state_pop(state);
for (size_t i=0; i<param; i++) for (size_t i=0; i<param; i++)
{ {
SK arg = state_pop(state); SK arg = state_pop(state);
@ -112,11 +118,21 @@ void exec_execute(struct exec* self,
f->val.ref f->val.ref
); );
assert(val_fun);
if (val_fun->type == TYPE_NATIVE_FUN) if (val_fun->type == TYPE_NATIVE_FUN)
{ {
struct vec ordered;
vec_init(&ordered);
for (size_t i=0; i<pvalues.size; i++)
{
SK arg = (SK)
pvalues.data[pvalues.size - 1 - i];
vec_push(&ordered, (void*) arg);
}
SK res = nfun_call(val_fun->val.nfun, SK res = nfun_call(val_fun->val.nfun,
state, state,
&pvalues); &ordered);
struct value* value = struct value* value =
state_try_get_value(state, res); state_try_get_value(state, res);
state_push( state_push(
@ -127,8 +143,10 @@ void exec_execute(struct exec* self,
); );
vec_free(&pvalues); vec_free(&pvalues);
vec_free_elements(&params, NULL); vec_free(&ordered);
vec_free_elements(&params, (void*) value_free);
vec_free(&params); vec_free(&params);
value_free(f);
free(f); free(f);
self->pc++; self->pc++;
break; break;

View File

@ -5,26 +5,35 @@ void natives_populate(struct state* state, struct sym* sym)
assert(state); assert(state);
assert(sym); assert(sym);
natives_decl(state, sym, "println", native_println, 1); natives_decl(state, sym, "println", native_println, -1);
} }
void natives_decl(struct state* state, void natives_decl(struct state* state,
struct sym* sym, struct sym* sym,
char* name, char* name,
nfun_body fun, nfun_body fun,
size_t arity) int arity)
{ {
assert(state); assert(state);
assert(sym); assert(sym);
int addr = state_add_nfun(state, fun, arity); sym_decl_global(sym, state->global_id, name);
sym_decl_native(sym, name, addr); state_add_nfun(state, fun, arity);
} }
SK native_println(struct state* state, struct vec* args) SK native_println(struct state* state, struct vec* args)
{ {
for (size_t i=0; i<args->size; i++)
{
struct value* arg struct value* arg
= state_try_get_value(state, (SK) args->data[0]); = state_try_get_value(state, (SK) args->data[i]);
printf("%s\n", arg->val.str); struct str str;
str_init(&str);
value_str(arg, &str);
if (i > 0) { printf(" "); }
printf("%s", str.value);
str_free(&str);
}
printf("\n");
return state_push_bool(state, true, 0); return state_push_bool(state, true, 0);
} }

View File

@ -1,6 +1,6 @@
#include "nfun.h" #include "nfun.h"
void nfun_init(struct nfun* self, nfun_body body, size_t arity) void nfun_init(struct nfun* self, nfun_body body, int arity)
{ {
assert(self); assert(self);
self->body = body; self->body = body;
@ -24,7 +24,7 @@ SK nfun_call(struct nfun* self,
line = state_line(state, (SK) args->data[0]); line = state_line(state, (SK) args->data[0]);
} }
if (self->arity != args->size) if (self->arity >= 0 && self->arity != (int) args->size)
{ {
errors_push(line, errors_push(line,
"wrong arity, expected %zu, got %zu.", "wrong arity, expected %zu, got %zu.",

View File

@ -214,7 +214,6 @@ struct node* parser_try_block(struct parser* self)
} }
struct token* tok = lexer_try_new_next(&self->lexer); struct token* tok = lexer_try_new_next(&self->lexer);
struct node* node = SK_TRY(parser_try_inner_block); struct node* node = SK_TRY(parser_try_inner_block);
if (!node) if (!node)
@ -226,9 +225,12 @@ struct node* parser_try_block(struct parser* self)
if (!lexer_next_is(&self->lexer, TOKEN_END)) if (!lexer_next_is(&self->lexer, TOKEN_END))
{ {
node_free(node); free(node); node_free(node); free(node);
token_free(tok); free(tok);
return NULL; return NULL;
} }
token_free(tok);
free(tok);
lexer_consume_next(&self->lexer); lexer_consume_next(&self->lexer);
return node; return node;
} }

View File

@ -41,7 +41,9 @@ void state_init(struct state* self)
assert(self); assert(self);
vec_init(&self->frames); vec_init(&self->frames);
self->addr = 1; self->addr = 1;
self->global_id = 1456;
state_push_frame(self); state_push_frame(self);
vec_init(&self->global_values);
vec_init(&self->globals); vec_init(&self->globals);
} }
@ -51,7 +53,10 @@ void state_free(struct state* self)
vec_free_elements(&self->frames, (void*) frame_free); vec_free_elements(&self->frames, (void*) frame_free);
vec_free(&self->frames); vec_free(&self->frames);
vec_free_elements(&self->globals, (void*) value_free); vec_free_elements(&self->global_values, (void*) value_free);
vec_free(&self->global_values);
vec_free_elements(&self->globals, NULL);
vec_free(&self->globals); vec_free(&self->globals);
} }
@ -61,25 +66,30 @@ SK state_make_ref(struct state* self)
struct value* value = state_try_get_value(self, val); struct value* value = state_try_get_value(self, val);
struct value* on_heap = value_new_clone(value); struct value* on_heap = value_new_clone(value);
vec_push(&self->globals, on_heap);
return state_push_ref( size_t addr = state_add_global(
self, self,
self->globals.size - 1, on_heap
on_heap->line
); );
return state_push_ref(self, addr, value->line);
} }
struct value* state_try_deref(struct state* self, size_t ref) struct value* state_try_deref(struct state* self, size_t ref)
{ {
assert(self); assert(self);
if (ref >= self->globals.size) for (size_t i=0; i<self->globals.size; i++)
{ {
return NULL; struct global const* global = self->globals.data[i];
if (global->addr == ref)
{
return self->global_values.data[ref];
}
} }
return self->globals.data[ref]; return NULL;
} }
struct frame* state_frame(struct state* self) struct frame* state_frame(struct state* self)
@ -302,7 +312,25 @@ void state_local_load(struct state* self,
} }
} }
fprintf(stderr, "cannot load %d\n", id); fprintf(stderr, "cannot load local %d\n", id);
abort();
}
void state_global_load(struct state* self,
int id)
{
for (size_t i=0; i<self->globals.size; i++)
{
struct global const* global = self->globals.data[i];
if (global->id == id)
{
state_push_ref(self, global->addr, 0);
return;
}
}
fprintf(stderr, "cannot load global %d\n", id);
abort(); abort();
} }
@ -726,6 +754,23 @@ SK state_eq(struct state* self)
); );
} }
int state_add_global(struct state* self,
struct value* value)
{
assert(self);
vec_push(&self->global_values, value);
size_t addr = self->global_values.size - 1;
struct global* global = malloc(sizeof(struct global));
global->id = self->global_id;
self->global_id++;
global->addr = addr;
vec_push(&self->globals, global);
return addr;
}
void state_call(struct state* self, struct fun* fun) void state_call(struct state* self, struct fun* fun)
{ {
assert(self); assert(self);
@ -742,7 +787,7 @@ void state_ret(struct state* self)
SK state_add_nfun(struct state* self, SK state_add_nfun(struct state* self,
nfun_body body, nfun_body body,
size_t arity) int arity)
{ {
struct nfun* fun = malloc(sizeof(struct nfun)); struct nfun* fun = malloc(sizeof(struct nfun));
nfun_init(fun, body, arity); nfun_init(fun, body, arity);
@ -753,6 +798,5 @@ SK state_add_nfun(struct state* self,
struct value* value = malloc(sizeof(struct value)); struct value* value = malloc(sizeof(struct value));
value_init(value, TYPE_NATIVE_FUN, val, 0); value_init(value, TYPE_NATIVE_FUN, val, 0);
vec_push(&self->globals, value); return state_add_global(self, value);
return self->globals.size - 1;
} }

View File

@ -71,6 +71,7 @@ void symbol_init(struct symbol* self,
self->id = id; self->id = id;
self->name = strdup(name); self->name = strdup(name);
self->is_const = false; self->is_const = false;
self->is_global = false;
self->closure_id = SK_NO_CLOSURE; self->closure_id = SK_NO_CLOSURE;
self->native_id = SK_NO_NATIVE; self->native_id = SK_NO_NATIVE;
self->env = env; self->env = env;
@ -88,6 +89,7 @@ void sym_init(struct sym* self)
self->id_counter = 1; self->id_counter = 1;
self->closure_counter = 1; self->closure_counter = 1;
self->native_counter = 1; self->native_counter = 1;
self->global_counter = 1;
self->env = malloc(sizeof(struct env)); self->env = malloc(sizeof(struct env));
env_init(self->env); env_init(self->env);
} }
@ -156,20 +158,16 @@ int sym_decl_closure(struct sym* self, int id, char const* name)
return self->closure_counter - 1; return self->closure_counter - 1;
} }
int sym_decl_native(struct sym* self, char const* name, int addr) int sym_decl_global(struct sym* self, int id, char const* name)
{ {
assert(self); assert(self);
assert(name); assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol)); struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, self->native_counter, name, self->env); symbol_init(symbol, id, name, self->env);
symbol->is_const = false; symbol->is_global = true;
symbol->native_id = addr;
vec_push(&self->env->symbols, symbol); vec_push(&self->env->symbols, symbol);
return id;
self->native_counter++;
return self->native_counter - 1;
} }
void sym_open_scope(struct sym* self) void sym_open_scope(struct sym* self)
{ {
assert(self); assert(self);

View File

@ -70,7 +70,7 @@ struct value* value_new_clone(struct value* self)
} break; } break;
case TYPE_STRING: { case TYPE_STRING: {
val.str = self->val.str; val.str = strdup(self->val.str);
value_init(clone, TYPE_STRING, val, self->line); value_init(clone, TYPE_STRING, val, self->line);
return clone; return clone;
} break; } break;