Refactor path logic.
This commit is contained in:
1 parent
b0e65d149f
commit
8c708f3c7a
5 files changed
+164
-141
No files matched your search
@@ -520,9 +520,9 @@ static block bind_bytecoded_builtins(block b) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
struct bytecoded_builtin builtin_def_1arg[] = {
|
struct bytecoded_builtin builtin_def_1arg[] = {
|
||||||
{"path", BLOCK(gen_op_simple(DUP),
|
{"path", BLOCK(gen_op_simple(PATH_BEGIN),
|
||||||
gen_call("arg", gen_noop()),
|
gen_call("arg", gen_noop()),
|
||||||
gen_op_simple(GETPATH))},
|
gen_op_simple(PATH_END))},
|
||||||
};
|
};
|
||||||
for (unsigned i=0; i<sizeof(builtin_def_1arg)/sizeof(builtin_def_1arg[0]); i++) {
|
for (unsigned i=0; i<sizeof(builtin_def_1arg)/sizeof(builtin_def_1arg[0]); i++) {
|
||||||
builtins = BLOCK(builtins, gen_function(builtin_def_1arg[i].name,
|
builtins = BLOCK(builtins, gen_function(builtin_def_1arg[i].name,
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ block gen_call(const char* name, block args) {
|
|||||||
|
|
||||||
|
|
||||||
block gen_subexp(block a) {
|
block gen_subexp(block a) {
|
||||||
return BLOCK(gen_op_simple(DUP), a, gen_op_simple(SWAP));
|
return BLOCK(gen_op_simple(SUBEXP_BEGIN), a, gen_op_simple(SUBEXP_END));
|
||||||
}
|
}
|
||||||
|
|
||||||
block gen_both(block a, block b) {
|
block gen_both(block a, block b) {
|
||||||
|
|||||||
@@ -19,78 +19,43 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
jv value;
|
|
||||||
int pathidx;
|
|
||||||
} stackval;
|
|
||||||
|
|
||||||
struct jq_state {
|
struct jq_state {
|
||||||
struct forkable_stack data_stk;
|
struct forkable_stack data_stk;
|
||||||
struct forkable_stack frame_stk;
|
struct forkable_stack frame_stk;
|
||||||
struct forkable_stack fork_stk;
|
struct forkable_stack fork_stk;
|
||||||
jv* pathbuf;
|
jv path;
|
||||||
int pathsize; // number of allocated elements
|
int subexp_nest;
|
||||||
int debug_trace_enabled;
|
int debug_trace_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
int path_push(jq_state *jq, stackval sv, jv val) {
|
|
||||||
int pos = sv.pathidx;
|
|
||||||
assert(pos <= jq->pathsize);
|
|
||||||
assert(pos >= 0);
|
|
||||||
if (pos == jq->pathsize) {
|
|
||||||
int oldpathsize = jq->pathsize;
|
|
||||||
jq->pathsize = oldpathsize ? oldpathsize * 2 : 100;
|
|
||||||
jq->pathbuf = jv_mem_realloc(jq->pathbuf, sizeof(jq->pathbuf[0]) * jq->pathsize);
|
|
||||||
for (int i=oldpathsize; i<jq->pathsize; i++) {
|
|
||||||
jq->pathbuf[i] = jv_invalid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jv_free(jq->pathbuf[pos]);
|
|
||||||
jq->pathbuf[pos] = val;
|
|
||||||
return pos + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
stackval stackval_replace(stackval value, jv newjs) {
|
|
||||||
jv_free(value.value);
|
|
||||||
stackval s = {newjs, value.pathidx};
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Probably all uses of this function are bugs
|
|
||||||
stackval stackval_root(jv v) {
|
|
||||||
stackval s = {v, 0};
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FORKABLE_STACK_HEADER;
|
FORKABLE_STACK_HEADER;
|
||||||
stackval sv;
|
jv val;
|
||||||
} data_stk_elem;
|
} data_stk_elem;
|
||||||
|
|
||||||
void stack_push(jq_state *jq, stackval val) {
|
void stack_push(jq_state *jq, jv val) {
|
||||||
assert(jv_is_valid(val.value));
|
assert(jv_is_valid(val));
|
||||||
data_stk_elem* s = forkable_stack_push(&jq->data_stk, sizeof(data_stk_elem));
|
data_stk_elem* s = forkable_stack_push(&jq->data_stk, sizeof(data_stk_elem));
|
||||||
s->sv = val;
|
s->val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
stackval stack_pop(jq_state *jq) {
|
jv stack_pop(jq_state *jq) {
|
||||||
data_stk_elem* s = forkable_stack_peek(&jq->data_stk);
|
data_stk_elem* s = forkable_stack_peek(&jq->data_stk);
|
||||||
stackval sv = s->sv;
|
jv val = s->val;
|
||||||
if (!forkable_stack_pop_will_free(&jq->data_stk)) {
|
if (!forkable_stack_pop_will_free(&jq->data_stk)) {
|
||||||
sv.value = jv_copy(sv.value);
|
val = jv_copy(val);
|
||||||
}
|
}
|
||||||
forkable_stack_pop(&jq->data_stk);
|
forkable_stack_pop(&jq->data_stk);
|
||||||
assert(jv_is_valid(sv.value));
|
assert(jv_is_valid(val));
|
||||||
return sv;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct forkpoint {
|
struct forkpoint {
|
||||||
FORKABLE_STACK_HEADER;
|
FORKABLE_STACK_HEADER;
|
||||||
struct forkable_stack_state saved_data_stack;
|
struct forkable_stack_state saved_data_stack;
|
||||||
struct forkable_stack_state saved_call_stack;
|
struct forkable_stack_state saved_call_stack;
|
||||||
|
int path_len, subexp_nest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -98,6 +63,9 @@ void stack_save(jq_state *jq){
|
|||||||
struct forkpoint* fork = forkable_stack_push(&jq->fork_stk, sizeof(struct forkpoint));
|
struct forkpoint* fork = forkable_stack_push(&jq->fork_stk, sizeof(struct forkpoint));
|
||||||
forkable_stack_save(&jq->data_stk, &fork->saved_data_stack);
|
forkable_stack_save(&jq->data_stk, &fork->saved_data_stack);
|
||||||
forkable_stack_save(&jq->frame_stk, &fork->saved_call_stack);
|
forkable_stack_save(&jq->frame_stk, &fork->saved_call_stack);
|
||||||
|
fork->path_len =
|
||||||
|
jv_get_kind(jq->path) == JV_KIND_ARRAY ? jv_array_length(jv_copy(jq->path)) : 0;
|
||||||
|
fork->subexp_nest = jq->subexp_nest;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_switch(jq_state *jq) {
|
void stack_switch(jq_state *jq) {
|
||||||
@@ -106,26 +74,47 @@ void stack_switch(jq_state *jq) {
|
|||||||
forkable_stack_switch(&jq->frame_stk, &fork->saved_call_stack);
|
forkable_stack_switch(&jq->frame_stk, &fork->saved_call_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void path_append(jq_state* jq, jv component) {
|
||||||
|
if (jq->subexp_nest == 0 && jv_get_kind(jq->path) == JV_KIND_ARRAY) {
|
||||||
|
int n1 = jv_array_length(jv_copy(jq->path));
|
||||||
|
jq->path = jv_array_append(jq->path, component);
|
||||||
|
int n2 = jv_array_length(jv_copy(jq->path));
|
||||||
|
assert(n2 == n1 + 1);
|
||||||
|
} else {
|
||||||
|
jv_free(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int stack_restore(jq_state *jq){
|
int stack_restore(jq_state *jq){
|
||||||
while (!forkable_stack_empty(&jq->data_stk) &&
|
while (!forkable_stack_empty(&jq->data_stk) &&
|
||||||
forkable_stack_pop_will_free(&jq->data_stk)) {
|
forkable_stack_pop_will_free(&jq->data_stk)) {
|
||||||
jv_free(stack_pop(jq).value);
|
jv_free(stack_pop(jq));
|
||||||
}
|
}
|
||||||
while (!forkable_stack_empty(&jq->frame_stk) &&
|
while (!forkable_stack_empty(&jq->frame_stk) &&
|
||||||
forkable_stack_pop_will_free(&jq->frame_stk)) {
|
forkable_stack_pop_will_free(&jq->frame_stk)) {
|
||||||
frame_pop(&jq->frame_stk);
|
frame_pop(&jq->frame_stk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forkable_stack_empty(&jq->fork_stk)) {
|
if (forkable_stack_empty(&jq->fork_stk)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
struct forkpoint* fork = forkable_stack_peek(&jq->fork_stk);
|
|
||||||
forkable_stack_restore(&jq->data_stk, &fork->saved_data_stack);
|
|
||||||
forkable_stack_restore(&jq->frame_stk, &fork->saved_call_stack);
|
|
||||||
forkable_stack_pop(&jq->fork_stk);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct forkpoint* fork = forkable_stack_peek(&jq->fork_stk);
|
||||||
|
forkable_stack_restore(&jq->data_stk, &fork->saved_data_stack);
|
||||||
|
forkable_stack_restore(&jq->frame_stk, &fork->saved_call_stack);
|
||||||
|
int path_len = fork->path_len;
|
||||||
|
if (jv_get_kind(jq->path) == JV_KIND_ARRAY) {
|
||||||
|
assert(path_len >= 0);
|
||||||
|
jq->path = jv_array_slice(jq->path, 0, path_len);
|
||||||
|
} else {
|
||||||
|
assert(path_len == 0);
|
||||||
|
}
|
||||||
|
jq->subexp_nest = fork->subexp_nest;
|
||||||
|
forkable_stack_pop(&jq->fork_stk);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uint16_t* pc) {
|
static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uint16_t* pc) {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t idx = *pc++;
|
uint16_t idx = *pc++;
|
||||||
@@ -179,9 +168,10 @@ jv jq_next(jq_state *jq) {
|
|||||||
param = forkable_stack_peek_next(&jq->data_stk, param);
|
param = forkable_stack_peek_next(&jq->data_stk, param);
|
||||||
}
|
}
|
||||||
if (!param) break;
|
if (!param) break;
|
||||||
jv_dump(jv_copy(param->sv.value), 0);
|
jv_dump(jv_copy(param->val), 0);
|
||||||
//printf("<%d>", jv_get_refcnt(param->sv.value));
|
//printf("<%d>", jv_get_refcnt(param->val));
|
||||||
printf("<%d>", param->sv.pathidx);
|
//printf(" -- ");
|
||||||
|
//jv_dump(jv_copy(jq->path), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backtracking) printf("\t<backtracking>");
|
if (backtracking) printf("\t<backtracking>");
|
||||||
@@ -200,46 +190,52 @@ jv jq_next(jq_state *jq) {
|
|||||||
case LOADK: {
|
case LOADK: {
|
||||||
jv v = jv_array_get(jv_copy(frame_current_bytecode(&jq->frame_stk)->constants), *pc++);
|
jv v = jv_array_get(jv_copy(frame_current_bytecode(&jq->frame_stk)->constants), *pc++);
|
||||||
assert(jv_is_valid(v));
|
assert(jv_is_valid(v));
|
||||||
stack_push(jq, stackval_replace(stack_pop(jq), v));
|
jv_free(stack_pop(jq));
|
||||||
|
stack_push(jq, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DUP: {
|
case DUP: {
|
||||||
stackval v = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
stackval v2 = v;
|
stack_push(jq, jv_copy(v));
|
||||||
v2.value = jv_copy(v.value);
|
|
||||||
stack_push(jq, v);
|
stack_push(jq, v);
|
||||||
stack_push(jq, v2);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DUP2: {
|
case DUP2: {
|
||||||
stackval keep = stack_pop(jq);
|
jv keep = stack_pop(jq);
|
||||||
stackval v = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
stackval v2 = v;
|
stack_push(jq, jv_copy(v));
|
||||||
v2.value = jv_copy(v.value);
|
|
||||||
stack_push(jq, v);
|
|
||||||
stack_push(jq, keep);
|
stack_push(jq, keep);
|
||||||
stack_push(jq, v2);
|
stack_push(jq, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SWAP: {
|
case SUBEXP_BEGIN: {
|
||||||
stackval a = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
stackval b = stack_pop(jq);
|
stack_push(jq, jv_copy(v));
|
||||||
|
stack_push(jq, v);
|
||||||
|
jq->subexp_nest++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SUBEXP_END: {
|
||||||
|
assert(jq->subexp_nest > 0);
|
||||||
|
jq->subexp_nest--;
|
||||||
|
jv a = stack_pop(jq);
|
||||||
|
jv b = stack_pop(jq);
|
||||||
stack_push(jq, a);
|
stack_push(jq, a);
|
||||||
stack_push(jq, b);
|
stack_push(jq, b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case POP: {
|
case POP: {
|
||||||
jv_free(stack_pop(jq).value);
|
jv_free(stack_pop(jq));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case APPEND: {
|
case APPEND: {
|
||||||
// FIXME paths
|
jv v = stack_pop(jq);
|
||||||
jv v = stack_pop(jq).value;
|
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t vidx = *pc++;
|
uint16_t vidx = *pc++;
|
||||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||||
@@ -250,14 +246,13 @@ jv jq_next(jq_state *jq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case INSERT: {
|
case INSERT: {
|
||||||
stackval stktop = stack_pop(jq);
|
jv stktop = stack_pop(jq);
|
||||||
jv v = stack_pop(jq).value;
|
jv v = stack_pop(jq);
|
||||||
jv k = stack_pop(jq).value;
|
jv k = stack_pop(jq);
|
||||||
stackval objv = stack_pop(jq);
|
jv objv = stack_pop(jq);
|
||||||
assert(jv_get_kind(k) == JV_KIND_STRING);
|
assert(jv_get_kind(k) == JV_KIND_STRING);
|
||||||
assert(jv_get_kind(objv.value) == JV_KIND_OBJECT);
|
assert(jv_get_kind(objv) == JV_KIND_OBJECT);
|
||||||
objv.value = jv_object_set(objv.value, k, v);
|
stack_push(jq, jv_object_set(objv, k, v));
|
||||||
stack_push(jq, objv);
|
|
||||||
stack_push(jq, stktop);
|
stack_push(jq, stktop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -273,7 +268,8 @@ jv jq_next(jq_state *jq) {
|
|||||||
jv_dump(jv_copy(*var), 0);
|
jv_dump(jv_copy(*var), 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
stack_push(jq, stackval_replace(stack_pop(jq), jv_copy(*var)));
|
jv_free(stack_pop(jq));
|
||||||
|
stack_push(jq, jv_copy(*var));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,39 +278,66 @@ jv jq_next(jq_state *jq) {
|
|||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||||
jv* var = frame_local_var(fp, v);
|
jv* var = frame_local_var(fp, v);
|
||||||
stackval val = stack_pop(jq);
|
jv val = stack_pop(jq);
|
||||||
if (jq->debug_trace_enabled) {
|
if (jq->debug_trace_enabled) {
|
||||||
printf("V%d = ", v);
|
printf("V%d = ", v);
|
||||||
jv_dump(jv_copy(val.value), 0);
|
jv_dump(jv_copy(val), 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
jv_free(*var);
|
jv_free(*var);
|
||||||
*var = val.value;
|
*var = val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GETPATH: {
|
case PATH_BEGIN: {
|
||||||
stackval path_end = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
stackval path_start = stack_pop(jq);
|
stack_push(jq, jq->path);
|
||||||
jv_free(path_end.value);
|
|
||||||
jv path = jv_array();
|
stack_save(jq);
|
||||||
for (int i=path_start.pathidx; i<path_end.pathidx; i++) {
|
frame_push_backtrack(&jq->frame_stk, pc - 1);
|
||||||
path = jv_array_append(path, jv_copy(jq->pathbuf[i]));
|
stack_switch(jq);
|
||||||
}
|
|
||||||
stack_push(jq, stackval_replace(path_start, path));
|
stack_push(jq, jv_number(jq->subexp_nest));
|
||||||
|
stack_push(jq, v);
|
||||||
|
|
||||||
|
jq->path = jv_array();
|
||||||
|
jq->subexp_nest = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PATH_END: {
|
||||||
|
jv v = stack_pop(jq);
|
||||||
|
jv_free(v); // discard value, only keep path
|
||||||
|
|
||||||
|
int old_subexp_nest = (int)jv_number_value(stack_pop(jq));
|
||||||
|
|
||||||
|
jv path = jq->path;
|
||||||
|
jq->path = stack_pop(jq);
|
||||||
|
|
||||||
|
stack_save(jq);
|
||||||
|
stack_push(jq, jv_copy(path));
|
||||||
|
frame_push_backtrack(&jq->frame_stk, pc - 1);
|
||||||
|
stack_switch(jq);
|
||||||
|
|
||||||
|
stack_push(jq, path);
|
||||||
|
jq->subexp_nest = old_subexp_nest;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ON_BACKTRACK(PATH_BEGIN):
|
||||||
|
case ON_BACKTRACK(PATH_END): {
|
||||||
|
jv_free(jq->path);
|
||||||
|
jq->path = stack_pop(jq);
|
||||||
|
goto do_backtrack;
|
||||||
|
}
|
||||||
|
|
||||||
case INDEX: {
|
case INDEX: {
|
||||||
stackval t = stack_pop(jq);
|
jv t = stack_pop(jq);
|
||||||
jv k = stack_pop(jq).value;
|
jv k = stack_pop(jq);
|
||||||
int pathidx = path_push(jq, t, jv_copy(k));
|
path_append(jq, jv_copy(k));
|
||||||
jv v = jv_get(t.value, k);
|
jv v = jv_get(t, k);
|
||||||
if (jv_is_valid(v)) {
|
if (jv_is_valid(v)) {
|
||||||
stackval sv;
|
stack_push(jq, v);
|
||||||
sv.value = v;
|
|
||||||
sv.pathidx = pathidx;
|
|
||||||
stack_push(jq, sv);
|
|
||||||
} else {
|
} else {
|
||||||
print_error(v);
|
print_error(v);
|
||||||
goto do_backtrack;
|
goto do_backtrack;
|
||||||
@@ -331,8 +354,8 @@ jv jq_next(jq_state *jq) {
|
|||||||
|
|
||||||
case JUMP_F: {
|
case JUMP_F: {
|
||||||
uint16_t offset = *pc++;
|
uint16_t offset = *pc++;
|
||||||
stackval t = stack_pop(jq);
|
jv t = stack_pop(jq);
|
||||||
jv_kind kind = jv_get_kind(t.value);
|
jv_kind kind = jv_get_kind(t);
|
||||||
if (kind == JV_KIND_FALSE || kind == JV_KIND_NULL) {
|
if (kind == JV_KIND_FALSE || kind == JV_KIND_NULL) {
|
||||||
pc += offset;
|
pc += offset;
|
||||||
}
|
}
|
||||||
@@ -341,50 +364,48 @@ jv jq_next(jq_state *jq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case EACH:
|
case EACH:
|
||||||
stack_push(jq, stackval_root(jv_number(-1)));
|
stack_push(jq, jv_number(-1));
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case ON_BACKTRACK(EACH): {
|
case ON_BACKTRACK(EACH): {
|
||||||
int idx = jv_number_value(stack_pop(jq).value);
|
int idx = jv_number_value(stack_pop(jq));
|
||||||
stackval container = stack_pop(jq);
|
jv container = stack_pop(jq);
|
||||||
|
|
||||||
int keep_going;
|
int keep_going;
|
||||||
jv key, value;
|
jv key, value;
|
||||||
if (jv_get_kind(container.value) == JV_KIND_ARRAY) {
|
if (jv_get_kind(container) == JV_KIND_ARRAY) {
|
||||||
if (opcode == EACH) idx = 0;
|
if (opcode == EACH) idx = 0;
|
||||||
else idx = idx + 1;
|
else idx = idx + 1;
|
||||||
keep_going = idx < jv_array_length(jv_copy(container.value));
|
keep_going = idx < jv_array_length(jv_copy(container));
|
||||||
if (keep_going) {
|
if (keep_going) {
|
||||||
key = jv_number(idx);
|
key = jv_number(idx);
|
||||||
value = jv_array_get(jv_copy(container.value), idx);
|
value = jv_array_get(jv_copy(container), idx);
|
||||||
}
|
}
|
||||||
} else if (jv_get_kind(container.value) == JV_KIND_OBJECT) {
|
} else if (jv_get_kind(container) == JV_KIND_OBJECT) {
|
||||||
if (opcode == EACH) idx = jv_object_iter(container.value);
|
if (opcode == EACH) idx = jv_object_iter(container);
|
||||||
else idx = jv_object_iter_next(container.value, idx);
|
else idx = jv_object_iter_next(container, idx);
|
||||||
keep_going = jv_object_iter_valid(container.value, idx);
|
keep_going = jv_object_iter_valid(container, idx);
|
||||||
if (keep_going) {
|
if (keep_going) {
|
||||||
key = jv_object_iter_key(container.value, idx);
|
key = jv_object_iter_key(container, idx);
|
||||||
value = jv_object_iter_value(container.value, idx);
|
value = jv_object_iter_value(container, idx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(opcode == EACH);
|
assert(opcode == EACH);
|
||||||
print_error(jv_invalid_with_msg(jv_string_fmt("Cannot iterate over %s",
|
print_error(jv_invalid_with_msg(jv_string_fmt("Cannot iterate over %s",
|
||||||
jv_kind_name(jv_get_kind(container.value)))));
|
jv_kind_name(jv_get_kind(container)))));
|
||||||
keep_going = 0;
|
keep_going = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keep_going) {
|
if (!keep_going) {
|
||||||
jv_free(container.value);
|
jv_free(container);
|
||||||
goto do_backtrack;
|
goto do_backtrack;
|
||||||
} else {
|
} else {
|
||||||
stack_save(jq);
|
stack_save(jq);
|
||||||
stack_push(jq, container);
|
stack_push(jq, container);
|
||||||
stack_push(jq, stackval_root(jv_number(idx)));
|
stack_push(jq, jv_number(idx));
|
||||||
frame_push_backtrack(&jq->frame_stk, pc - 1);
|
frame_push_backtrack(&jq->frame_stk, pc - 1);
|
||||||
stack_switch(jq);
|
stack_switch(jq);
|
||||||
|
path_append(jq, key);
|
||||||
stackval sv = {value,
|
stack_push(jq, value);
|
||||||
path_push(jq, container, key)};
|
|
||||||
stack_push(jq, sv);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -415,24 +436,24 @@ jv jq_next(jq_state *jq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case YIELD: {
|
case YIELD: {
|
||||||
jv value = stack_pop(jq).value;
|
jv value = stack_pop(jq);
|
||||||
frame_push_backtrack(&jq->frame_stk, pc);
|
frame_push_backtrack(&jq->frame_stk, pc);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CALL_BUILTIN: {
|
case CALL_BUILTIN: {
|
||||||
int nargs = *pc++;
|
int nargs = *pc++;
|
||||||
stackval top = stack_pop(jq);
|
jv top = stack_pop(jq);
|
||||||
cfunc_input[0] = top.value;
|
cfunc_input[0] = top;
|
||||||
for (int i = 1; i < nargs; i++) {
|
for (int i = 1; i < nargs; i++) {
|
||||||
cfunc_input[i] = stack_pop(jq).value;
|
cfunc_input[i] = stack_pop(jq);
|
||||||
}
|
}
|
||||||
struct cfunction* func = &frame_current_bytecode(&jq->frame_stk)->globals->cfunctions[*pc++];
|
struct cfunction* func = &frame_current_bytecode(&jq->frame_stk)->globals->cfunctions[*pc++];
|
||||||
top.value = cfunction_invoke(func, cfunc_input);
|
top = cfunction_invoke(func, cfunc_input);
|
||||||
if (jv_is_valid(top.value)) {
|
if (jv_is_valid(top)) {
|
||||||
stack_push(jq, top);
|
stack_push(jq, top);
|
||||||
} else {
|
} else {
|
||||||
print_error(top.value);
|
print_error(top);
|
||||||
goto do_backtrack;
|
goto do_backtrack;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -470,11 +491,12 @@ void jq_init(struct bytecode* bc, jv input, jq_state **jq, int flags) {
|
|||||||
jq_state *new_jq;
|
jq_state *new_jq;
|
||||||
new_jq = jv_mem_alloc(sizeof(*new_jq));
|
new_jq = jv_mem_alloc(sizeof(*new_jq));
|
||||||
memset(new_jq, 0, sizeof(*new_jq));
|
memset(new_jq, 0, sizeof(*new_jq));
|
||||||
forkable_stack_init(&new_jq->data_stk, sizeof(stackval) * 100);
|
new_jq->path = jv_null();
|
||||||
|
forkable_stack_init(&new_jq->data_stk, sizeof(data_stk_elem) * 100);
|
||||||
forkable_stack_init(&new_jq->frame_stk, 1024);
|
forkable_stack_init(&new_jq->frame_stk, 1024);
|
||||||
forkable_stack_init(&new_jq->fork_stk, 1024);
|
forkable_stack_init(&new_jq->fork_stk, 1024);
|
||||||
|
|
||||||
stack_push(new_jq, stackval_root(input));
|
stack_push(new_jq, input);
|
||||||
struct closure top = {bc, -1};
|
struct closure top = {bc, -1};
|
||||||
frame_push(&new_jq->frame_stk, top, 0);
|
frame_push(&new_jq->frame_stk, top, 0);
|
||||||
frame_push_backtrack(&new_jq->frame_stk, bc->code);
|
frame_push_backtrack(&new_jq->frame_stk, bc->code);
|
||||||
@@ -501,10 +523,7 @@ void jq_teardown(jq_state **jq) {
|
|||||||
forkable_stack_free(&old_jq->data_stk);
|
forkable_stack_free(&old_jq->data_stk);
|
||||||
forkable_stack_free(&old_jq->frame_stk);
|
forkable_stack_free(&old_jq->frame_stk);
|
||||||
|
|
||||||
for (int i=0; i<old_jq->pathsize; i++) {
|
jv_free(old_jq->path);
|
||||||
jv_free(old_jq->pathbuf[i]);
|
|
||||||
}
|
|
||||||
jv_mem_free(old_jq->pathbuf);
|
|
||||||
jv_mem_free(old_jq);
|
jv_mem_free(old_jq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (jv_get_kind(x)) {
|
switch (jv_get_kind(x)) {
|
||||||
|
default:
|
||||||
case JV_KIND_INVALID:
|
case JV_KIND_INVALID:
|
||||||
assert(0 && "Invalid value");
|
assert(0 && "Invalid value");
|
||||||
break;
|
break;
|
||||||
|
|||||||
+5
-2
@@ -1,7 +1,6 @@
|
|||||||
OP(LOADK, CONSTANT, 1, 1)
|
OP(LOADK, CONSTANT, 1, 1)
|
||||||
OP(DUP, NONE, 1, 2)
|
OP(DUP, NONE, 1, 2)
|
||||||
OP(DUP2, NONE, 2, 3)
|
OP(DUP2, NONE, 2, 3)
|
||||||
OP(SWAP, NONE, 2, 2)
|
|
||||||
OP(POP, NONE, 1, 0)
|
OP(POP, NONE, 1, 0)
|
||||||
OP(LOADV, VARIABLE, 1, 1)
|
OP(LOADV, VARIABLE, 1, 1)
|
||||||
OP(STOREV, VARIABLE, 1, 0)
|
OP(STOREV, VARIABLE, 1, 0)
|
||||||
@@ -15,7 +14,11 @@ OP(BACKTRACK, NONE, 0, 0)
|
|||||||
OP(APPEND, VARIABLE,1, 0)
|
OP(APPEND, VARIABLE,1, 0)
|
||||||
OP(INSERT, NONE, 4, 2)
|
OP(INSERT, NONE, 4, 2)
|
||||||
|
|
||||||
OP(GETPATH, NONE, 2, 1)
|
OP(SUBEXP_BEGIN, NONE, 1, 2)
|
||||||
|
OP(SUBEXP_END, NONE, 2, 2)
|
||||||
|
|
||||||
|
OP(PATH_BEGIN, NONE, 1, 2)
|
||||||
|
OP(PATH_END, NONE, 2, 1)
|
||||||
|
|
||||||
OP(CALL_BUILTIN, CFUNC, -1, 1)
|
OP(CALL_BUILTIN, CFUNC, -1, 1)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user