Compare commits

...

2 Commits

Author SHA1 Message Date
bog b5f0713fee improved println 🎨 better global support 🐛 string duplication with clone. 2024-04-07 05:23:59 +02:00
bog 88aad1ee75 native functions. 2024-04-06 20:44:58 +02:00
21 changed files with 411 additions and 98 deletions

1
.gitignore vendored
View File

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

View File

@ -25,6 +25,9 @@ add_library(skopy-lib SHARED
src/sym.c
src/fun.c
src/nfun.c
src/natives.c
)
file(GLOB_RECURSE

View File

@ -13,6 +13,7 @@
#include "vec.h"
#include "errors.h"
#define SK_ENUM_ENUM(X) X
#define SK_ENUM_STR(X) #X

View File

@ -5,6 +5,8 @@
#include "prog.h"
#include "sym.h"
struct state;
struct compiler
{
struct vec var_names;
@ -16,12 +18,14 @@ void compiler_free(struct compiler* self);
void compiler_compile(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym);
struct sym* sym,
struct state* state);
void compiler_compile_children(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym);
struct sym* sym,
struct state* state);
void compiler_compile_value(struct compiler* self,
struct node* node,
@ -32,17 +36,20 @@ void compiler_compile_value(struct compiler* self,
void compiler_compile_and(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym);
struct sym* sym,
struct state* state);
void compiler_compile_or(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym);
struct sym* sym,
struct state* state);
void compiler_compile_if(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct state* state,
struct vec* to_end);
#endif

View File

@ -4,12 +4,14 @@
#include "commons.h"
#include "prog.h"
#include "sym.h"
#include "state.h"
struct module
{
struct str source;
struct prog prog;
struct sym sym;
struct state state;
};
void module_init(struct module* self);

17
lib/include/natives.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef SK_NATIVES_H
#define SK_NATIVES_H
#include "commons.h"
#include "state.h"
#include "sym.h"
void natives_populate(struct state* state, struct sym* sym);
void natives_decl(struct state* state,
struct sym* sym,
char* name,
nfun_body fun,
int arity);
SK native_println(struct state* state, struct vec* args);
#endif

21
lib/include/nfun.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef SK_NFUN_H
#define SK_NFUN_H
#include "commons.h"
#include "state.h"
typedef SK (*nfun_body)(struct state*, struct vec*);
struct nfun
{
nfun_body body;
int arity;
};
void nfun_init(struct nfun* self, nfun_body body, int arity);
void nfun_free(struct nfun* self);
SK nfun_call(struct nfun* self,
struct state* state,
struct vec* args);
#endif

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

@ -1,7 +1,6 @@
#ifndef SK_STATE_H
#define SK_STATE_H
#include "commons.h"
#include "value.h"
#define SK size_t
@ -27,13 +26,23 @@ 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*);
void stack_value_init(struct stack_value* self,
size_t addr,
struct value* new_value);
@ -53,7 +62,6 @@ struct frame* state_frame(struct state* self);
void state_push_frame(struct state* self);
void state_pop_frame(struct state* self);
bool state_has_top(struct state* self);
SK state_top(struct state* self);
struct value* state_try_get_value(struct state* self, SK value);
struct local* state_try_get_local_by_id(struct state* self, int id);
@ -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,6 +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,
int arity);
#endif

View File

@ -3,13 +3,16 @@
#include "commons.h"
#define SK_NO_CLOSURE (-1)
#define SK_NO_NATIVE (-1)
struct symbol
{
int id;
int closure_id;
int native_id;
char* name;
bool is_const;
bool is_global;
struct env* env;
};
@ -23,6 +26,8 @@ struct sym
{
int id_counter;
int closure_counter;
int native_counter;
int global_counter;
struct env* env;
};
@ -46,6 +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_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

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

View File

@ -1,5 +1,7 @@
#include "compiler.h"
#include "token.h"
#include "state.h"
#include "natives.h"
void compiler_init(struct compiler* self)
{
@ -16,7 +18,8 @@ void compiler_free(struct compiler* self)
void compiler_compile(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym)
struct sym* sym,
struct state* state)
{
assert(self);
assert(node);
@ -28,7 +31,7 @@ void compiler_compile(struct compiler* self,
for (size_t i=0; i<node->children.size; i++)
{
compiler_compile(self, node->children.data[i],
prog, sym);
prog, sym, state);
}
} break;
@ -37,7 +40,7 @@ void compiler_compile(struct compiler* self,
for (size_t i=0; i<node->children.size; i++)
{
compiler_compile(self, node->children.data[i],
prog, sym);
prog, sym, state);
}
sym_close_scope(sym);
} break;
@ -49,10 +52,10 @@ void compiler_compile(struct compiler* self,
for (size_t i=0; i<args->children.size; i++)
{
compiler_compile(self, args->children.data[i],
prog, sym);
prog, sym, state);
}
compiler_compile(self, target, prog, sym);
compiler_compile(self, target, prog, sym, state);
prog_add_instr(prog, OP_CALL, args->children.size);
} break;
@ -60,7 +63,8 @@ void compiler_compile(struct compiler* self,
struct vec to_end;
vec_init(&to_end);
compiler_compile_if(self, node, prog, sym, &to_end);
compiler_compile_if(self, node, prog, sym, state,
&to_end);
size_t end_point = prog->params.size;
for (size_t i=0; i<to_end.size; i++)
@ -73,20 +77,20 @@ void compiler_compile(struct compiler* self,
} break;
case NODE_NOT: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break;
case NODE_AND: {
compiler_compile_and(self, node, prog, sym);
compiler_compile_and(self, node, prog, sym, state);
} break;
case NODE_OR: {
compiler_compile_or(self, node, prog, sym);
compiler_compile_or(self, node, prog, sym, state);
} break;
case NODE_ASSERT_EQ: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM);
} break;
@ -103,7 +107,7 @@ void compiler_compile(struct compiler* self,
}
struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym);
compiler_compile(self, expr, prog, sym, state);
int id = sym_decl_var(sym, ident->token->value);
@ -122,7 +126,7 @@ void compiler_compile(struct compiler* self,
ident->token->value);
}
struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym);
compiler_compile(self, expr, prog, sym, state);
int id = sym_decl_const(sym, ident->token->value);
prog_add_instr(prog, OP_LOCAL_STORE, id);
char* name = vec_pop(&self->var_names);
@ -148,7 +152,7 @@ void compiler_compile(struct compiler* self,
break;
}
compiler_compile(self, expr, prog, sym);
compiler_compile(self, expr, prog, sym, state);
if (symbol->closure_id != SK_NO_CLOSURE)
{
@ -165,28 +169,29 @@ void compiler_compile(struct compiler* self,
node->token->value);
if (!symbol)
{
errors_push(node->token->line,
"unknown identifier '%s'.",
node->token->value);
break;
}
struct env* itr = sym->env->parent;
struct symbol* context = NULL;
while (itr)
{
struct symbol* s = env_try_get(itr, symbol->name);
struct symbol const* s = env_try_get(itr, symbol->name);
if (s)
{
context = s;
break;
}
itr = itr->parent;
}
if (0 && context)
if (symbol->is_global)
{
prog_add_instr(prog, OP_LOCAL_LOAD, context->id);
prog_add_instr(prog, OP_GLOBAL_LOAD, symbol->id);
}
else if (symbol->closure_id != SK_NO_CLOSURE)
{
@ -200,7 +205,7 @@ void compiler_compile(struct compiler* self,
case NODE_RETURN: {
compiler_compile(self, node->children.data[0],
prog, sym);
prog, sym, state);
prog_add_instr(prog, OP_RET, SK_NO_PARAM);
} break;
@ -210,6 +215,8 @@ void compiler_compile(struct compiler* self,
prog_init(p);
fun_init(fun, p);
natives_populate(state, fun->sym);
struct node* params = node->children.data[0];
struct node* body = node->children.data[1];
@ -253,7 +260,8 @@ void compiler_compile(struct compiler* self,
}
}
}
compiler_compile(self, body, p, fun->sym);
compiler_compile(self, body, p, fun->sym, state);
union val val;
val.fun = fun;
@ -291,70 +299,70 @@ void compiler_compile(struct compiler* self,
} break;
case NODE_LT: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
} break;
case NODE_LE: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break;
case NODE_GT: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
} break;
case NODE_GE: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break;
case NODE_EQUAL: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
} break;
case NODE_NOT_EQUAL: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break;
case NODE_ADD: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_ADD, SK_NO_PARAM);
} break;
case NODE_SUB: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_SUB, SK_NO_PARAM);
} break;
case NODE_MUL: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_MUL, SK_NO_PARAM);
} break;
case NODE_DIV: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_DIV, SK_NO_PARAM);
} break;
case NODE_MOD: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_MOD, SK_NO_PARAM);
} break;
case NODE_POW: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_POW, SK_NO_PARAM);
} break;
case NODE_USUB: {
compiler_compile_children(self, node, prog, sym);
compiler_compile_children(self, node, prog, sym, state);
prog_add_instr(prog, OP_USUB, SK_NO_PARAM);
} break;
@ -369,7 +377,8 @@ void compiler_compile(struct compiler* self,
void compiler_compile_children(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym)
struct sym* sym,
struct state* state)
{
assert(self);
assert(node);
@ -378,7 +387,7 @@ void compiler_compile_children(struct compiler* self,
for (size_t i=0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog, sym);
compiler_compile(self, child, prog, sym, state);
}
}
@ -399,7 +408,8 @@ void compiler_compile_value(struct compiler* self,
void compiler_compile_and(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym)
struct sym* sym,
struct state* state)
{
assert(self);
assert(node);
@ -412,7 +422,7 @@ void compiler_compile_and(struct compiler* self,
for (size_t i =0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog, sym);
compiler_compile(self, child, prog, sym, state);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false
vec_push(&to_false, (void*) brf);
}
@ -442,7 +452,8 @@ void compiler_compile_and(struct compiler* self,
void compiler_compile_or(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym)
struct sym* sym,
struct state* state)
{
assert(self);
assert(node);
@ -454,7 +465,7 @@ void compiler_compile_or(struct compiler* self,
for (size_t i =0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog, sym);
compiler_compile(self, child, prog, sym, state);
prog_add_instr(prog, OP_NOT, 0);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true
vec_push(&to_true, (void*) brf);
@ -486,15 +497,16 @@ void compiler_compile_if(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct state* state,
struct vec* to_end)
{
struct node* cond = node->children.data[0];
struct node* block = node->children.data[1];
compiler_compile(self, cond, prog, sym);
compiler_compile(self, cond, prog, sym, state);
size_t brf = prog_add_instr(prog, OP_BRF, 40); // to next
compiler_compile(self, block, prog, sym);
compiler_compile(self, block, prog, sym, state);
size_t br = prog_add_instr(prog, OP_BR, 0); // to end
vec_push(to_end, (void*) br);
@ -507,11 +519,11 @@ void compiler_compile_if(struct compiler* self,
struct node* next = node->children.data[2];
if (next->kind == NODE_IF)
{
compiler_compile_if(self, next, prog, sym, to_end);
compiler_compile_if(self, next, prog, sym, state, to_end);
}
else
{
compiler_compile(self, next, prog, sym);
compiler_compile(self, next, prog, sym, state);
}
}
}

View File

@ -1,6 +1,7 @@
#include "exec.h"
#include "sym.h"
#include "fun.h"
#include "nfun.h"
void exec_init(struct exec* self)
{
@ -39,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++;
@ -93,19 +99,70 @@ void exec_execute(struct exec* self,
struct vec params;
vec_init(&params);
struct vec pvalues;
vec_init(&pvalues);
SK function = state_pop(state);
for (size_t i=0; i<param; i++)
{
SK arg = state_pop(state);
vec_push(&pvalues, (void*) arg);
vec_push(&params, (void*) value_new_clone(state_try_get_value(state, arg)));
}
struct value* f = value_new_clone(state_try_get_value(state, function));
struct fun* fun = state_try_deref(
struct value* val_fun = state_try_deref(
state,
f->val.ref
)->val.fun;
);
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,
&ordered);
struct value* value =
state_try_get_value(state, res);
state_push(
state,
value->type,
value->val,
value->line
);
vec_free(&pvalues);
vec_free(&ordered);
vec_free_elements(&params, (void*) value_free);
vec_free(&params);
value_free(f);
free(f);
self->pc++;
break;
}
vec_free(&pvalues);
if (!val_fun)
{
vec_free_elements(&params, NULL);
vec_free(&params);
errors_push(f->line, "cannot deref nil ref");
free(f);
return;
}
struct fun* fun = val_fun->val.fun;
state_call(state, fun);
for (size_t i=0; i<params.size; i++)
@ -191,6 +248,14 @@ void exec_execute(struct exec* self,
);
} break;
case TYPE_REF: {
state_push_ref(
state,
constant->val.ref,
constant->line
);
} break;
case TYPE_BOOL: {
state_push_bool(
state,

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

@ -3,13 +3,17 @@
#include "compiler.h"
#include "state.h"
#include "exec.h"
#include "natives.h"
void module_init(struct module* self)
{
assert(self);
str_init(&self->source);
prog_init(&self->prog);
state_init(&self->state);
sym_init(&self->sym);
natives_populate(&self->state, &self->sym);
}
void module_free(struct module* self)
@ -18,6 +22,7 @@ void module_free(struct module* self)
str_free(&self->source);
prog_free(&self->prog);
sym_free(&self->sym);
state_free(&self->state);
}
void module_load_source(struct module* self,
@ -54,14 +59,13 @@ int module_compile(struct module* self)
struct compiler compiler;
compiler_init(&compiler);
compiler_compile(&compiler, root, &self->prog, &self->sym);
compiler_compile(&compiler, root, &self->prog, &self->sym,
&self->state);
struct exec exec;
exec_init(&exec);
struct state state;
state_init(&state);
exec_execute(&exec, &state, &self->prog);
exec_execute(&exec, &self->state, &self->prog);
if (!errors_ok())
{
@ -69,25 +73,8 @@ int module_compile(struct module* self)
goto free_state;
}
if (state_has_top(&state))
{
struct value* value = state_try_get_value(
&state,
state_top(&state)
);
assert(value);
struct str str;
str_init(&str);
value_str(value, &str);
printf("%s\n", str.value);
str_free(&str);
}
// Free
free_state:
state_free(&state);
exec_free(&exec);
compiler_free(&compiler);
free_node:

39
lib/src/natives.c Normal file
View File

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

39
lib/src/nfun.c Normal file
View File

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

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

@ -1,4 +1,5 @@
#include "state.h"
#include "nfun.h"
void stack_value_init(struct stack_value* self,
size_t addr,
@ -40,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);
}
@ -50,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);
}
@ -60,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)
@ -105,11 +116,6 @@ void state_pop_frame(struct state* self)
frame_free(frame);
free(frame);
}
bool state_has_top(struct state* self)
{
struct frame* frame = state_frame(self);
return frame->stack.size > 0;
}
SK state_top(struct state* self)
{
@ -306,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();
}
@ -730,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);
@ -743,3 +784,19 @@ void state_ret(struct state* self)
assert(self);
state_pop_frame(self);
}
SK state_add_nfun(struct state* self,
nfun_body body,
int arity)
{
struct nfun* fun = malloc(sizeof(struct nfun));
nfun_init(fun, body, arity);
union val val;
val.nfun = fun;
struct value* value = malloc(sizeof(struct value));
value_init(value, TYPE_NATIVE_FUN, val, 0);
return state_add_global(self, value);
}

View File

@ -21,6 +21,7 @@ struct env* env_new_clone(struct env* self)
new_symbol->name = strdup(symbol->name);
new_symbol->is_const = symbol->is_const;
new_symbol->closure_id = symbol->closure_id;
new_symbol->native_id = symbol->native_id;
new_symbol->env = clone;
vec_push(&clone->symbols, new_symbol);
@ -70,7 +71,9 @@ 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;
}
@ -85,6 +88,8 @@ void sym_init(struct sym* self)
assert(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);
}
@ -153,6 +158,16 @@ int sym_decl_closure(struct sym* self, int id, char const* name)
return self->closure_counter - 1;
}
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, id, name, self->env);
symbol->is_global = true;
vec_push(&self->env->symbols, symbol);
return id;
}
void sym_open_scope(struct sym* self)
{
assert(self);

View File

@ -1,4 +1,5 @@
#include "value.h"
#include "nfun.h"
SK_ENUM_C(TypeKind, TYPE_KIND);
@ -27,6 +28,12 @@ void value_free(struct value* self)
fun_free(self->val.fun);
free(self->val.fun);
}
if (self->type == TYPE_NATIVE_FUN)
{
nfun_free(self->val.nfun);
free(self->val.nfun);
}
}
struct value* value_new_clone(struct value* self)
@ -63,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;
@ -74,6 +81,14 @@ struct value* value_new_clone(struct value* self)
return clone;
} break;
case TYPE_NATIVE_FUN: {
val.nfun = malloc(sizeof(struct nfun));
val.nfun->body = self->val.nfun->body;
val.nfun->arity = self->val.nfun->arity;
value_init(clone, TYPE_NATIVE_FUN, val, self->line);
return clone;
} break;
default: {
fprintf(stderr, "cannot clone value '%s'\n",
TypeKindStr[self->type]);
@ -111,6 +126,10 @@ void value_str(struct value* self, struct str* dest)
str_format(dest, "<fun:%p>", self->val.fun);
} break;
case TYPE_NATIVE_FUN: {
str_format(dest, "<nfun:%p>", self->val.nfun);
} break;
case TYPE_REF: {
str_format(dest, "<ref:%zu>", self->val.ref);
} break;