first pass at assignment
This commit is contained in:
1 parent
a847d2250f
commit
6c8b55793a
8 files changed
+117
-11
No files matched your search
+19
@@ -288,6 +288,25 @@ block gen_collect(block expr) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ block gen_op_symbol(opcode op, const char* name);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
+33
-11
@@ -12,6 +12,8 @@
|
||||
#include "forkable_stack.h"
|
||||
#include "frame_layout.h"
|
||||
|
||||
#include "jv.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
json_t* value;
|
||||
@@ -108,6 +110,8 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
|
||||
return *frame_closure_arg(fr, idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define stack_push stk_push
|
||||
#define stack_pop stk_pop
|
||||
|
||||
@@ -245,20 +249,37 @@ json_t* jq_next() {
|
||||
}
|
||||
#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");
|
||||
}
|
||||
@@ -314,6 +335,7 @@ json_t* jq_next() {
|
||||
pc++; // skip offset this time
|
||||
break;
|
||||
}
|
||||
|
||||
case ON_BACKTRACK(FORK): {
|
||||
uint16_t offset = *pc++;
|
||||
pc += offset;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#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
|
||||
@@ -12,6 +12,7 @@
|
||||
"==" { return EQ; }
|
||||
"as" { return AS; }
|
||||
"def" { return DEF; }
|
||||
"|=" { return SETPIPE; }
|
||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
||||
|
||||
[[:digit:]]+ { yylval->num = atoi(yytext); return NUMBER;}
|
||||
|
||||
@@ -14,6 +14,9 @@ OP(BACKTRACK, NONE, 0, 0)
|
||||
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)
|
||||
|
||||
|
||||
+18
@@ -28,6 +28,8 @@
|
||||
%token EQ "=="
|
||||
%token AS "as"
|
||||
%token DEF "def"
|
||||
%token SETPIPE "|="
|
||||
%nonassoc '=' SETPIPE
|
||||
%nonassoc EQ
|
||||
%left '+'
|
||||
|
||||
@@ -76,6 +78,22 @@ Term "as" '$' IDENT '|' Exp {
|
||||
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);
|
||||
} |
|
||||
|
||||
@@ -153,3 +153,4 @@ def f(x): $$x | $$x; $$f([.], . + [42])
|
||||
[[1,2,3],42]
|
||||
[[1,2,3,42]]
|
||||
[1,2,3,42,42]
|
||||
|
||||
Reference in new issue
Block a user