diff --git a/.gitignore b/.gitignore
index 1e46243..600228e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
*\#*
build
.cache
+vgcore*
diff --git a/lib/include/natives.h b/lib/include/natives.h
index a6d9379..f4050c9 100644
--- a/lib/include/natives.h
+++ b/lib/include/natives.h
@@ -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);
diff --git a/lib/include/nfun.h b/lib/include/nfun.h
index a313fca..915a1cd 100644
--- a/lib/include/nfun.h
+++ b/lib/include/nfun.h
@@ -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,
diff --git a/lib/include/prog.h b/lib/include/prog.h
index 1743686..3eb2372 100644
--- a/lib/include/prog.h
+++ b/lib/include/prog.h
@@ -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);
diff --git a/lib/include/state.h b/lib/include/state.h
index 7db78a3..bb22b4c 100644
--- a/lib/include/state.h
+++ b/lib/include/state.h
@@ -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
diff --git a/lib/include/sym.h b/lib/include/sym.h
index b387ce6..5d0826b 100644
--- a/lib/include/sym.h
+++ b/lib/include/sym.h
@@ -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);
diff --git a/lib/src/compiler.c b/lib/src/compiler.c
index 38f6c7a..92e78e5 100644
--- a/lib/src/compiler.c
+++ b/lib/src/compiler.c
@@ -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;
diff --git a/lib/src/exec.c b/lib/src/exec.c
index fe71ffc..8f73362 100644
--- a/lib/src/exec.c
+++ b/lib/src/exec.c
@@ -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; ival.ref
);
+ assert(val_fun);
+
if (val_fun->type == TYPE_NATIVE_FUN)
{
+ struct vec ordered;
+ vec_init(&ordered);
+ for (size_t i=0; ival.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(¶ms, NULL);
+ vec_free(&ordered);
+ vec_free_elements(¶ms, (void*) value_free);
vec_free(¶ms);
+ value_free(f);
free(f);
self->pc++;
break;
diff --git a/lib/src/fun.c b/lib/src/fun.c
index 91a8066..6648cf8 100644
--- a/lib/src/fun.c
+++ b/lib/src/fun.c
@@ -83,7 +83,7 @@ struct closure* fun_try_get_closure(struct fun* self, int id)
for (size_t i=0; iclosures.size; i++)
{
struct closure* c = self->closures.data[i];
-
+
if (c->id == id)
{
return c;
diff --git a/lib/src/natives.c b/lib/src/natives.c
index d141078..d5101ec 100644
--- a/lib/src/natives.c
+++ b/lib/src/natives.c
@@ -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; isize; 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);
}
diff --git a/lib/src/nfun.c b/lib/src/nfun.c
index 1e69f27..9c3ed33 100644
--- a/lib/src/nfun.c
+++ b/lib/src/nfun.c
@@ -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.",
diff --git a/lib/src/parser.c b/lib/src/parser.c
index 1a7b170..e6a248e 100644
--- a/lib/src/parser.c
+++ b/lib/src/parser.c
@@ -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;
}
diff --git a/lib/src/state.c b/lib/src/state.c
index f735f73..e22f681 100644
--- a/lib/src/state.c
+++ b/lib/src/state.c
@@ -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; iglobals.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; iglobals.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);
}
diff --git a/lib/src/sym.c b/lib/src/sym.c
index 4ff857c..af87085 100644
--- a/lib/src/sym.c
+++ b/lib/src/sym.c
@@ -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);
diff --git a/lib/src/value.c b/lib/src/value.c
index 27e46ca..6f56c54 100644
--- a/lib/src/value.c
+++ b/lib/src/value.c
@@ -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;