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
.cache
vgcore*

View File

@ -10,7 +10,7 @@ void natives_decl(struct state* state,
struct sym* sym,
char* name,
nfun_body fun,
size_t arity);
int arity);
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
{
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);
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_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \
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);

View File

@ -26,11 +26,19 @@ struct frame
struct fun* fun;
};
struct global
{
int id;
size_t addr;
};
struct state
{
struct vec frames;
size_t addr;
int global_id;
struct vec globals;
struct vec global_values;
};
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,
int id);
void state_global_load(struct state* self,
int id);
void state_closure_load(struct state* self,
int id);
@ -107,9 +118,12 @@ SK state_lt(struct state* self);
SK state_gt(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_ret(struct state* self);
SK state_add_nfun(struct state* self,
nfun_body body,
size_t arity);
int arity);
#endif

View File

@ -12,6 +12,7 @@ struct symbol
int native_id;
char* name;
bool is_const;
bool is_global;
struct env* env;
};
@ -26,6 +27,7 @@ struct sym
int id_counter;
int closure_counter;
int native_counter;
int global_counter;
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_const(struct sym* self, 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_close_scope(struct sym* self);

View File

@ -189,14 +189,9 @@ void compiler_compile(struct compiler* self,
itr = itr->parent;
}
if (symbol->native_id != SK_NO_NATIVE)
if (symbol->is_global)
{
struct value* value = malloc(sizeof(struct value));
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);
prog_add_instr(prog, OP_GLOBAL_LOAD, symbol->id);
}
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);
union val val;

View File

@ -40,6 +40,11 @@ void exec_execute(struct exec* self,
self->pc++;
} break;
case OP_GLOBAL_LOAD: {
state_global_load(state, param);
self->pc++;
} break;
case OP_LOCAL_LOAD: {
state_local_load(state, param);
self->pc++;
@ -98,6 +103,7 @@ void exec_execute(struct exec* self,
vec_init(&pvalues);
SK function = state_pop(state);
for (size_t i=0; i<param; i++)
{
SK arg = state_pop(state);
@ -112,11 +118,21 @@ void exec_execute(struct exec* self,
f->val.ref
);
assert(val_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,
state,
&pvalues);
&ordered);
struct value* value =
state_try_get_value(state, res);
state_push(
@ -127,8 +143,10 @@ void exec_execute(struct exec* self,
);
vec_free(&pvalues);
vec_free_elements(&params, NULL);
vec_free(&ordered);
vec_free_elements(&params, (void*) value_free);
vec_free(&params);
value_free(f);
free(f);
self->pc++;
break;

View File

@ -83,7 +83,7 @@ struct closure* fun_try_get_closure(struct fun* self, int id)
for (size_t i=0; i<self->closures.size; i++)
{
struct closure* c = self->closures.data[i];
if (c->id == id)
{
return c;

View File

@ -5,26 +5,35 @@ void natives_populate(struct state* state, struct sym* sym)
assert(state);
assert(sym);
natives_decl(state, sym, "println", native_println, 1);
natives_decl(state, sym, "println", native_println, -1);
}
void natives_decl(struct state* state,
struct sym* sym,
char* name,
nfun_body fun,
size_t arity)
int arity)
{
assert(state);
assert(sym);
int addr = state_add_nfun(state, fun, arity);
sym_decl_native(sym, name, addr);
sym_decl_global(sym, state->global_id, name);
state_add_nfun(state, fun, arity);
}
SK native_println(struct state* state, struct vec* args)
{
struct value* arg
= state_try_get_value(state, (SK) args->data[0]);
for (size_t i=0; i<args->size; i++)
{
struct value* arg
= 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);
}

View File

@ -1,6 +1,6 @@
#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);
self->body = body;
@ -24,7 +24,7 @@ SK nfun_call(struct nfun* self,
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,
"wrong arity, expected %zu, got %zu.",

View File

@ -92,17 +92,17 @@ struct node* parser_try_expr(struct parser* self)
if (lexer_next_is(&self->lexer, TOKEN_RETURN))
{
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_RETURN,
node_init(node, NODE_RETURN,
lexer_try_new_next(&self->lexer));
struct node* child = SK_TRY(parser_try_expr);
if (!child)
{
node_free(node); free(node);
return NULL;
}
node_push_new_child(node, child);
return node;
}
@ -162,11 +162,11 @@ struct node* parser_try_fun_decl(struct parser* self)
free(fun);
return NULL;
}
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT,
node_init(ident, NODE_IDENT,
lexer_try_new_next(&self->lexer));
if (!lexer_next_is(&self->lexer, TOKEN_OPAR))
{
node_free(fun); free(fun);
@ -214,7 +214,6 @@ struct node* parser_try_block(struct parser* self)
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* node = SK_TRY(parser_try_inner_block);
if (!node)
@ -226,9 +225,12 @@ struct node* parser_try_block(struct parser* self)
if (!lexer_next_is(&self->lexer, TOKEN_END))
{
node_free(node); free(node);
token_free(tok); free(tok);
return NULL;
}
token_free(tok);
free(tok);
lexer_consume_next(&self->lexer);
return node;
}

View File

@ -41,7 +41,9 @@ void state_init(struct state* self)
assert(self);
vec_init(&self->frames);
self->addr = 1;
self->global_id = 1456;
state_push_frame(self);
vec_init(&self->global_values);
vec_init(&self->globals);
}
@ -51,7 +53,10 @@ void state_free(struct state* self)
vec_free_elements(&self->frames, (void*) frame_free);
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);
}
@ -61,25 +66,30 @@ SK state_make_ref(struct state* self)
struct value* value = state_try_get_value(self, val);
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->globals.size - 1,
on_heap->line
on_heap
);
return state_push_ref(self, addr, value->line);
}
struct value* state_try_deref(struct state* self, size_t ref)
{
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)
@ -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();
}
@ -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)
{
assert(self);
@ -742,7 +787,7 @@ void state_ret(struct state* self)
SK state_add_nfun(struct state* self,
nfun_body body,
size_t arity)
int arity)
{
struct nfun* fun = malloc(sizeof(struct nfun));
nfun_init(fun, body, arity);
@ -753,6 +798,5 @@ SK state_add_nfun(struct state* self,
struct value* value = malloc(sizeof(struct value));
value_init(value, TYPE_NATIVE_FUN, val, 0);
vec_push(&self->globals, value);
return self->globals.size - 1;
return state_add_global(self, value);
}

View File

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

View File

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