1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-21 12:43:15 +00:00

Add wrapping functions for easy conversion between c api and

internal values.
This commit is contained in:
Calvin Rose 2017-04-17 18:46:28 -04:00
parent f52e290206
commit 6e71984fc5
11 changed files with 135 additions and 93 deletions

View File

@ -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)

View File

@ -1,23 +0,0 @@
#include <gst/gst.h>
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);
}

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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);
}

View File

@ -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));
}

71
core/util.c Normal file
View File

@ -0,0 +1,71 @@
#include <gst/gst.h>
/* 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);
}

View File

@ -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);

View File

@ -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

View File

@ -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)))