mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 00:20:26 +00:00
More work on serilaization
This commit is contained in:
parent
6220b70105
commit
58edb63607
@ -481,19 +481,16 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
|
||||
/* We have a named literal */
|
||||
return compile_literal(c, opts, lit);
|
||||
} else if (level > 0) {
|
||||
/* We have an upvalue */
|
||||
if (level > 1) {
|
||||
/* We have an upvalue from a parent function. Make
|
||||
* sure that the chain of functions up to the upvalue keep
|
||||
* their parent references */
|
||||
uint32_t i = level;
|
||||
GstScope *scope = c->tail;
|
||||
for (i = level; i > 1; --i) {
|
||||
scope->touchParent = 1;
|
||||
scope = scope->parent;
|
||||
}
|
||||
scope->touchEnv = 1;
|
||||
/* We have an upvalue from a parent function. Make
|
||||
* sure that the chain of functions up to the upvalue keep
|
||||
* their parent references */
|
||||
uint32_t i = level;
|
||||
GstScope *scope = c->tail;
|
||||
for (i = level; i > 1; --i) {
|
||||
scope->touchParent = 1;
|
||||
scope = scope->parent;
|
||||
}
|
||||
scope->touchEnv = 1;
|
||||
ret = compiler_get_target(c, opts);
|
||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_UPV);
|
||||
gst_buffer_push_u16(c->vm, buffer, ret.index);
|
||||
|
@ -240,7 +240,8 @@ static const char *gst_deserialize_impl(
|
||||
uint16_t prevsize = 0;
|
||||
uint8_t statusbyte;
|
||||
t = gst_thread(vm, gst_wrap_nil(), 64);
|
||||
gst_array_push(vm, visited, gst_wrap_thread(t));
|
||||
ret = gst_wrap_thread(t);
|
||||
gst_array_push(vm, visited, ret);
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &ret);
|
||||
if (err != NULL) return err;
|
||||
if (ret.type == GST_NIL) {
|
||||
@ -250,30 +251,26 @@ static const char *gst_deserialize_impl(
|
||||
} else {
|
||||
return "expected thread parent to thread";
|
||||
}
|
||||
ret = gst_wrap_thread(t);
|
||||
deser_assert(data < end, UEB);
|
||||
statusbyte = *data++;
|
||||
read_u32(length);
|
||||
/* Check for empty thread - TODO check for valid state */
|
||||
if (length == 0)
|
||||
break;
|
||||
/* Set status */
|
||||
if (statusbyte == 0) t->status = GST_THREAD_PENDING;
|
||||
else if (statusbyte == 1) t->status = GST_THREAD_ALIVE;
|
||||
else t->status = GST_THREAD_DEAD;
|
||||
t->status = statusbyte % 4;
|
||||
/* Add frames */
|
||||
for (i = 0; i < length; ++i) {
|
||||
GstValue callee, env;
|
||||
uint32_t pcoffset;
|
||||
uint16_t ret, args, size, j;
|
||||
/* Create a new frame */
|
||||
if (i > 0)
|
||||
gst_thread_beginframe(vm, t, gst_wrap_nil(), 0);
|
||||
/* Read the stack */
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &callee);
|
||||
if (err != NULL) return err;
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &env);
|
||||
if (err != NULL) return err;
|
||||
if (env.type != GST_FUNCENV && env.type != GST_NIL)
|
||||
return "expected funcenv in stackframe";
|
||||
/* Create a new frame */
|
||||
if (i > 0)
|
||||
gst_thread_beginframe(vm, t, gst_wrap_nil(), 0);
|
||||
read_u32(pcoffset);
|
||||
read_u32(ret);
|
||||
read_u32(args);
|
||||
@ -282,15 +279,16 @@ static const char *gst_deserialize_impl(
|
||||
stack = gst_thread_stack(t);
|
||||
if (callee.type == GST_FUNCTION) {
|
||||
gst_frame_pc(stack) = callee.data.function->def->byteCode + pcoffset;
|
||||
if (env.type == GST_FUNCENV)
|
||||
gst_frame_env(stack) = env.data.env;
|
||||
else
|
||||
gst_frame_env(stack) = NULL;
|
||||
}
|
||||
gst_frame_ret(stack) = ret;
|
||||
gst_frame_args(stack) = args;
|
||||
gst_frame_size(stack) = size;
|
||||
gst_frame_prevsize(stack) = prevsize;
|
||||
gst_frame_callee(stack) = callee;
|
||||
if (env.type == GST_NIL)
|
||||
gst_frame_env(stack) = NULL;
|
||||
else
|
||||
gst_frame_env(stack) = env.data.env;
|
||||
prevsize = size;
|
||||
/* Push stack args */
|
||||
for (j = 0; j < size; ++j) {
|
||||
@ -333,6 +331,8 @@ static const char *gst_deserialize_impl(
|
||||
def->literalsLen = literalsLen;
|
||||
if (literalsLen > 0) {
|
||||
def->literals = gst_alloc(vm, literalsLen * sizeof(GstValue));
|
||||
} else {
|
||||
def->literals = NULL;
|
||||
}
|
||||
for (i = 0; i < literalsLen; ++i) {
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, def->literals + i);
|
||||
@ -385,6 +385,9 @@ static const char *gst_deserialize_impl(
|
||||
if (err != NULL) return err;
|
||||
err = gst_deserialize_impl(vm, data, end, &data, visited, &env);
|
||||
if (err != NULL) return err;
|
||||
printf("parent: %s\n", (const char *)gst_to_string(vm, parent));
|
||||
printf("def: %s\n", (const char *)gst_to_string(vm, def));
|
||||
printf("env: %s\n", (const char *)gst_to_string(vm, env));
|
||||
if (parent.type == GST_NIL) {
|
||||
ret.data.function->parent = NULL;
|
||||
} else if (parent.type == GST_FUNCTION) {
|
||||
@ -472,6 +475,7 @@ const char *gst_serialize_impl(
|
||||
#define write_u16(b) gst_buffer_push_u16(vm, buffer, (b))
|
||||
#define write_dbl(b) gst_buffer_push_real(vm, buffer, (b))
|
||||
#define write_int(b) gst_buffer_push_integer(vm, buffer, (b))
|
||||
/*printf("Type: %d\n", x.type);*/
|
||||
|
||||
/* Check non reference types - if successful, return NULL */
|
||||
switch (x.type) {
|
||||
@ -613,9 +617,7 @@ const char *gst_serialize_impl(
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil());
|
||||
if (err != NULL) return err;
|
||||
/* Write the status byte */
|
||||
if (t->status == GST_THREAD_PENDING) write_byte(0);
|
||||
else if (t->status == GST_THREAD_ALIVE) write_byte(1);
|
||||
else write_byte(2);
|
||||
write_byte(t->status);
|
||||
/* Write number of stack frames */
|
||||
write_u32(framecount);
|
||||
/* Write stack frames */
|
||||
@ -689,19 +691,17 @@ const char *gst_serialize_impl(
|
||||
|
||||
case GST_FUNCTION: /* Function */
|
||||
{
|
||||
GstValue pv, ev, dv;
|
||||
GstFunction *fn = x.data.function;
|
||||
write_byte(214);
|
||||
if (fn->parent)
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_function(fn->parent));
|
||||
else
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil());
|
||||
pv = fn->parent ? gst_wrap_function(fn->parent) : gst_wrap_nil();
|
||||
dv = gst_wrap_funcdef(fn->def);
|
||||
ev = fn->env ? gst_wrap_funcenv(fn->env) : gst_wrap_nil();
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, pv);
|
||||
if (err != NULL) return err;
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_funcdef(fn->def));
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, dv);
|
||||
if (err != NULL) return err;
|
||||
if (fn->env == NULL)
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil());
|
||||
else
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_funcenv(fn->env));
|
||||
err = gst_serialize_impl(vm, buffer, visited, nextId, ev);
|
||||
if (err != NULL) return err;
|
||||
}
|
||||
break;
|
||||
|
@ -648,7 +648,10 @@ int gst_stl_funcenv(Gst *vm) {
|
||||
GstFunction *fn;
|
||||
if (!gst_check_function(vm, 0, &fn))
|
||||
gst_c_throwc(vm, "expected function");
|
||||
gst_c_return(vm, gst_wrap_funcenv(fn->env));
|
||||
if (fn->env)
|
||||
gst_c_return(vm, gst_wrap_funcenv(fn->env));
|
||||
else
|
||||
return GST_RETURN_OK;
|
||||
}
|
||||
|
||||
int gst_stl_funcdef(Gst *vm) {
|
||||
|
27
core/vm.c
27
core/vm.c
@ -161,16 +161,6 @@ int gst_continue(Gst *vm) {
|
||||
{
|
||||
GstFunction *fn;
|
||||
v1 = gst_frame_callee(stack);
|
||||
if (v1.type != GST_FUNCTION)
|
||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||
if (gst_frame_env(stack) == NULL) {
|
||||
gst_frame_env(stack) = gst_alloc(vm, sizeof(GstFuncEnv));
|
||||
gst_frame_env(stack)->thread = vm->thread;
|
||||
gst_frame_env(stack)->stackOffset = vm->thread->count;
|
||||
gst_frame_env(stack)->values = NULL;
|
||||
}
|
||||
if (pc[2] > v1.data.function->def->literalsLen)
|
||||
gst_error(vm, GST_NO_UPVALUE);
|
||||
temp = v1.data.function->def->literals[pc[2]];
|
||||
if (temp.type != GST_FUNCDEF)
|
||||
gst_error(vm, "cannot create closure from non-funcdef");
|
||||
@ -180,7 +170,20 @@ int gst_continue(Gst *vm) {
|
||||
fn->parent = v1.data.function;
|
||||
else
|
||||
fn->parent = NULL;
|
||||
fn->env = gst_frame_env(stack);
|
||||
if (v1.type != GST_FUNCTION)
|
||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||
if (gst_frame_env(stack) == NULL && (fn->def->flags & GST_FUNCDEF_FLAG_NEEDSENV)) {
|
||||
gst_frame_env(stack) = gst_alloc(vm, sizeof(GstFuncEnv));
|
||||
gst_frame_env(stack)->thread = vm->thread;
|
||||
gst_frame_env(stack)->stackOffset = vm->thread->count;
|
||||
gst_frame_env(stack)->values = NULL;
|
||||
}
|
||||
if (pc[2] > v1.data.function->def->literalsLen)
|
||||
gst_error(vm, GST_NO_UPVALUE);
|
||||
if (fn->def->flags & GST_FUNCDEF_FLAG_NEEDSENV)
|
||||
fn->env = gst_frame_env(stack);
|
||||
else
|
||||
fn->env = NULL;
|
||||
temp.type = GST_FUNCTION;
|
||||
temp.data.function = fn;
|
||||
stack[pc[1]] = temp;
|
||||
@ -365,6 +368,8 @@ int gst_continue(Gst *vm) {
|
||||
temp.data.thread->status = GST_THREAD_ALIVE;
|
||||
vm->thread = temp.data.thread;
|
||||
stack = gst_thread_stack(temp.data.thread);
|
||||
if (gst_frame_callee(stack).type != GST_FUNCTION)
|
||||
goto vm_return;
|
||||
stack[gst_frame_ret(stack)] = v1;
|
||||
pc = gst_frame_pc(stack);
|
||||
continue;
|
||||
|
18
libs/serialize.gst
Normal file
18
libs/serialize.gst
Normal file
@ -0,0 +1,18 @@
|
||||
(export! "scheck" (fn [x]
|
||||
(: dat (serialize x))
|
||||
(: deser (deserialize dat))
|
||||
(print (debugp deser))
|
||||
deser
|
||||
))
|
||||
|
||||
(scheck 1)
|
||||
(scheck true)
|
||||
(scheck nil)
|
||||
(scheck "asdasdasd")
|
||||
(scheck (struct 1 2 3 4))
|
||||
(scheck (tuple 1 2 3))
|
||||
(scheck 123412.12)
|
||||
(scheck (funcdef (fn [] 1)))
|
||||
(scheck (funcenv (fn [] 1)))
|
||||
(scheck (funcenv ((fn [a] (fn [] a)) 1)))
|
||||
(scheck (fn [] 1))
|
Loading…
Reference in New Issue
Block a user