Move from Jansson to JV - interpreter loop

Passes tests, but leaks some memory.
This commit is contained in:
Stephen Dolan committed 2012-09-02 17:20:13 +01:00
1 parent 2cb9a6e61d
commit f72c5ffac0
7 files changed
+90 -103

No files matched your search

+2 -2
View File
@@ -17,8 +17,8 @@ parser.tab.c: parser.y lexer.yy.h
bison -W -d parser.y -v --report-file=parser.info bison -W -d parser.y -v --report-file=parser.info
parser.tab.h: parser.tab.c parser.tab.h: parser.tab.c
parsertest: parser.tab.c lexer.yy.c main.c opcode.c bytecode.c compile.c execute.c builtin.c parsertest: parser.tab.c lexer.yy.c main.c opcode.c bytecode.c compile.c execute.c builtin.c jv.c jv_parse.c jv_print.c jv_dtoa.c
$(CC) -o $@ $^ -ljansson $(CC) -o $@ $^
jvtest: jvtest.c jv.c jv_print.c jvtest: jvtest.c jv.c jv_print.c
$(CC) -DNO_JANSSON -o $@ $^ $(CC) -DNO_JANSSON -o $@ $^
+71 -75
View File
@@ -1,10 +1,8 @@
#include <jansson.h>
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "opcode.h" #include "opcode.h"
#include "bytecode.h" #include "bytecode.h"
#include "compile.h" #include "compile.h"
@@ -16,16 +14,16 @@
typedef struct { typedef struct {
json_t* value; jv value;
int pathidx; int pathidx;
} stackval; } stackval;
json_t** pathbuf; jv* pathbuf;
int pathsize; // number of allocated elements int pathsize; // number of allocated elements
// FIXME mem
int path_push(stackval sv, json_t* val) { int path_push(stackval sv, jv val) {
int pos = sv.pathidx; int pos = sv.pathidx;
assert(pos <= pathsize); assert(pos <= pathsize);
assert(pos >= 0); assert(pos >= 0);
@@ -37,14 +35,15 @@ int path_push(stackval sv, json_t* val) {
return pos + 1; return pos + 1;
} }
stackval stackval_replace(stackval value, json_t* newjs) { stackval stackval_replace(stackval value, jv newjs) {
jv_free(value.value);
stackval s = {newjs, value.pathidx}; stackval s = {newjs, value.pathidx};
return s; return s;
} }
// Probably all uses of this function are bugs // Probably all uses of this function are bugs
stackval stackval_root(json_t* v) { stackval stackval_root(jv v) {
stackval s = {v, 0}; stackval s = {v, 0};
return s; return s;
} }
@@ -63,7 +62,9 @@ void stk_push(stackval val) {
stackval stk_pop() { stackval stk_pop() {
data_stk_elem* s = forkable_stack_peek(&data_stk); data_stk_elem* s = forkable_stack_peek(&data_stk);
stackval sv = s->sv; stackval sv = s->sv;
forkable_stack_pop(&data_stk); if (!forkable_stack_pop(&data_stk)) {
sv.value = jv_copy(sv.value);
}
return sv; return sv;
} }
@@ -118,9 +119,9 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES) #define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
json_t* jq_next() { jv jq_next() {
json_t* cfunc_input[MAX_CFUNCTION_ARGS] = {0}; jv cfunc_input[MAX_CFUNCTION_ARGS];
json_t* cfunc_output[MAX_CFUNCTION_ARGS] = {0}; jv cfunc_output[MAX_CFUNCTION_ARGS];
assert(!forkable_stack_empty(&frame_stk)); assert(!forkable_stack_empty(&frame_stk));
uint16_t* pc = *frame_current_retaddr(&frame_stk); uint16_t* pc = *frame_current_retaddr(&frame_stk);
@@ -143,7 +144,7 @@ json_t* jq_next() {
} else { } else {
param = forkable_stack_peek_next(&data_stk, param); param = forkable_stack_peek_next(&data_stk, param);
} }
json_dumpf(param->sv.value, stdout, JSON_ENCODE_ANY); jv_dump(jv_copy(param->sv.value));
if (i < opdesc->stack_in-1) printf(" | "); if (i < opdesc->stack_in-1) printf(" | ");
} }
@@ -159,16 +160,18 @@ json_t* jq_next() {
default: assert(0 && "invalid instruction"); default: assert(0 && "invalid instruction");
case LOADK: { case LOADK: {
json_t* v = json_array_get(frame_current_bytecode(&frame_stk)->constants, *pc++); jv v = jv_array_get(jv_copy(frame_current_bytecode(&frame_stk)->constants), *pc++);
assert(v); //FIXME assert(v);
stack_push(stackval_replace(stack_pop(), v)); stack_push(stackval_replace(stack_pop(), v));
break; break;
} }
case DUP: { case DUP: {
stackval v = stack_pop(); stackval v = stack_pop();
stackval v2 = v;
v2.value = jv_copy(v.value);
stack_push(v); stack_push(v);
stack_push(v); stack_push(v2);
break; break;
} }
@@ -181,44 +184,42 @@ json_t* jq_next() {
} }
case POP: { case POP: {
stack_pop(); jv_free(stack_pop().value);
break; break;
} }
case APPEND: { case APPEND: {
// FIXME paths // FIXME paths
json_t* v = stack_pop().value; jv v = stack_pop().value;
json_t* array = stack_pop().value; jv array = stack_pop().value;
array = json_copy(array); array = jv_array_append(array, v);
json_array_append(array, v);
stack_push(stackval_root(array)); stack_push(stackval_root(array));
break; break;
} }
case INSERT: { case INSERT: {
stackval stktop = stack_pop(); stackval stktop = stack_pop();
json_t* v = stack_pop().value; jv v = stack_pop().value;
json_t* k = stack_pop().value; jv k = stack_pop().value;
stackval objv = stack_pop(); stackval objv = stack_pop();
assert(json_is_string(k)); assert(jv_get_kind(k) == JV_KIND_STRING);
assert(json_is_object(objv.value)); assert(jv_get_kind(objv.value) == JV_KIND_OBJECT);
json_t* obj = json_copy(objv.value); objv.value = jv_object_set(objv.value, k, v);
json_object_set(obj, json_string_value(k), v); stack_push(objv);
assert(json_is_object(obj));
stack_push(stackval_replace(objv, obj));
stack_push(stktop); stack_push(stktop);
break; break;
} }
// FIXME: loadv/storev may do too much copying/freeing
case LOADV: { case LOADV: {
uint16_t level = *pc++; uint16_t level = *pc++;
uint16_t v = *pc++; uint16_t v = *pc++;
frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level); frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
json_t** var = frame_local_var(fp, v); jv* var = frame_local_var(fp, v);
printf("V%d = ", v); printf("V%d = ", v);
json_dumpf(*var, stdout, JSON_ENCODE_ANY); jv_dump(jv_copy(*var));
printf("\n"); printf("\n");
stack_push(stackval_replace(stack_pop(), *var)); stack_push(stackval_replace(stack_pop(), jv_copy(*var)));
break; break;
} }
@@ -226,43 +227,31 @@ json_t* jq_next() {
uint16_t level = *pc++; uint16_t level = *pc++;
uint16_t v = *pc++; uint16_t v = *pc++;
frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level); frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
json_t** var = frame_local_var(fp, v); jv* 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); jv_dump(jv_copy(val.value));
printf("\n"); printf("\n");
jv_free(*var);
*var = val.value; *var = val.value;
break; break;
} }
#if 0
case DISPLAY: {
stackval sv = stack_pop();
if (sv.value) {
json_dumpf(sv.value, stdout, JSON_ENCODE_ANY);
} else {
printf("#ERROR");
}
printf(" - ");
for (int i = 0; i < sv.pathidx; i++) {
printf("/");
json_dumpf(pathbuf[i], stdout, JSON_ENCODE_ANY);
}
printf("\n");
return;
}
#endif
case ASSIGN_DBG: { case ASSIGN_DBG: {
assert(0);
/*
stackval replacement = stack_pop(); stackval replacement = stack_pop();
stackval path_end = stack_pop(); stackval path_end = stack_pop();
stackval path_start = stack_pop(); stackval path_start = stack_pop();
json_t* obj = jv_insert(path_start.value, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx); json_t* obj = jv_insert(path_start.value, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
stack_push(stackval_replace(path_start, obj)); stack_push(stackval_replace(path_start, obj));
*/
break; break;
} }
case ASSIGN: { case ASSIGN: {
assert(0);
/*
stackval replacement = stack_pop(); stackval replacement = stack_pop();
stackval path_end = stack_pop(); stackval path_end = stack_pop();
stackval path_start = stack_pop(); stackval path_start = stack_pop();
@@ -272,17 +261,18 @@ json_t* jq_next() {
frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level); frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
json_t** var = frame_local_var(fp, v); json_t** var = frame_local_var(fp, v);
*var = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx); *var = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
*/
break; break;
} }
case INDEX: { case INDEX: {
stackval t = stack_pop(); stackval t = stack_pop();
json_t* k = stack_pop().value; jv k = stack_pop().value;
json_t* v = jv_lookup(t.value, k); jv v = jv_lookup(t.value, k);
if (v) { if (1 /* fixme invalid lookups */) {
stackval sv; stackval sv;
sv.value = v; sv.value = v;
sv.pathidx = path_push(t, k); sv.pathidx = 0; //FIXME path_push(t, k);
stack_push(sv); stack_push(sv);
} else { } else {
assert(0 && "bad lookup"); assert(0 && "bad lookup");
@@ -298,23 +288,24 @@ json_t* jq_next() {
} }
case EACH: case EACH:
stack_push(stackval_root(json_integer(0))); stack_push(stackval_root(jv_number(0)));
// fallthrough // fallthrough
case ON_BACKTRACK(EACH): { case ON_BACKTRACK(EACH): {
json_t* idxj = stack_pop().value; int idx = jv_number_value(stack_pop().value);
int idx = json_integer_value(idxj);
stackval array = stack_pop(); stackval array = stack_pop();
if (idx >= json_array_size(array.value)) { if (idx >= jv_array_length(jv_copy(array.value))) {
goto do_backtrack; goto do_backtrack;
} else { } else {
stack_save(); stack_save();
stack_push(array); stackval array2 = array;
stack_push(stackval_root(json_integer(idx+1))); array2.value = jv_copy(array2.value);
stack_push(array2);
stack_push(stackval_root(jv_number(idx+1)));
frame_push_backtrack(&frame_stk, pc - 1); frame_push_backtrack(&frame_stk, pc - 1);
stack_switch(); stack_switch();
stackval sv = {json_array_get(array.value, idx), stackval sv = {jv_array_get(array.value, idx),
path_push(array, json_integer(idx))}; path_push(array, jv_number(idx))};
stack_push(sv); stack_push(sv);
} }
break; break;
@@ -323,7 +314,8 @@ json_t* jq_next() {
do_backtrack: do_backtrack:
case BACKTRACK: { case BACKTRACK: {
if (forkable_stack_empty(&fork_stk)) { if (forkable_stack_empty(&fork_stk)) {
return 0; // FIXME: invalid
return jv_null();
} }
stack_restore(); stack_restore();
pc = *frame_current_retaddr(&frame_stk); pc = *frame_current_retaddr(&frame_stk);
@@ -347,7 +339,7 @@ json_t* jq_next() {
} }
case YIELD: { case YIELD: {
json_t* value = stack_pop().value; jv value = stack_pop().value;
frame_push_backtrack(&frame_stk, pc); frame_push_backtrack(&frame_stk, pc);
return value; return value;
} }
@@ -361,7 +353,8 @@ json_t* jq_next() {
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++]; struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
printf(" call %s\n", func->name); printf(" call %s\n", func->name);
func->fptr(cfunc_input, cfunc_output); func->fptr(cfunc_input, cfunc_output);
stack_push(stackval_replace(top, cfunc_output[0])); top.value = cfunc_output[0];
stack_push(top);
break; break;
} }
@@ -370,15 +363,16 @@ json_t* jq_next() {
pc++; // skip nclosures pc++; // skip nclosures
pc++; // skip level pc++; // skip level
stackval top = stack_pop(); stackval top = stack_pop();
json_t* a = stack_pop().value; jv a = stack_pop().value;
json_t* b = stack_pop().value; jv b = stack_pop().value;
cfunc_input[0] = top.value; cfunc_input[0] = top.value;
cfunc_input[1] = a; cfunc_input[1] = a;
cfunc_input[2] = b; cfunc_input[2] = b;
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++]; struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
printf(" call %s\n", func->name); printf(" call %s\n", func->name);
func->fptr(cfunc_input, cfunc_output); func->fptr(cfunc_input, cfunc_output);
stack_push(stackval_replace(top, cfunc_output[0])); top.value = cfunc_output[0];
stack_push(top);
break; break;
} }
@@ -409,7 +403,7 @@ json_t* jq_next() {
} }
void jq_init(struct bytecode* bc, json_t* input) { void jq_init(struct bytecode* bc, jv input) {
forkable_stack_init(&data_stk, sizeof(stackval) * 1000); // FIXME: lower this number, see if it breaks forkable_stack_init(&data_stk, sizeof(stackval) * 1000); // FIXME: lower this number, see if it breaks
forkable_stack_init(&frame_stk, 10240); // FIXME: lower this number, see if it breaks forkable_stack_init(&frame_stk, 10240); // FIXME: lower this number, see if it breaks
forkable_stack_init(&fork_stk, 10240); // FIXME: lower this number, see if it breaks forkable_stack_init(&fork_stk, 10240); // FIXME: lower this number, see if it breaks
@@ -421,10 +415,12 @@ void jq_init(struct bytecode* bc, json_t* input) {
} }
void run_program(struct bytecode* bc) { void run_program(struct bytecode* bc) {
jq_init(bc, json_loadf(stdin, 0, 0)); char buf[4096];
json_t* result; fgets(buf, sizeof(buf), stdin);
while ((result = jq_next())) { jq_init(bc, jv_parse(buf));
json_dumpf(result, stdout, JSON_ENCODE_ANY); jv result;
while (jv_get_kind(result = jq_next()) != JV_KIND_NULL) {
jv_dump(result);
printf("\n"); printf("\n");
} }
printf("end of results\n"); printf("end of results\n");
-14
View File
@@ -1,14 +0,0 @@
#include "opcode.h"
#define MAX_CFUNCTION_PARAM 10
typedef struct {
json_t* value;
int pathidx;
} stackval;
typedef void (*cfunction_ptr)(stackval* input, stackval* output);
struct cfunction {
cfunction_ptr fptr;
const char* name;
opcode callop;
};
+5 -1
View File
@@ -83,10 +83,14 @@ static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
} }
} }
static void forkable_stack_pop(struct forkable_stack* s) { // Returns 1 if the object being popped can not be accessed again
// (i.e. was not saved with a fork)
static int forkable_stack_pop(struct forkable_stack* s) {
forkable_stack_check(s); forkable_stack_check(s);
int finalpop = s->pos < s->savedlimit ? 1 : 0;
struct forkable_stack_header* elem = forkable_stack_peek(s); struct forkable_stack_header* elem = forkable_stack_peek(s);
s->pos = elem->next; s->pos = elem->next;
return finalpop;
} }
+5 -3
View File
@@ -1,7 +1,6 @@
#ifndef FRAME_LAYOUT_H #ifndef FRAME_LAYOUT_H
#include "forkable_stack.h" #include "forkable_stack.h"
#include "bytecode.h" #include "bytecode.h"
#include <jansson.h>
struct closure { struct closure {
struct bytecode* bc; struct bytecode* bc;
@@ -18,7 +17,7 @@ typedef union frame_elem {
FORKABLE_STACK_HEADER; FORKABLE_STACK_HEADER;
struct continuation cont; struct continuation cont;
struct closure closure; struct closure closure;
json_t* jsonval; jv jsonval;
} *frame_ptr; } *frame_ptr;
/* /*
@@ -43,7 +42,7 @@ static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
return &fr[2+closure].closure; return &fr[2+closure].closure;
} }
static json_t** frame_local_var(frame_ptr fr, int var) { static jv* frame_local_var(frame_ptr fr, int var) {
assert(var >= 0); assert(var >= 0);
assert(var < frame_self(fr)->bc->nlocals); assert(var < frame_self(fr)->bc->nlocals);
return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval; return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
@@ -85,6 +84,9 @@ static frame_ptr frame_push(struct forkable_stack* stk, struct closure cl, uint1
cc->bc = cl.bc; cc->bc = cl.bc;
cc->env = cl.env; cc->env = cl.env;
cc->retaddr = retaddr; cc->retaddr = retaddr;
for (int i=0; i<cl.bc->nlocals; i++) {
*frame_local_var(fp, i) = jv_null();
}
return fp; return fp;
} }
+1 -1
View File
@@ -239,7 +239,7 @@ jv jv_array_concat(jv a, jv b) {
assert(jv_get_kind(b) == JV_KIND_ARRAY); assert(jv_get_kind(b) == JV_KIND_ARRAY);
// FIXME: could be much faster // FIXME: could be much faster
for (int i=0; i<jv_array_length(b); i++) { for (int i=0; i<jv_array_length(jv_copy(b)); i++) {
a = jv_array_append(a, jv_array_get(jv_copy(b), i)); a = jv_array_append(a, jv_array_get(jv_copy(b), i));
} }
jv_free(b); jv_free(b);
+6 -7
View File
@@ -6,10 +6,10 @@
block compile(const char* str); block compile(const char* str);
//void jq_init(struct bytecode* bc, jv value); void jq_init(struct bytecode* bc, jv value);
//jv jq_next(); jv jq_next();
//void run_program(struct bytecode* bc); void run_program(struct bytecode* bc);
int skipline(const char* buf) { int skipline(const char* buf) {
int p = 0; int p = 0;
@@ -39,13 +39,12 @@ void run_tests() {
printf("\n"); printf("\n");
fgets(buf, sizeof(buf), testdata); fgets(buf, sizeof(buf), testdata);
jv input = jv_parse(buf); jv input = jv_parse(buf);
jv_free(input); //jq_init(bc, input); jq_init(bc, input);
while (fgets(buf, sizeof(buf), testdata)) { while (fgets(buf, sizeof(buf), testdata)) {
if (skipline(buf)) break; if (skipline(buf)) break;
jv expected = jv_parse(buf); jv expected = jv_parse(buf);
//jv actual = jq_next(); FIXME jv actual = jq_next();
jv actual = jv_copy(expected);
if (!1) { if (!1) {
printf("Insufficient results\n"); printf("Insufficient results\n");
pass = 0; pass = 0;
@@ -84,5 +83,5 @@ int main(int argc, char* argv[]) {
block_free(blk); block_free(blk);
dump_disassembly(0, bc); dump_disassembly(0, bc);
printf("\n"); printf("\n");
//run_program(bc); run_program(bc);
} }