diff --git a/client/main.c b/client/main.c index 9af9a177..05338763 100644 --- a/client/main.c +++ b/client/main.c @@ -29,12 +29,13 @@ #include /* Compile and run an ast */ -int debug_compile_and_run(Gst *vm, GstValue ast) { +int debug_compile_and_run(Gst *vm, GstValue ast, GstValue env) { GstCompiler c; GstValue func; /* Try to compile generated AST */ gst_compiler(&c, vm); gst_compiler_usemodule(&c, "std"); + gst_compiler_globals(&c, env); func = gst_wrap_function(gst_compiler_compile(&c, ast)); /* Check for compilation errors */ if (c.error) { @@ -92,7 +93,7 @@ int debug_run(Gst *vm, FILE *in) { printf("Unexpected end of source\n"); return 1; } - return debug_compile_and_run(vm, ast); + return debug_compile_and_run(vm, ast, gst_wrap_nil()); } /* A simple repl */ @@ -100,6 +101,7 @@ int debug_repl(Gst *vm) { char buffer[1024] = {0}; const char *reader = buffer; GstParser p; + GstValue *st; int reset; for (;;) { /* Init parser */ @@ -127,7 +129,10 @@ int debug_repl(Gst *vm) { printf("Unexpected end of source\n"); continue; } - if (0 == debug_compile_and_run(vm, gst_parse_consume(&p))) { + /* Add _ to environemt */ + st = gst_struct_begin(vm, 1); + gst_struct_put(st, gst_string_cv(vm, "_"), vm->ret); + if (0 == debug_compile_and_run(vm, gst_parse_consume(&p), gst_wrap_struct(gst_struct_end(vm, st)))) { printf("%s\n", gst_to_string(vm, vm->ret)); } } diff --git a/core/compile.c b/core/compile.c index 6d3abb19..7c6e71e0 100644 --- a/core/compile.c +++ b/core/compile.c @@ -1072,7 +1072,7 @@ void gst_compiler_globals(GstCompiler *c, GstValue env) { /* Use a module that was loaded into the vm */ void gst_compiler_usemodule(GstCompiler *c, const char *modulename) { - GstValue mod = gst_object_get(c->vm->rootenv, gst_string_cv(c->vm, modulename)); + GstValue mod = gst_object_get(c->vm->modules, gst_string_cv(c->vm, modulename)); gst_compiler_globals(c, mod); } diff --git a/core/gc.c b/core/gc.c index cc9dc844..dea231a9 100644 --- a/core/gc.c +++ b/core/gc.c @@ -264,19 +264,14 @@ void gst_mem_tag(void *mem, uint32_t tags) { /* Run garbage collection */ void gst_collect(Gst *vm) { - GstValueUnion renv; /* Thread can be null */ - if (vm->thread) { - GstValueUnion t; - t.thread = vm->thread; - gst_mark(vm, t, GST_THREAD); - } - renv.object = vm->rootenv; - gst_mark(vm, renv, GST_OBJECT); + if (vm->thread) + gst_mark_value(vm, gst_wrap_thread(vm->thread)); + gst_mark_value(vm, gst_wrap_object(vm->modules)); + gst_mark_value(vm, gst_wrap_object(vm->registry)); gst_mark_value(vm, vm->ret); - if (vm->scratch) { + if (vm->scratch) gc_header(vm->scratch)->color = vm->black; - } gst_sweep(vm); vm->nextCollection = 0; } diff --git a/core/stl.c b/core/stl.c index 50b68a70..d6df5300 100644 --- a/core/stl.c +++ b/core/stl.c @@ -414,18 +414,19 @@ int gst_stl_serialize(Gst *vm) { /* TODO - add userdata to allow for manipulation of FILE pointers. */ int gst_stl_open(Gst *vm) { - GstValue ret; const uint8_t *fname = gst_to_string(vm, gst_arg(vm, 0)); const uint8_t *fmode = gst_to_string(vm, gst_arg(vm, 1)); FILE *f; + FILE **fp; + GstValue *st; if (gst_count_args(vm) < 2) gst_c_throwc(vm, "expected filename and filemode"); f = fopen((const char *)fname, (const char *)fmode); if (!f) gst_c_throwc(vm, "could not open file"); - ret.type = GST_USERDATA; - ret.data.pointer = f; - gst_c_return(vm, ret); + st = gst_struct_begin(vm, 0); + fp = gst_userdata(vm, sizeof(FILE *), gst_struct_end(vm, st)); + gst_c_return(vm, gst_wrap_userdata(fp)); } /****/ @@ -464,5 +465,5 @@ static const GstModuleItem const std_module[] = { /* Load all libraries */ void gst_stl_load(Gst *vm) { - gst_c_register(vm, "std", gst_c_module_struct(vm, std_module)); + gst_module_put(vm, "std", gst_cmodule_struct(vm, std_module)); } diff --git a/core/util.c b/core/util.c index 844456bb..545e8462 100644 --- a/core/util.c +++ b/core/util.c @@ -56,7 +56,7 @@ GST_WRAP_DEFINE(funcdef, GstFuncDef *, GST_FUNCDEF, def) #undef GST_WRAP_DEFINE -GstValue gst_c_module_object(Gst *vm, const GstModuleItem *mod) { +GstValue gst_cmodule_object(Gst *vm, const GstModuleItem *mod) { GstObject *module = gst_object(vm, 10); while (mod->name != NULL) { GstValue key = gst_string_cv(vm, mod->name); @@ -66,7 +66,7 @@ GstValue gst_c_module_object(Gst *vm, const GstModuleItem *mod) { return gst_wrap_object(module); } -GstValue gst_c_module_struct(Gst *vm, const GstModuleItem *mod) { +GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) { uint32_t count = 0; const GstModuleItem *m = mod; GstValue *st; @@ -86,8 +86,26 @@ GstValue gst_c_module_struct(Gst *vm, const GstModuleItem *mod) { } -void gst_c_register(Gst *vm, const char *packagename, GstValue mod) { - if (vm->rootenv == NULL) - vm->rootenv = gst_object(vm, 10); - gst_object_put(vm, vm->rootenv, gst_string_cv(vm, packagename), mod); +void gst_module_put(Gst *vm, const char *packagename, GstValue mod) { + if (vm->modules == NULL) + vm->modules = gst_object(vm, 10); + gst_object_put(vm, vm->modules, gst_string_cv(vm, packagename), mod); +} + +GstValue gst_module_get(Gst *vm, const char *packagename) { + if (!vm->modules) + return gst_wrap_nil(); + return gst_object_get(vm->modules, gst_string_cv(vm, packagename)); +} + +void gst_register_put(Gst *vm, const char *name, GstValue c) { + if (vm->registry == NULL) + vm->registry = gst_object(vm, 10); + gst_object_put(vm, vm->registry, gst_string_cv(vm, name), c); +} + +GstValue gst_register_get(Gst *vm, const char *name) { + if (!vm->registry) + return gst_wrap_nil(); + return gst_object_get(vm->registry, gst_string_cv(vm, name)); } diff --git a/core/vm.c b/core/vm.c index 2749aee5..a14a2726 100644 --- a/core/vm.c +++ b/core/vm.c @@ -498,16 +498,17 @@ void gst_init(Gst *vm) { /* Garbage collection */ vm->blocks = NULL; vm->nextCollection = 0; - /* Setting memoryInterval to zero currently forces + /* Setting memoryInterval to zero forces * a collection pretty much every cycle, which is - * obviously horrible for performance. It helps ensure + * obviously horrible for performance, but helps ensure * there are no memory bugs during dev */ vm->memoryInterval = 2000; vm->black = 0; /* Add thread */ vm->thread = NULL; /* Set up global env */ - vm->rootenv = NULL; + vm->modules = NULL; + vm->registry = NULL; /* Set up scratch memory */ vm->scratch = NULL; vm->scratch_len = 0; @@ -522,7 +523,8 @@ void gst_init(Gst *vm) { void gst_deinit(Gst *vm) { gst_clear_memory(vm); vm->thread = NULL; - vm->rootenv = NULL; + vm->modules = NULL; + vm->registry = NULL; vm->ret.type = GST_NIL; vm->scratch = NULL; vm->scratch_len = 0; diff --git a/include/gst/gst.h b/include/gst/gst.h index c2df7acb..439ae53a 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -283,13 +283,13 @@ struct Gst { uint32_t cache_capacity; uint32_t cache_count; uint32_t cache_deleted; - /* Scratch memory */ + /* Scratch memory (should be marked in gc) */ char *scratch; uint32_t scratch_len; - /* Thread */ + /* GC roots */ GstThread *thread; - /* A GC root */ - GstObject *rootenv; + GstObject *modules; + GstObject *registry; /* Return state */ const char *crash; GstValue ret; /* Returned value from gst_start. Also holds errors. */ @@ -511,9 +511,12 @@ uint16_t gst_count_args(Gst *vm); /* C Api */ /***/ -GstValue gst_c_module_object(Gst *vm, const GstModuleItem *mod); -GstValue gst_c_module_struct(Gst *vm, const GstModuleItem *mod); -void gst_c_register(Gst *vm, const char *packagename, GstValue mod); +GstValue gst_cmodule_object(Gst *vm, const GstModuleItem *mod); +GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod); +void gst_module_put(Gst *vm, const char *packagename, GstValue mod); +GstValue gst_module_get(Gst *vm, const char *packagename); +void gst_register_put(Gst *vm, const char *packagename, GstValue mod); +GstValue gst_register_get(Gst *vm, const char *name); /* Wrap data in GstValue */ GstValue gst_wrap_nil();