✨ native functions.
parent
06b379c99c
commit
88aad1ee75
|
@ -25,6 +25,9 @@ add_library(skopy-lib SHARED
|
|||
|
||||
src/sym.c
|
||||
src/fun.c
|
||||
|
||||
src/nfun.c
|
||||
src/natives.c
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "vec.h"
|
||||
#include "errors.h"
|
||||
|
||||
|
||||
#define SK_ENUM_ENUM(X) X
|
||||
#define SK_ENUM_STR(X) #X
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
size_t arity);
|
||||
|
||||
SK native_println(struct state* state, struct vec* args);
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
size_t arity;
|
||||
};
|
||||
|
||||
void nfun_init(struct nfun* self, nfun_body body, size_t arity);
|
||||
void nfun_free(struct nfun* self);
|
||||
|
||||
SK nfun_call(struct nfun* self,
|
||||
struct state* state,
|
||||
struct vec* args);
|
||||
#endif
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef SK_STATE_H
|
||||
#define SK_STATE_H
|
||||
|
||||
#include "commons.h"
|
||||
#include "value.h"
|
||||
|
||||
#define SK size_t
|
||||
|
@ -34,6 +33,8 @@ struct state
|
|||
struct vec globals;
|
||||
};
|
||||
|
||||
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 +54,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);
|
||||
|
@ -109,4 +109,7 @@ SK state_eq(struct state* self);
|
|||
|
||||
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);
|
||||
#endif
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
#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;
|
||||
struct env* env;
|
||||
|
@ -23,6 +25,7 @@ struct sym
|
|||
{
|
||||
int id_counter;
|
||||
int closure_counter;
|
||||
int native_counter;
|
||||
struct env* env;
|
||||
};
|
||||
|
||||
|
@ -46,6 +49,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);
|
||||
|
||||
void sym_open_scope(struct sym* self);
|
||||
void sym_close_scope(struct sym* self);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,34 @@ 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->native_id != SK_NO_NATIVE)
|
||||
{
|
||||
prog_add_instr(prog, OP_LOCAL_LOAD, context->id);
|
||||
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);
|
||||
}
|
||||
else if (symbol->closure_id != SK_NO_CLOSURE)
|
||||
{
|
||||
|
@ -200,7 +210,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 +220,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 +265,7 @@ 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 +303,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 +381,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 +391,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 +412,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 +426,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 +456,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 +469,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 +501,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 +523,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "exec.h"
|
||||
#include "sym.h"
|
||||
#include "fun.h"
|
||||
#include "nfun.h"
|
||||
|
||||
void exec_init(struct exec* self)
|
||||
{
|
||||
|
@ -93,19 +94,57 @@ void exec_execute(struct exec* self,
|
|||
struct vec params;
|
||||
vec_init(¶ms);
|
||||
|
||||
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(¶ms, (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;
|
||||
);
|
||||
|
||||
if (val_fun->type == TYPE_NATIVE_FUN)
|
||||
{
|
||||
SK res = nfun_call(val_fun->val.nfun,
|
||||
state,
|
||||
&pvalues);
|
||||
struct value* value =
|
||||
state_try_get_value(state, res);
|
||||
state_push(
|
||||
state,
|
||||
value->type,
|
||||
value->val,
|
||||
value->line
|
||||
);
|
||||
|
||||
vec_free(&pvalues);
|
||||
vec_free_elements(¶ms, NULL);
|
||||
vec_free(¶ms);
|
||||
free(f);
|
||||
self->pc++;
|
||||
break;
|
||||
}
|
||||
|
||||
vec_free(&pvalues);
|
||||
if (!val_fun)
|
||||
{
|
||||
vec_free_elements(¶ms, NULL);
|
||||
vec_free(¶ms);
|
||||
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 +230,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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#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,
|
||||
size_t arity)
|
||||
{
|
||||
assert(state);
|
||||
assert(sym);
|
||||
int addr = state_add_nfun(state, fun, arity);
|
||||
sym_decl_native(sym, name, addr);
|
||||
}
|
||||
|
||||
SK native_println(struct state* state, struct vec* args)
|
||||
{
|
||||
struct value* arg
|
||||
= state_try_get_value(state, (SK) args->data[0]);
|
||||
|
||||
printf("%s\n", arg->val.str);
|
||||
return state_push_bool(state, true, 0);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#include "nfun.h"
|
||||
|
||||
void nfun_init(struct nfun* self, nfun_body body, size_t 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 != 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;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include "state.h"
|
||||
#include "nfun.h"
|
||||
|
||||
void stack_value_init(struct stack_value* self,
|
||||
size_t addr,
|
||||
|
@ -105,11 +106,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)
|
||||
{
|
||||
|
@ -743,3 +739,20 @@ void state_ret(struct state* self)
|
|||
assert(self);
|
||||
state_pop_frame(self);
|
||||
}
|
||||
|
||||
SK state_add_nfun(struct state* self,
|
||||
nfun_body body,
|
||||
size_t 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);
|
||||
|
||||
vec_push(&self->globals, value);
|
||||
return self->globals.size - 1;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -71,6 +72,7 @@ void symbol_init(struct symbol* self,
|
|||
self->name = strdup(name);
|
||||
self->is_const = false;
|
||||
self->closure_id = SK_NO_CLOSURE;
|
||||
self->native_id = SK_NO_NATIVE;
|
||||
self->env = env;
|
||||
}
|
||||
|
||||
|
@ -85,6 +87,7 @@ void sym_init(struct sym* self)
|
|||
assert(self);
|
||||
self->id_counter = 1;
|
||||
self->closure_counter = 1;
|
||||
self->native_counter = 1;
|
||||
self->env = malloc(sizeof(struct env));
|
||||
env_init(self->env);
|
||||
}
|
||||
|
@ -153,6 +156,20 @@ 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)
|
||||
{
|
||||
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;
|
||||
vec_push(&self->env->symbols, symbol);
|
||||
|
||||
self->native_counter++;
|
||||
return self->native_counter - 1;
|
||||
}
|
||||
|
||||
void sym_open_scope(struct sym* self)
|
||||
{
|
||||
assert(self);
|
||||
|
|
|
@ -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)
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue