mirror of
https://github.com/janet-lang/janet
synced 2024-12-01 12:29:54 +00:00
Merge remote-tracking branch 'upstream/master' into typed-array
This commit is contained in:
commit
4d3c655058
@ -2,6 +2,7 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## 0.4.0 - ??
|
## 0.4.0 - ??
|
||||||
|
- Remove `callable?`.
|
||||||
- Remove `tuple/append` and `tuple/prepend`, which may have seened like `O(1)`
|
- Remove `tuple/append` and `tuple/prepend`, which may have seened like `O(1)`
|
||||||
operations. Instead, use the `splice` special to extend tuples.
|
operations. Instead, use the `splice` special to extend tuples.
|
||||||
- Add `-m` flag to main client to allow specifying where to load
|
- Add `-m` flag to main client to allow specifying where to load
|
||||||
|
@ -165,6 +165,7 @@ static Janet cfun_array_slice(int32_t argc, Janet *argv) {
|
|||||||
JanetRange range = janet_getslice(argc, argv);
|
JanetRange range = janet_getslice(argc, argv);
|
||||||
JanetView view = janet_getindexed(argv, 0);
|
JanetView view = janet_getindexed(argv, 0);
|
||||||
JanetArray *array = janet_array(range.end - range.start);
|
JanetArray *array = janet_array(range.end - range.start);
|
||||||
|
if (array->data)
|
||||||
memcpy(array->data, view.items + range.start, sizeof(Janet) * (range.end - range.start));
|
memcpy(array->data, view.items + range.start, sizeof(Janet) * (range.end - range.start));
|
||||||
array->count = range.end - range.start;
|
array->count = range.end - range.start;
|
||||||
return janet_wrap_array(array);
|
return janet_wrap_array(array);
|
||||||
|
@ -642,7 +642,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
|
|||||||
}
|
}
|
||||||
/* Allocate bytecode array */
|
/* Allocate bytecode array */
|
||||||
def->bytecode_length = blength;
|
def->bytecode_length = blength;
|
||||||
def->bytecode = malloc(sizeof(int32_t) * blength);
|
def->bytecode = malloc(sizeof(uint32_t) * blength);
|
||||||
if (NULL == def->bytecode) {
|
if (NULL == def->bytecode) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,7 @@ static Janet cfun_buffer_new_filled(int32_t argc, Janet *argv) {
|
|||||||
byte = janet_getinteger(argv, 1) & 0xFF;
|
byte = janet_getinteger(argv, 1) & 0xFF;
|
||||||
}
|
}
|
||||||
JanetBuffer *buffer = janet_buffer(count);
|
JanetBuffer *buffer = janet_buffer(count);
|
||||||
|
if (buffer->data)
|
||||||
memset(buffer->data, byte, count);
|
memset(buffer->data, byte, count);
|
||||||
buffer->count = count;
|
buffer->count = count;
|
||||||
return janet_wrap_buffer(buffer);
|
return janet_wrap_buffer(buffer);
|
||||||
@ -236,6 +237,7 @@ static Janet cfun_buffer_slice(int32_t argc, Janet *argv) {
|
|||||||
JanetRange range = janet_getslice(argc, argv);
|
JanetRange range = janet_getslice(argc, argv);
|
||||||
JanetByteView view = janet_getbytes(argv, 0);
|
JanetByteView view = janet_getbytes(argv, 0);
|
||||||
JanetBuffer *buffer = janet_buffer(range.end - range.start);
|
JanetBuffer *buffer = janet_buffer(range.end - range.start);
|
||||||
|
if (buffer->data)
|
||||||
memcpy(buffer->data, view.bytes + range.start, range.end - range.start);
|
memcpy(buffer->data, view.bytes + range.start, range.end - range.start);
|
||||||
buffer->count = range.end - range.start;
|
buffer->count = range.end - range.start;
|
||||||
return janet_wrap_buffer(buffer);
|
return janet_wrap_buffer(buffer);
|
||||||
|
@ -478,6 +478,9 @@ static int macroexpand1(
|
|||||||
c->current_mapping.start = janet_tuple_sm_start(form);
|
c->current_mapping.start = janet_tuple_sm_start(form);
|
||||||
c->current_mapping.end = janet_tuple_sm_end(form);
|
c->current_mapping.end = janet_tuple_sm_end(form);
|
||||||
}
|
}
|
||||||
|
/* Bracketed tuples are not specials or macros! */
|
||||||
|
if (janet_tuple_flag(form) & JANET_TUPLE_FLAG_BRACKETCTOR)
|
||||||
|
return 0;
|
||||||
if (!janet_checktype(form[0], JANET_SYMBOL))
|
if (!janet_checktype(form[0], JANET_SYMBOL))
|
||||||
return 0;
|
return 0;
|
||||||
const uint8_t *name = janet_unwrap_symbol(form[0]);
|
const uint8_t *name = janet_unwrap_symbol(form[0]);
|
||||||
@ -493,7 +496,7 @@ static int macroexpand1(
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Evaluate macro */
|
/* Evaluate macro */
|
||||||
JanetFiber *fiberp;
|
JanetFiber *fiberp = NULL;
|
||||||
JanetFunction *macro = janet_unwrap_function(macroval);
|
JanetFunction *macro = janet_unwrap_function(macroval);
|
||||||
int lock = janet_gclock();
|
int lock = janet_gclock();
|
||||||
JanetSignal status = janet_pcall(
|
JanetSignal status = janet_pcall(
|
||||||
|
@ -798,18 +798,12 @@ JanetTable *janet_core_env(void) {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
/* Unmarshal from core image */
|
/* Unmarshal from core image */
|
||||||
Janet marsh_out;
|
Janet marsh_out = janet_unmarshal(
|
||||||
int status = janet_unmarshal(
|
|
||||||
janet_core_image,
|
janet_core_image,
|
||||||
janet_core_image_size,
|
janet_core_image_size,
|
||||||
0,
|
0,
|
||||||
&marsh_out,
|
|
||||||
env,
|
env,
|
||||||
NULL);
|
NULL);
|
||||||
if (status) {
|
|
||||||
printf("error unmarshaling core image\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
janet_gcroot(marsh_out);
|
janet_gcroot(marsh_out);
|
||||||
env = janet_unwrap_table(marsh_out);
|
env = janet_unwrap_table(marsh_out);
|
||||||
#endif
|
#endif
|
||||||
|
@ -192,7 +192,7 @@ static Janet cfun_debug_break(int32_t argc, Janet *argv) {
|
|||||||
|
|
||||||
static Janet cfun_debug_unbreak(int32_t argc, Janet *argv) {
|
static Janet cfun_debug_unbreak(int32_t argc, Janet *argv) {
|
||||||
JanetFuncDef *def;
|
JanetFuncDef *def;
|
||||||
int32_t offset;
|
int32_t offset = 0;
|
||||||
helper_find(argc, argv, &def, &offset);
|
helper_find(argc, argv, &def, &offset);
|
||||||
janet_debug_unbreak(def, offset);
|
janet_debug_unbreak(def, offset);
|
||||||
return janet_wrap_nil();
|
return janet_wrap_nil();
|
||||||
@ -200,7 +200,7 @@ static Janet cfun_debug_unbreak(int32_t argc, Janet *argv) {
|
|||||||
|
|
||||||
static Janet cfun_debug_fbreak(int32_t argc, Janet *argv) {
|
static Janet cfun_debug_fbreak(int32_t argc, Janet *argv) {
|
||||||
JanetFuncDef *def;
|
JanetFuncDef *def;
|
||||||
int32_t offset;
|
int32_t offset = 0;
|
||||||
helper_find_fun(argc, argv, &def, &offset);
|
helper_find_fun(argc, argv, &def, &offset);
|
||||||
janet_debug_break(def, offset);
|
janet_debug_break(def, offset);
|
||||||
return janet_wrap_nil();
|
return janet_wrap_nil();
|
||||||
|
@ -391,9 +391,8 @@ static int janet_gc_idequals(Janet lhs, Janet rhs) {
|
|||||||
* a value and all its children. */
|
* a value and all its children. */
|
||||||
int janet_gcunroot(Janet root) {
|
int janet_gcunroot(Janet root) {
|
||||||
Janet *vtop = janet_vm_roots + janet_vm_root_count;
|
Janet *vtop = janet_vm_roots + janet_vm_root_count;
|
||||||
Janet *v = janet_vm_roots;
|
|
||||||
/* Search from top to bottom as access is most likely LIFO */
|
/* Search from top to bottom as access is most likely LIFO */
|
||||||
for (v = janet_vm_roots; v < vtop; v++) {
|
for (Janet *v = janet_vm_roots; v < vtop; v++) {
|
||||||
if (janet_gc_idequals(root, *v)) {
|
if (janet_gc_idequals(root, *v)) {
|
||||||
*v = janet_vm_roots[--janet_vm_root_count];
|
*v = janet_vm_roots[--janet_vm_root_count];
|
||||||
return 1;
|
return 1;
|
||||||
@ -405,10 +404,9 @@ int janet_gcunroot(Janet root) {
|
|||||||
/* Remove a root value from the GC. This sets the effective reference count to 0. */
|
/* Remove a root value from the GC. This sets the effective reference count to 0. */
|
||||||
int janet_gcunrootall(Janet root) {
|
int janet_gcunrootall(Janet root) {
|
||||||
Janet *vtop = janet_vm_roots + janet_vm_root_count;
|
Janet *vtop = janet_vm_roots + janet_vm_root_count;
|
||||||
Janet *v = janet_vm_roots;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
/* Search from top to bottom as access is most likely LIFO */
|
/* Search from top to bottom as access is most likely LIFO */
|
||||||
for (v = janet_vm_roots; v < vtop; v++) {
|
for (Janet *v = janet_vm_roots; v < vtop; v++) {
|
||||||
if (janet_gc_idequals(root, *v)) {
|
if (janet_gc_idequals(root, *v)) {
|
||||||
*v = janet_vm_roots[--janet_vm_root_count];
|
*v = janet_vm_roots[--janet_vm_root_count];
|
||||||
vtop--;
|
vtop--;
|
||||||
|
@ -198,6 +198,9 @@ static Janet cfun_io_fread(int32_t argc, Janet *argv) {
|
|||||||
if (fsize < 0) {
|
if (fsize < 0) {
|
||||||
janet_panicf("could not get file size of %v", argv[0]);
|
janet_panicf("could not get file size of %v", argv[0]);
|
||||||
}
|
}
|
||||||
|
if (fsize > (INT32_MAX)) {
|
||||||
|
janet_panic("file to large to read into buffer");
|
||||||
|
}
|
||||||
fseek(iof->file, 0, SEEK_SET);
|
fseek(iof->file, 0, SEEK_SET);
|
||||||
read_chunk(iof, buffer, (int32_t) fsize);
|
read_chunk(iof, buffer, (int32_t) fsize);
|
||||||
}
|
}
|
||||||
|
254
src/core/marsh.c
254
src/core/marsh.c
@ -30,8 +30,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
jmp_buf err;
|
|
||||||
Janet current;
|
|
||||||
JanetBuffer *buf;
|
JanetBuffer *buf;
|
||||||
JanetTable seen;
|
JanetTable seen;
|
||||||
JanetTable *rreg;
|
JanetTable *rreg;
|
||||||
@ -40,26 +38,6 @@ typedef struct {
|
|||||||
int32_t nextid;
|
int32_t nextid;
|
||||||
} MarshalState;
|
} MarshalState;
|
||||||
|
|
||||||
enum {
|
|
||||||
MR_OK,
|
|
||||||
MR_STACKOVERFLOW,
|
|
||||||
MR_NYI,
|
|
||||||
MR_NRV,
|
|
||||||
MR_C_STACKFRAME,
|
|
||||||
MR_OVERFLOW,
|
|
||||||
MR_LIVEFIBER
|
|
||||||
} MarshalResult;
|
|
||||||
|
|
||||||
const char *mr_strings[] = {
|
|
||||||
"",
|
|
||||||
"stack overflow",
|
|
||||||
"type NYI",
|
|
||||||
"no registry value",
|
|
||||||
"fiber has c stack frame",
|
|
||||||
"buffer overflow",
|
|
||||||
"alive fiber"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Lead bytes in marshaling protocol */
|
/* Lead bytes in marshaling protocol */
|
||||||
enum {
|
enum {
|
||||||
LB_REAL = 200,
|
LB_REAL = 200,
|
||||||
@ -156,10 +134,12 @@ static void marshal_one_fiber(MarshalState *st, JanetFiber *fiber, int flags);
|
|||||||
static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags);
|
static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags);
|
||||||
static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags);
|
static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags);
|
||||||
|
|
||||||
|
/* Prevent stack overflows */
|
||||||
|
#define MARSH_STACKCHECK if ((flags & 0xFFFF) > JANET_RECURSION_GUARD) janet_panic("stack overflow")
|
||||||
|
|
||||||
/* Marshal a function env */
|
/* Marshal a function env */
|
||||||
static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags) {
|
static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags) {
|
||||||
if ((flags & 0xFFFF) > JANET_RECURSION_GUARD)
|
MARSH_STACKCHECK;
|
||||||
longjmp(st->err, MR_STACKOVERFLOW);
|
|
||||||
for (int32_t i = 0; i < janet_v_count(st->seen_envs); i++) {
|
for (int32_t i = 0; i < janet_v_count(st->seen_envs); i++) {
|
||||||
if (st->seen_envs[i] == env) {
|
if (st->seen_envs[i] == env) {
|
||||||
pushbyte(st, LB_FUNCENV_REF);
|
pushbyte(st, LB_FUNCENV_REF);
|
||||||
@ -191,8 +171,7 @@ static void janet_func_addflags(JanetFuncDef *def) {
|
|||||||
|
|
||||||
/* Marshal a function def */
|
/* Marshal a function def */
|
||||||
static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
|
static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
|
||||||
if ((flags & 0xFFFF) > JANET_RECURSION_GUARD)
|
MARSH_STACKCHECK;
|
||||||
longjmp(st->err, MR_STACKOVERFLOW);
|
|
||||||
for (int32_t i = 0; i < janet_v_count(st->seen_defs); i++) {
|
for (int32_t i = 0; i < janet_v_count(st->seen_defs); i++) {
|
||||||
if (st->seen_defs[i] == def) {
|
if (st->seen_defs[i] == def) {
|
||||||
pushbyte(st, LB_FUNCDEF_REF);
|
pushbyte(st, LB_FUNCDEF_REF);
|
||||||
@ -254,12 +233,11 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
|
|||||||
|
|
||||||
/* Marshal a fiber */
|
/* Marshal a fiber */
|
||||||
static void marshal_one_fiber(MarshalState *st, JanetFiber *fiber, int flags) {
|
static void marshal_one_fiber(MarshalState *st, JanetFiber *fiber, int flags) {
|
||||||
|
MARSH_STACKCHECK;
|
||||||
int32_t fflags = fiber->flags;
|
int32_t fflags = fiber->flags;
|
||||||
if ((flags & 0xFFFF) > JANET_RECURSION_GUARD)
|
|
||||||
longjmp(st->err, MR_STACKOVERFLOW);
|
|
||||||
if (fiber->child) fflags |= JANET_FIBER_FLAG_HASCHILD;
|
if (fiber->child) fflags |= JANET_FIBER_FLAG_HASCHILD;
|
||||||
if (janet_fiber_status(fiber) == JANET_STATUS_ALIVE)
|
if (janet_fiber_status(fiber) == JANET_STATUS_ALIVE)
|
||||||
longjmp(st->err, MR_LIVEFIBER);
|
janet_panic("cannot marshal alive fiber");
|
||||||
pushint(st, fflags);
|
pushint(st, fflags);
|
||||||
pushint(st, fiber->frame);
|
pushint(st, fiber->frame);
|
||||||
pushint(st, fiber->stackstart);
|
pushint(st, fiber->stackstart);
|
||||||
@ -271,7 +249,7 @@ static void marshal_one_fiber(MarshalState *st, JanetFiber *fiber, int flags) {
|
|||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
JanetStackFrame *frame = (JanetStackFrame *)(fiber->data + i - JANET_FRAME_SIZE);
|
JanetStackFrame *frame = (JanetStackFrame *)(fiber->data + i - JANET_FRAME_SIZE);
|
||||||
if (frame->env) frame->flags |= JANET_STACKFRAME_HASENV;
|
if (frame->env) frame->flags |= JANET_STACKFRAME_HASENV;
|
||||||
if (!frame->func) longjmp(st->err, MR_C_STACKFRAME);
|
if (!frame->func) janet_panic("cannot marshal fiber with c stackframe");
|
||||||
pushint(st, frame->flags);
|
pushint(st, frame->flags);
|
||||||
pushint(st, frame->prevframe);
|
pushint(st, frame->prevframe);
|
||||||
int32_t pcdiff = (int32_t)(frame->pc - frame->func->def->bytecode);
|
int32_t pcdiff = (int32_t)(frame->pc - frame->func->def->bytecode);
|
||||||
@ -332,11 +310,8 @@ static int marshal_one_abstract(MarshalState *st, Janet x, int flags) {
|
|||||||
/* The main body of the marshaling function. Is the main
|
/* The main body of the marshaling function. Is the main
|
||||||
* entry point for the mutually recursive functions. */
|
* entry point for the mutually recursive functions. */
|
||||||
static void marshal_one(MarshalState *st, Janet x, int flags) {
|
static void marshal_one(MarshalState *st, Janet x, int flags) {
|
||||||
Janet parent = st->current;
|
MARSH_STACKCHECK;
|
||||||
JanetType type = janet_type(x);
|
JanetType type = janet_type(x);
|
||||||
st->current = x;
|
|
||||||
if ((flags & 0xFFFF) > JANET_RECURSION_GUARD)
|
|
||||||
longjmp(st->err, MR_STACKOVERFLOW);
|
|
||||||
|
|
||||||
/* Check simple primitives (non reference types, no benefit from memoization) */
|
/* Check simple primitives (non reference types, no benefit from memoization) */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -346,12 +321,12 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
case JANET_FALSE:
|
case JANET_FALSE:
|
||||||
case JANET_TRUE:
|
case JANET_TRUE:
|
||||||
pushbyte(st, 200 + type);
|
pushbyte(st, 200 + type);
|
||||||
goto done;
|
return;
|
||||||
case JANET_NUMBER: {
|
case JANET_NUMBER: {
|
||||||
double xval = janet_unwrap_number(x);
|
double xval = janet_unwrap_number(x);
|
||||||
if (janet_checkintrange(xval)) {
|
if (janet_checkintrange(xval)) {
|
||||||
pushint(st, (int32_t) xval);
|
pushint(st, (int32_t) xval);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -364,7 +339,7 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
if (janet_checkint(check)) {
|
if (janet_checkint(check)) {
|
||||||
pushbyte(st, LB_REFERENCE);
|
pushbyte(st, LB_REFERENCE);
|
||||||
pushint(st, janet_unwrap_integer(check));
|
pushint(st, janet_unwrap_integer(check));
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
if (st->rreg) {
|
if (st->rreg) {
|
||||||
check = janet_table_get(st->rreg, x);
|
check = janet_table_get(st->rreg, x);
|
||||||
@ -374,7 +349,7 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
pushbyte(st, LB_REGISTRY);
|
pushbyte(st, LB_REGISTRY);
|
||||||
pushint(st, janet_string_length(regname));
|
pushint(st, janet_string_length(regname));
|
||||||
pushbytes(st, regname, janet_string_length(regname));
|
pushbytes(st, regname, janet_string_length(regname));
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,8 +381,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
pushbyte(st, LB_REAL);
|
pushbyte(st, LB_REAL);
|
||||||
pushbytes(st, u.bytes, 8);
|
pushbytes(st, u.bytes, 8);
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_STRING:
|
case JANET_STRING:
|
||||||
case JANET_SYMBOL:
|
case JANET_SYMBOL:
|
||||||
case JANET_KEYWORD: {
|
case JANET_KEYWORD: {
|
||||||
@ -421,8 +396,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
pushbyte(st, lb);
|
pushbyte(st, lb);
|
||||||
pushint(st, length);
|
pushint(st, length);
|
||||||
pushbytes(st, str, length);
|
pushbytes(st, str, length);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_BUFFER: {
|
case JANET_BUFFER: {
|
||||||
JanetBuffer *buffer = janet_unwrap_buffer(x);
|
JanetBuffer *buffer = janet_unwrap_buffer(x);
|
||||||
/* Record reference */
|
/* Record reference */
|
||||||
@ -430,8 +405,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
pushbyte(st, LB_BUFFER);
|
pushbyte(st, LB_BUFFER);
|
||||||
pushint(st, buffer->count);
|
pushint(st, buffer->count);
|
||||||
pushbytes(st, buffer->data, buffer->count);
|
pushbytes(st, buffer->data, buffer->count);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_ARRAY: {
|
case JANET_ARRAY: {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
JanetArray *a = janet_unwrap_array(x);
|
JanetArray *a = janet_unwrap_array(x);
|
||||||
@ -440,8 +415,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
pushint(st, a->count);
|
pushint(st, a->count);
|
||||||
for (i = 0; i < a->count; i++)
|
for (i = 0; i < a->count; i++)
|
||||||
marshal_one(st, a->data[i], flags + 1);
|
marshal_one(st, a->data[i], flags + 1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_TUPLE: {
|
case JANET_TUPLE: {
|
||||||
int32_t i, count, flag;
|
int32_t i, count, flag;
|
||||||
const Janet *tup = janet_unwrap_tuple(x);
|
const Janet *tup = janet_unwrap_tuple(x);
|
||||||
@ -454,8 +429,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
marshal_one(st, tup[i], flags + 1);
|
marshal_one(st, tup[i], flags + 1);
|
||||||
/* Mark as seen AFTER marshaling */
|
/* Mark as seen AFTER marshaling */
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_TABLE: {
|
case JANET_TABLE: {
|
||||||
JanetTable *t = janet_unwrap_table(x);
|
JanetTable *t = janet_unwrap_table(x);
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
@ -469,8 +444,8 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
marshal_one(st, t->data[i].key, flags + 1);
|
marshal_one(st, t->data[i].key, flags + 1);
|
||||||
marshal_one(st, t->data[i].value, flags + 1);
|
marshal_one(st, t->data[i].value, flags + 1);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_STRUCT: {
|
case JANET_STRUCT: {
|
||||||
int32_t count;
|
int32_t count;
|
||||||
const JanetKV *struct_ = janet_unwrap_struct(x);
|
const JanetKV *struct_ = janet_unwrap_struct(x);
|
||||||
@ -485,17 +460,13 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
}
|
}
|
||||||
/* Mark as seen AFTER marshaling */
|
/* Mark as seen AFTER marshaling */
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_ABSTRACT: {
|
case JANET_ABSTRACT: {
|
||||||
if (marshal_one_abstract(st, x, flags)) {
|
if (marshal_one_abstract(st, x, flags)) {
|
||||||
goto done;
|
return;
|
||||||
} else {
|
|
||||||
goto noregval;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case JANET_CFUNCTION:
|
|
||||||
goto noregval;
|
|
||||||
case JANET_FUNCTION: {
|
case JANET_FUNCTION: {
|
||||||
pushbyte(st, LB_FUNCTION);
|
pushbyte(st, LB_FUNCTION);
|
||||||
JanetFunction *func = janet_unwrap_function(x);
|
JanetFunction *func = janet_unwrap_function(x);
|
||||||
@ -504,56 +475,39 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
for (int32_t i = 0; i < func->def->environments_length; i++)
|
for (int32_t i = 0; i < func->def->environments_length; i++)
|
||||||
marshal_one_env(st, func->envs[i], flags + 1);
|
marshal_one_env(st, func->envs[i], flags + 1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
case JANET_FIBER: {
|
case JANET_FIBER: {
|
||||||
MARK_SEEN();
|
MARK_SEEN();
|
||||||
pushbyte(st, LB_FIBER);
|
pushbyte(st, LB_FIBER);
|
||||||
marshal_one_fiber(st, janet_unwrap_fiber(x), flags + 1);
|
marshal_one_fiber(st, janet_unwrap_fiber(x), flags + 1);
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
default:
|
|
||||||
goto nyi;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef MARK_SEEN
|
|
||||||
|
|
||||||
done:
|
|
||||||
st->current = parent;
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
/* Errors */
|
default: {
|
||||||
|
janet_panicf("no registry value and cannot marshal %p", x);
|
||||||
nyi:
|
return;
|
||||||
longjmp(st->err, MR_NYI);
|
}
|
||||||
|
}
|
||||||
noregval:
|
#undef MARK_SEEN
|
||||||
longjmp(st->err, MR_NRV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_marshal(
|
void janet_marshal(
|
||||||
JanetBuffer *buf,
|
JanetBuffer *buf,
|
||||||
Janet x,
|
Janet x,
|
||||||
Janet *errval,
|
|
||||||
JanetTable *rreg,
|
JanetTable *rreg,
|
||||||
int flags) {
|
int flags) {
|
||||||
int status;
|
|
||||||
MarshalState st;
|
MarshalState st;
|
||||||
st.buf = buf;
|
st.buf = buf;
|
||||||
st.nextid = 0;
|
st.nextid = 0;
|
||||||
st.seen_defs = NULL;
|
st.seen_defs = NULL;
|
||||||
st.seen_envs = NULL;
|
st.seen_envs = NULL;
|
||||||
st.rreg = rreg;
|
st.rreg = rreg;
|
||||||
st.current = x;
|
|
||||||
janet_table_init(&st.seen, 0);
|
janet_table_init(&st.seen, 0);
|
||||||
if (!(status = setjmp(st.err)))
|
|
||||||
marshal_one(&st, x, flags);
|
marshal_one(&st, x, flags);
|
||||||
if (status && errval)
|
/* Clean up. See comment in janet_unmarshal about autoreleasing memory on panics.*/
|
||||||
*errval = st.current;
|
|
||||||
janet_table_deinit(&st.seen);
|
janet_table_deinit(&st.seen);
|
||||||
janet_v_free(st.seen_envs);
|
janet_v_free(st.seen_envs);
|
||||||
janet_v_free(st.seen_defs);
|
janet_v_free(st.seen_defs);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -562,9 +516,11 @@ typedef struct {
|
|||||||
JanetTable *reg;
|
JanetTable *reg;
|
||||||
JanetFuncEnv **lookup_envs;
|
JanetFuncEnv **lookup_envs;
|
||||||
JanetFuncDef **lookup_defs;
|
JanetFuncDef **lookup_defs;
|
||||||
|
const uint8_t *start;
|
||||||
const uint8_t *end;
|
const uint8_t *end;
|
||||||
} UnmarshalState;
|
} UnmarshalState;
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
enum {
|
enum {
|
||||||
UMR_OK,
|
UMR_OK,
|
||||||
UMR_STACKOVERFLOW,
|
UMR_STACKOVERFLOW,
|
||||||
@ -594,33 +550,48 @@ const char *umr_strings[] = {
|
|||||||
"invalid fiber",
|
"invalid fiber",
|
||||||
"invalid abstract",
|
"invalid abstract",
|
||||||
};
|
};
|
||||||
|
=======
|
||||||
|
#define MARSH_EOS(st, data) do { \
|
||||||
|
if ((data) >= (st)->end) janet_panic("unexpected end of source");\
|
||||||
|
} while (0)
|
||||||
|
>>>>>>> upstream/master
|
||||||
|
|
||||||
/* Helper to read a 32 bit integer from an unmarshal state */
|
/* Helper to read a 32 bit integer from an unmarshal state */
|
||||||
static int32_t readint(UnmarshalState *st, const uint8_t **atdata) {
|
static int32_t readint(UnmarshalState *st, const uint8_t **atdata) {
|
||||||
const uint8_t *data = *atdata;
|
const uint8_t *data = *atdata;
|
||||||
int32_t ret;
|
int32_t ret;
|
||||||
if (data >= st->end) longjmp(st->err, UMR_EOS);
|
MARSH_EOS(st, data);
|
||||||
if (*data < 128) {
|
if (*data < 128) {
|
||||||
ret = *data++;
|
ret = *data++;
|
||||||
} else if (*data < 192) {
|
} else if (*data < 192) {
|
||||||
if (data + 2 > st->end) longjmp(st->err, UMR_EOS);
|
MARSH_EOS(st, data + 1);
|
||||||
ret = ((data[0] & 0x3F) << 8) + data[1];
|
ret = ((data[0] & 0x3F) << 8) + data[1];
|
||||||
ret = ((ret << 18) >> 18);
|
ret = ((ret << 18) >> 18);
|
||||||
data += 2;
|
data += 2;
|
||||||
} else if (*data == LB_INTEGER) {
|
} else if (*data == LB_INTEGER) {
|
||||||
if (data + 5 > st->end) longjmp(st->err, UMR_EOS);
|
MARSH_EOS(st, data + 4);
|
||||||
ret = ((int32_t)(data[1]) << 24) |
|
ret = ((int32_t)(data[1]) << 24) |
|
||||||
((int32_t)(data[2]) << 16) |
|
((int32_t)(data[2]) << 16) |
|
||||||
((int32_t)(data[3]) << 8) |
|
((int32_t)(data[3]) << 8) |
|
||||||
(int32_t)(data[4]);
|
(int32_t)(data[4]);
|
||||||
data += 5;
|
data += 5;
|
||||||
} else {
|
} else {
|
||||||
longjmp(st->err, UMR_EXPECTED_INTEGER);
|
janet_panicf("expected integer, got byte %x at index %d",
|
||||||
|
*data,
|
||||||
|
data - st->start);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
*atdata = data;
|
*atdata = data;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Assert a janet type */
|
||||||
|
static void janet_asserttype(Janet x, JanetType t) {
|
||||||
|
if (!janet_checktype(x, t)) {
|
||||||
|
janet_panicf("expected type %T, got %v", 1 << t, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Forward declarations for mutual recursion */
|
/* Forward declarations for mutual recursion */
|
||||||
static const uint8_t *unmarshal_one(
|
static const uint8_t *unmarshal_one(
|
||||||
UnmarshalState *st,
|
UnmarshalState *st,
|
||||||
@ -649,13 +620,12 @@ static const uint8_t *unmarshal_one_env(
|
|||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
JanetFuncEnv **out,
|
JanetFuncEnv **out,
|
||||||
int flags) {
|
int flags) {
|
||||||
const uint8_t *end = st->end;
|
MARSH_EOS(st, data);
|
||||||
if (data >= end) longjmp(st->err, UMR_EOS);
|
|
||||||
if (*data == LB_FUNCENV_REF) {
|
if (*data == LB_FUNCENV_REF) {
|
||||||
data++;
|
data++;
|
||||||
int32_t index = readint(st, &data);
|
int32_t index = readint(st, &data);
|
||||||
if (index < 0 || index >= janet_v_count(st->lookup_envs))
|
if (index < 0 || index >= janet_v_count(st->lookup_envs))
|
||||||
longjmp(st->err, UMR_INVALID_REFERENCE);
|
janet_panicf("invalid funcenv reference %d", index);
|
||||||
*out = st->lookup_envs[index];
|
*out = st->lookup_envs[index];
|
||||||
} else {
|
} else {
|
||||||
JanetFuncEnv *env = janet_gcalloc(JANET_MEMORY_FUNCENV, sizeof(JanetFuncEnv));
|
JanetFuncEnv *env = janet_gcalloc(JANET_MEMORY_FUNCENV, sizeof(JanetFuncEnv));
|
||||||
@ -668,11 +638,13 @@ static const uint8_t *unmarshal_one_env(
|
|||||||
Janet fiberv;
|
Janet fiberv;
|
||||||
/* On stack variant */
|
/* On stack variant */
|
||||||
data = unmarshal_one(st, data, &fiberv, flags);
|
data = unmarshal_one(st, data, &fiberv, flags);
|
||||||
if (!janet_checktype(fiberv, JANET_FIBER)) longjmp(st->err, UMR_EXPECTED_FIBER);
|
janet_asserttype(fiberv, JANET_FIBER);
|
||||||
env->as.fiber = janet_unwrap_fiber(fiberv);
|
env->as.fiber = janet_unwrap_fiber(fiberv);
|
||||||
/* Unmarshalling fiber may set values */
|
/* Unmarshalling fiber may set values */
|
||||||
if (env->offset != 0 && env->offset != offset) longjmp(st->err, UMR_UNKNOWN);
|
if (env->offset != 0 && env->offset != offset)
|
||||||
if (env->length != 0 && env->length != length) longjmp(st->err, UMR_UNKNOWN);
|
janet_panic("invalid funcenv offset");
|
||||||
|
if (env->length != 0 && env->length != length)
|
||||||
|
janet_panic("invalid funcenv length");
|
||||||
} else {
|
} else {
|
||||||
/* Off stack variant */
|
/* Off stack variant */
|
||||||
env->as.values = malloc(sizeof(Janet) * length);
|
env->as.values = malloc(sizeof(Janet) * length);
|
||||||
@ -695,13 +667,12 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
JanetFuncDef **out,
|
JanetFuncDef **out,
|
||||||
int flags) {
|
int flags) {
|
||||||
const uint8_t *end = st->end;
|
MARSH_EOS(st, data);
|
||||||
if (data >= end) longjmp(st->err, UMR_EOS);
|
|
||||||
if (*data == LB_FUNCDEF_REF) {
|
if (*data == LB_FUNCDEF_REF) {
|
||||||
data++;
|
data++;
|
||||||
int32_t index = readint(st, &data);
|
int32_t index = readint(st, &data);
|
||||||
if (index < 0 || index >= janet_v_count(st->lookup_defs))
|
if (index < 0 || index >= janet_v_count(st->lookup_defs))
|
||||||
longjmp(st->err, UMR_INVALID_REFERENCE);
|
janet_panicf("invalid funcdef reference %d", index);
|
||||||
*out = st->lookup_defs[index];
|
*out = st->lookup_defs[index];
|
||||||
} else {
|
} else {
|
||||||
/* Initialize with values that will not break garbage collection
|
/* Initialize with values that will not break garbage collection
|
||||||
@ -738,13 +709,13 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) {
|
if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) {
|
||||||
Janet x;
|
Janet x;
|
||||||
data = unmarshal_one(st, data, &x, flags + 1);
|
data = unmarshal_one(st, data, &x, flags + 1);
|
||||||
if (!janet_checktype(x, JANET_STRING)) longjmp(st->err, UMR_EXPECTED_STRING);
|
janet_asserttype(x, JANET_STRING);
|
||||||
def->name = janet_unwrap_string(x);
|
def->name = janet_unwrap_string(x);
|
||||||
}
|
}
|
||||||
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) {
|
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) {
|
||||||
Janet x;
|
Janet x;
|
||||||
data = unmarshal_one(st, data, &x, flags + 1);
|
data = unmarshal_one(st, data, &x, flags + 1);
|
||||||
if (!janet_checktype(x, JANET_STRING)) longjmp(st->err, UMR_EXPECTED_STRING);
|
janet_asserttype(x, JANET_STRING);
|
||||||
def->source = janet_unwrap_string(x);
|
def->source = janet_unwrap_string(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,7 +738,7 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < bytecode_length; i++) {
|
for (int32_t i = 0; i < bytecode_length; i++) {
|
||||||
if (data + 4 > end) longjmp(st->err, UMR_EOS);
|
MARSH_EOS(st, data + 3);
|
||||||
def->bytecode[i] =
|
def->bytecode[i] =
|
||||||
(uint32_t)(data[0]) |
|
(uint32_t)(data[0]) |
|
||||||
((uint32_t)(data[1]) << 8) |
|
((uint32_t)(data[1]) << 8) |
|
||||||
@ -823,7 +794,8 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Validate */
|
/* Validate */
|
||||||
if (janet_verify(def)) longjmp(st->err, UMR_INVALID_BYTECODE);
|
if (janet_verify(def))
|
||||||
|
janet_panic("funcdef has invalid bytecode");
|
||||||
|
|
||||||
/* Set def */
|
/* Set def */
|
||||||
*out = def;
|
*out = def;
|
||||||
@ -868,7 +840,7 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
if ((int32_t)(frame + JANET_FRAME_SIZE) > fiber->stackstart ||
|
if ((int32_t)(frame + JANET_FRAME_SIZE) > fiber->stackstart ||
|
||||||
fiber->stackstart > fiber->stacktop ||
|
fiber->stackstart > fiber->stacktop ||
|
||||||
fiber->stacktop > fiber->maxstack) {
|
fiber->stacktop > fiber->maxstack) {
|
||||||
goto error;
|
janet_panic("fiber has incorrect stack setup");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate stack memory */
|
/* Allocate stack memory */
|
||||||
@ -896,9 +868,7 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
/* Get function */
|
/* Get function */
|
||||||
Janet funcv;
|
Janet funcv;
|
||||||
data = unmarshal_one(st, data, &funcv, flags + 1);
|
data = unmarshal_one(st, data, &funcv, flags + 1);
|
||||||
if (!janet_checktype(funcv, JANET_FUNCTION)) {
|
janet_asserttype(funcv, JANET_FUNCTION);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
func = janet_unwrap_function(funcv);
|
func = janet_unwrap_function(funcv);
|
||||||
def = func->def;
|
def = func->def;
|
||||||
|
|
||||||
@ -908,17 +878,25 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
int32_t offset = stack;
|
int32_t offset = stack;
|
||||||
int32_t length = stacktop - stack;
|
int32_t length = stacktop - stack;
|
||||||
data = unmarshal_one_env(st, data, &env, flags + 1);
|
data = unmarshal_one_env(st, data, &env, flags + 1);
|
||||||
if (env->offset != 0 && env->offset != offset) goto error;
|
if (env->offset != 0 && env->offset != offset)
|
||||||
if (env->length != 0 && env->length != offset) goto error;
|
janet_panic("funcenv offset does not match fiber frame");
|
||||||
|
if (env->length != 0 && env->length != length)
|
||||||
|
janet_panic("funcenv length does not match fiber frame");
|
||||||
env->offset = offset;
|
env->offset = offset;
|
||||||
env->length = length;
|
env->length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Error checking */
|
/* Error checking */
|
||||||
int32_t expected_framesize = def->slotcount;
|
int32_t expected_framesize = def->slotcount;
|
||||||
if (expected_framesize != stacktop - stack) goto error;
|
if (expected_framesize != stacktop - stack) {
|
||||||
if (pcdiff < 0 || pcdiff >= def->bytecode_length) goto error;
|
janet_panic("fiber stackframe size mismatch");
|
||||||
if ((int32_t)(prevframe + JANET_FRAME_SIZE) > stack) goto error;
|
}
|
||||||
|
if (pcdiff < 0 || pcdiff >= def->bytecode_length) {
|
||||||
|
janet_panic("fiber stackframe has invalid pc");
|
||||||
|
}
|
||||||
|
if ((int32_t)(prevframe + JANET_FRAME_SIZE) > stack) {
|
||||||
|
janet_panic("fibre stackframe does not align with previous frame");
|
||||||
|
}
|
||||||
|
|
||||||
/* Get stack items */
|
/* Get stack items */
|
||||||
for (int32_t i = stack; i < stacktop; i++)
|
for (int32_t i = stack; i < stacktop; i++)
|
||||||
@ -935,14 +913,16 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
stacktop = stack - JANET_FRAME_SIZE;
|
stacktop = stack - JANET_FRAME_SIZE;
|
||||||
stack = prevframe;
|
stack = prevframe;
|
||||||
}
|
}
|
||||||
if (stack < 0) goto error;
|
if (stack < 0) {
|
||||||
|
janet_panic("fiber has too many stackframes");
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for child fiber */
|
/* Check for child fiber */
|
||||||
if (fiber->flags & JANET_FIBER_FLAG_HASCHILD) {
|
if (fiber->flags & JANET_FIBER_FLAG_HASCHILD) {
|
||||||
Janet fiberv;
|
Janet fiberv;
|
||||||
fiber->flags &= ~JANET_FIBER_FLAG_HASCHILD;
|
fiber->flags &= ~JANET_FIBER_FLAG_HASCHILD;
|
||||||
data = unmarshal_one(st, data, &fiberv, flags + 1);
|
data = unmarshal_one(st, data, &fiberv, flags + 1);
|
||||||
if (!janet_checktype(fiberv, JANET_FIBER)) longjmp(st->err, UMR_EXPECTED_FIBER);
|
janet_asserttype(fiberv, JANET_FIBER);
|
||||||
fiber->child = janet_unwrap_fiber(fiberv);
|
fiber->child = janet_unwrap_fiber(fiberv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -950,10 +930,6 @@ static const uint8_t *unmarshal_one_fiber(
|
|||||||
fiber->frame = frame;
|
fiber->frame = frame;
|
||||||
*out = fiber;
|
*out = fiber;
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
error:
|
|
||||||
longjmp(st->err, UMR_INVALID_FIBER);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -991,7 +967,7 @@ void janet_unmarshal_janet(JanetMarshalContext *ctx, Janet *out) {
|
|||||||
static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) {
|
static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) {
|
||||||
uint32_t tag = readint(st, &data);
|
uint32_t tag = readint(st, &data);
|
||||||
const JanetAbstractTypeInfo *info = janet_get_abstract_type_info(tag);
|
const JanetAbstractTypeInfo *info = janet_get_abstract_type_info(tag);
|
||||||
if (info == NULL) goto error;
|
if (info == NULL) return NULL;
|
||||||
if (info->unmarshal) {
|
if (info->unmarshal) {
|
||||||
void *p = janet_abstract(info->at, info->size);
|
void *p = janet_abstract(info->at, info->size);
|
||||||
JanetMarshalContext context = {NULL, st, flags, data};
|
JanetMarshalContext context = {NULL, st, flags, data};
|
||||||
@ -999,9 +975,6 @@ static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *
|
|||||||
*out = janet_wrap_abstract(p);
|
*out = janet_wrap_abstract(p);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
error:
|
|
||||||
longjmp(st->err, UMR_INVALID_ABSTRACT);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,13 +987,9 @@ static const uint8_t *unmarshal_one(
|
|||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
Janet *out,
|
Janet *out,
|
||||||
int flags) {
|
int flags) {
|
||||||
const uint8_t *end = st->end;
|
|
||||||
uint8_t lead;
|
uint8_t lead;
|
||||||
if ((flags & 0xFFFF) > JANET_RECURSION_GUARD) {
|
MARSH_STACKCHECK;
|
||||||
longjmp(st->err, UMR_STACKOVERFLOW);
|
MARSH_EOS(st, data);
|
||||||
}
|
|
||||||
#define EXTRA(N) if (data + N > end) longjmp(st->err, UMR_EOS)
|
|
||||||
EXTRA(1);
|
|
||||||
lead = data[0];
|
lead = data[0];
|
||||||
if (lead < 200) {
|
if (lead < 200) {
|
||||||
*out = janet_wrap_integer(readint(st, &data));
|
*out = janet_wrap_integer(readint(st, &data));
|
||||||
@ -1038,7 +1007,7 @@ static const uint8_t *unmarshal_one(
|
|||||||
return data + 1;
|
return data + 1;
|
||||||
case LB_INTEGER:
|
case LB_INTEGER:
|
||||||
/* Long integer */
|
/* Long integer */
|
||||||
EXTRA(5);
|
MARSH_EOS(st, data + 4);
|
||||||
*out = janet_wrap_integer(
|
*out = janet_wrap_integer(
|
||||||
(data[4]) |
|
(data[4]) |
|
||||||
(data[3] << 8) |
|
(data[3] << 8) |
|
||||||
@ -1052,7 +1021,7 @@ static const uint8_t *unmarshal_one(
|
|||||||
double d;
|
double d;
|
||||||
uint8_t bytes[8];
|
uint8_t bytes[8];
|
||||||
} u;
|
} u;
|
||||||
EXTRA(9);
|
MARSH_EOS(st, data + 8);
|
||||||
#ifdef JANET_BIG_ENDIAN
|
#ifdef JANET_BIG_ENDIAN
|
||||||
u.bytes[0] = data[8];
|
u.bytes[0] = data[8];
|
||||||
u.bytes[1] = data[7];
|
u.bytes[1] = data[7];
|
||||||
@ -1076,7 +1045,7 @@ static const uint8_t *unmarshal_one(
|
|||||||
case LB_REGISTRY: {
|
case LB_REGISTRY: {
|
||||||
data++;
|
data++;
|
||||||
int32_t len = readint(st, &data);
|
int32_t len = readint(st, &data);
|
||||||
EXTRA(len);
|
MARSH_EOS(st, data - 1 + len);
|
||||||
if (lead == LB_STRING) {
|
if (lead == LB_STRING) {
|
||||||
const uint8_t *str = janet_string(data, len);
|
const uint8_t *str = janet_string(data, len);
|
||||||
*out = janet_wrap_string(str);
|
*out = janet_wrap_string(str);
|
||||||
@ -1168,7 +1137,7 @@ static const uint8_t *unmarshal_one(
|
|||||||
janet_array_push(&st->lookup, *out);
|
janet_array_push(&st->lookup, *out);
|
||||||
} else if (lead == LB_REFERENCE) {
|
} else if (lead == LB_REFERENCE) {
|
||||||
if (len < 0 || len >= st->lookup.count)
|
if (len < 0 || len >= st->lookup.count)
|
||||||
longjmp(st->err, UMR_INVALID_REFERENCE);
|
janet_panicf("invalid reference %d", len);
|
||||||
*out = st->lookup.data[len];
|
*out = st->lookup.data[len];
|
||||||
} else {
|
} else {
|
||||||
/* Table */
|
/* Table */
|
||||||
@ -1178,7 +1147,7 @@ static const uint8_t *unmarshal_one(
|
|||||||
if (lead == LB_TABLE_PROTO) {
|
if (lead == LB_TABLE_PROTO) {
|
||||||
Janet proto;
|
Janet proto;
|
||||||
data = unmarshal_one(st, data, &proto, flags + 1);
|
data = unmarshal_one(st, data, &proto, flags + 1);
|
||||||
if (!janet_checktype(proto, JANET_TABLE)) longjmp(st->err, UMR_EXPECTED_TABLE);
|
janet_asserttype(proto, JANET_TABLE);
|
||||||
t->proto = janet_unwrap_table(proto);
|
t->proto = janet_unwrap_table(proto);
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < len; i++) {
|
for (int32_t i = 0; i < len; i++) {
|
||||||
@ -1190,36 +1159,39 @@ static const uint8_t *unmarshal_one(
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
longjmp(st->err, UMR_UNKNOWN);
|
janet_panicf("unknown byte %x at index %d",
|
||||||
|
*data,
|
||||||
|
(int)(data - st->start));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#undef EXTRA
|
#undef EXTRA
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_unmarshal(
|
Janet janet_unmarshal(
|
||||||
const uint8_t *bytes,
|
const uint8_t *bytes,
|
||||||
size_t len,
|
size_t len,
|
||||||
int flags,
|
int flags,
|
||||||
Janet *out,
|
|
||||||
JanetTable *reg,
|
JanetTable *reg,
|
||||||
const uint8_t **next) {
|
const uint8_t **next) {
|
||||||
int status;
|
|
||||||
/* Avoid longjmp clobber warning in GCC */
|
|
||||||
UnmarshalState st;
|
UnmarshalState st;
|
||||||
|
st.start = bytes;
|
||||||
st.end = bytes + len;
|
st.end = bytes + len;
|
||||||
st.lookup_defs = NULL;
|
st.lookup_defs = NULL;
|
||||||
st.lookup_envs = NULL;
|
st.lookup_envs = NULL;
|
||||||
st.reg = reg;
|
st.reg = reg;
|
||||||
janet_array_init(&st.lookup, 0);
|
janet_array_init(&st.lookup, 0);
|
||||||
if (!(status = setjmp(st.err))) {
|
Janet out;
|
||||||
const uint8_t *nextbytes = unmarshal_one(&st, bytes, out, flags);
|
const uint8_t *nextbytes = unmarshal_one(&st, bytes, &out, flags);
|
||||||
if (next) *next = nextbytes;
|
if (next) *next = nextbytes;
|
||||||
}
|
/* Clean up - this should be auto released on panics, TODO. We should
|
||||||
|
* change the vector implementation to track allocations for auto release, and
|
||||||
|
* make st.lookup auto release as well, or move to heap. */
|
||||||
janet_array_deinit(&st.lookup);
|
janet_array_deinit(&st.lookup);
|
||||||
janet_v_free(st.lookup_defs);
|
janet_v_free(st.lookup_defs);
|
||||||
janet_v_free(st.lookup_envs);
|
janet_v_free(st.lookup_envs);
|
||||||
return status;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* C functions */
|
/* C functions */
|
||||||
@ -1234,8 +1206,6 @@ static Janet cfun_marshal(int32_t argc, Janet *argv) {
|
|||||||
janet_arity(argc, 1, 2);
|
janet_arity(argc, 1, 2);
|
||||||
JanetBuffer *buffer;
|
JanetBuffer *buffer;
|
||||||
JanetTable *rreg = NULL;
|
JanetTable *rreg = NULL;
|
||||||
Janet err_param = janet_wrap_nil();
|
|
||||||
int status;
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
rreg = janet_gettable(argv, 1);
|
rreg = janet_gettable(argv, 1);
|
||||||
}
|
}
|
||||||
@ -1244,9 +1214,7 @@ static Janet cfun_marshal(int32_t argc, Janet *argv) {
|
|||||||
} else {
|
} else {
|
||||||
buffer = janet_buffer(10);
|
buffer = janet_buffer(10);
|
||||||
}
|
}
|
||||||
status = janet_marshal(buffer, argv[0], &err_param, rreg, 0);
|
janet_marshal(buffer, argv[0], rreg, 0);
|
||||||
if (status)
|
|
||||||
janet_panicf("%s for %V", mr_strings[status], err_param);
|
|
||||||
return janet_wrap_buffer(buffer);
|
return janet_wrap_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1254,16 +1222,10 @@ static Janet cfun_unmarshal(int32_t argc, Janet *argv) {
|
|||||||
janet_arity(argc, 1, 2);
|
janet_arity(argc, 1, 2);
|
||||||
JanetByteView view = janet_getbytes(argv, 0);
|
JanetByteView view = janet_getbytes(argv, 0);
|
||||||
JanetTable *reg = NULL;
|
JanetTable *reg = NULL;
|
||||||
Janet ret;
|
|
||||||
int status;
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
reg = janet_gettable(argv, 1);
|
reg = janet_gettable(argv, 1);
|
||||||
}
|
}
|
||||||
status = janet_unmarshal(view.bytes, (size_t) view.len, 0, &ret, reg, NULL);
|
return janet_unmarshal(view.bytes, (size_t) view.len, 0, reg, NULL);
|
||||||
if (status) {
|
|
||||||
janet_panic(umr_strings[status]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const JanetReg marsh_cfuns[] = {
|
static const JanetReg marsh_cfuns[] = {
|
||||||
|
@ -125,6 +125,7 @@ static Janet os_execute(int32_t argc, Janet *argv) {
|
|||||||
static Janet os_execute(int32_t argc, Janet *argv) {
|
static Janet os_execute(int32_t argc, Janet *argv) {
|
||||||
janet_arity(argc, 1, -1);
|
janet_arity(argc, 1, -1);
|
||||||
const uint8_t **child_argv = malloc(sizeof(uint8_t *) * (argc + 1));
|
const uint8_t **child_argv = malloc(sizeof(uint8_t *) * (argc + 1));
|
||||||
|
int status = 0;
|
||||||
if (NULL == child_argv) {
|
if (NULL == child_argv) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -141,9 +142,10 @@ static Janet os_execute(int32_t argc, Janet *argv) {
|
|||||||
if (-1 == execve((const char *)child_argv[0], (char **)child_argv, NULL)) {
|
if (-1 == execve((const char *)child_argv[0], (char **)child_argv, NULL)) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
int status;
|
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
|
}
|
||||||
|
free(child_argv);
|
||||||
return janet_wrap_integer(status);
|
return janet_wrap_integer(status);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -946,9 +946,11 @@ static uint32_t peg_compile1(Builder *b, Janet peg) {
|
|||||||
sizeof(peg_specials) / sizeof(SpecialPair),
|
sizeof(peg_specials) / sizeof(SpecialPair),
|
||||||
sizeof(SpecialPair),
|
sizeof(SpecialPair),
|
||||||
sym);
|
sym);
|
||||||
if (!sp)
|
if (sp) {
|
||||||
peg_panicf(b, "unknown special %S", sym);
|
|
||||||
sp->special(b, len - 1, tup + 1);
|
sp->special(b, len - 1, tup + 1);
|
||||||
|
} else {
|
||||||
|
peg_panicf(b, "unknown special %S", sym);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1055,7 +1057,6 @@ static Janet cfun_peg_match(int32_t argc, Janet *argv) {
|
|||||||
s.captures = janet_array(0);
|
s.captures = janet_array(0);
|
||||||
s.scratch = janet_buffer(10);
|
s.scratch = janet_buffer(10);
|
||||||
s.tags = janet_buffer(10);
|
s.tags = janet_buffer(10);
|
||||||
|
|
||||||
s.constants = peg->constants;
|
s.constants = peg->constants;
|
||||||
s.bytecode = peg->bytecode;
|
s.bytecode = peg->bytecode;
|
||||||
const uint8_t *result = peg_rule(&s, s.bytecode, bytes.bytes + start);
|
const uint8_t *result = peg_rule(&s, s.bytecode, bytes.bytes + start);
|
||||||
|
@ -182,8 +182,7 @@ static Janet cfun_string_repeat(int32_t argc, Janet *argv) {
|
|||||||
if (mulres > INT32_MAX) janet_panic("result string is too long");
|
if (mulres > INT32_MAX) janet_panic("result string is too long");
|
||||||
uint8_t *newbuf = janet_string_begin((int32_t) mulres);
|
uint8_t *newbuf = janet_string_begin((int32_t) mulres);
|
||||||
uint8_t *end = newbuf + mulres;
|
uint8_t *end = newbuf + mulres;
|
||||||
uint8_t *p = newbuf;
|
for (uint8_t *p = newbuf; p < end; p += view.len) {
|
||||||
for (p = newbuf; p < end; p += view.len) {
|
|
||||||
memcpy(p, view.bytes, view.len);
|
memcpy(p, view.bytes, view.len);
|
||||||
}
|
}
|
||||||
return janet_wrap_string(janet_string_end(newbuf));
|
return janet_wrap_string(janet_string_end(newbuf));
|
||||||
|
@ -44,7 +44,7 @@ JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted = 0;
|
|||||||
/* Initialize the cache (allocate cache memory) */
|
/* Initialize the cache (allocate cache memory) */
|
||||||
void janet_symcache_init() {
|
void janet_symcache_init() {
|
||||||
janet_vm_cache_capacity = 1024;
|
janet_vm_cache_capacity = 1024;
|
||||||
janet_vm_cache = calloc(1, janet_vm_cache_capacity * sizeof(const uint8_t **));
|
janet_vm_cache = calloc(1, janet_vm_cache_capacity * sizeof(const uint8_t *));
|
||||||
if (NULL == janet_vm_cache) {
|
if (NULL == janet_vm_cache) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ notfound:
|
|||||||
static void janet_cache_resize(uint32_t newCapacity) {
|
static void janet_cache_resize(uint32_t newCapacity) {
|
||||||
uint32_t i, oldCapacity;
|
uint32_t i, oldCapacity;
|
||||||
const uint8_t **oldCache = janet_vm_cache;
|
const uint8_t **oldCache = janet_vm_cache;
|
||||||
const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t **));
|
const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t *));
|
||||||
if (newCache == NULL) {
|
if (newCache == NULL) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -852,7 +852,12 @@ JanetSignal janet_pcall(
|
|||||||
const Janet *argv,
|
const Janet *argv,
|
||||||
Janet *out,
|
Janet *out,
|
||||||
JanetFiber **f) {
|
JanetFiber **f) {
|
||||||
JanetFiber *fiber = janet_fiber(fun, 64, argc, argv);
|
JanetFiber *fiber;
|
||||||
|
if (f && *f) {
|
||||||
|
fiber = janet_fiber_reset(*f, fun, argc, argv);
|
||||||
|
} else {
|
||||||
|
fiber = janet_fiber(fun, 64, argc, argv);
|
||||||
|
}
|
||||||
if (f) *f = fiber;
|
if (f) *f = fiber;
|
||||||
if (!fiber) {
|
if (!fiber) {
|
||||||
*out = janet_cstringv("arity mismatch");
|
*out = janet_cstringv("arity mismatch");
|
||||||
|
@ -1141,17 +1141,15 @@ typedef void (*JanetModule)(JanetTable *);
|
|||||||
JANET_API JanetModule janet_native(const char *name, const uint8_t **error);
|
JANET_API JanetModule janet_native(const char *name, const uint8_t **error);
|
||||||
|
|
||||||
/* Marshaling */
|
/* Marshaling */
|
||||||
JANET_API int janet_marshal(
|
JANET_API void janet_marshal(
|
||||||
JanetBuffer *buf,
|
JanetBuffer *buf,
|
||||||
Janet x,
|
Janet x,
|
||||||
Janet *errval,
|
|
||||||
JanetTable *rreg,
|
JanetTable *rreg,
|
||||||
int flags);
|
int flags);
|
||||||
JANET_API int janet_unmarshal(
|
JANET_API Janet janet_unmarshal(
|
||||||
const uint8_t *bytes,
|
const uint8_t *bytes,
|
||||||
size_t len,
|
size_t len,
|
||||||
int flags,
|
int flags,
|
||||||
Janet *out,
|
|
||||||
JanetTable *reg,
|
JanetTable *reg,
|
||||||
const uint8_t **next);
|
const uint8_t **next);
|
||||||
JANET_API JanetTable *janet_env_lookup(JanetTable *env);
|
JANET_API JanetTable *janet_env_lookup(JanetTable *env);
|
||||||
|
@ -61,5 +61,12 @@
|
|||||||
|
|
||||||
(check-image issue-53-x "issue 53 regression")
|
(check-image issue-53-x "issue 53 regression")
|
||||||
|
|
||||||
|
# Bracket tuple issue
|
||||||
|
|
||||||
|
(def do 3)
|
||||||
|
(assert (= [3 1 2 3] [do 1 2 3]) "bracket tuples are never special forms")
|
||||||
|
(assert (= ~(,defn 1 2 3) [defn 1 2 3]) "bracket tuples are never macros")
|
||||||
|
(assert (= ~(,+ 1 2 3) [+ 1 2 3]) "bracket tuples are never function calls")
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user