mirror of
https://github.com/janet-lang/janet
synced 2024-12-25 07:50:27 +00:00
Make reflective compilation less stateful
This commit is contained in:
parent
6d3e3d8246
commit
88a24531de
129
core/compile.c
129
core/compile.c
@ -72,7 +72,6 @@ struct SlotTracker {
|
|||||||
Slot *slots;
|
Slot *slots;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
SlotTracker *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A GstScope is a lexical scope in the program. It is
|
/* A GstScope is a lexical scope in the program. It is
|
||||||
@ -188,11 +187,7 @@ static uint16_t compiler_get_local(GstCompiler *c, GstScope *scope) {
|
|||||||
if (scope->nextLocal + 1 == 0) {
|
if (scope->nextLocal + 1 == 0) {
|
||||||
c_error(c, "too many local variables");
|
c_error(c, "too many local variables");
|
||||||
}
|
}
|
||||||
++scope->nextLocal;
|
return scope->nextLocal++;
|
||||||
if (scope->nextLocal > scope->frameSize) {
|
|
||||||
scope->frameSize = scope->nextLocal;
|
|
||||||
}
|
|
||||||
return scope->nextLocal - 1;
|
|
||||||
} else {
|
} else {
|
||||||
return scope->freeHeap[--scope->heapSize];
|
return scope->freeHeap[--scope->heapSize];
|
||||||
}
|
}
|
||||||
@ -220,9 +215,6 @@ static void tracker_init(GstCompiler *c, SlotTracker *tracker) {
|
|||||||
tracker->slots = gst_alloc(c->vm, 10 * sizeof(Slot));
|
tracker->slots = gst_alloc(c->vm, 10 * sizeof(Slot));
|
||||||
tracker->count = 0;
|
tracker->count = 0;
|
||||||
tracker->capacity = 10;
|
tracker->capacity = 10;
|
||||||
/* Push to tracker stack */
|
|
||||||
tracker->next = (SlotTracker *) c->trackers;
|
|
||||||
c->trackers = tracker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free up a slot if it is a temporary slot (does not
|
/* Free up a slot if it is a temporary slot (does not
|
||||||
@ -319,8 +311,6 @@ static void compiler_tracker_free(GstCompiler *c, GstScope *scope, SlotTracker *
|
|||||||
for (i = tracker->count - 1; i < tracker->count; --i) {
|
for (i = tracker->count - 1; i < tracker->count; --i) {
|
||||||
compiler_drop_slot(c, scope, tracker->slots[i]);
|
compiler_drop_slot(c, scope, tracker->slots[i]);
|
||||||
}
|
}
|
||||||
/* Pop from tracker stack */
|
|
||||||
c->trackers = tracker->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new Slot to a slot tracker. */
|
/* Add a new Slot to a slot tracker. */
|
||||||
@ -1102,7 +1092,6 @@ void gst_compiler(GstCompiler *c, Gst *vm) {
|
|||||||
c->buffer = gst_buffer(vm, 128);
|
c->buffer = gst_buffer(vm, 128);
|
||||||
c->tail = NULL;
|
c->tail = NULL;
|
||||||
c->error.type = GST_NIL;
|
c->error.type = GST_NIL;
|
||||||
c->trackers = NULL;
|
|
||||||
compiler_push_scope(c, 0);
|
compiler_push_scope(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,6 +1117,19 @@ void gst_compiler_globals(GstCompiler *c, GstValue env) {
|
|||||||
gst_table_put(c->vm, scope->namedLiterals, data[i], data[i + 1]);
|
gst_table_put(c->vm, scope->namedLiterals, data[i], data[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add many global variables and bind to nil */
|
||||||
|
void gst_compiler_nilglobals(GstCompiler *c, GstValue env) {
|
||||||
|
GstScope *scope = c->tail;
|
||||||
|
const GstValue *data;
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t i;
|
||||||
|
if (gst_hashtable_view(env, &data, &len))
|
||||||
|
for (i = 0; i < len; i += 2)
|
||||||
|
if (data[i].type == GST_STRING)
|
||||||
|
gst_table_put(c->vm, scope->namedLiterals, data[i], gst_wrap_nil());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Use a module that was loaded into the vm */
|
/* Use a module that was loaded into the vm */
|
||||||
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
|
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
|
||||||
GstValue mod = gst_table_get(c->vm->modules, gst_string_cv(c->vm, modulename));
|
GstValue mod = gst_table_get(c->vm->modules, gst_string_cv(c->vm, modulename));
|
||||||
@ -1141,7 +1143,6 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
|||||||
GstFuncDef *def;
|
GstFuncDef *def;
|
||||||
if (setjmp(c->onError)) {
|
if (setjmp(c->onError)) {
|
||||||
/* Clear all but root scope */
|
/* Clear all but root scope */
|
||||||
c->trackers = NULL;
|
|
||||||
if (c->tail)
|
if (c->tail)
|
||||||
c->tail->parent = NULL;
|
c->tail->parent = NULL;
|
||||||
if (c->error.type == GST_NIL)
|
if (c->error.type == GST_NIL)
|
||||||
@ -1169,103 +1170,25 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
|||||||
/* Stl */
|
/* Stl */
|
||||||
/***/
|
/***/
|
||||||
|
|
||||||
/* GC mark all memory used by the compiler */
|
|
||||||
static void gst_compiler_mark(Gst *vm, void *data, uint32_t len) {
|
|
||||||
SlotTracker *st;
|
|
||||||
GstScope *scope;
|
|
||||||
GstCompiler *c = (GstCompiler *) data;
|
|
||||||
if (len != sizeof(GstCompiler))
|
|
||||||
return;
|
|
||||||
/* Mark compiler */
|
|
||||||
gst_mark_value(vm, gst_wrap_buffer(c->buffer));
|
|
||||||
gst_mark_value(vm, c->error);
|
|
||||||
/* Mark trackers - the trackers themselves are all on the stack. */
|
|
||||||
st = (SlotTracker *) c->trackers;
|
|
||||||
while (st) {
|
|
||||||
if (st->slots)
|
|
||||||
gst_mark_mem(vm, st->slots);
|
|
||||||
st = st->next;
|
|
||||||
}
|
|
||||||
/* Mark scopes */
|
|
||||||
scope = c->tail;
|
|
||||||
while (scope) {
|
|
||||||
gst_mark_mem(vm, scope);
|
|
||||||
if (scope->freeHeap)
|
|
||||||
gst_mark_mem(vm, scope->freeHeap);
|
|
||||||
gst_mark_value(vm, gst_wrap_array(scope->literalsArray));
|
|
||||||
gst_mark_value(vm, gst_wrap_table(scope->locals));
|
|
||||||
gst_mark_value(vm, gst_wrap_table(scope->literals));
|
|
||||||
gst_mark_value(vm, gst_wrap_table(scope->namedLiterals));
|
|
||||||
gst_mark_value(vm, gst_wrap_table(scope->nilNamedLiterals));
|
|
||||||
scope = scope->parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compiler userdata type */
|
|
||||||
static const GstUserType gst_stl_compilertype = {
|
|
||||||
"std.compiler",
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&gst_compiler_mark
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Create a compiler userdata */
|
|
||||||
static int gst_stl_compiler(Gst *vm) {
|
|
||||||
GstCompiler *c = gst_userdata(vm, sizeof(GstCompiler), &gst_stl_compilertype);
|
|
||||||
gst_compiler(c, vm);
|
|
||||||
gst_c_return(vm, gst_wrap_userdata(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a binding to the compiler's current scope. */
|
|
||||||
static int gst_stl_compiler_binding(Gst *vm) {
|
|
||||||
GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype);
|
|
||||||
GstScope *scope;
|
|
||||||
GstValue sym;
|
|
||||||
const uint8_t *data;
|
|
||||||
uint32_t len;
|
|
||||||
if (!c)
|
|
||||||
gst_c_throwc(vm, "expected compiler");
|
|
||||||
if (!gst_chararray_view(gst_arg(vm, 1), &data, &len))
|
|
||||||
gst_c_throwc(vm, "expected string/buffer");
|
|
||||||
scope = c->tail;
|
|
||||||
sym = gst_wrap_string(gst_string_b(c->vm, data, len));
|
|
||||||
gst_table_put(c->vm, scope->namedLiterals, sym, gst_arg(vm, 2));
|
|
||||||
gst_c_return(vm, gst_wrap_userdata(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compile a value */
|
/* Compile a value */
|
||||||
static int gst_stl_compiler_compile(Gst *vm) {
|
static int gst_stl_compile(Gst *vm) {
|
||||||
GstFunction *ret;
|
GstFunction *ret;
|
||||||
GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype);
|
GstValue std;
|
||||||
if (!c)
|
GstCompiler c;
|
||||||
gst_c_throwc(vm, "expected compiler");
|
gst_compiler(&c, vm);
|
||||||
ret = gst_compiler_compile(c, gst_arg(vm, 1));
|
std = gst_table_get(vm->modules, gst_string_cv(vm, "std"));
|
||||||
if (ret == NULL)
|
gst_compiler_globals(&c, std);
|
||||||
gst_c_throw(vm, c->error);
|
gst_compiler_globals(&c, gst_arg(vm, 1));
|
||||||
|
gst_compiler_nilglobals(&c, gst_arg(vm, 2));
|
||||||
|
ret = gst_compiler_compile(&c, gst_arg(vm, 0));
|
||||||
|
if (!ret)
|
||||||
|
gst_c_throw(vm, c.error);
|
||||||
gst_c_return(vm, gst_wrap_function(ret));
|
gst_c_return(vm, gst_wrap_function(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use an environment during compilation. Names that are declared more than
|
|
||||||
* once should use their final declared value. */
|
|
||||||
static int gst_stl_compiler_bindings(Gst *vm) {
|
|
||||||
GstValue env;
|
|
||||||
GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype);
|
|
||||||
if (!c)
|
|
||||||
gst_c_throwc(vm, "expected compiler");
|
|
||||||
env = gst_arg(vm, 1);
|
|
||||||
if (env.type != GST_TABLE && env.type != GST_STRUCT)
|
|
||||||
gst_c_throwc(vm, "expected table/struct");
|
|
||||||
gst_compiler_globals(c, env);
|
|
||||||
gst_c_return(vm, gst_wrap_userdata(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The module stuff */
|
/* The module stuff */
|
||||||
static const GstModuleItem gst_compile_module[] = {
|
static const GstModuleItem gst_compile_module[] = {
|
||||||
{"compiler", gst_stl_compiler},
|
{"compile", gst_stl_compile},
|
||||||
{"compile", gst_stl_compiler_compile},
|
|
||||||
{"binding!", gst_stl_compiler_binding},
|
|
||||||
{"bindings!", gst_stl_compiler_bindings},
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ struct GstCompiler {
|
|||||||
jmp_buf onError;
|
jmp_buf onError;
|
||||||
GstScope *tail;
|
GstScope *tail;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
void *trackers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the Compiler */
|
/* Initialize the Compiler */
|
||||||
|
Loading…
Reference in New Issue
Block a user