🐛 function now on the heap.

main
bog 2024-04-03 06:28:03 +02:00
parent 0a3d7d4aea
commit 7468605289
10 changed files with 112 additions and 8 deletions

View File

@ -26,3 +26,20 @@ var d = fun(x)
end
assert d(3) eq 5
var e = fun(n)
if n == 0
1
else
n * e(n - 1)
end
end
assert e(5) eq 120
var f = fun(x, n)
x(x(n))
end
assert f(fun(x) x * 2 end, 2) eq 8

View File

@ -7,6 +7,7 @@
struct compiler
{
struct vec var_names;
};
void compiler_init(struct compiler* self);

View File

@ -13,7 +13,7 @@ G(OP_USUB), G(OP_ASSERT_EQ), \
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_CALL), G(OP_RET), G(OP_MAKE_REF)
SK_ENUM_H(Opcode, OPCODE);

View File

@ -30,6 +30,7 @@ struct state
{
struct vec frames;
size_t addr;
struct vec globals;
};
void stack_value_init(struct stack_value* self,
@ -44,6 +45,9 @@ void frame_free(struct frame* self);
void state_init(struct state* self);
void state_free(struct state* self);
SK state_make_ref(struct state* self);
struct value* state_try_deref(struct state* self, size_t ref);
struct frame* state_frame(struct state* self);
void state_push_frame(struct state* self);
void state_pop_frame(struct state* self);
@ -64,6 +68,7 @@ SK state_push_bool(struct state* self, bool boolean, int line);
SK state_push_float(struct state* self, double real, int line);
SK state_push_string(struct state* self, char const* str, int line);
SK state_push_fun(struct state* self, struct fun* fun, int line);
SK state_push_ref(struct state* self, size_t ref, int line);
struct local* state_try_get_local(struct state* self, int id);

View File

@ -7,7 +7,7 @@
#define TYPE_KIND(G) \
G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \
G(TYPE_STRING), G(TYPE_FUN)
G(TYPE_STRING), G(TYPE_FUN), G(TYPE_REF)
SK_ENUM_H(TypeKind, TYPE_KIND);
@ -18,6 +18,7 @@ union val
bool boolean;
char* str;
struct fun* fun;
size_t ref;
};
struct value

View File

@ -4,11 +4,13 @@
void compiler_init(struct compiler* self)
{
assert(self);
vec_init(&self->var_names);
}
void compiler_free(struct compiler* self)
{
assert(self);
vec_free(&self->var_names);
}
void compiler_compile(struct compiler* self,
@ -90,6 +92,8 @@ void compiler_compile(struct compiler* self,
case NODE_VAR_DECL: {
struct node* ident = node->children.data[0];
vec_push(&self->var_names, strdup(ident->token->value));
struct symbol const* s = sym_try_get(sym, ident->token->value);
if (s && s->env == sym->env)
@ -102,10 +106,13 @@ void compiler_compile(struct compiler* self,
compiler_compile(self, expr, prog, sym);
int id = sym_decl_var(sym, ident->token->value);
prog_add_instr(prog, OP_LOCAL_STORE, id);
char* name = vec_pop(&self->var_names);
free(name);
} break;
case NODE_CONST_DECL: {
struct node* ident = node->children.data[0];
vec_push(&self->var_names, strdup(ident->token->value));
struct symbol const* s = sym_try_get(sym, ident->token->value);
if (s && s->env == sym->env)
{
@ -116,6 +123,8 @@ void compiler_compile(struct compiler* self,
compiler_compile(self, expr, prog, sym);
int id = sym_decl_const(sym, ident->token->value);
prog_add_instr(prog, OP_LOCAL_STORE, id);
char* name = vec_pop(&self->var_names);
free(name);
} break;
case NODE_ASSIGN: {
@ -164,6 +173,10 @@ void compiler_compile(struct compiler* self,
struct sym mysym;
sym_init(&mysym);
char* var_name =
self->var_names.size > 0 ?
self->var_names.data[self->var_names.size - 1]
: NULL;
for (size_t i=0; i<args->children.size; i++)
{
@ -172,6 +185,10 @@ void compiler_compile(struct compiler* self,
sym_decl_var(&mysym, name);
}
if (var_name)
{
sym_decl_var(&mysym, var_name);
}
compiler_compile(self, body, p, &mysym);
sym_free(&mysym);
fun_init(fun, p);
@ -180,6 +197,7 @@ void compiler_compile(struct compiler* self,
val.fun = fun;
compiler_compile_value(self, node, prog, TYPE_FUN,
val);
prog_add_instr(prog, OP_MAKE_REF, SK_NO_PARAM);
} break;
case NODE_BOOL: {
union val val;

View File

@ -89,7 +89,8 @@ void exec_execute(struct exec* self,
vec_push(&params, (void*) value_new_clone(state_try_get_value(state, arg)));
}
struct value* f = state_try_get_value(state, function);
struct value* f = value_new_clone(state_try_get_value(state, function));
state_call(state);
for (size_t i=0; i<params.size; i++)
{
@ -98,16 +99,22 @@ void exec_execute(struct exec* self,
state_push(state, val->type, val->val, val->line);
state_local_store(state, i+1);
}
state_push(state, f->type, f->val, f->line);
state_local_store(state, params.size + 1);
vec_free_elements(&params, NULL);
vec_free(&params);
assert(f->type == TYPE_FUN);
assert(f->type == TYPE_REF);
struct exec ex;
exec_init(&ex);
exec_execute(&ex, state, f->val.fun->prog);
struct value* fun_val =
state_try_deref(state, f->val.ref);
exec_execute(&ex, state, fun_val->val.fun->prog);
struct value* res = value_new_clone(state_try_get_value(
state,
@ -117,6 +124,13 @@ void exec_execute(struct exec* self,
state_ret(state);
state_push(state, res->type, res->val, res->line);
value_free(res); free(res);
free(f);
self->pc++;
} break;
case OP_MAKE_REF: {
state_make_ref(state);
self->pc++;
} break;

View File

@ -18,7 +18,6 @@ void fun_free(struct fun* self)
struct fun* fun_new_clone(struct fun* self)
{
(void) self;
struct fun* clone = malloc(sizeof(struct fun));
fun_init(clone, prog_new_clone(self->prog));
return clone;

View File

@ -40,6 +40,7 @@ void state_init(struct state* self)
vec_init(&self->frames);
self->addr = 1;
state_push_frame(self);
vec_init(&self->globals);
}
void state_free(struct state* self)
@ -47,6 +48,36 @@ void state_free(struct state* self)
assert(self);
vec_free_elements(&self->frames, (void*) frame_free);
vec_free(&self->frames);
vec_free_elements(&self->globals, (void*) value_free);
vec_free(&self->globals);
}
SK state_make_ref(struct state* self)
{
SK val = state_pop(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(
self,
self->globals.size - 1,
on_heap->line
);
}
struct value* state_try_deref(struct state* self, size_t ref)
{
assert(self);
if (ref >= self->globals.size)
{
return NULL;
}
return self->globals.data[ref];
}
struct frame* state_frame(struct state* self)
@ -177,7 +208,15 @@ SK state_push_fun(struct state* self, struct fun* fun, int line)
assert(self);
union val val;
val.fun = fun;
return state_push(self, TYPE_FUN, val ,line);
return state_push(self, TYPE_FUN, val, line);
}
SK state_push_ref(struct state* self,size_t ref, int line)
{
assert(self);
union val val;
val.ref = ref;
return state_push(self, TYPE_REF, val, line);
}
struct local* state_try_get_local(struct state* self, int id)

View File

@ -44,6 +44,12 @@ struct value* value_new_clone(struct value* self)
return clone;
} break;
case TYPE_REF: {
val.ref = self->val.ref;
value_init(clone, TYPE_REF, val, self->line);
return clone;
} break;
case TYPE_FLOAT: {
val.real = self->val.real;
value_init(clone, TYPE_FLOAT, val, self->line);
@ -105,6 +111,10 @@ void value_str(struct value* self, struct str* dest)
str_format(dest, "<fun:%p>", self->val.fun);
} break;
case TYPE_REF: {
str_format(dest, "<ref:%zu>", self->val.ref);
} break;
case TYPE_STRING: {
str_format(dest, "%s", self->val.str);
} break;