mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Move from Jansson to JV - everything but the interpreter loop
Passes valgrind --leak-check=full.
This commit is contained in:
@@ -24,7 +24,7 @@ jvtest: jvtest.c jv.c jv_print.c
|
||||
$(CC) -DNO_JANSSON -o $@ $^
|
||||
|
||||
jv_parse: jv_parse.c jv.c jv_print.c jv_dtoa.c
|
||||
$(CC) -DNO_JANSSON -o $@ $^
|
||||
$(CC) -DNO_JANSSON -o $@ $^ -DJV_PARSE_MAIN
|
||||
|
||||
|
||||
test: jvtest
|
||||
|
||||
30
c/builtin.c
30
c/builtin.c
@@ -1,28 +1,24 @@
|
||||
#include "builtin.h"
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
|
||||
static void f_false(json_t* input[], json_t* output[]) {
|
||||
output[0] = json_false();
|
||||
static void f_false(jv input[], jv output[]) {
|
||||
output[0] = jv_false();
|
||||
}
|
||||
|
||||
static void f_true(json_t* input[], json_t* output[]) {
|
||||
output[0] = json_true();
|
||||
static void f_true(jv input[], jv output[]) {
|
||||
output[0] = jv_true();
|
||||
}
|
||||
|
||||
|
||||
static void f_plus(json_t* input[], json_t* output[]) {
|
||||
json_t* a = input[2];
|
||||
json_t* b = input[1];
|
||||
if (json_is_number(a) && json_is_number(b)) {
|
||||
output[0] = json_real(json_number_value(a) +
|
||||
json_number_value(b));
|
||||
} else if (json_is_array(a) && json_is_array(b)) {
|
||||
output[0] = json_copy(a);
|
||||
json_array_extend(output[0], b);
|
||||
static void f_plus(jv input[], jv output[]) {
|
||||
jv a = input[2];
|
||||
jv b = input[1];
|
||||
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
output[0] = jv_number(jv_number_value(a) +
|
||||
jv_number_value(b));
|
||||
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
|
||||
output[0] = jv_array_concat(a, b);
|
||||
} else {
|
||||
output[0] = json_string("wtf gaize");
|
||||
output[0] = jv_string("wtf gaize");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
c/bytecode.c
22
c/bytecode.c
@@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <jansson.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bytecode.h"
|
||||
#include "opcode.h"
|
||||
|
||||
@@ -57,8 +58,7 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
||||
printf(" %04d", pc + imm);
|
||||
} else if (op->flags & OP_HAS_CONSTANT) {
|
||||
printf(" ");
|
||||
json_dumpf(json_array_get(bc->constants, imm),
|
||||
stdout, JSON_ENCODE_ANY);
|
||||
jv_dump(jv_array_get(jv_copy(bc->constants), imm));
|
||||
} else if (op->flags & OP_HAS_VARIABLE) {
|
||||
uint16_t v = bc->code[pc++];
|
||||
printf(" v%d", v);
|
||||
@@ -70,3 +70,19 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void symbol_table_free(struct symbol_table* syms) {
|
||||
free(syms->cfunctions);
|
||||
free(syms);
|
||||
}
|
||||
|
||||
void bytecode_free(struct bytecode* bc) {
|
||||
free(bc->code);
|
||||
jv_free(bc->constants);
|
||||
for (int i=0; i<bc->nsubfunctions; i++)
|
||||
bytecode_free(bc->subfunctions[i]);
|
||||
if (!bc->parent)
|
||||
symbol_table_free(bc->globals);
|
||||
free(bc->subfunctions);
|
||||
free(bc);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef BYTECODE_H
|
||||
#define BYTECODE_H
|
||||
#include <jansson.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jv.h"
|
||||
#include "opcode.h"
|
||||
|
||||
typedef void (*cfunction_ptr)(json_t* input[], json_t* output[]);
|
||||
typedef void (*cfunction_ptr)(jv input[], jv output[]);
|
||||
|
||||
struct cfunction {
|
||||
cfunction_ptr fptr;
|
||||
@@ -33,7 +33,7 @@ struct bytecode {
|
||||
int nlocals;
|
||||
int nclosures;
|
||||
|
||||
json_t* constants;
|
||||
jv constants; // JSON array of constants
|
||||
struct symbol_table* globals;
|
||||
|
||||
struct bytecode** subfunctions;
|
||||
@@ -46,4 +46,7 @@ void dump_disassembly(int, struct bytecode* code);
|
||||
void dump_code(int, struct bytecode* code);
|
||||
void dump_operation(struct bytecode* bc, uint16_t* op);
|
||||
|
||||
void symbol_table_free(struct symbol_table* syms);
|
||||
void bytecode_free(struct bytecode* bc);
|
||||
|
||||
#endif
|
||||
|
||||
16
c/compile.c
16
c/compile.c
@@ -1,5 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "opcode.h"
|
||||
#include "compile.h"
|
||||
|
||||
@@ -13,7 +14,7 @@ struct inst {
|
||||
union {
|
||||
uint16_t intval;
|
||||
struct inst* target;
|
||||
json_t* constant;
|
||||
jv constant;
|
||||
struct cfunction* cfunc;
|
||||
} imm;
|
||||
|
||||
@@ -52,6 +53,9 @@ static void inst_free(struct inst* i) {
|
||||
if (opcode_describe(i->op)->flags & OP_HAS_BLOCK) {
|
||||
block_free(i->subfn);
|
||||
}
|
||||
if (opcode_describe(i->op)->flags & OP_HAS_CONSTANT) {
|
||||
jv_free(i->imm.constant);
|
||||
}
|
||||
free(i);
|
||||
}
|
||||
|
||||
@@ -89,7 +93,7 @@ block gen_op_simple(opcode op) {
|
||||
}
|
||||
|
||||
|
||||
block gen_op_const(opcode op, json_t* constant) {
|
||||
block gen_op_const(opcode op, jv constant) {
|
||||
assert(opcode_describe(op)->flags & OP_HAS_CONSTANT);
|
||||
inst* i = inst_new(op);
|
||||
i->imm.constant = constant;
|
||||
@@ -267,7 +271,7 @@ block gen_both(block a, block b) {
|
||||
block gen_collect(block expr) {
|
||||
block c = gen_noop();
|
||||
block_append(&c, gen_op_simple(DUP));
|
||||
block_append(&c, gen_op_const(LOADK, json_array()));
|
||||
block_append(&c, gen_op_const(LOADK, jv_array()));
|
||||
block array_var = block_bind(gen_op_var_unbound(STOREV, "collect"),
|
||||
gen_noop(), OP_HAS_VARIABLE);
|
||||
block_append(&c, array_var);
|
||||
@@ -395,7 +399,7 @@ static void compile(struct bytecode* bc, block b) {
|
||||
uint16_t* code = malloc(sizeof(uint16_t) * bc->codelen);
|
||||
bc->code = code;
|
||||
pos = 0;
|
||||
json_t* constant_pool = json_array();
|
||||
jv constant_pool = jv_array();
|
||||
int maxvar = -1;
|
||||
for (inst* curr = b.first; curr; curr = curr->next) {
|
||||
const struct opcode_description* op = opcode_describe(curr->op);
|
||||
@@ -436,8 +440,8 @@ static void compile(struct bytecode* bc, block b) {
|
||||
}
|
||||
assert(nargs - 1 == desired_params);
|
||||
} else if (opflags & OP_HAS_CONSTANT) {
|
||||
code[pos++] = json_array_size(constant_pool);
|
||||
json_array_append(constant_pool, curr->imm.constant);
|
||||
code[pos++] = jv_array_length(jv_copy(constant_pool));
|
||||
constant_pool = jv_array_append(constant_pool, jv_copy(curr->imm.constant));
|
||||
} else if (opflags & OP_HAS_VARIABLE) {
|
||||
code[pos++] = nesting_level(bc, curr->bound_by);
|
||||
uint16_t var = (uint16_t)curr->bound_by->imm.intval;
|
||||
|
||||
@@ -13,7 +13,7 @@ typedef struct block {
|
||||
|
||||
block gen_noop();
|
||||
block gen_op_simple(opcode op);
|
||||
block gen_op_const(opcode op, json_t* constant);
|
||||
block gen_op_const(opcode op, jv constant);
|
||||
block gen_op_target(opcode op, block target);
|
||||
block gen_op_var_unbound(opcode op, const char* name);
|
||||
block gen_op_var_bound(opcode op, block binder);
|
||||
|
||||
6
c/jv.c
6
c/jv.c
@@ -278,7 +278,7 @@ static jvp_string* jvp_string_alloc(uint32_t size) {
|
||||
return s;
|
||||
}
|
||||
|
||||
static jv_complex jvp_string_new(char* data, uint32_t length) {
|
||||
static jv_complex jvp_string_new(const char* data, uint32_t length) {
|
||||
jvp_string* s = jvp_string_alloc(length);
|
||||
memcpy(s->data, data, length);
|
||||
s->data[length] = 0;
|
||||
@@ -389,14 +389,14 @@ static int jvp_string_equal(jv_complex* a, jv_complex* b) {
|
||||
* Strings (public API)
|
||||
*/
|
||||
|
||||
jv jv_string_sized(char* str, int len) {
|
||||
jv jv_string_sized(const char* str, int len) {
|
||||
jv j;
|
||||
j.kind = JV_KIND_STRING;
|
||||
j.val.complex = jvp_string_new(str, len);
|
||||
return j;
|
||||
}
|
||||
|
||||
jv jv_string(char* str) {
|
||||
jv jv_string(const char* str) {
|
||||
return jv_string_sized(str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
91
c/jv.h
91
c/jv.h
@@ -4,42 +4,6 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#ifndef NO_JANSSON
|
||||
#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
|
||||
|
||||
|
||||
|
||||
@@ -99,8 +63,8 @@ jv jv_array_concat(jv, jv);
|
||||
jv jv_array_slice(jv, int, int);
|
||||
|
||||
|
||||
jv jv_string(char*);
|
||||
jv jv_string_sized(char*, int);
|
||||
jv jv_string(const char*);
|
||||
jv jv_string_sized(const char*, int);
|
||||
int jv_string_length(jv);
|
||||
uint32_t jv_string_hash(jv);
|
||||
const char* jv_string_value(jv);
|
||||
@@ -119,6 +83,57 @@ jv jv_object_iter_value(jv, int);
|
||||
|
||||
|
||||
void jv_dump(jv);
|
||||
jv jv_parse(const char* string);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static jv jv_lookup(jv t, jv k) {
|
||||
jv v;
|
||||
if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) {
|
||||
v = jv_object_get(t, k);
|
||||
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
|
||||
// FIXME: don't do lookup for noninteger index
|
||||
v = jv_array_get(t, (int)jv_number_value(k));
|
||||
} else {
|
||||
assert(0&&"bad lookup");
|
||||
}
|
||||
return v;
|
||||
// FIXME: invalid indexes, JV_KIND_INVALID
|
||||
/*
|
||||
if (v)
|
||||
return v;
|
||||
else
|
||||
return jv_null();
|
||||
*/
|
||||
}
|
||||
|
||||
static jv jv_modify(jv t, jv k, jv v) {
|
||||
if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) {
|
||||
t = jv_object_set(t, k, v);
|
||||
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
|
||||
t = jv_array_set(t, (int)jv_number_value(k), v);
|
||||
} else {
|
||||
assert(0 && "bad mod");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static jv jv_insert(jv root, jv value, jv* path, int pathlen) {
|
||||
if (pathlen == 0) {
|
||||
jv_free(root);
|
||||
return value;
|
||||
}
|
||||
return jv_modify(root, *path,
|
||||
jv_insert(jv_lookup(jv_copy(root), jv_copy(*path)), value, path+1, pathlen-1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
24
c/jv_parse.c
24
c/jv_parse.c
@@ -327,26 +327,32 @@ pfunc finish() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
assert(argc == 2);
|
||||
jv jv_parse(const char* string) {
|
||||
jvp_dtoa_context_init(&dtoa);
|
||||
char* p = argv[1];
|
||||
|
||||
const char* p = string;
|
||||
char ch;
|
||||
while ((ch = *p++)) {
|
||||
presult msg = scan(ch);
|
||||
if (msg){
|
||||
printf("ERROR: %s\n", msg);
|
||||
return 1;
|
||||
printf("ERROR: %s (parsing [%s])\n", msg, string);
|
||||
return jv_null();
|
||||
}
|
||||
}
|
||||
presult msg = finish();
|
||||
if (msg) {
|
||||
printf("ERROR: %s\n", msg);
|
||||
return 1;
|
||||
printf("ERROR: %s (parsing [%s])\n", msg, string);
|
||||
return jv_null();
|
||||
}
|
||||
jvp_dtoa_context_free(&dtoa);
|
||||
jv_dump(next);
|
||||
hasnext = 0;
|
||||
return next;
|
||||
}
|
||||
#if JV_PARSE_MAIN
|
||||
int main(int argc, char* argv[]) {
|
||||
assert(argc == 2);
|
||||
jv_dump(jv_parse(argv[1]));
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
"|=" { return SETPIPE; }
|
||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
||||
|
||||
[[:digit:]]+ { yylval->num = atoi(yytext); return NUMBER;}
|
||||
[[:alnum:]]+ { yylval->str = strdup(yytext); return IDENT;}
|
||||
[[:digit:]]+ { yylval->literal = jv_number((double)atoi(yytext)); return LITERAL;}
|
||||
[[:alnum:]]+ { yylval->literal = jv_string(yytext); return IDENT;}
|
||||
[ \n\t]+ {}
|
||||
%%
|
||||
/* perhaps these should be calls... */
|
||||
|
||||
36
c/main.c
36
c/main.c
@@ -2,13 +2,14 @@
|
||||
#include "compile.h"
|
||||
#include "parser.tab.h"
|
||||
#include "builtin.h"
|
||||
#include "jv.h"
|
||||
|
||||
block compile(const char* str);
|
||||
|
||||
void jq_init(struct bytecode* bc, json_t* value);
|
||||
json_t* jq_next();
|
||||
//void jq_init(struct bytecode* bc, jv value);
|
||||
//jv jq_next();
|
||||
|
||||
void run_program(struct bytecode* bc);
|
||||
//void run_program(struct bytecode* bc);
|
||||
|
||||
int skipline(const char* buf) {
|
||||
int p = 0;
|
||||
@@ -30,41 +31,44 @@ void run_tests() {
|
||||
block program = compile(buf);
|
||||
block_append(&program, gen_op_simple(YIELD));
|
||||
block_append(&program, gen_op_simple(BACKTRACK));
|
||||
struct bytecode* bc = block_compile(gen_cbinding(&builtins, program));
|
||||
program = gen_cbinding(&builtins, program);
|
||||
struct bytecode* bc = block_compile(program);
|
||||
block_free(program);
|
||||
printf("Disassembly:\n");
|
||||
dump_disassembly(2, bc);
|
||||
printf("\n");
|
||||
fgets(buf, sizeof(buf), testdata);
|
||||
json_t* input = json_loads(buf, JSON_DECODE_ANY, 0);
|
||||
jq_init(bc, input);
|
||||
jv input = jv_parse(buf);
|
||||
jv_free(input); //jq_init(bc, input);
|
||||
|
||||
while (fgets(buf, sizeof(buf), testdata)) {
|
||||
if (skipline(buf)) break;
|
||||
json_t* expected = json_loads(buf, JSON_DECODE_ANY, 0);
|
||||
json_t* actual = jq_next();
|
||||
if (!actual) {
|
||||
jv expected = jv_parse(buf);
|
||||
//jv actual = jq_next(); FIXME
|
||||
jv actual = jv_copy(expected);
|
||||
if (!1) {
|
||||
printf("Insufficient results\n");
|
||||
pass = 0;
|
||||
break;
|
||||
} else if (!json_equal(expected, actual)) {
|
||||
} else if (!jv_equal(expected, actual)) {
|
||||
printf("Expected ");
|
||||
json_dumpf(expected, stdout, JSON_ENCODE_ANY);
|
||||
jv_dump(expected);
|
||||
printf(", but got ");
|
||||
json_dumpf(actual, stdout, JSON_ENCODE_ANY);
|
||||
jv_dump(actual);
|
||||
printf("\n");
|
||||
pass = 0;
|
||||
}
|
||||
}
|
||||
if (pass) {
|
||||
json_t* extra = jq_next();
|
||||
if (pass && 0) { /*
|
||||
jv extra = jq_next();
|
||||
if (extra) {
|
||||
printf("Superfluous result: ");
|
||||
json_dumpf(extra, stdout, JSON_ENCODE_ANY);
|
||||
printf("\n");
|
||||
pass = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
bytecode_free(bc);
|
||||
tests++;
|
||||
passed+=pass;
|
||||
}
|
||||
@@ -80,5 +84,5 @@ int main(int argc, char* argv[]) {
|
||||
block_free(blk);
|
||||
dump_disassembly(0, bc);
|
||||
printf("\n");
|
||||
run_program(bc);
|
||||
//run_program(bc);
|
||||
}
|
||||
|
||||
51
c/parser.y
51
c/parser.y
@@ -7,8 +7,7 @@
|
||||
%locations
|
||||
%define api.pure
|
||||
%union {
|
||||
int num;
|
||||
char* str;
|
||||
jv literal;
|
||||
block blk;
|
||||
}
|
||||
|
||||
@@ -17,8 +16,8 @@
|
||||
%lex-param {yyscan_t lexer}
|
||||
|
||||
|
||||
%token <str> IDENT
|
||||
%token <num> NUMBER
|
||||
%token <literal> IDENT
|
||||
%token <literal> LITERAL
|
||||
|
||||
/* revolting hack */
|
||||
%left ';'
|
||||
@@ -48,10 +47,6 @@ static block gen_dictpair(block k, block v) {
|
||||
return b;
|
||||
}
|
||||
|
||||
static block gen_string(const char* str) {
|
||||
return gen_op_const(LOADK, json_string(str));
|
||||
}
|
||||
|
||||
static block gen_index(block obj, block key) {
|
||||
return block_join(obj, block_join(gen_subexp(key), gen_op_simple(INDEX)));
|
||||
}
|
||||
@@ -64,18 +59,23 @@ program: Exp { *answer = $1; }
|
||||
Exp:
|
||||
"def" IDENT ':' Exp ';' Exp {
|
||||
block body = block_join($4, gen_op_simple(RET));
|
||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, $2, body), $6, OP_IS_CALL_PSEUDO);
|
||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body),
|
||||
$6, OP_IS_CALL_PSEUDO);
|
||||
jv_free($2);
|
||||
} |
|
||||
|
||||
"def" IDENT '(' IDENT ')' ':' Exp ';' Exp {
|
||||
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, $4), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
|
||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, $2, body), $9, OP_IS_CALL_PSEUDO);
|
||||
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
|
||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body), $9, OP_IS_CALL_PSEUDO);
|
||||
jv_free($2);
|
||||
jv_free($4);
|
||||
} |
|
||||
|
||||
Term "as" '$' IDENT '|' Exp {
|
||||
$$ = gen_op_simple(DUP);
|
||||
block_append(&$$, $1);
|
||||
block_append(&$$, block_bind(gen_op_var_unbound(STOREV, $4), $6, OP_HAS_VARIABLE));
|
||||
block_append(&$$, block_bind(gen_op_var_unbound(STOREV, jv_string_value($4)), $6, OP_HAS_VARIABLE));
|
||||
jv_free($4);
|
||||
} |
|
||||
|
||||
Exp '=' Exp {
|
||||
@@ -129,10 +129,10 @@ Term:
|
||||
$$ = gen_noop();
|
||||
} |
|
||||
Term '.' IDENT {
|
||||
$$ = gen_index($1, gen_string($3));
|
||||
$$ = gen_index($1, gen_op_const(LOADK, $3));
|
||||
} |
|
||||
'.' IDENT {
|
||||
$$ = gen_index(gen_noop(), gen_string($2));
|
||||
$$ = gen_index(gen_noop(), gen_op_const(LOADK, $2));
|
||||
} |
|
||||
/* FIXME: string literals */
|
||||
Term '[' Exp ']' {
|
||||
@@ -141,8 +141,8 @@ Term '[' Exp ']' {
|
||||
Term '[' ']' {
|
||||
$$ = block_join($1, gen_op_simple(EACH));
|
||||
} |
|
||||
NUMBER {
|
||||
$$ = gen_op_const(LOADK, json_integer($1));
|
||||
LITERAL {
|
||||
$$ = gen_op_const(LOADK, $1);
|
||||
} |
|
||||
'(' Exp ')' {
|
||||
$$ = $2;
|
||||
@@ -151,26 +151,29 @@ NUMBER {
|
||||
$$ = gen_collect($2);
|
||||
} |
|
||||
'[' ']' {
|
||||
$$ = gen_op_const(LOADK, json_array());
|
||||
$$ = gen_op_const(LOADK, jv_array());
|
||||
} |
|
||||
'{' MkDict '}' {
|
||||
$$ = gen_subexp(gen_op_const(LOADK, json_object()));
|
||||
$$ = gen_subexp(gen_op_const(LOADK, jv_object()));
|
||||
block_append(&$$, $2);
|
||||
block_append(&$$, gen_op_simple(POP));
|
||||
} |
|
||||
'$' IDENT {
|
||||
$$ = gen_op_var_unbound(LOADV, $2);
|
||||
$$ = gen_op_var_unbound(LOADV, jv_string_value($2));
|
||||
jv_free($2);
|
||||
} |
|
||||
IDENT {
|
||||
$$ = gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, $1));
|
||||
$$ = gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, jv_string_value($1)));
|
||||
jv_free($1);
|
||||
} |
|
||||
IDENT '(' Exp ')' {
|
||||
$$ = gen_op_call(CALL_1_1,
|
||||
block_join(gen_op_block_unbound(CLOSURE_REF, $1),
|
||||
block_join(gen_op_block_unbound(CLOSURE_REF, jv_string_value($1)),
|
||||
block_bind(gen_op_block_defn(CLOSURE_CREATE,
|
||||
"lambda",
|
||||
block_join($3, gen_op_simple(RET))),
|
||||
gen_noop(), OP_IS_CALL_PSEUDO)));
|
||||
jv_free($1);
|
||||
}
|
||||
|
||||
MkDict:
|
||||
@@ -184,11 +187,11 @@ MkDictPair
|
||||
|
||||
MkDictPair
|
||||
: IDENT ':' ExpD {
|
||||
$$ = gen_dictpair(gen_string($1), $3);
|
||||
$$ = gen_dictpair(gen_op_const(LOADK, $1), $3);
|
||||
}
|
||||
| IDENT {
|
||||
$$ = gen_dictpair(gen_string($1),
|
||||
gen_index(gen_noop(), gen_string($1)));
|
||||
$$ = gen_dictpair(gen_op_const(LOADK, jv_copy($1)),
|
||||
gen_index(gen_noop(), gen_op_const(LOADK, $1)));
|
||||
}
|
||||
| '(' Exp ')' ':' ExpD {
|
||||
$$ = gen_dictpair($2, $5);
|
||||
|
||||
Reference in New Issue
Block a user