From 79d81f4beef13612241be3fe16c29a65272a4bf6 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 21 Aug 2012 18:24:38 +0100 Subject: [PATCH] Closures over variables --- c/bytecode.c | 9 +++++++-- c/compile.c | 3 +-- c/execute.c | 8 ++++++-- c/opcode.c | 2 +- c/opcode.h | 5 ++++- c/testdata | 2 +- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/c/bytecode.c b/c/bytecode.c index 82e38f4..08d7fff 100644 --- a/c/bytecode.c +++ b/c/bytecode.c @@ -35,7 +35,7 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) { printf("%04d ", pc); const struct opcode_description* op = opcode_describe(bc->code[pc++]); 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++]; if (op->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) { for (int i=0; iflags & OP_HAS_BRANCH) { printf(" %04d", pc + imm); } else if (op->flags & OP_HAS_CONSTANT) { + printf(" "); json_dumpf(json_array_get(bc->constants, imm), stdout, JSON_ENCODE_ANY); } 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 { printf(" %d", imm); } diff --git a/c/compile.c b/c/compile.c index 8944633..cf5834b 100644 --- a/c/compile.c +++ b/c/compile.c @@ -344,8 +344,7 @@ static void compile(struct bytecode* bc, block b) { code[pos++] = json_array_size(constant_pool); json_array_append(constant_pool, curr->imm.constant); } else if (opflags & OP_HAS_VARIABLE) { - // no closing over variables yet - assert(curr->bound_by->compiled == bc); + code[pos++] = nesting_level(bc, curr->bound_by); uint16_t var = (uint16_t)curr->bound_by->imm.intval; code[pos++] = var; if (var > maxvar) maxvar = var; diff --git a/c/execute.c b/c/execute.c index 8bd8ec3..5245682 100644 --- a/c/execute.c +++ b/c/execute.c @@ -204,15 +204,19 @@ json_t* jq_next() { } case LOADV: { + uint16_t level = *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)); break; } case STOREV: { + uint16_t level = *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(); printf("V%d = ", v); json_dumpf(val.value, stdout, JSON_ENCODE_ANY); diff --git a/c/opcode.c b/c/opcode.c index ff41f86..87179a5 100644 --- a/c/opcode.c +++ b/c/opcode.c @@ -2,7 +2,7 @@ #define NONE 0 #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 CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC) #define UFUNC (OP_HAS_IMMEDIATE | OP_HAS_UFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST) diff --git a/c/opcode.h b/c/opcode.h index 262ecb3..87d2434 100644 --- a/c/opcode.h +++ b/c/opcode.h @@ -25,6 +25,7 @@ enum { OP_HAS_VARIABLE_LENGTH_ARGLIST = 256, OP_HAS_BLOCK = 512, OP_HAS_BINDING = 1024, + OP_HAS_DOUBLE_IMMEDIATE = 2048, }; struct opcode_description { opcode op; @@ -36,6 +37,8 @@ struct opcode_description { const struct opcode_description* opcode_describe(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 diff --git a/c/testdata b/c/testdata index cc4d17b..cefc4b0 100644 --- a/c/testdata +++ b/c/testdata @@ -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] 1 -[300.0, 600.0] \ No newline at end of file +[301.0, 601.0] -- 2.50.0