From 6e71984fc577eea840e095f82d7bb18d78827a8b Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Mon, 17 Apr 2017 18:46:28 -0400 Subject: [PATCH] Add wrapping functions for easy conversion between c api and internal values. --- Makefile | 4 +-- core/capi.c | 23 -------------- core/compile.c | 25 ++++++++++----- core/ds.c | 2 +- core/gc.c | 4 +-- core/serialize.c | 4 +-- core/stl.c | 61 ++++++++++--------------------------- core/util.c | 71 +++++++++++++++++++++++++++++++++++++++++++ include/gst/compile.h | 2 +- include/gst/gst.h | 26 +++++++++++++--- libs/stl.gst | 6 +--- 11 files changed, 135 insertions(+), 93 deletions(-) delete mode 100644 core/capi.c create mode 100644 core/util.c diff --git a/Makefile b/Makefile index f8d5bd40..2de36a55 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,8 @@ all: $(GST_TARGET) ##### The core vm and runtime ##### ################################### GST_CORE_SOURCES=$(addprefix core/,\ - compile.c disasm.c parse.c stl.c strings.c ids.c \ - value.c vm.c ds.c gc.c thread.c serialize.c capi.c) + compile.c disasm.c parse.c stl.c strings.c ids.c util.c\ + value.c vm.c ds.c gc.c thread.c serialize.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/core/capi.c b/core/capi.c deleted file mode 100644 index 2584b6ba..00000000 --- a/core/capi.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -GstObject *gst_c_module(Gst *vm, const GstModuleItem *mod) { - GstObject *module = gst_object(vm, 10); - while (mod->name != NULL) { - GstValue key = gst_string_cv(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_string_cv(vm, packagename), modv); -} diff --git a/core/compile.c b/core/compile.c index 86cb6508..1786b7e3 100644 --- a/core/compile.c +++ b/core/compile.c @@ -1027,12 +1027,23 @@ void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) { } /* Add many global variables */ -void gst_compiler_globals(GstCompiler *c, GstObject *env) { +void gst_compiler_globals(GstCompiler *c, GstValue env) { uint32_t i; - for (i = 0; i < env->capacity; i += 2) { - if (env->data[i].type == GST_STRING) { - compiler_declare_symbol(c, c->tail, env->data[i]); - gst_array_push(c->vm, c->env, env->data[i + 1]); + if (env.type == GST_OBJECT) { + GstObject *o = env.data.object; + for (i = 0; i < o->capacity; i += 2) { + if (o->data[i].type == GST_STRING) { + compiler_declare_symbol(c, c->tail, o->data[i]); + gst_array_push(c->vm, c->env, o->data[i + 1]); + } + } + } else if (env.type == GST_STRUCT) { + const GstValue *st = env.data.st; + for (i = 0; i < gst_struct_capacity(st); i += 2) { + if (st[i].type == GST_STRING) { + compiler_declare_symbol(c, c->tail, st[i]); + gst_array_push(c->vm, c->env, st[i + 1]); + } } } } @@ -1040,9 +1051,7 @@ void gst_compiler_globals(GstCompiler *c, GstObject *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)); - if (mod.type == GST_OBJECT) { - gst_compiler_globals(c, mod.data.object); - } + gst_compiler_globals(c, mod); } /* Compile interface. Returns a function that evaluates the diff --git a/core/ds.c b/core/ds.c index 5b45790b..097ff0a8 100644 --- a/core/ds.c +++ b/core/ds.c @@ -137,7 +137,7 @@ GstValue gst_array_peek(GstArray *array) { /****/ /* Create new userdata */ -void *gst_userdata(Gst *vm, uint32_t size, GstObject *meta) { +void *gst_userdata(Gst *vm, uint32_t size, const GstValue *meta) { char *data = gst_alloc(vm, sizeof(GstUserdataHeader) + size); GstUserdataHeader *header = (GstUserdataHeader *)data; void *user = data + sizeof(GstUserdataHeader); diff --git a/core/gc.c b/core/gc.c index 5bff8632..06b4ed34 100644 --- a/core/gc.c +++ b/core/gc.c @@ -161,8 +161,8 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) { GstUserdataHeader *userHeader = (GstUserdataHeader *)x.string - 1; gc_header(userHeader)->color = vm->black; GstValueUnion temp; - temp.object = userHeader->meta; - gst_mark(vm, temp, GST_OBJECT); + temp.st = userHeader->meta; + gst_mark(vm, temp, GST_STRUCT); } case GST_FUNCENV: diff --git a/core/serialize.c b/core/serialize.c index 9a522164..52f6f243 100644 --- a/core/serialize.c +++ b/core/serialize.c @@ -370,10 +370,10 @@ static const char *gst_deserialize_impl( ret.type = GST_USERDATA; err = gst_deserialize_impl(vm, data, end, &data, visited, &meta); if (err != NULL) return err; - deser_assert(meta.type == GST_OBJECT, "userdata requires valid meta"); + deser_assert(meta.type == GST_STRUCT, "userdata requires valid meta struct"); read_u32(length); deser_datacheck(length); - ret.data.pointer = gst_userdata(vm, length, meta.data.object); + ret.data.pointer = gst_userdata(vm, length, meta.data.st); gst_memcpy(ret.data.pointer, data, length); gst_array_push(vm, visited, ret); } diff --git a/core/stl.c b/core/stl.c index fc1dad5d..7c0e08f2 100644 --- a/core/stl.c +++ b/core/stl.c @@ -204,86 +204,64 @@ int gst_stl_type(Gst *vm) { int gst_stl_array(Gst *vm) { uint32_t i; uint32_t count = gst_count_args(vm); - GstValue ret; GstArray *array = gst_array(vm, count); - for (i = 0; i < count; ++i) { + for (i = 0; i < count; ++i) array->data[i] = gst_arg(vm, i); - } - ret.type = GST_ARRAY; - ret.data.array = array; - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_array(array)); } /* Create tuple */ int gst_stl_tuple(Gst *vm) { uint32_t i; uint32_t count = gst_count_args(vm); - GstValue ret; GstValue *tuple= gst_tuple_begin(vm, count); - for (i = 0; i < count; ++i) { + for (i = 0; i < count; ++i) tuple[i] = gst_arg(vm, i); - } - ret.type = GST_TUPLE; - ret.data.tuple = gst_tuple_end(vm, tuple); - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_tuple(gst_tuple_end(vm, tuple))); } /* Create object */ int gst_stl_object(Gst *vm) { uint32_t i; uint32_t count = gst_count_args(vm); - GstValue ret; GstObject *object; - if (count % 2 != 0) { + if (count % 2 != 0) gst_c_throwc(vm, "expected even number of arguments"); - } object = gst_object(vm, count * 2); - for (i = 0; i < count; i += 2) { + for (i = 0; i < count; i += 2) gst_object_put(vm, object, gst_arg(vm, i), gst_arg(vm, i + 1)); - } - ret.type = GST_OBJECT; - ret.data.object = object; - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_object(object)); } /* Create struct */ int gst_stl_struct(Gst *vm) { uint32_t i; uint32_t count = gst_count_args(vm); - GstValue ret; GstValue *st; - if (count % 2 != 0) { + if (count % 2 != 0) gst_c_throwc(vm, "expected even number of arguments"); - } st = gst_struct_begin(vm, count * 2); - for (i = 0; i < count; i += 2) { + for (i = 0; i < count; i += 2) gst_struct_put(st, gst_arg(vm, i), gst_arg(vm, i + 1)); - } - ret.type = GST_STRUCT; - ret.data.st = gst_struct_end(vm, st); - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_struct(gst_struct_end(vm, st))); } /* Create a buffer */ int gst_stl_buffer(Gst *vm) { uint32_t i, count; - GstValue buf; - buf.type = GST_BYTEBUFFER; - buf.data.buffer = gst_buffer(vm, 10); + GstBuffer *buf = gst_buffer(vm, 10); count = gst_count_args(vm); for (i = 0; i < count; ++i) { const uint8_t *string = gst_to_string(vm, gst_arg(vm, i)); - gst_buffer_append(vm, buf.data.buffer, string, gst_string_length(string)); + gst_buffer_append(vm, buf, string, gst_string_length(string)); } - gst_c_return(vm, buf); + gst_c_return(vm, gst_wrap_buffer(buf)); } /* Concatenate string */ int gst_stl_strcat(Gst *vm) { - GstValue ret; uint32_t j, count, length, index; uint8_t *str; - const uint8_t *cstr; count = gst_count_args(vm); length = 0; index = 0; @@ -302,10 +280,7 @@ int gst_stl_strcat(Gst *vm) { gst_memcpy(str + index, arg.data.string, slen); index += slen; } - cstr = gst_string_end(vm, str); - ret.type = GST_STRING; - ret.data.string = cstr; - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_string(gst_string_end(vm, str))); } /* Associative rawget */ @@ -372,11 +347,8 @@ int gst_stl_print(Gst *vm) { /* To string */ int gst_stl_tostring(Gst *vm) { - GstValue ret; const uint8_t *string = gst_to_string(vm, gst_arg(vm, 0)); - ret.type = GST_STRING; - ret.data.string = string; - gst_c_return(vm, ret); + gst_c_return(vm, gst_wrap_string(string)); } /* Exit */ @@ -454,6 +426,5 @@ static const GstModuleItem const std_module[] = { /* Load all libraries */ void gst_stl_load(Gst *vm) { - GstObject *module = gst_c_module(vm, std_module); - gst_c_register(vm, "std", module); + gst_c_register(vm, "std", gst_c_module_struct(vm, std_module)); } diff --git a/core/util.c b/core/util.c new file mode 100644 index 00000000..215377b5 --- /dev/null +++ b/core/util.c @@ -0,0 +1,71 @@ +#include + +/* Wrapper functions wrap a data type that is used from C into a + * gst value, which can then be used in gst. */ + +GstValue gst_wrap_nil() { + GstValue y; + y.type = GST_NIL; + return y; +} + +#define GST_WRAP_DEFINE(NAME, TYPE, GTYPE, UM)\ +GstValue gst_wrap_##NAME(TYPE x) {\ + GstValue y;\ + y.type = GTYPE;\ + y.data.UM = x;\ + return y;\ +} + +GST_WRAP_DEFINE(number, GstNumber, GST_NUMBER, number) +GST_WRAP_DEFINE(boolean, int, GST_BOOLEAN, boolean) +GST_WRAP_DEFINE(string, const uint8_t *, GST_STRING, string) +GST_WRAP_DEFINE(array, GstArray *, GST_ARRAY, array) +GST_WRAP_DEFINE(tuple, const GstValue *, GST_TUPLE, tuple) +GST_WRAP_DEFINE(struct, const GstValue *, GST_STRUCT, st) +GST_WRAP_DEFINE(thread, GstThread *, GST_THREAD, thread) +GST_WRAP_DEFINE(buffer, GstBuffer *, GST_BYTEBUFFER, buffer) +GST_WRAP_DEFINE(function, GstFunction *, GST_FUNCTION, function) +GST_WRAP_DEFINE(cfunction, GstCFunction, GST_CFUNCTION, cfunction) +GST_WRAP_DEFINE(object, GstObject *, GST_OBJECT, object) +GST_WRAP_DEFINE(userdata, void *, GST_USERDATA, pointer) +GST_WRAP_DEFINE(funcenv, GstFuncEnv *, GST_FUNCENV, env) +GST_WRAP_DEFINE(funcdef, GstFuncDef *, GST_FUNCDEF, def) + +#undef GST_WRAP_DEFINE + +GstValue gst_c_module_object(Gst *vm, const GstModuleItem *mod) { + GstObject *module = gst_object(vm, 10); + while (mod->name != NULL) { + GstValue key = gst_string_cv(vm, mod->name); + gst_object_put(vm, module, key, gst_wrap_cfunction(mod->data)); + mod++; + } + return gst_wrap_object(module); +} + +GstValue gst_c_module_struct(Gst *vm, const GstModuleItem *mod) { + uint32_t count = 0; + const GstModuleItem *m = mod; + GstValue *st; + while (m->name != NULL) { + ++count; + ++m; + } + st = gst_struct_begin(vm, count); + m = mod; + while (m->name != NULL) { + gst_struct_put(st, + gst_string_cv(vm, m->name), + gst_wrap_cfunction(m->data)); + ++m; + } + return gst_wrap_struct(gst_struct_end(vm, st)); + +} + +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); +} diff --git a/include/gst/compile.h b/include/gst/compile.h index 0893051c..6bc54037 100644 --- a/include/gst/compile.h +++ b/include/gst/compile.h @@ -21,7 +21,7 @@ struct GstCompiler { void gst_compiler(GstCompiler *c, Gst *vm); /* Add many globals */ -void gst_compiler_globals(GstCompiler *c, GstObject *env); +void gst_compiler_globals(GstCompiler *c, GstValue env); /* Register a global for the compilation environment. */ void gst_compiler_global(GstCompiler *c, const char *name, GstValue x); diff --git a/include/gst/gst.h b/include/gst/gst.h index 91ef0828..9274a7b1 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -241,7 +241,7 @@ struct GstFunction { /* Contains information about userdata */ struct GstUserdataHeader { uint32_t size; - GstObject *meta; + const GstValue *meta; }; /* VM return status from c function */ @@ -344,7 +344,7 @@ GstValue gst_array_pop(GstArray *array); /* Userdata functions */ /****/ -void *gst_userdata(Gst *vm, uint32_t size, GstObject *meta); +void *gst_userdata(Gst *vm, uint32_t size, const GstValue *meta); /****/ /* Tuple functions */ @@ -489,7 +489,25 @@ 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); +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); + +/* Wrap data in GstValue */ +GstValue gst_wrap_nil(); +GstValue gst_wrap_number(GstNumber x); +GstValue gst_wrap_boolean(int x); +GstValue gst_wrap_string(const uint8_t *x); +GstValue gst_wrap_array(GstArray *x); +GstValue gst_wrap_tuple(const GstValue *x); +GstValue gst_wrap_struct(const GstValue *x); +GstValue gst_wrap_thread(GstThread *x); +GstValue gst_wrap_buffer(GstBuffer *x); +GstValue gst_wrap_function(GstFunction *x); +GstValue gst_wrap_cfunction(GstCFunction x); +GstValue gst_wrap_object(GstObject *x); +GstValue gst_wrap_userdata(void *x); +GstValue gst_wrap_funcenv(GstFuncEnv *x); +GstValue gst_wrap_funcdef(GstFuncDef *x); #endif // GST_H_defined diff --git a/libs/stl.gst b/libs/stl.gst index 101ea886..26ddb05b 100644 --- a/libs/stl.gst +++ b/libs/stl.gst @@ -1,6 +1,2 @@ -(: f (fn [x] (strcat (tostring x) "-abumba"))) +(print 1) -(: i 100) -(while (> i 0) (print i) (: i (- i 1))) - -(print (strcat (tostring (+ 1 2 3)) 'a 'b (f 'c)))