mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Closures over variables
This commit is contained in:
@@ -35,7 +35,7 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
|||||||
printf("%04d ", pc);
|
printf("%04d ", pc);
|
||||||
const struct opcode_description* op = opcode_describe(bc->code[pc++]);
|
const struct opcode_description* op = opcode_describe(bc->code[pc++]);
|
||||||
printf("%s", op->name);
|
printf("%s", op->name);
|
||||||
if (op->flags & OP_HAS_IMMEDIATE) {
|
if (op->flags & OP_HAS_IMMEDIATE || op->flags & OP_HAS_DOUBLE_IMMEDIATE) {
|
||||||
uint16_t imm = bc->code[pc++];
|
uint16_t imm = bc->code[pc++];
|
||||||
if (op->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) {
|
if (op->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) {
|
||||||
for (int i=0; i<imm; i++) {
|
for (int i=0; i<imm; i++) {
|
||||||
@@ -53,10 +53,15 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
|||||||
} else if (op->flags & OP_HAS_BRANCH) {
|
} else if (op->flags & OP_HAS_BRANCH) {
|
||||||
printf(" %04d", pc + imm);
|
printf(" %04d", pc + imm);
|
||||||
} else if (op->flags & OP_HAS_CONSTANT) {
|
} else if (op->flags & OP_HAS_CONSTANT) {
|
||||||
|
printf(" ");
|
||||||
json_dumpf(json_array_get(bc->constants, imm),
|
json_dumpf(json_array_get(bc->constants, imm),
|
||||||
stdout, JSON_ENCODE_ANY);
|
stdout, JSON_ENCODE_ANY);
|
||||||
} else if (op->flags & OP_HAS_VARIABLE) {
|
} else if (op->flags & OP_HAS_VARIABLE) {
|
||||||
printf(" v%d", imm);
|
uint16_t v = bc->code[pc++];
|
||||||
|
printf(" v%d", v);
|
||||||
|
if (imm) {
|
||||||
|
printf("^%d", imm);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
printf(" %d", imm);
|
printf(" %d", imm);
|
||||||
}
|
}
|
||||||
|
@@ -344,8 +344,7 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
code[pos++] = json_array_size(constant_pool);
|
code[pos++] = json_array_size(constant_pool);
|
||||||
json_array_append(constant_pool, curr->imm.constant);
|
json_array_append(constant_pool, curr->imm.constant);
|
||||||
} else if (opflags & OP_HAS_VARIABLE) {
|
} else if (opflags & OP_HAS_VARIABLE) {
|
||||||
// no closing over variables yet
|
code[pos++] = nesting_level(bc, curr->bound_by);
|
||||||
assert(curr->bound_by->compiled == bc);
|
|
||||||
uint16_t var = (uint16_t)curr->bound_by->imm.intval;
|
uint16_t var = (uint16_t)curr->bound_by->imm.intval;
|
||||||
code[pos++] = var;
|
code[pos++] = var;
|
||||||
if (var > maxvar) maxvar = var;
|
if (var > maxvar) maxvar = var;
|
||||||
|
@@ -204,15 +204,19 @@ json_t* jq_next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LOADV: {
|
case LOADV: {
|
||||||
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
json_t** var = frame_local_var(frame_current(&frame_stk), v);
|
frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
|
||||||
|
json_t** var = frame_local_var(fp, v);
|
||||||
stack_push(stackval_replace(stack_pop(), *var));
|
stack_push(stackval_replace(stack_pop(), *var));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STOREV: {
|
case STOREV: {
|
||||||
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
json_t** var = frame_local_var(frame_current(&frame_stk), v);
|
frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
|
||||||
|
json_t** var = frame_local_var(fp, v);
|
||||||
stackval val = stack_pop();
|
stackval val = stack_pop();
|
||||||
printf("V%d = ", v);
|
printf("V%d = ", v);
|
||||||
json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
|
json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#define NONE 0
|
#define NONE 0
|
||||||
#define CONSTANT (OP_HAS_IMMEDIATE | OP_HAS_CONSTANT)
|
#define CONSTANT (OP_HAS_IMMEDIATE | OP_HAS_CONSTANT)
|
||||||
#define VARIABLE (OP_HAS_IMMEDIATE | OP_HAS_VARIABLE | OP_HAS_BINDING)
|
#define VARIABLE (OP_HAS_DOUBLE_IMMEDIATE | OP_HAS_VARIABLE | OP_HAS_BINDING)
|
||||||
#define BRANCH (OP_HAS_IMMEDIATE | OP_HAS_BRANCH)
|
#define BRANCH (OP_HAS_IMMEDIATE | OP_HAS_BRANCH)
|
||||||
#define CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC)
|
#define CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC)
|
||||||
#define UFUNC (OP_HAS_IMMEDIATE | OP_HAS_UFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST)
|
#define UFUNC (OP_HAS_IMMEDIATE | OP_HAS_UFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST)
|
||||||
|
@@ -25,6 +25,7 @@ enum {
|
|||||||
OP_HAS_VARIABLE_LENGTH_ARGLIST = 256,
|
OP_HAS_VARIABLE_LENGTH_ARGLIST = 256,
|
||||||
OP_HAS_BLOCK = 512,
|
OP_HAS_BLOCK = 512,
|
||||||
OP_HAS_BINDING = 1024,
|
OP_HAS_BINDING = 1024,
|
||||||
|
OP_HAS_DOUBLE_IMMEDIATE = 2048,
|
||||||
};
|
};
|
||||||
struct opcode_description {
|
struct opcode_description {
|
||||||
opcode op;
|
opcode op;
|
||||||
@@ -36,6 +37,8 @@ struct opcode_description {
|
|||||||
const struct opcode_description* opcode_describe(opcode op);
|
const struct opcode_description* opcode_describe(opcode op);
|
||||||
|
|
||||||
static inline int opcode_length(opcode op) {
|
static inline int opcode_length(opcode op) {
|
||||||
return 1 + (opcode_describe(op)->flags & OP_HAS_IMMEDIATE ? 1 : 0);
|
return 1 +
|
||||||
|
(opcode_describe(op)->flags & OP_HAS_IMMEDIATE ? 1 : 0) +
|
||||||
|
(opcode_describe(op)->flags & OP_HAS_DOUBLE_IMMEDIATE ? 2 : 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -140,4 +140,4 @@ def f: . + 1; def g: def g: . + 100; $$f | $$g | $$f; ($$f | $$g), $$g
|
|||||||
|
|
||||||
[[100,200][] as $x | def f: . + $x; $$f | $$f | $$f]
|
[[100,200][] as $x | def f: . + $x; $$f | $$f | $$f]
|
||||||
1
|
1
|
||||||
[300.0, 600.0]
|
[301.0, 601.0]
|
||||||
|
Reference in New Issue
Block a user