From e28e31f818a38873812228c97986b6e1cd73aefd Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 12 Apr 2017 21:21:46 -0400 Subject: [PATCH] Begin implementing module system. --- Makefile | 2 +- client/main.c | 12 +++------ core/capi.c | 23 +++++++++++++++++ core/compile.c | 58 +++++++++++++++++++++---------------------- core/gc.c | 4 ++- core/stl.c | 15 +++-------- core/vm.c | 5 ++-- include/gst/compile.h | 10 ++++---- include/gst/gst.h | 20 +++++++++++++-- include/gst/stl.h | 3 +-- 10 files changed, 90 insertions(+), 62 deletions(-) create mode 100644 core/capi.c diff --git a/Makefile b/Makefile index 9be68274..754dbfa9 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ all: $(GST_TARGET) ################################### GST_CORE_SOURCES=$(addprefix core/,\ compile.c disasm.c parse.c stl.c strings.c \ - value.c vm.c ds.c gc.c thread.c serialize.c) + value.c vm.c ds.c gc.c thread.c serialize.c capi.c) GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES)) $(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS) ar rcs $(GST_CORELIB) $(GST_CORE_OBJECTS) diff --git a/client/main.c b/client/main.c index 220992ea..64c342ce 100644 --- a/client/main.c +++ b/client/main.c @@ -16,10 +16,7 @@ void debug_repl(FILE *in, FILE *out) { GstCompiler c; gst_init(&vm); - - vm.rootenv.type = GST_OBJECT; - vm.rootenv.data.object = gst_object(&vm, 10); - gst_object_put(&vm, vm.rootenv.data.object, gst_load_csymbol(&vm, "_ENV"), vm.rootenv); + gst_stl_load(&vm); for (;;) { @@ -61,9 +58,8 @@ void debug_repl(FILE *in, FILE *out) { /* Try to compile generated AST */ gst_compiler(&c, &vm); func.type = GST_NIL; - gst_compiler_add_global(&c, "ans", func); - gst_stl_load(&c); - gst_compiler_env(&c, vm.rootenv); + gst_compiler_usemodule(&c, "std"); + gst_compiler_global(&c, "ans", gst_object_get(vm.rootenv, gst_load_csymbol(&vm, "ans"))); func.type = GST_FUNCTION; func.data.function = gst_compiler_compile(&c, p.value); @@ -98,7 +94,7 @@ void debug_repl(FILE *in, FILE *out) { continue; } else if (out) { fprintf(out, "%s\n", (char *)gst_to_string(&vm, vm.ret)); - gst_object_put(&vm, vm.rootenv.data.object, gst_load_csymbol(&vm, "ans"), vm.ret); + gst_object_put(&vm, vm.rootenv, gst_load_csymbol(&vm, "ans"), vm.ret); } } diff --git a/core/capi.c b/core/capi.c new file mode 100644 index 00000000..7b873897 --- /dev/null +++ b/core/capi.c @@ -0,0 +1,23 @@ +#include + +GstObject *gst_c_module(Gst *vm, const GstModuleItem *mod) { + GstObject *module = gst_object(vm, 10); + while (mod->name != NULL) { + GstValue key = gst_load_csymbol(vm, mod->name); + GstValue val; + val.type = GST_CFUNCTION; + val.data.cfunction = mod->data; + gst_object_put(vm, module, key, val); + mod++; + } + return module; +} + +void gst_c_register(Gst *vm, const char *packagename, GstObject *mod) { + GstValue modv; + if (vm->rootenv == NULL) + vm->rootenv = gst_object(vm, 10); + modv.type = GST_OBJECT; + modv.data.object = mod; + gst_object_put(vm, vm->rootenv, gst_load_csymbol(vm, packagename), modv); +} diff --git a/core/compile.c b/core/compile.c index c421c764..c0592181 100644 --- a/core/compile.c +++ b/core/compile.c @@ -327,7 +327,8 @@ static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValu /* Try to resolve a symbol. If the symbol can be resovled, return true and * pass back the level and index by reference. */ -static int symbol_resolve(GstScope *scope, GstValue x, uint16_t *level, uint16_t *index) { +static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index) { + GstScope *scope = c->tail; uint32_t currentLevel = scope->level; while (scope) { GstValue check = gst_object_get(scope->locals, x); @@ -336,6 +337,7 @@ static int symbol_resolve(GstScope *scope, GstValue x, uint16_t *level, uint16_t *index = (uint16_t) check.data.number; return 1; } + scope = scope->parent; } return 0; @@ -409,13 +411,13 @@ static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) { /* Compile a symbol. Resolves any kind of symbol. */ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { GstBuffer * buffer = c->buffer; - GstScope * scope = c->tail; uint16_t index = 0; uint16_t level = 0; Slot ret; if (opts.resultUnused) return nil_slot(); - if (!symbol_resolve(scope, sym, &level, &index)) + if (!symbol_resolve(c, sym, &level, &index)) { c_error(c, "undefined symbol"); + } if (level > 0) { /* We have an upvalue */ ret = compiler_get_target(c, opts); @@ -452,7 +454,7 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV Slot slot; subOpts.isTail = 0; subOpts.resultUnused = 0; - if (symbol_resolve(scope, left, &level, &target)) { + if (symbol_resolve(c, left, &level, &target)) { /* Check if we have an up value. Otherwise, it's just a normal * local variable */ if (level != 0) { @@ -1022,39 +1024,35 @@ void gst_compiler(GstCompiler *c, Gst *vm) { compiler_push_scope(c, 0); } -/* Add environment */ -void gst_compiler_env(GstCompiler *c, GstValue env) { +/* Add a global variable */ +void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) { + GstValue sym = gst_load_csymbol(c->vm, name); + compiler_declare_symbol(c, c->tail, sym); + gst_array_push(c->vm, c->env, x); +} + +/* Add many global variables */ +void gst_compiler_globals(GstCompiler *c, GstObject *env) { uint32_t i; GstBucket *bucket; - /* Register everything in environment */ - if (env.type == GST_OBJECT) { - for (i = 0; i < env.data.object->capacity; ++i) { - bucket = env.data.object->buckets[i]; - while (bucket) { - if (bucket->key.type == GST_SYMBOL) { - compiler_declare_symbol(c, c->tail, bucket->key); - gst_array_push(c->vm, c->env, bucket->value); - } - bucket = bucket->next; + for (i = 0; i < env->capacity; ++i) { + bucket = env->buckets[i]; + while (bucket) { + if (bucket->key.type == GST_SYMBOL) { + compiler_declare_symbol(c, c->tail, bucket->key); + gst_array_push(c->vm, c->env, bucket->value); } + bucket = bucket->next; } } } -/* Register a global for the compilation environment. */ -void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x) { - GstValue sym = gst_load_cstring(c->vm, name); - sym.type = GST_SYMBOL; - compiler_declare_symbol(c, c->tail, sym); - gst_array_push(c->vm, c->env, x); -} - -/* Register a global c function for the compilation environment. */ -void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f) { - GstValue func; - func.type = GST_CFUNCTION; - func.data.cfunction = f; - gst_compiler_add_global(c, name, func); +/* 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_load_csymbol(c->vm, modulename)); + if (mod.type == GST_OBJECT) { + gst_compiler_globals(c, mod.data.object); + } } /* Compile interface. Returns a function that evaluates the diff --git a/core/gc.c b/core/gc.c index b308c867..61a70d8a 100644 --- a/core/gc.c +++ b/core/gc.c @@ -235,13 +235,15 @@ 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); } - gst_mark_value(vm, vm->rootenv); + renv.object = vm->rootenv; + gst_mark(vm, renv, GST_OBJECT); gst_mark_value(vm, vm->ret); gst_sweep(vm); vm->nextCollection = 0; diff --git a/core/stl.c b/core/stl.c index 43768a88..669422e2 100644 --- a/core/stl.c +++ b/core/stl.c @@ -396,12 +396,7 @@ int gst_stl_serialize(Gst *vm) { /* Bootstraping */ /****/ -struct GstRegistryItem { - const char *name; - GstCFunction func; -}; - -static const struct GstRegistryItem const registry[] = { +static const GstModuleItem const std_module[] = { {"+", gst_stl_add}, {"*", gst_stl_mul}, {"-", gst_stl_sub}, @@ -430,9 +425,7 @@ static const struct GstRegistryItem const registry[] = { }; /* Load all libraries */ -void gst_stl_load(GstCompiler *c) { - const struct GstRegistryItem *item; - for (item = registry; item->name; ++item) { - gst_compiler_add_global_cfunction(c, item->name, item->func); - } +void gst_stl_load(Gst *vm) { + GstObject *module = gst_c_module(vm, std_module); + gst_c_register(vm, "std", module); } diff --git a/core/vm.c b/core/vm.c index 433abb61..552185cb 100644 --- a/core/vm.c +++ b/core/vm.c @@ -504,16 +504,17 @@ void gst_init(Gst *vm) { vm->black = 0; /* Add thread */ vm->thread = NULL; - vm->rootenv.type = GST_NIL; /* Set up string cache */ gst_stringcache_init(vm, 128); + /* Set up global env */ + vm->rootenv = NULL; } /* Clear all memory associated with the VM */ void gst_deinit(Gst *vm) { gst_clear_memory(vm); vm->thread = NULL; - vm->rootenv.type = GST_NIL; + vm->rootenv = NULL; vm->ret.type = GST_NIL; gst_stringcache_deinit(vm); } diff --git a/include/gst/compile.h b/include/gst/compile.h index 7ff6a599..0893051c 100644 --- a/include/gst/compile.h +++ b/include/gst/compile.h @@ -20,14 +20,14 @@ struct GstCompiler { /* Initialize the Compiler */ void gst_compiler(GstCompiler *c, Gst *vm); -/* Register an environment for compilation */ -void gst_compiler_env(GstCompiler *c, GstValue env); +/* Add many globals */ +void gst_compiler_globals(GstCompiler *c, GstObject *env); /* Register a global for the compilation environment. */ -void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x); +void gst_compiler_global(GstCompiler *c, const char *name, GstValue x); -/* Register a global c function for the compilation environment. */ -void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f); +/* Use a module */ +void gst_compiler_usemodule(GstCompiler *c, const char *modulename); /* Compile a function that evaluates the given form. */ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form); diff --git a/include/gst/gst.h b/include/gst/gst.h index df318872..b3b3e617 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -131,6 +131,15 @@ typedef union GstValueUnion GstValueUnion; /* Definitely implementation details */ typedef struct GstBucket GstBucket; +/* API Types */ +typedef struct GstModuleItem GstModuleItem; + +/* C Api data types */ +struct GstModuleItem { + const char *name; + GstCFunction data; +}; + /* Union datatype */ union GstValueUnion { GstBoolean boolean; @@ -174,7 +183,7 @@ struct GstThread { } status; }; -/* A dynamic array type. Useful for implementing a stack. */ +/* A dynamic array type. */ struct GstArray { uint32_t count; uint32_t capacity; @@ -257,7 +266,7 @@ struct Gst { /* Thread */ GstThread *thread; /* A GC root */ - GstValue rootenv; + GstObject *rootenv; /* Return state */ const char *crash; GstValue ret; /* Returned value from gst_start. Also holds errors. */ @@ -462,4 +471,11 @@ GstValue gst_arg(Gst *vm, uint16_t index); void gst_set_arg(Gst *vm, uint16_t index, GstValue x); uint16_t gst_count_args(Gst *vm); +/***/ +/* C Api */ +/***/ + +GstObject *gst_c_module(Gst *vm, const GstModuleItem *mod); +void gst_c_register(Gst *vm, const char *packagename, GstObject *mod); + #endif // GST_H_defined diff --git a/include/gst/stl.h b/include/gst/stl.h index 1a02700c..13ae70b9 100644 --- a/include/gst/stl.h +++ b/include/gst/stl.h @@ -2,10 +2,9 @@ #define stl_h_INCLUDED #include -#include /* Load the standard library */ -void gst_stl_load(GstCompiler *c); +void gst_stl_load(Gst *vm); #endif // stl_h_INCLUDED