mirror of
https://github.com/janet-lang/janet
synced 2025-02-02 10:19:10 +00:00
Add wrapping functions for easy conversion between c api and
internal values.
This commit is contained in:
parent
f52e290206
commit
6e71984fc5
4
Makefile
4
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)
|
||||
|
23
core/capi.c
23
core/capi.c
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
61
core/stl.c
61
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));
|
||||
}
|
||||
|
71
core/util.c
Normal file
71
core/util.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
Loading…
Reference in New Issue
Block a user