return c;
}
+block gen_assign(block expr) {
+ block c = gen_noop();
+ block_append(&c, gen_op_simple(DUP));
+ block result_var = block_bind(gen_op_var_unbound(STOREV, "result"),
+ gen_noop(), OP_HAS_VARIABLE);
+ block_append(&c, result_var);
+
+ block loop = gen_noop();
+ block_append(&loop, gen_op_simple(DUP));
+ block_append(&loop, expr);
+ block_append(&loop, gen_op_var_bound(ASSIGN, result_var));
+ block_append(&loop, gen_op_simple(BACKTRACK));
+
+ block_append(&c, gen_op_target(FORK, loop));
+ block_append(&c, loop);
+ block_append(&c, gen_op_var_bound(LOADV, result_var));
+ return c;
+}
+
block gen_else(block a, block b) {
assert(0);
}
block gen_subexp(block a);
block gen_both(block a, block b);
block gen_collect(block expr);
+block gen_assign(block expr);
block gen_else(block a, block b);
#include "forkable_stack.h"
#include "frame_layout.h"
+#include "jv.h"
+
typedef struct {
json_t* value;
return *frame_closure_arg(fr, idx);
}
}
+
+
#define stack_push stk_push
#define stack_pop stk_pop
}
#endif
+ case ASSIGN_DBG: {
+ stackval replacement = stack_pop();
+ stackval path_end = 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);
+ stack_push(stackval_replace(path_start, obj));
+ break;
+ }
+
+ case ASSIGN: {
+ stackval replacement = stack_pop();
+ stackval path_end = stack_pop();
+ stackval path_start = stack_pop();
+
+ uint16_t level = *pc++;
+ uint16_t v = *pc++;
+ frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
+ json_t** var = frame_local_var(fp, v);
+ *var = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
+ break;
+ }
+
case INDEX: {
stackval t = stack_pop();
json_t* k = stack_pop().value;
- stackval v;
- if (json_is_string(k)) {
- v.value = json_object_get(t.value, json_string_value(k));
- } else if (json_is_integer(k)) {
- v.value = json_array_get(t.value, json_integer_value(k));
- } else {
- assert(0 && "key neither string nor int");
- }
- if (v.value) {
- v.pathidx = path_push(t, k);
- stack_push(v);
+ json_t* v = jv_lookup(t.value, k);
+ if (v) {
+ stackval sv;
+ sv.value = v;
+ sv.pathidx = path_push(t, k);
+ stack_push(sv);
} else {
assert(0 && "bad lookup");
}
pc++; // skip offset this time
break;
}
+
case ON_BACKTRACK(FORK): {
uint16_t offset = *pc++;
pc += offset;
--- /dev/null
+#ifndef JV_H
+#define JV_H
+
+#include <jansson.h>
+
+static json_t* jv_lookup(json_t* t, json_t* k) {
+ json_t* v;
+ if (json_is_object(t) && json_is_string(k)) {
+ v = json_object_get(t, json_string_value(k));
+ } else if (json_is_array(t) && json_is_number(k)) {
+ v = json_array_get(t, json_integer_value(k));
+ } else {
+ assert(0&&"bad lookup");
+ }
+ if (v)
+ return v;
+ else
+ return json_null();
+}
+
+static json_t* jv_modify(json_t* t, json_t* k, json_t* v) {
+ t = json_copy(t);
+ if (json_is_object(t) && json_is_string(k)) {
+ json_object_set(t, json_string_value(k), v);
+ } else if (json_is_array(t) && json_is_number(k)) {
+ json_array_set(t, json_integer_value(k), v);
+ } else {
+ assert(0 && "bad mod");
+ }
+ return t;
+}
+
+static json_t* jv_insert(json_t* root, json_t* value, json_t** path, int pathlen) {
+ if (pathlen == 0) {
+ return value;
+ }
+ return jv_modify(root, *path, jv_insert(jv_lookup(root, *path), value, path+1, pathlen-1));
+}
+
+
+#endif
"==" { return EQ; }
"as" { return AS; }
"def" { return DEF; }
+"|=" { return SETPIPE; }
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
[[:digit:]]+ { yylval->num = atoi(yytext); return NUMBER;}
OP(APPEND, NONE, 2, 1)
OP(INSERT, NONE, 4, 2)
+OP(ASSIGN_DBG, NONE, 3, 1)
+OP(ASSIGN, VARIABLE, 3, 0)
+
OP(CALL_BUILTIN_1_1, CFUNC, 1, 1)
OP(CALL_BUILTIN_3_1, CFUNC, 3, 1)
%token EQ "=="
%token AS "as"
%token DEF "def"
+%token SETPIPE "|="
+%nonassoc '=' SETPIPE
%nonassoc EQ
%left '+'
block_append(&$$, block_bind(gen_op_var_unbound(STOREV, $4), $6, OP_HAS_VARIABLE));
} |
+Exp '=' Exp {
+ block assign = gen_op_simple(DUP);
+ block_append(&assign, $3);
+ block_append(&assign, gen_op_simple(SWAP));
+ block_append(&assign, $1);
+ block_append(&assign, gen_op_simple(SWAP));
+ $$ = gen_assign(assign);
+} |
+
+Exp "|=" Exp {
+ block assign = $1;
+ block_append(&assign, gen_op_simple(DUP));
+ block_append(&assign, $3);
+ $$ = gen_assign(assign);
+} |
+
Exp '|' Exp {
$$ = block_join($1, $3);
} |
[[1,2,3],42]
[[1,2,3,42]]
[1,2,3,42,42]
+