diff --git a/.gitignore b/.gitignore index 7a53e6ec2a..acdf76c27b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ tests/*.trs cscope.in.out cscope.out cscope.po.out +jq.dSYM diff --git a/Makefile.am b/Makefile.am index 0dd1906f11..9ff75274b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,8 @@ LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \ src/jq_test.c src/jv.c src/jv_alloc.c src/jv_aux.c \ src/jv_dtoa.c src/jv_file.c src/jv_parse.c src/jv_print.c \ src/jv_unicode.c src/linker.c src/locfile.c src/util.c \ + src/decNumber/decContext.c src/decNumber/decNumber.c \ + src/jv_dtoa_tsd.c \ ${LIBJQ_INCS} ### C build options @@ -186,9 +188,13 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \ tests/modules/test_bind_order.jq \ tests/modules/test_bind_order0.jq \ tests/modules/test_bind_order1.jq \ - tests/modules/test_bind_order2.jq tests/onig.supp \ - tests/onig.test tests/optional.test tests/setup \ - tests/torture/input0.json tests/utf8-truncate.jq + tests/modules/test_bind_order2.jq \ + tests/onig.supp tests/local.supp \ + tests/onig.test tests/setup tests/torture/input0.json \ + tests/optional.test tests/optionaltest \ + tests/utf8-truncate.jq tests/utf8test \ + tests/base64.test tests/base64test \ + tests/jq-f-test.sh tests/shtest # README.md is expected in Github projects, good stuff in it, so we'll # distribute it and install it with the package in the doc directory. diff --git a/configure.ac b/configure.ac index 4710269730..2d6bf1cb24 100644 --- a/configure.ac +++ b/configure.ac @@ -136,17 +136,9 @@ AC_CHECK_MEMBER([struct tm.tm_gmtoff], [AC_DEFINE([HAVE_TM_TM_GMT_OFF],1,[Define AC_CHECK_MEMBER([struct tm.__tm_gmtoff], [AC_DEFINE([HAVE_TM___TM_GMT_OFF],1,[Define to 1 if the system has the __tm_gmt_off field in struct tm])], [], [[#include ]]) -AC_ARG_ENABLE([pthread-tls], - [AC_HELP_STRING([--enable-pthread-tls], - [Enable use of pthread thread local storage])], - [], - [enable_pthread_tls=no]) - -if test $enable_pthread_tls = yes; then - AC_FIND_FUNC([pthread_key_create], [pthread], [#include ], [NULL, NULL]) - AC_FIND_FUNC([pthread_once], [pthread], [#include ], [NULL, NULL]) - AC_FIND_FUNC([atexit], [pthread], [#include ], [NULL]) -fi +AC_FIND_FUNC([pthread_key_create], [pthread], [#include ], [NULL, NULL]) +AC_FIND_FUNC([pthread_once], [pthread], [#include ], [NULL, NULL]) +AC_FIND_FUNC([atexit], [pthread], [#include ], [NULL]) dnl libm math.h functions AC_CHECK_MATH_FUNC(acos) diff --git a/docs/content/manual/v1.6/manual.yml b/docs/content/manual/v1.6/manual.yml index b495d1e12f..04e190489a 100644 --- a/docs/content/manual/v1.6/manual.yml +++ b/docs/content/manual/v1.6/manual.yml @@ -292,11 +292,37 @@ sections: program can be a useful way of formatting JSON output from, say, `curl`. + An important point about the identity filter is that it + guarantees to preserve the literal decimal representation + of values. This is particularly important when dealing with numbers + which can't be losslessly converted to an IEEE754 double precision + representation. + + jq doesn't truncate the literal numbers to double unless there + is a need to make arithmetic operations with the number. + Comparisions are carried out over the untruncated big decimal + representation of the number. + + jq will also try to maintain the original decimal precision of the provided + number literal. See below for examples. + examples: - program: '.' input: '"Hello, world!"' output: ['"Hello, world!"'] + - program: '. | tojson' + input: '12345678909876543212345' + output: ['"12345678909876543212345"'] + + - program: 'map([., . == 1]) | tojson' + input: '[1, 1.000, 1.0, 100e-2]' + output: ['"[[1,true],[1.000,true],[1.0,true],[1.00,true]]"'] + + - program: '. as $big | [$big, $big + 1] | map(. > 10000000000000000000000000000000)' + input: '10000000000000000000000000000001' + output: ['[true, false]'] + - title: "Object Identifier-Index: `.foo`, `.foo.bar`" body: | @@ -512,6 +538,16 @@ sections: expression that takes an input, ignores it, and returns 42 instead. + Numbers in jq are internally represented by their IEEE754 double + precision approximation. Any arithmetic operation with numbers, + whether they are literals or results of previous filters, will + produce a double precision floating point result. + + However, when parsing a literal jq will store the original literal + string. If no mutation is applied to this value then it will make + to the output in its original form, even if conversion to double + would result in a loss. + entries: - title: "Array construction: `[]`" body: | @@ -630,6 +666,18 @@ sections: try to add a string to an object you'll get an error message and no result. + Please note that all numbers are converted to IEEE754 double precision + floating point representation. Arithmetic and logical operators are working + with these converted doubles. Results of all such operations are also limited + to the double precision. + + The only exception to this behaviour of number is a snapshot of original number + literal. When a number which originally was provided as a literal is never + mutated until the end of the program then it is printed to the output in its + original literal form. This also includes cases when the original literal + would be truncated when converted to the IEEE754 double precision floating point + number. + entries: - title: "Addition: `+`" body: | diff --git a/src/builtin.c b/src/builtin.c index f52f56e208..b67f9c8d0e 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -90,8 +90,11 @@ static jv f_plus(jq_state *jq, jv input, jv a, jv b) { jv_free(b); return a; } else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) + + jv r = jv_number(jv_number_value(a) + jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) { return jv_string_concat(a, b); } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) { @@ -274,7 +277,10 @@ static jv f_rtrimstr(jq_state *jq, jv input, jv right) { static jv f_minus(jq_state *jq, jv input, jv a, jv b) { jv_free(input); if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) - jv_number_value(b)); + jv r = jv_number(jv_number_value(a) - jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) { jv out = jv_array(); jv_array_foreach(a, i, x) { @@ -302,7 +308,10 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) { jv_kind bk = jv_get_kind(b); jv_free(input); if (ak == JV_KIND_NUMBER && bk == JV_KIND_NUMBER) { - return jv_number(jv_number_value(a) * jv_number_value(b)); + jv r = jv_number(jv_number_value(a) * jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if ((ak == JV_KIND_STRING && bk == JV_KIND_NUMBER) || (ak == JV_KIND_NUMBER && bk == JV_KIND_STRING)) { jv str = a; @@ -336,7 +345,10 @@ static jv f_divide(jq_state *jq, jv input, jv a, jv b) { if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { if (jv_number_value(b) == 0.0) return type_error2(a, b, "cannot be divided because the divisor is zero"); - return jv_number(jv_number_value(a) / jv_number_value(b)); + jv r = jv_number(jv_number_value(a) / jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) { return jv_string_split(a, b); } else { @@ -349,7 +361,10 @@ static jv f_mod(jq_state *jq, jv input, jv a, jv b) { if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { if ((intmax_t)jv_number_value(b) == 0) return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero"); - return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b)); + jv r = jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b)); + jv_free(a); + jv_free(b); + return r; } else { return type_error2(a, b, "cannot be divided (remainder)"); } @@ -440,7 +455,9 @@ static jv f_length(jq_state *jq, jv input) { } else if (jv_get_kind(input) == JV_KIND_STRING) { return jv_number(jv_string_length_codepoints(input)); } else if (jv_get_kind(input) == JV_KIND_NUMBER) { - return jv_number(fabs(jv_number_value(input))); + jv r = jv_number(fabs(jv_number_value(input))); + jv_free(input); + return r; } else if (jv_get_kind(input) == JV_KIND_NULL) { jv_free(input); return jv_number(0); diff --git a/src/execute.c b/src/execute.c index 65c6bc7766..fd2ab2c7be 100644 --- a/src/execute.c +++ b/src/execute.c @@ -509,21 +509,25 @@ jv jq_next(jq_state *jq) { uint16_t v = *pc++; jv* var = frame_local_var(jq, v, level); jv max = stack_pop(jq); - if (raising) goto do_backtrack; + if (raising) { + jv_free(max); + goto do_backtrack; + } if (jv_get_kind(*var) != JV_KIND_NUMBER || jv_get_kind(max) != JV_KIND_NUMBER) { set_error(jq, jv_invalid_with_msg(jv_string_fmt("Range bounds must be numeric"))); jv_free(max); goto do_backtrack; - } else if (jv_number_value(jv_copy(*var)) >= jv_number_value(jv_copy(max))) { + } else if (jv_number_value(*var) >= jv_number_value(max)) { /* finished iterating */ + jv_free(max); goto do_backtrack; } else { - jv curr = jv_copy(*var); + jv curr = *var; *var = jv_number(jv_number_value(*var) + 1); struct stack_pos spos = stack_get_pos(jq); - stack_push(jq, jv_copy(max)); + stack_push(jq, max); stack_save(jq, pc - 3, spos); stack_push(jq, curr); @@ -1010,6 +1014,9 @@ jq_state *jq_init(void) { jq->attrs = jv_object(); jq->path = jv_null(); jq->value_at_path = jv_null(); + + jq->nomem_handler = NULL; + jq->nomem_handler_data = NULL; return jq; } diff --git a/src/jq_test.c b/src/jq_test.c index 7a396b9435..2b40d4d6f3 100644 --- a/src/jq_test.c +++ b/src/jq_test.c @@ -6,20 +6,32 @@ #include "jq.h" static void jv_test(); -static void run_jq_tests(jv, int, FILE *); +static void run_jq_tests(jv, int, FILE *, int, int); int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) { FILE *testdata = stdin; + int skip = -1; + int take = -1; jv_test(); if (argc > 0) { - testdata = fopen(argv[0], "r"); - if (!testdata) { - perror("fopen"); - exit(1); + for(int i = 0; i < argc; i++) { + if (!strcmp(argv[i], "--skip")) { + skip = atoi(argv[i+1]); + i++; + } else if (!strcmp(argv[i], "--take")) { + take = atoi(argv[i+1]); + i++; + } else { + testdata = fopen(argv[i], "r"); + if (!testdata) { + perror("fopen"); + exit(1); + } + } } } - run_jq_tests(libdirs, verbose, testdata); + run_jq_tests(libdirs, verbose, testdata, skip, take); return 0; } @@ -53,7 +65,7 @@ static void test_err_cb(void *data, jv e) { jv_free(e); } -static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { +static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata, int skip, int take) { char prog[4096]; char buf[4096]; struct err_data err_msg; @@ -63,6 +75,9 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { int check_msg = 0; jq_state *jq = NULL; + int tests_to_skip = skip; + int tests_to_take = take; + jq = jq_init(); assert(jq); if (jv_get_kind(lib_dirs) == JV_KIND_NULL) @@ -80,6 +95,34 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { continue; } if (prog[strlen(prog)-1] == '\n') prog[strlen(prog)-1] = 0; + + if (skip > 0) { + skip--; + + // skip past test data + while (fgets(buf, sizeof(buf), testdata)) { + lineno++; + if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) + break; + } + + must_fail = 0; + check_msg = 0; + + continue; + } else if (skip == 0) { + printf("Skipped %d tests\n", tests_to_skip); + skip = -1; + } + + if (take > 0) { + take--; + } else if (take == 0) { + printf("Hit the number of tests limit (%d), breaking\n", tests_to_take); + take = -1; + break; + } + printf("Testing '%s' at line number %u\n", prog, lineno); int pass = 1; tests++; @@ -179,7 +222,21 @@ static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) { passed+=pass; } jq_teardown(&jq); - printf("%d of %d tests passed (%d malformed)\n", passed,tests,invalid); + + int total_skipped = tests_to_skip > 0 ? tests_to_skip : 0; + + if (skip > 0) { + total_skipped = tests_to_skip - skip; + } + + printf("%d of %d tests passed (%d malformed, %d skipped)\n", + passed, tests, invalid, total_skipped); + + if (skip > 0) { + printf("WARN: skipped past the end of file, exiting with status 2\n"); + exit(2); + } + if (passed != tests) exit(1); } diff --git a/src/jv.c b/src/jv.c index 2f87bab58a..d9799933f7 100644 --- a/src/jv.c +++ b/src/jv.c @@ -14,6 +14,15 @@ #include "jv_unicode.h" #include "util.h" +#include "jv_dtoa.h" +#include "jv_dtoa_tsd.h" + +// this means that we will manage the space for the struct +#define DECNUMDIGITS 1 +#include "decNumber/decNumber.h" + +#include "jv_type_private.h" + /* * Internal refcounting helpers */ @@ -38,14 +47,33 @@ static int jvp_refcnt_unshared(jv_refcnt* c) { return c->count == 1; } -/* - * Simple values (true, false, null) - */ +#define KIND_MASK 0xF +#define PFLAGS_MASK 0xF0 +#define PTYPE_MASK 0x70 + +typedef enum { + JVP_PAYLOAD_NONE = 0, + JVP_PAYLOAD_ALLOCATED = 0x80, +} payload_flags; + +#define JVP_MAKE_PFLAGS(ptype, allocated) ((((ptype) << 4) & PTYPE_MASK) | ((allocated) ? JVP_PAYLOAD_ALLOCATED : 0)) +#define JVP_MAKE_FLAGS(kind, pflags) ((kind & KIND_MASK) | (pflags & PFLAGS_MASK)) + +#define JVP_FLAGS(j) ((j).kind_flags) +#define JVP_KIND(j) (JVP_FLAGS(j) & KIND_MASK) -#define KIND_MASK 0xf +#define JVP_HAS_FLAGS(j, flags) (JVP_FLAGS(j) == flags) +#define JVP_HAS_KIND(j, kind) (JVP_KIND(j) == kind) + +#define JVP_IS_ALLOCATED(j) (j.kind_flags & JVP_PAYLOAD_ALLOCATED) + +#define JVP_FLAGS_NULL JVP_MAKE_FLAGS(JV_KIND_NULL, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_INVALID JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_FALSE JVP_MAKE_FLAGS(JV_KIND_FALSE, JVP_PAYLOAD_NONE) +#define JVP_FLAGS_TRUE JVP_MAKE_FLAGS(JV_KIND_TRUE, JVP_PAYLOAD_NONE) jv_kind jv_get_kind(jv x) { - return x.kind_flags & KIND_MASK; + return JVP_KIND(x); } const char* jv_kind_name(jv_kind k) { @@ -63,10 +91,10 @@ const char* jv_kind_name(jv_kind k) { return ""; } -static const jv JV_NULL = {JV_KIND_NULL, 0, 0, 0, {0}}; -static const jv JV_INVALID = {JV_KIND_INVALID, 0, 0, 0, {0}}; -static const jv JV_FALSE = {JV_KIND_FALSE, 0, 0, 0, {0}}; -static const jv JV_TRUE = {JV_KIND_TRUE, 0, 0, 0, {0}}; +const jv JV_NULL = {JVP_FLAGS_NULL, 0, 0, 0, {0}}; +const jv JV_INVALID = {JVP_FLAGS_INVALID, 0, 0, 0, {0}}; +const jv JV_FALSE = {JVP_FLAGS_FALSE, 0, 0, 0, {0}}; +const jv JV_TRUE = {JVP_FLAGS_TRUE, 0, 0, 0, {0}}; jv jv_true() { return JV_TRUE; @@ -88,19 +116,21 @@ jv jv_bool(int x) { * Invalid objects, with optional error messages */ +#define JVP_FLAGS_INVALID_MSG JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_ALLOCATED) + typedef struct { jv_refcnt refcnt; jv errmsg; } jvp_invalid; jv jv_invalid_with_msg(jv err) { - if (jv_get_kind(err) == JV_KIND_NULL) + if (JVP_HAS_KIND(err, JV_KIND_NULL)) return JV_INVALID; jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid)); i->refcnt = JV_REFCNT_INIT; i->errmsg = err; - jv x = {JV_KIND_INVALID, 0, 0, 0, {&i->refcnt}}; + jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, {&i->refcnt}}; return x; } @@ -109,26 +139,30 @@ jv jv_invalid() { } jv jv_invalid_get_msg(jv inv) { - assert(jv_get_kind(inv) == JV_KIND_INVALID); + assert(JVP_HAS_KIND(inv, JV_KIND_INVALID)); + jv x; - if (inv.u.ptr == 0) - x = jv_null(); - else + if (JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG)) { x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg); + } + else { + x = jv_null(); + } + jv_free(inv); return x; } int jv_invalid_has_msg(jv inv) { - jv msg = jv_invalid_get_msg(inv); - int r = jv_get_kind(msg) != JV_KIND_NULL; - jv_free(msg); + assert(JVP_HAS_KIND(inv, JV_KIND_INVALID)); + int r = JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG); + jv_free(inv); return r; } static void jvp_invalid_free(jv x) { - assert(jv_get_kind(x) == JV_KIND_INVALID); - if (x.u.ptr != 0 && jvp_refcnt_dec(x.u.ptr)) { + assert(JVP_HAS_KIND(x, JV_KIND_INVALID)); + if (JVP_HAS_FLAGS(x, JVP_FLAGS_INVALID_MSG) && jvp_refcnt_dec(x.u.ptr)) { jv_free(((jvp_invalid*)x.u.ptr)->errmsg); jv_mem_free(x.u.ptr); } @@ -138,20 +172,265 @@ static void jvp_invalid_free(jv x) { * Numbers */ +enum { + JVP_NUMBER_NATIVE = 0, + JVP_NUMBER_DECIMAL = 1 +}; + +#define JV_NUMBER_SIZE_INIT (0) +#define JV_NUMBER_SIZE_CONVERTED (1) + +#define JVP_FLAGS_NUMBER_NATIVE JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0)) +#define JVP_FLAGS_NUMBER_NATIVE_STR JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 1)) +#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1)) + +#define STR(x) #x +#define XSTR(x) STR(x) +#define DBL_MAX_STR XSTR(DBL_MAX) +#define DBL_MIN_STR "-" XSTR(DBL_MAX) + +// the decimal precision of binary double +#define BIN64_DEC_PRECISION (17) +#define DEC_NUMBER_STRING_GUARD (14) + +#include + +static pthread_key_t dec_ctx_key; +static pthread_key_t dec_ctx_dbl_key; +static pthread_once_t dec_ctx_once = PTHREAD_ONCE_INIT; + +#define DEC_CONTEXT() tsd_dec_ctx_get(&dec_ctx_key) +#define DEC_CONTEXT_TO_DOUBLE() tsd_dec_ctx_get(&dec_ctx_dbl_key) + +// atexit finalizer to clean up the tsd dec contexts if main() exits +// without having called pthread_exit() +static void tsd_dec_ctx_fini() { + jv_mem_free(pthread_getspecific(dec_ctx_key)); + jv_mem_free(pthread_getspecific(dec_ctx_dbl_key)); + pthread_setspecific(dec_ctx_key, NULL); + pthread_setspecific(dec_ctx_dbl_key, NULL); +} + +static void tsd_dec_ctx_init() { + if (pthread_key_create(&dec_ctx_key, jv_mem_free) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + if (pthread_key_create(&dec_ctx_dbl_key, jv_mem_free) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + atexit(tsd_dec_ctx_fini); +} + +static decContext* tsd_dec_ctx_get(pthread_key_t *key) { + pthread_once(&dec_ctx_once, tsd_dec_ctx_init); // cannot fail + decContext *ctx = (decContext*)pthread_getspecific(*key); + if (ctx) { + return ctx; + } + + decContext _ctx = { + 0, + DEC_MAX_EMAX, + DEC_MIN_EMAX, + DEC_ROUND_HALF_UP, + 0, /*no errors*/ + 0, /*status*/ + 0, /*no clamping*/ + }; + if (key == &dec_ctx_key) { + _ctx.digits = DEC_MAX_DIGITS; + } else if (key == &dec_ctx_dbl_key) { + _ctx.digits = BIN64_DEC_PRECISION; + } + + ctx = malloc(sizeof(decContext)); + if (ctx) { + *ctx = _ctx; + if (pthread_setspecific(*key, ctx) != 0) { + fprintf(stderr, "error: cannot store thread specific data"); + abort(); + } + } + return ctx; +} + +typedef struct { + jv_refcnt refcnt; + double num_double; + char * literal_data; + decNumber num_decimal; // must be the last field in the structure for memory management +} jvp_literal_number; + +typedef struct { + decNumber number; + decNumberUnit units[1]; +} decNumberSingle; + +typedef struct { + decNumber number; + decNumberUnit units[BIN64_DEC_PRECISION]; +} decNumberDoublePrecision; + + +static inline int jvp_number_is_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL); +} + +static jvp_literal_number* jvp_literal_number_ptr(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + return (jvp_literal_number*)j.u.ptr; +} + +static decNumber* jvp_dec_number_ptr(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + return &(((jvp_literal_number*)j.u.ptr)->num_decimal); +} + +static jvp_literal_number* jvp_literal_number_alloc(unsigned literal_length) { + + /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */ + int units = ((literal_length+DECDPUN-1)/DECDPUN); + + jvp_literal_number* n = jv_mem_alloc( + sizeof(jvp_literal_number) + + sizeof(decNumberUnit) * units + ); + + return n; +} + +static jv jvp_literal_number_new(const char * literal) { + + jvp_literal_number * n = jvp_literal_number_alloc(strlen(literal)); + + n->refcnt = JV_REFCNT_INIT; + n->literal_data = NULL; + decContext *ctx = DEC_CONTEXT(); + decNumberFromString(&n->num_decimal, literal, ctx); + n->num_double = NAN; + + if (ctx->status & DEC_Conversion_syntax) { + jv_mem_free(n); + return JV_INVALID; + } + + jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, JV_NUMBER_SIZE_INIT, {&n->refcnt}}; + return r; +} + +static double jvp_literal_number_to_double(jv j) { + assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)); + + decNumber *p_dec_number = jvp_dec_number_ptr(j); + decNumberDoublePrecision dec_double; + char literal[BIN64_DEC_PRECISION + DEC_NUMBER_STRING_GUARD + 1]; + + // reduce the number to the shortest possible form + // while also making sure than no more than BIN64_DEC_PRECISION + // digits are used (dec_context_to_double) + decNumberReduce(&dec_double.number, p_dec_number, DEC_CONTEXT_TO_DOUBLE()); + + decNumberToString(&dec_double.number, literal); + + char *end; + return jvp_strtod(tsd_dtoa_context_get(), literal, &end); +} + + +static int jvp_number_equal(jv a, jv b) { + return jvp_number_cmp(a, b) == 0; +} + +static const char* jvp_literal_number_literal(jv n) { + assert(JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)); + decNumber *pdec = jvp_dec_number_ptr(n); + jvp_literal_number* plit = jvp_literal_number_ptr(n); + + if (decNumberIsNaN(pdec)) { + return "null"; + } + + if (decNumberIsInfinite(pdec)) { + // For backward compatibiltiy. + if (decNumberIsNegative(pdec)) { + return DBL_MIN_STR; + } else { + return DBL_MAX_STR; + } + } + + if (plit->literal_data == NULL) { + int len = jvp_dec_number_ptr(n)->digits + 14; + plit->literal_data = jv_mem_alloc(len); + + // Preserve the actual precision as we have parsed it + // don't do decNumberTrim(pdec); + + decNumberToString(pdec, plit->literal_data); + } + + return plit->literal_data; +} + +int jv_number_has_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL); +} + +const char* jv_number_get_literal(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + + if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) { + return jvp_literal_number_literal(n); + } else { + return NULL; + } +} + +static void jvp_number_free(jv j) { + assert(JVP_HAS_KIND(j, JV_KIND_NUMBER)); + if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL) && jvp_refcnt_dec(j.u.ptr)) { + jvp_literal_number* n = jvp_literal_number_ptr(j); + if (n->literal_data) { + jv_mem_free(n->literal_data); + } + jv_mem_free(n); + } +} + +jv jv_number_with_literal(const char * literal) { + return jvp_literal_number_new(literal); +} + jv jv_number(double x) { - jv j = {JV_KIND_NUMBER, 0, 0, 0, {.number = x}}; + jv j = {JVP_FLAGS_NUMBER_NATIVE, 0, 0, 0, {.number = x}}; return j; } double jv_number_value(jv j) { - assert(jv_get_kind(j) == JV_KIND_NUMBER); - return j.u.number; + assert(JVP_HAS_KIND(j, JV_KIND_NUMBER)); + if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) { + jvp_literal_number* n = jvp_literal_number_ptr(j); + + if (j.size != JV_NUMBER_SIZE_CONVERTED) { + n->num_double = jvp_literal_number_to_double(j); + j.size = JV_NUMBER_SIZE_CONVERTED; + } + + return n->num_double; + } else { + return j.u.number; + } } int jv_is_integer(jv j){ - if(jv_get_kind(j) != JV_KIND_NUMBER){ + if(!JVP_HAS_KIND(j, JV_KIND_NUMBER)){ return 0; } + double x = jv_number_value(j); double ipart; @@ -160,11 +439,53 @@ int jv_is_integer(jv j){ return fabs(fpart) < DBL_EPSILON; } +int jvp_number_is_nan(jv n) { + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); + + if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) { + decNumber *pdec = jvp_dec_number_ptr(n); + return decNumberIsNaN(pdec); + } else { + return n.u.number != n.u.number; + } +} + +int jvp_number_cmp(jv a, jv b) { + assert(JVP_HAS_KIND(a, JV_KIND_NUMBER)); + assert(JVP_HAS_KIND(b, JV_KIND_NUMBER)); + + if(JVP_HAS_FLAGS(a, JVP_FLAGS_NUMBER_LITERAL) && JVP_HAS_FLAGS(b, JVP_FLAGS_NUMBER_LITERAL)) { + decNumberSingle res; + decNumberCompare(&res.number, + jvp_dec_number_ptr(a), + jvp_dec_number_ptr(b), + DEC_CONTEXT() + ); + if (decNumberIsZero(&res.number)) { + return 0; + } else if (decNumberIsNegative(&res.number)) { + return -1; + } else { + return 1; + } + } else { + double da = jv_number_value(a), db = jv_number_value(b); + if (da < db) { + return -1; + } else if (da == db) { + return 0; + } else { + return 1; + } + } +} + /* * Arrays (internal helpers) */ #define ARRAY_SIZE_ROUND_UP(n) (((n)*3)/2) +#define JVP_FLAGS_ARRAY JVP_MAKE_FLAGS(JV_KIND_ARRAY, JVP_PAYLOAD_ALLOCATED) static int imax(int a, int b) { if (a>b) return a; @@ -179,7 +500,7 @@ typedef struct { } jvp_array; static jvp_array* jvp_array_ptr(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return (jvp_array*)a.u.ptr; } @@ -192,12 +513,12 @@ static jvp_array* jvp_array_alloc(unsigned size) { } static jv jvp_array_new(unsigned size) { - jv r = {JV_KIND_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; + jv r = {JVP_FLAGS_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}}; return r; } static void jvp_array_free(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); if (jvp_refcnt_dec(a.u.ptr)) { jvp_array* array = jvp_array_ptr(a); for (int i=0; ilength; i++) { @@ -208,17 +529,17 @@ static void jvp_array_free(jv a) { } static int jvp_array_length(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return a.size; } static int jvp_array_offset(jv a) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); return a.offset; } static jv* jvp_array_read(jv a, int i) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); if (i >= 0 && i < jvp_array_length(a)) { jvp_array* array = jvp_array_ptr(a); assert(i + jvp_array_offset(a) < array->length); @@ -255,7 +576,7 @@ static jv* jvp_array_write(jv* a, int i) { } new_array->length = new_length; jvp_array_free(*a); - jv new_jv = {JV_KIND_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; + jv new_jv = {JVP_FLAGS_ARRAY, 0, 0, new_length, {&new_array->refcnt}}; *a = new_jv; return &new_array->elements[i]; } @@ -286,8 +607,33 @@ static void jvp_clamp_slice_params(int len, int *pstart, int *pend) if (*pend < *pstart) *pend = *pstart; } + +static int jvp_array_contains(jv a, jv b) { + int r = 1; + jv_array_foreach(b, bi, belem) { + int ri = 0; + jv_array_foreach(a, ai, aelem) { + if (jv_contains(aelem, jv_copy(belem))) { + ri = 1; + break; + } + } + jv_free(belem); + if (!ri) { + r = 0; + break; + } + } + return r; +} + + +/* + * Public + */ + static jv jvp_array_slice(jv a, int start, int end) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); int len = jvp_array_length(a); jvp_clamp_slice_params(len, &start, &end); assert(0 <= start && start <= end && end <= len); @@ -324,14 +670,14 @@ jv jv_array() { } int jv_array_length(jv j) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); int len = jvp_array_length(j); jv_free(j); return len; } jv jv_array_get(jv j, int idx) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); jv* slot = jvp_array_read(j, idx); jv val; if (slot) { @@ -344,7 +690,7 @@ jv jv_array_get(jv j, int idx) { } jv jv_array_set(jv j, int idx, jv val) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); if (idx < 0) idx = jvp_array_length(j) + idx; @@ -366,8 +712,8 @@ jv jv_array_append(jv j, jv val) { } jv jv_array_concat(jv a, jv b) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); - assert(jv_get_kind(b) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); + assert(JVP_HAS_KIND(b, JV_KIND_ARRAY)); // FIXME: could be faster jv_array_foreach(b, i, elem) { @@ -378,44 +724,22 @@ jv jv_array_concat(jv a, jv b) { } jv jv_array_slice(jv a, int start, int end) { - assert(jv_get_kind(a) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(a, JV_KIND_ARRAY)); // copy/free of a coalesced return jvp_array_slice(a, start, end); } -int jv_array_contains(jv a, jv b) { - int r = 1; - jv_array_foreach(b, bi, belem) { - int ri = 0; - jv_array_foreach(a, ai, aelem) { - if (jv_contains(aelem, jv_copy(belem))) { - ri = 1; - break; - } - } - jv_free(belem); - if (!ri) { - r = 0; - break; - } - } - jv_free(a); - jv_free(b); - return r; -} - jv jv_array_indexes(jv a, jv b) { jv res = jv_array(); int idx = -1; jv_array_foreach(a, ai, aelem) { + jv_free(aelem); jv_array_foreach(b, bi, belem) { - // quieten compiler warnings about aelem not being used... by - // using it - if ((bi == 0 && !jv_equal(jv_copy(aelem), jv_copy(belem))) || - (bi > 0 && !jv_equal(jv_array_get(jv_copy(a), ai + bi), jv_copy(belem)))) + if (!jv_equal(jv_array_get(jv_copy(a), ai + bi), jv_copy(belem))) idx = -1; else if (bi == 0 && idx == -1) idx = ai; + jv_free(belem); } if (idx > -1) res = jv_array_append(res, jv_number(idx)); @@ -426,11 +750,12 @@ jv jv_array_indexes(jv a, jv b) { return res; } - /* * Strings (internal helpers) */ +#define JVP_FLAGS_STRING JVP_MAKE_FLAGS(JV_KIND_STRING, JVP_PAYLOAD_ALLOCATED) + typedef struct { jv_refcnt refcnt; uint32_t hash; @@ -442,7 +767,7 @@ typedef struct { } jvp_string; static jvp_string* jvp_string_ptr(jv a) { - assert(jv_get_kind(a) == JV_KIND_STRING); + assert(JVP_HAS_KIND(a, JV_KIND_STRING)); return (jvp_string*)a.u.ptr; } @@ -474,7 +799,7 @@ static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) { length = out - s->data; s->data[length] = 0; s->length_hashed = length << 1; - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -485,7 +810,7 @@ static jv jvp_string_new(const char* data, uint32_t length) { if (data != NULL) memcpy(s->data, data, length); s->data[length] = 0; - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -493,7 +818,7 @@ static jv jvp_string_empty_new(uint32_t length) { jvp_string* s = jvp_string_alloc(length); s->length_hashed = 0; memset(s->data, 0, length); - jv r = {JV_KIND_STRING, 0, 0, 0, {&s->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}}; return r; } @@ -536,7 +861,7 @@ static jv jvp_string_append(jv string, const char* data, uint32_t len) { memcpy(news->data + currlen, data, len); news->data[currlen + len] = 0; jvp_string_free(string); - jv r = {JV_KIND_STRING, 0, 0, 0, {&news->refcnt}}; + jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&news->refcnt}}; return r; } } @@ -603,9 +928,10 @@ static uint32_t jvp_string_hash(jv jstr) { return h1; } + static int jvp_string_equal(jv a, jv b) { - assert(jv_get_kind(a) == JV_KIND_STRING); - assert(jv_get_kind(b) == JV_KIND_STRING); + assert(JVP_HAS_KIND(a, JV_KIND_STRING)); + assert(JVP_HAS_KIND(b, JV_KIND_STRING)); jvp_string* stra = jvp_string_ptr(a); jvp_string* strb = jvp_string_ptr(b); if (jvp_string_length(stra) != jvp_string_length(strb)) return 0; @@ -632,14 +958,14 @@ jv jv_string(const char* str) { } int jv_string_length_bytes(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); int r = jvp_string_length(jvp_string_ptr(j)); jv_free(j); return r; } int jv_string_length_codepoints(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char* i = jv_string_value(j); const char* end = i + jv_string_length_bytes(jv_copy(j)); int c = 0, len = 0; @@ -650,8 +976,8 @@ int jv_string_length_codepoints(jv j) { jv jv_string_indexes(jv j, jv k) { - assert(jv_get_kind(j) == JV_KIND_STRING); - assert(jv_get_kind(k) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); + assert(JVP_HAS_KIND(k, JV_KIND_STRING)); const char *jstr = jv_string_value(j); const char *idxstr = jv_string_value(k); const char *p; @@ -672,8 +998,8 @@ jv jv_string_indexes(jv j, jv k) { } jv jv_string_split(jv j, jv sep) { - assert(jv_get_kind(j) == JV_KIND_STRING); - assert(jv_get_kind(sep) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); + assert(JVP_HAS_KIND(sep, JV_KIND_STRING)); const char *jstr = jv_string_value(j); const char *jend = jstr + jv_string_length_bytes(jv_copy(j)); const char *sepstr = jv_string_value(sep); @@ -704,7 +1030,7 @@ jv jv_string_split(jv j, jv sep) { } jv jv_string_explode(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char* i = jv_string_value(j); int len = jv_string_length_bytes(jv_copy(j)); const char* end = i + len; @@ -717,7 +1043,7 @@ jv jv_string_explode(jv j) { } jv jv_string_implode(jv j) { - assert(jv_get_kind(j) == JV_KIND_ARRAY); + assert(JVP_HAS_KIND(j, JV_KIND_ARRAY)); int len = jv_array_length(jv_copy(j)); jv s = jv_string_empty(len); int i; @@ -726,8 +1052,9 @@ jv jv_string_implode(jv j) { for (i = 0; i < len; i++) { jv n = jv_array_get(jv_copy(j), i); - assert(jv_get_kind(n) == JV_KIND_NUMBER); + assert(JVP_HAS_KIND(n, JV_KIND_NUMBER)); int nv = jv_number_value(n); + jv_free(n); if (nv > 0x10FFFF) nv = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER s = jv_string_append_codepoint(s, nv); @@ -738,19 +1065,19 @@ jv jv_string_implode(jv j) { } unsigned long jv_string_hash(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); uint32_t hash = jvp_string_hash(j); jv_free(j); return hash; } const char* jv_string_value(jv j) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); return jvp_string_ptr(j)->data; } jv jv_string_slice(jv j, int start, int end) { - assert(jv_get_kind(j) == JV_KIND_STRING); + assert(JVP_HAS_KIND(j, JV_KIND_STRING)); const char *s = jv_string_value(j); int len = jv_string_length_bytes(jv_copy(j)); int i; @@ -861,6 +1188,8 @@ jv jv_string_fmt(const char* fmt, ...) { * Objects (internal helpers) */ +#define JVP_FLAGS_OBJECT JVP_MAKE_FLAGS(JV_KIND_OBJECT, JVP_PAYLOAD_ALLOCATED) + struct object_slot { int next; /* next slot with same hash, for collisions */ uint32_t hash; @@ -897,22 +1226,22 @@ static jv jvp_object_new(int size) { for (int i=0; irefcnt}}; + jv r = {JVP_FLAGS_OBJECT, 0, 0, size, {&obj->refcnt}}; return r; } static jvp_object* jvp_object_ptr(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return (jvp_object*)o.u.ptr; } static uint32_t jvp_object_mask(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return (o.size * 2) - 1; } static int jvp_object_size(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); return o.size; } @@ -960,7 +1289,7 @@ static struct object_slot* jvp_object_add_slot(jv object, jv key, int* bucket) { } static jv* jvp_object_read(jv object, jv key) { - assert(jv_get_kind(key) == JV_KIND_STRING); + assert(JVP_HAS_KIND(key, JV_KIND_STRING)); int* bucket = jvp_object_find_bucket(object, key); struct object_slot* slot = jvp_object_find_slot(object, key, bucket); if (slot == 0) return 0; @@ -968,7 +1297,7 @@ static jv* jvp_object_read(jv object, jv key) { } static void jvp_object_free(jv o) { - assert(jv_get_kind(o) == JV_KIND_OBJECT); + assert(JVP_HAS_KIND(o, JV_KIND_OBJECT)); if (jvp_refcnt_dec(o.u.ptr)) { for (int i=0; istring; - assert(jv_get_kind(s) == JV_KIND_STRING); + assert(JVP_HAS_KIND(s, JV_KIND_STRING)); return jv_copy(s); } @@ -1243,34 +1569,36 @@ jv jv_object_iter_value(jv object, int iter) { * Memory management */ jv jv_copy(jv j) { - if (jv_get_kind(j) == JV_KIND_ARRAY || - jv_get_kind(j) == JV_KIND_STRING || - jv_get_kind(j) == JV_KIND_OBJECT || - (jv_get_kind(j) == JV_KIND_INVALID && j.u.ptr != 0)) { + if (JVP_IS_ALLOCATED(j)) { jvp_refcnt_inc(j.u.ptr); } return j; } void jv_free(jv j) { - if (jv_get_kind(j) == JV_KIND_ARRAY) { - jvp_array_free(j); - } else if (jv_get_kind(j) == JV_KIND_STRING) { - jvp_string_free(j); - } else if (jv_get_kind(j) == JV_KIND_OBJECT) { - jvp_object_free(j); - } else if (jv_get_kind(j) == JV_KIND_INVALID) { - jvp_invalid_free(j); + switch(JVP_KIND(j)) { + case JV_KIND_ARRAY: + jvp_array_free(j); + break; + case JV_KIND_STRING: + jvp_string_free(j); + break; + case JV_KIND_OBJECT: + jvp_object_free(j); + break; + case JV_KIND_INVALID: + jvp_invalid_free(j); + break; + case JV_KIND_NUMBER: + jvp_number_free(j); + break; } } int jv_get_refcnt(jv j) { - switch (jv_get_kind(j)) { - case JV_KIND_ARRAY: - case JV_KIND_STRING: - case JV_KIND_OBJECT: + if (JVP_IS_ALLOCATED(j)) { return j.u.ptr->count; - default: + } else { return 1; } } @@ -1283,14 +1611,17 @@ int jv_equal(jv a, jv b) { int r; if (jv_get_kind(a) != jv_get_kind(b)) { r = 0; - } else if (jv_get_kind(a) == JV_KIND_NUMBER) { - r = jv_number_value(a) == jv_number_value(b); - } else if (a.kind_flags == b.kind_flags && + } else if (JVP_IS_ALLOCATED(a) && + JVP_IS_ALLOCATED(b) && + a.kind_flags == b.kind_flags && a.size == b.size && a.u.ptr == b.u.ptr) { r = 1; } else { switch (jv_get_kind(a)) { + case JV_KIND_NUMBER: + r = jvp_number_equal(a, b); + break; case JV_KIND_ARRAY: r = jvp_array_equal(a, b); break; @@ -1317,18 +1648,10 @@ int jv_identical(jv a, jv b) { || a.size != b.size) { r = 0; } else { - switch (jv_get_kind(a)) { - case JV_KIND_ARRAY: - case JV_KIND_STRING: - case JV_KIND_OBJECT: + if (JVP_IS_ALLOCATED(a) /* b has the same flags */) { r = a.u.ptr == b.u.ptr; - break; - case JV_KIND_NUMBER: - r = memcmp(&a.u.number, &b.u.number, sizeof(a.u.number)) == 0; - break; - default: - r = 1; - break; + } else { + r = memcmp(&a.u.ptr, &b.u.ptr, sizeof(a.u)) == 0; } } jv_free(a); @@ -1340,11 +1663,11 @@ int jv_contains(jv a, jv b) { int r = 1; if (jv_get_kind(a) != jv_get_kind(b)) { r = 0; - } else if (jv_get_kind(a) == JV_KIND_OBJECT) { - r = jv_object_contains(jv_copy(a), jv_copy(b)); - } else if (jv_get_kind(a) == JV_KIND_ARRAY) { - r = jv_array_contains(jv_copy(a), jv_copy(b)); - } else if (jv_get_kind(a) == JV_KIND_STRING) { + } else if (JVP_HAS_KIND(a, JV_KIND_OBJECT)) { + r = jvp_object_contains(a, b); + } else if (JVP_HAS_KIND(a, JV_KIND_ARRAY)) { + r = jvp_array_contains(a, b); + } else if (JVP_HAS_KIND(a, JV_KIND_STRING)) { int b_len = jv_string_length_bytes(jv_copy(b)); if (b_len != 0) { r = _jq_memmem(jv_string_value(a), jv_string_length_bytes(jv_copy(a)), diff --git a/src/jv.h b/src/jv.h index d111c80b29..8c96f822f0 100644 --- a/src/jv.h +++ b/src/jv.h @@ -54,16 +54,19 @@ jv jv_invalid_with_msg(jv); jv jv_invalid_get_msg(jv); int jv_invalid_has_msg(jv); - jv jv_null(void); jv jv_true(void); jv jv_false(void); jv jv_bool(int); jv jv_number(double); +jv jv_number_with_literal(const char*); double jv_number_value(jv); int jv_is_integer(jv); +int jv_number_has_literal(jv n); +const char* jv_number_get_literal(jv); + jv jv_array(void); jv jv_array_sized(int); int jv_array_length(jv); diff --git a/src/jv_aux.c b/src/jv_aux.c index 129cd043d1..eca2345fec 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -2,6 +2,16 @@ #include #include #include "jv_alloc.h" +#include "jv_type_private.h" + +// making this static verbose function here +// until we introduce a less confusing naming scheme +// of jv_* API with regards to the memory management +static double jv_number_get_value_and_consume(jv number) { + double value = jv_number_value(number); + jv_free(number); + return value; +} static int parse_slice(jv j, jv slice, int* pstart, int* pend) { // Array slices @@ -32,6 +42,8 @@ static int parse_slice(jv j, jv slice, int* pstart, int* pend) { } else { double dstart = jv_number_value(start_jv); double dend = jv_number_value(end_jv); + jv_free(start_jv); + jv_free(end_jv); if (dstart < 0) dstart += len; if (dend < 0) dend += len; if (dstart < 0) dstart = 0; @@ -69,6 +81,7 @@ jv jv_get(jv t, jv k) { jv_free(v); v = jv_null(); } + jv_free(k); } else { jv_free(t); jv_free(k); @@ -135,6 +148,7 @@ jv jv_set(jv t, jv k, jv v) { (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) { if (isnull) t = jv_array(); t = jv_array_set(t, (int)jv_number_value(k), v); + jv_free(k); } else if (jv_get_kind(k) == JV_KIND_OBJECT && (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) { if (isnull) t = jv_array(); @@ -202,6 +216,7 @@ jv jv_has(jv t, jv k) { jv_get_kind(k) == JV_KIND_NUMBER) { jv elem = jv_array_get(t, (int)jv_number_value(k)); ret = jv_bool(jv_is_valid(elem)); + jv_free(k); jv_free(elem); } else { ret = jv_invalid_with_msg(jv_string_fmt("Cannot check whether %s has a %s key", @@ -240,6 +255,7 @@ static jv jv_dels(jv t, jv keys) { ends = jv_array_append(ends, jv_number(end)); } else { jv_free(new_array); + jv_free(key); new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers")); goto arr_out; } @@ -258,7 +274,7 @@ static jv jv_dels(jv t, jv keys) { jv_array_foreach(t, i, elem) { int del = 0; while (neg_idx < jv_array_length(jv_copy(neg_keys))) { - int delidx = len + (int)jv_number_value(jv_array_get(jv_copy(neg_keys), neg_idx)); + int delidx = len + (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(neg_keys), neg_idx)); if (i == delidx) { del = 1; } @@ -268,7 +284,7 @@ static jv jv_dels(jv t, jv keys) { neg_idx++; } while (nonneg_idx < jv_array_length(jv_copy(nonneg_keys))) { - int delidx = (int)jv_number_value(jv_array_get(jv_copy(nonneg_keys), nonneg_idx)); + int delidx = (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(nonneg_keys), nonneg_idx)); if (i == delidx) { del = 1; } @@ -278,8 +294,8 @@ static jv jv_dels(jv t, jv keys) { nonneg_idx++; } for (int sidx=0; !del && sidx +#include +#include + +#include "jv_dtoa_tsd.h" +#include "jv_dtoa.h" +#include "jv_alloc.h" + + +static pthread_key_t dtoa_ctx_key; +static pthread_once_t dtoa_ctx_once = PTHREAD_ONCE_INIT; + +static void tsd_dtoa_ctx_dtor(struct dtoa_context *ctx) { + if (ctx) { + jvp_dtoa_context_free(ctx); + jv_mem_free(ctx); + } +} + +static void tsd_dtoa_ctx_fini() { + struct dtoa_context *ctx = pthread_getspecific(dtoa_ctx_key); + tsd_dtoa_ctx_dtor(ctx); + pthread_setspecific(dtoa_ctx_key, NULL); +} + +static void tsd_dtoa_ctx_init() { + if (pthread_key_create(&dtoa_ctx_key, tsd_dtoa_ctx_dtor) != 0) { + fprintf(stderr, "error: cannot create thread specific key"); + abort(); + } + atexit(tsd_dtoa_ctx_fini); +} + +inline struct dtoa_context *tsd_dtoa_context_get() { + pthread_once(&dtoa_ctx_once, tsd_dtoa_ctx_init); // cannot fail + struct dtoa_context *ctx = (struct dtoa_context*)pthread_getspecific(dtoa_ctx_key); + if (!ctx) { + ctx = malloc(sizeof(struct dtoa_context)); + jvp_dtoa_context_init(ctx); + if (pthread_setspecific(dtoa_ctx_key, ctx) != 0) { + fprintf(stderr, "error: cannot set thread specific data"); + abort(); + } + } + return ctx; +} \ No newline at end of file diff --git a/src/jv_dtoa_tsd.h b/src/jv_dtoa_tsd.h new file mode 100644 index 0000000000..2431d08e38 --- /dev/null +++ b/src/jv_dtoa_tsd.h @@ -0,0 +1,4 @@ +#ifndef JV_DTOA_TSD_H +#define JV_DTOA_TSD_H +struct dtoa_context *tsd_dtoa_context_get(); +#endif diff --git a/src/jv_parse.c b/src/jv_parse.c index 51ad9f0947..d709e4161f 100644 --- a/src/jv_parse.c +++ b/src/jv_parse.c @@ -124,14 +124,19 @@ static void parser_free(struct jv_parser* p) { static pfunc value(struct jv_parser* p, jv val) { if ((p->flags & JV_PARSE_STREAMING)) { - if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE) + if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE) { + jv_free(val); return "Expected separator between values"; + } if (p->stacklen > 0) p->last_seen = JV_LAST_VALUE; else p->last_seen = JV_LAST_NONE; } else { - if (jv_is_valid(p->next)) return "Expected separator between values"; + if (jv_is_valid(p->next)) { + jv_free(val); + return "Expected separator between values"; + } } jv_free(p->next); p->next = val; @@ -256,8 +261,12 @@ static pfunc stream_token(struct jv_parser* p, char ch) { break; case ':': - if (p->stacklen == 0 || jv_get_kind(jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER) + last = jv_invalid(); + if (p->stacklen == 0 || jv_get_kind(last = jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER) { + jv_free(last); return "':' not as part of an object"; + } + jv_free(last); if (!jv_is_valid(p->next) || p->last_seen == JV_LAST_NONE) return "Expected string key before ':'"; if (jv_get_kind(p->next) != JV_KIND_STRING) @@ -492,11 +501,11 @@ static pfunc check_literal(struct jv_parser* p) { } else { // FIXME: better parser p->tokenbuf[p->tokenpos] = 0; - char* end = 0; - double d = jvp_strtod(&p->dtoa, p->tokenbuf, &end); - if (end == 0 || *end != 0) + jv number = jv_number_with_literal(p->tokenbuf); + if (jv_get_kind(number) == JV_KIND_INVALID) { return "Invalid numeric literal"; - TRY(value(p, jv_number(d))); + } + TRY(value(p, number)); } p->tokenpos = 0; return 0; diff --git a/src/jv_print.c b/src/jv_print.c index 5ebc01e628..6c84803504 100644 --- a/src/jv_print.c +++ b/src/jv_print.c @@ -11,8 +11,10 @@ #include "jv.h" #include "jv_dtoa.h" +#include "jv_dtoa_tsd.h" #include "jv_unicode.h" #include "jv_alloc.h" +#include "jv_type_private.h" #ifndef MAX_PRINT_DEPTH #define MAX_PRINT_DEPTH (256) @@ -229,15 +231,24 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI put_str("true", F, S, flags & JV_PRINT_ISATTY); break; case JV_KIND_NUMBER: { - double d = jv_number_value(x); - if (d != d) { - // JSON doesn't have NaN, so we'll render it as "null" - put_str("null", F, S, flags & JV_PRINT_ISATTY); + if (jvp_number_is_nan(x)) { + jv_dump_term(C, jv_null(), flags, indent, F, S); } else { - // Normalise infinities to something we can print in valid JSON - if (d > DBL_MAX) d = DBL_MAX; - if (d < -DBL_MAX) d = -DBL_MAX; - put_str(jvp_dtoa_fmt(C, buf, d), F, S, flags & JV_PRINT_ISATTY); + const char * literal_data = jv_number_get_literal(x); + if (literal_data) { + put_str(literal_data, F, S, flags & JV_PRINT_ISATTY); + } else { + double d = jv_number_value(x); + if (d != d) { + // JSON doesn't have NaN, so we'll render it as "null" + put_str("null", F, S, flags & JV_PRINT_ISATTY); + } else { + // Normalise infinities to something we can print in valid JSON + if (d > DBL_MAX) d = DBL_MAX; + if (d < -DBL_MAX) d = -DBL_MAX; + put_str(jvp_dtoa_fmt(C, buf, d), F, S, flags & JV_PRINT_ISATTY); + } + } } break; } @@ -357,10 +368,7 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI } void jv_dumpf(jv x, FILE *f, int flags) { - struct dtoa_context C; - jvp_dtoa_context_init(&C); - jv_dump_term(&C, x, flags, 0, f, 0); - jvp_dtoa_context_free(&C); + jv_dump_term(tsd_dtoa_context_get(), x, flags, 0, f, 0); } void jv_dump(jv x, int flags) { @@ -376,11 +384,8 @@ void jv_show(jv x, int flags) { } jv jv_dump_string(jv x, int flags) { - struct dtoa_context C; - jvp_dtoa_context_init(&C); jv s = jv_string(""); - jv_dump_term(&C, x, flags, 0, 0, &s); - jvp_dtoa_context_free(&C); + jv_dump_term(tsd_dtoa_context_get(), x, flags, 0, 0, &s); return s; } diff --git a/src/jv_type_private.h b/src/jv_type_private.h new file mode 100644 index 0000000000..5996282ba5 --- /dev/null +++ b/src/jv_type_private.h @@ -0,0 +1,7 @@ +#ifndef JV_TYPE_PRIVATE +#define JV_TYPE_PRIVATE + +int jvp_number_cmp(jv, jv); +int jvp_number_is_nan(jv); + +#endif //JV_TYPE_PRIVATE diff --git a/src/parser.c b/src/parser.c index d9210a980b..b6574e52c8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -61,8 +65,8 @@ -/* Copy the first part of user declarations. */ -#line 1 "src/parser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "src/parser.y" /* yacc.c:337 */ #include #include @@ -73,13 +77,16 @@ #define YYMALLOC jv_mem_alloc #define YYFREE jv_mem_free -#line 77 "src/parser.c" /* yacc.c:339 */ - +#line 81 "src/parser.c" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -103,7 +110,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 11 "src/parser.y" /* yacc.c:355 */ +#line 11 "src/parser.y" /* yacc.c:352 */ #include "locfile.h" struct lexer_param; @@ -120,7 +127,7 @@ struct lexer_param; } \ } while (0) -#line 124 "src/parser.c" /* yacc.c:355 */ +#line 131 "src/parser.c" /* yacc.c:352 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -226,12 +233,12 @@ struct lexer_param; union YYSTYPE { -#line 31 "src/parser.y" /* yacc.c:355 */ +#line 31 "src/parser.y" /* yacc.c:352 */ jv literal; block blk; -#line 235 "src/parser.c" /* yacc.c:355 */ +#line 242 "src/parser.c" /* yacc.c:352 */ }; typedef union YYSTYPE YYSTYPE; @@ -259,8 +266,8 @@ int yyparse (block* answer, int* errors, struct locfile* locations, struct lexer #endif /* !YY_YY_SRC_PARSER_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 124 "src/parser.y" /* yacc.c:358 */ +/* Second part of user prologue. */ +#line 124 "src/parser.y" /* yacc.c:354 */ #include "lexer.h" struct lexer_param { @@ -312,7 +319,7 @@ static jv check_object_key(block k) { char errbuf[15]; return jv_string_fmt("Cannot use %s (%s) as object key", jv_kind_name(block_const_kind(k)), - jv_dump_string_trunc(jv_copy(block_const(k)), errbuf, sizeof(errbuf))); + jv_dump_string_trunc(block_const(k), errbuf, sizeof(errbuf))); } return jv_invalid(); } @@ -356,19 +363,25 @@ static block constant_fold(block a, block b, int op) { jv res = jv_invalid(); if (block_const_kind(a) == JV_KIND_NUMBER) { - double na = jv_number_value(block_const(a)); - double nb = jv_number_value(block_const(b)); + jv jv_a = block_const(a); + jv jv_b = block_const(b); + + double na = jv_number_value(jv_a); + double nb = jv_number_value(jv_b); + + int cmp = jv_cmp(jv_a, jv_b); + switch (op) { case '+': res = jv_number(na + nb); break; case '-': res = jv_number(na - nb); break; case '*': res = jv_number(na * nb); break; case '/': res = jv_number(na / nb); break; - case EQ: res = (na == nb ? jv_true() : jv_false()); break; - case NEQ: res = (na != nb ? jv_true() : jv_false()); break; - case '<': res = (na < nb ? jv_true() : jv_false()); break; - case '>': res = (na > nb ? jv_true() : jv_false()); break; - case LESSEQ: res = (na <= nb ? jv_true() : jv_false()); break; - case GREATEREQ: res = (na >= nb ? jv_true() : jv_false()); break; + case EQ: res = (cmp == 0 ? jv_true() : jv_false()); break; + case NEQ: res = (cmp != 0 ? jv_true() : jv_false()); break; + case '<': res = (cmp < 0 ? jv_true() : jv_false()); break; + case '>': res = (cmp > 0 ? jv_true() : jv_false()); break; + case LESSEQ: res = (cmp <= 0 ? jv_true() : jv_false()); break; + case GREATEREQ: res = (cmp >= 0 ? jv_true() : jv_false()); break; default: break; } } else if (op == '+' && block_const_kind(a) == JV_KIND_STRING) { @@ -434,7 +447,7 @@ static block gen_update(block object, block val, int optype) { } -#line 438 "src/parser.c" /* yacc.c:358 */ +#line 451 "src/parser.c" /* yacc.c:354 */ #ifdef short # undef short @@ -455,13 +468,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -473,7 +486,7 @@ typedef short int yytype_int16; # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -509,15 +522,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -525,7 +529,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -689,16 +693,16 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 322 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 302 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -738,23 +742,23 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 300, 300, 303, 308, 311, 322, 325, 330, 333, - 338, 342, 345, 349, 353, 357, 360, 363, 368, 372, - 376, 381, 388, 392, 396, 400, 404, 408, 412, 416, - 420, 424, 428, 432, 436, 440, 444, 448, 452, 458, - 464, 468, 472, 476, 480, 484, 488, 492, 496, 501, - 504, 521, 530, 537, 545, 556, 561, 567, 570, 575, - 579, 583, 590, 590, 594, 594, 601, 604, 607, 613, - 616, 621, 624, 627, 633, 636, 639, 647, 651, 654, - 657, 660, 663, 666, 669, 672, 675, 679, 685, 688, - 691, 694, 697, 700, 703, 706, 709, 712, 715, 718, - 721, 724, 727, 730, 733, 736, 739, 746, 750, 759, - 771, 776, 777, 778, 779, 782, 785, 790, 795, 798, - 803, 806, 811, 815, 818, 823, 826, 831, 834, 839, - 842, 845, 848, 851, 854, 862, 868, 871, 874, 877, - 880, 883, 886, 889, 892, 895, 898, 901, 904, 907, - 910, 913, 916, 919, 922, 927, 930, 931, 932, 935, - 938, 941, 944, 948, 952, 956, 960, 964, 968, 976 + 0, 306, 306, 309, 314, 317, 328, 331, 336, 339, + 344, 348, 351, 355, 359, 363, 366, 369, 374, 378, + 382, 387, 394, 398, 402, 406, 410, 414, 418, 422, + 426, 430, 434, 438, 442, 446, 450, 454, 458, 464, + 470, 474, 478, 482, 486, 490, 494, 498, 502, 507, + 510, 527, 536, 543, 551, 562, 567, 573, 576, 581, + 585, 589, 596, 596, 600, 600, 607, 610, 613, 619, + 622, 627, 630, 633, 639, 642, 645, 653, 657, 660, + 663, 666, 669, 672, 675, 678, 681, 685, 691, 694, + 697, 700, 703, 706, 709, 712, 715, 718, 721, 724, + 727, 730, 733, 736, 739, 742, 745, 752, 756, 765, + 777, 782, 783, 784, 785, 788, 791, 796, 801, 804, + 809, 812, 817, 821, 824, 829, 832, 837, 840, 845, + 848, 851, 854, 857, 860, 868, 874, 877, 880, 883, + 886, 889, 892, 895, 898, 901, 904, 907, 910, 913, + 916, 919, 922, 925, 928, 933, 936, 937, 938, 941, + 944, 947, 950, 954, 958, 962, 966, 970, 974, 982 }; #endif @@ -1455,22 +1459,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, answer, errors, locations, lexer_param_ptr, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, answer, errors, locations, lexer_param_ptr, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -1529,10 +1533,10 @@ do { \ /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED -static unsigned +static int yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { - unsigned res = 0; + int res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { @@ -1575,15 +1579,15 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yylocationp); YYUSE (answer); YYUSE (errors); @@ -1593,26 +1597,26 @@ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvalue return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, answer, errors, locations, lexer_param_ptr); - YYFPRINTF (yyoutput, ")"); + YY_LOCATION_PRINT (yyo, *yylocationp); + YYFPRINTF (yyo, ": "); + yy_symbol_value_print (yyo, yytype, yyvaluep, yylocationp, answer, errors, locations, lexer_param_ptr); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -1646,7 +1650,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, block* answer, int* errors, struct locfile* locations, struct lexer_param* lexer_param_ptr) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -1657,7 +1661,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , &(yylsp[(yyi + 1) - (yynrhs)]) , answer, errors, locations, lexer_param_ptr); YYFPRINTF (stderr, "\n"); } @@ -1761,7 +1765,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -1779,7 +1786,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -1857,10 +1864,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -1872,6 +1879,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -1883,9 +1891,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -1939,193 +1948,192 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocatio YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yytype) { - case 4: /* IDENT */ + case 4: /* IDENT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1946 "src/parser.c" /* yacc.c:1257 */ +#line 1955 "src/parser.c" /* yacc.c:1257 */ break; case 5: /* FIELD */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1952 "src/parser.c" /* yacc.c:1257 */ +#line 1961 "src/parser.c" /* yacc.c:1257 */ break; case 6: /* LITERAL */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1958 "src/parser.c" /* yacc.c:1257 */ +#line 1967 "src/parser.c" /* yacc.c:1257 */ break; case 7: /* FORMAT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1964 "src/parser.c" /* yacc.c:1257 */ +#line 1973 "src/parser.c" /* yacc.c:1257 */ break; case 42: /* QQSTRING_TEXT */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 1970 "src/parser.c" /* yacc.c:1257 */ +#line 1979 "src/parser.c" /* yacc.c:1257 */ break; case 71: /* Module */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1976 "src/parser.c" /* yacc.c:1257 */ +#line 1985 "src/parser.c" /* yacc.c:1257 */ break; case 72: /* Imports */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1982 "src/parser.c" /* yacc.c:1257 */ +#line 1991 "src/parser.c" /* yacc.c:1257 */ break; case 73: /* FuncDefs */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1988 "src/parser.c" /* yacc.c:1257 */ +#line 1997 "src/parser.c" /* yacc.c:1257 */ break; case 74: /* Exp */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 1994 "src/parser.c" /* yacc.c:1257 */ +#line 2003 "src/parser.c" /* yacc.c:1257 */ break; case 75: /* Import */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2000 "src/parser.c" /* yacc.c:1257 */ +#line 2009 "src/parser.c" /* yacc.c:1257 */ break; case 76: /* ImportWhat */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2006 "src/parser.c" /* yacc.c:1257 */ +#line 2015 "src/parser.c" /* yacc.c:1257 */ break; case 77: /* ImportFrom */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2012 "src/parser.c" /* yacc.c:1257 */ +#line 2021 "src/parser.c" /* yacc.c:1257 */ break; case 78: /* FuncDef */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2018 "src/parser.c" /* yacc.c:1257 */ +#line 2027 "src/parser.c" /* yacc.c:1257 */ break; case 79: /* Params */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2024 "src/parser.c" /* yacc.c:1257 */ +#line 2033 "src/parser.c" /* yacc.c:1257 */ break; case 80: /* Param */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2030 "src/parser.c" /* yacc.c:1257 */ +#line 2039 "src/parser.c" /* yacc.c:1257 */ break; case 81: /* String */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2036 "src/parser.c" /* yacc.c:1257 */ +#line 2045 "src/parser.c" /* yacc.c:1257 */ break; case 84: /* QQString */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2042 "src/parser.c" /* yacc.c:1257 */ +#line 2051 "src/parser.c" /* yacc.c:1257 */ break; case 85: /* ElseBody */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2048 "src/parser.c" /* yacc.c:1257 */ +#line 2057 "src/parser.c" /* yacc.c:1257 */ break; case 86: /* ExpD */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2054 "src/parser.c" /* yacc.c:1257 */ +#line 2063 "src/parser.c" /* yacc.c:1257 */ break; case 87: /* Term */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2060 "src/parser.c" /* yacc.c:1257 */ +#line 2069 "src/parser.c" /* yacc.c:1257 */ break; case 88: /* Args */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2066 "src/parser.c" /* yacc.c:1257 */ +#line 2075 "src/parser.c" /* yacc.c:1257 */ break; case 89: /* Arg */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2072 "src/parser.c" /* yacc.c:1257 */ +#line 2081 "src/parser.c" /* yacc.c:1257 */ break; case 90: /* RepPatterns */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2078 "src/parser.c" /* yacc.c:1257 */ +#line 2087 "src/parser.c" /* yacc.c:1257 */ break; case 91: /* Patterns */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2084 "src/parser.c" /* yacc.c:1257 */ +#line 2093 "src/parser.c" /* yacc.c:1257 */ break; case 92: /* Pattern */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2090 "src/parser.c" /* yacc.c:1257 */ +#line 2099 "src/parser.c" /* yacc.c:1257 */ break; case 93: /* ArrayPats */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2096 "src/parser.c" /* yacc.c:1257 */ +#line 2105 "src/parser.c" /* yacc.c:1257 */ break; case 94: /* ObjPats */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2102 "src/parser.c" /* yacc.c:1257 */ +#line 2111 "src/parser.c" /* yacc.c:1257 */ break; case 95: /* ObjPat */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2108 "src/parser.c" /* yacc.c:1257 */ +#line 2117 "src/parser.c" /* yacc.c:1257 */ break; case 96: /* Keyword */ #line 36 "src/parser.y" /* yacc.c:1257 */ { jv_free(((*yyvaluep).literal)); } -#line 2114 "src/parser.c" /* yacc.c:1257 */ +#line 2123 "src/parser.c" /* yacc.c:1257 */ break; case 97: /* MkDict */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2120 "src/parser.c" /* yacc.c:1257 */ +#line 2129 "src/parser.c" /* yacc.c:1257 */ break; case 98: /* MkDictPair */ #line 37 "src/parser.y" /* yacc.c:1257 */ { block_free(((*yyvaluep).blk)); } -#line 2126 "src/parser.c" /* yacc.c:1257 */ +#line 2135 "src/parser.c" /* yacc.c:1257 */ break; - default: break; } @@ -2231,23 +2239,31 @@ YYLTYPE yylloc = yyloc_default; yylsp[0] = yylloc; goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -2265,15 +2281,11 @@ YYLTYPE yylloc = yyloc_default; &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); - - yyls = yyls1; yyss = yyss1; yyvs = yyvs1; + yyls = yyls1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -2290,23 +2302,23 @@ YYLTYPE yylloc = yyloc_default; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -2315,11 +2327,11 @@ YYLTYPE yylloc = yyloc_default; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -2392,7 +2404,7 @@ YYLTYPE yylloc = yyloc_default; /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -2408,37 +2420,38 @@ YYLTYPE yylloc = yyloc_default; GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ + /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: -#line 300 "src/parser.y" /* yacc.c:1646 */ +#line 306 "src/parser.y" /* yacc.c:1667 */ { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), gen_op_simple(TOP), (yyvsp[0].blk)); } -#line 2422 "src/parser.c" /* yacc.c:1646 */ +#line 2435 "src/parser.c" /* yacc.c:1667 */ break; case 3: -#line 303 "src/parser.y" /* yacc.c:1646 */ +#line 309 "src/parser.y" /* yacc.c:1667 */ { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2430 "src/parser.c" /* yacc.c:1646 */ +#line 2443 "src/parser.c" /* yacc.c:1667 */ break; case 4: -#line 308 "src/parser.y" /* yacc.c:1646 */ +#line 314 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2438 "src/parser.c" /* yacc.c:1646 */ +#line 2451 "src/parser.c" /* yacc.c:1667 */ break; case 5: -#line 311 "src/parser.y" /* yacc.c:1646 */ +#line 317 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -2448,374 +2461,374 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_module((yyvsp[-1].blk)); } } -#line 2452 "src/parser.c" /* yacc.c:1646 */ +#line 2465 "src/parser.c" /* yacc.c:1667 */ break; case 6: -#line 322 "src/parser.y" /* yacc.c:1646 */ +#line 328 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2460 "src/parser.c" /* yacc.c:1646 */ +#line 2473 "src/parser.c" /* yacc.c:1667 */ break; case 7: -#line 325 "src/parser.y" /* yacc.c:1646 */ +#line 331 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2468 "src/parser.c" /* yacc.c:1646 */ +#line 2481 "src/parser.c" /* yacc.c:1667 */ break; case 8: -#line 330 "src/parser.y" /* yacc.c:1646 */ +#line 336 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 2476 "src/parser.c" /* yacc.c:1646 */ +#line 2489 "src/parser.c" /* yacc.c:1667 */ break; case 9: -#line 333 "src/parser.y" /* yacc.c:1646 */ +#line 339 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2484 "src/parser.c" /* yacc.c:1646 */ +#line 2497 "src/parser.c" /* yacc.c:1667 */ break; case 10: -#line 338 "src/parser.y" /* yacc.c:1646 */ +#line 344 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_bind_referenced((yyvsp[-1].blk), (yyvsp[0].blk), OP_IS_CALL_PSEUDO); } -#line 2492 "src/parser.c" /* yacc.c:1646 */ +#line 2505 "src/parser.c" /* yacc.c:1667 */ break; case 11: -#line 342 "src/parser.y" /* yacc.c:1646 */ +#line 348 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_destructure((yyvsp[-4].blk), (yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2500 "src/parser.c" /* yacc.c:1646 */ +#line 2513 "src/parser.c" /* yacc.c:1667 */ break; case 12: -#line 345 "src/parser.y" /* yacc.c:1646 */ +#line 351 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_reduce((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2508 "src/parser.c" /* yacc.c:1646 */ +#line 2521 "src/parser.c" /* yacc.c:1667 */ break; case 13: -#line 349 "src/parser.y" /* yacc.c:1646 */ +#line 355 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_foreach((yyvsp[-9].blk), (yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2516 "src/parser.c" /* yacc.c:1646 */ +#line 2529 "src/parser.c" /* yacc.c:1667 */ break; case 14: -#line 353 "src/parser.y" /* yacc.c:1646 */ +#line 359 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_foreach((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), gen_noop()); } -#line 2524 "src/parser.c" /* yacc.c:1646 */ +#line 2537 "src/parser.c" /* yacc.c:1667 */ break; case 15: -#line 357 "src/parser.y" /* yacc.c:1646 */ +#line 363 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2532 "src/parser.c" /* yacc.c:1646 */ +#line 2545 "src/parser.c" /* yacc.c:1667 */ break; case 16: -#line 360 "src/parser.y" /* yacc.c:1646 */ +#line 366 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), gen_noop()); } -#line 2540 "src/parser.c" /* yacc.c:1646 */ +#line 2553 "src/parser.c" /* yacc.c:1667 */ break; case 17: -#line 363 "src/parser.y" /* yacc.c:1646 */ +#line 369 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "Possibly unterminated 'if' statement"); (yyval.blk) = (yyvsp[-2].blk); } -#line 2549 "src/parser.c" /* yacc.c:1646 */ +#line 2562 "src/parser.c" /* yacc.c:1667 */ break; case 18: -#line 368 "src/parser.y" /* yacc.c:1646 */ +#line 374 "src/parser.y" /* yacc.c:1667 */ { //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, $4); (yyval.blk) = gen_try((yyvsp[-2].blk), gen_try_handler((yyvsp[0].blk))); } -#line 2558 "src/parser.c" /* yacc.c:1646 */ +#line 2571 "src/parser.c" /* yacc.c:1667 */ break; case 19: -#line 372 "src/parser.y" /* yacc.c:1646 */ +#line 378 "src/parser.y" /* yacc.c:1667 */ { //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, gen_op_simple(BACKTRACK)); (yyval.blk) = gen_try((yyvsp[0].blk), gen_op_simple(BACKTRACK)); } -#line 2567 "src/parser.c" /* yacc.c:1646 */ +#line 2580 "src/parser.c" /* yacc.c:1667 */ break; case 20: -#line 376 "src/parser.y" /* yacc.c:1646 */ +#line 382 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "Possibly unterminated 'try' statement"); (yyval.blk) = (yyvsp[-2].blk); } -#line 2576 "src/parser.c" /* yacc.c:1646 */ +#line 2589 "src/parser.c" /* yacc.c:1667 */ break; case 21: -#line 381 "src/parser.y" /* yacc.c:1646 */ +#line 387 "src/parser.y" /* yacc.c:1667 */ { jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[-2].literal))); (yyval.blk) = gen_location((yyloc), locations, gen_label(jv_string_value(v), (yyvsp[0].blk))); jv_free((yyvsp[-2].literal)); jv_free(v); } -#line 2587 "src/parser.c" /* yacc.c:1646 */ +#line 2600 "src/parser.c" /* yacc.c:1667 */ break; case 22: -#line 388 "src/parser.y" /* yacc.c:1646 */ +#line 394 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_try((yyvsp[-1].blk), gen_op_simple(BACKTRACK)); } -#line 2595 "src/parser.c" /* yacc.c:1646 */ +#line 2608 "src/parser.c" /* yacc.c:1667 */ break; case 23: -#line 392 "src/parser.y" /* yacc.c:1646 */ +#line 398 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("_assign", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2603 "src/parser.c" /* yacc.c:1646 */ +#line 2616 "src/parser.c" /* yacc.c:1667 */ break; case 24: -#line 396 "src/parser.y" /* yacc.c:1646 */ +#line 402 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_or((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2611 "src/parser.c" /* yacc.c:1646 */ +#line 2624 "src/parser.c" /* yacc.c:1667 */ break; case 25: -#line 400 "src/parser.y" /* yacc.c:1646 */ +#line 406 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_and((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2619 "src/parser.c" /* yacc.c:1646 */ +#line 2632 "src/parser.c" /* yacc.c:1667 */ break; case 26: -#line 404 "src/parser.y" /* yacc.c:1646 */ +#line 410 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_definedor((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2627 "src/parser.c" /* yacc.c:1646 */ +#line 2640 "src/parser.c" /* yacc.c:1667 */ break; case 27: -#line 408 "src/parser.y" /* yacc.c:1646 */ +#line 414 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_definedor_assign((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2635 "src/parser.c" /* yacc.c:1646 */ +#line 2648 "src/parser.c" /* yacc.c:1667 */ break; case 28: -#line 412 "src/parser.y" /* yacc.c:1646 */ +#line 418 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("_modify", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2643 "src/parser.c" /* yacc.c:1646 */ +#line 2656 "src/parser.c" /* yacc.c:1667 */ break; case 29: -#line 416 "src/parser.y" /* yacc.c:1646 */ +#line 422 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2651 "src/parser.c" /* yacc.c:1646 */ +#line 2664 "src/parser.c" /* yacc.c:1667 */ break; case 30: -#line 420 "src/parser.y" /* yacc.c:1646 */ +#line 426 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_both((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2659 "src/parser.c" /* yacc.c:1646 */ +#line 2672 "src/parser.c" /* yacc.c:1667 */ break; case 31: -#line 424 "src/parser.y" /* yacc.c:1646 */ +#line 430 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2667 "src/parser.c" /* yacc.c:1646 */ +#line 2680 "src/parser.c" /* yacc.c:1667 */ break; case 32: -#line 428 "src/parser.y" /* yacc.c:1646 */ +#line 434 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2675 "src/parser.c" /* yacc.c:1646 */ +#line 2688 "src/parser.c" /* yacc.c:1667 */ break; case 33: -#line 432 "src/parser.y" /* yacc.c:1646 */ +#line 438 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 2683 "src/parser.c" /* yacc.c:1646 */ +#line 2696 "src/parser.c" /* yacc.c:1667 */ break; case 34: -#line 436 "src/parser.y" /* yacc.c:1646 */ +#line 442 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2691 "src/parser.c" /* yacc.c:1646 */ +#line 2704 "src/parser.c" /* yacc.c:1667 */ break; case 35: -#line 440 "src/parser.y" /* yacc.c:1646 */ +#line 446 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2699 "src/parser.c" /* yacc.c:1646 */ +#line 2712 "src/parser.c" /* yacc.c:1667 */ break; case 36: -#line 444 "src/parser.y" /* yacc.c:1646 */ +#line 450 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2707 "src/parser.c" /* yacc.c:1646 */ +#line 2720 "src/parser.c" /* yacc.c:1667 */ break; case 37: -#line 448 "src/parser.y" /* yacc.c:1646 */ +#line 454 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2715 "src/parser.c" /* yacc.c:1646 */ +#line 2728 "src/parser.c" /* yacc.c:1667 */ break; case 38: -#line 452 "src/parser.y" /* yacc.c:1646 */ +#line 458 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '/'); if (block_is_const_inf((yyval.blk))) FAIL((yyloc), "Division by zero?"); } -#line 2725 "src/parser.c" /* yacc.c:1646 */ +#line 2738 "src/parser.c" /* yacc.c:1667 */ break; case 39: -#line 458 "src/parser.y" /* yacc.c:1646 */ +#line 464 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '%'); if (block_is_const_inf((yyval.blk))) FAIL((yyloc), "Remainder by zero?"); } -#line 2735 "src/parser.c" /* yacc.c:1646 */ +#line 2748 "src/parser.c" /* yacc.c:1667 */ break; case 40: -#line 464 "src/parser.y" /* yacc.c:1646 */ +#line 470 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '/'); } -#line 2743 "src/parser.c" /* yacc.c:1646 */ +#line 2756 "src/parser.c" /* yacc.c:1667 */ break; case 41: -#line 468 "src/parser.y" /* yacc.c:1646 */ +#line 474 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '%'); } -#line 2751 "src/parser.c" /* yacc.c:1646 */ +#line 2764 "src/parser.c" /* yacc.c:1667 */ break; case 42: -#line 472 "src/parser.y" /* yacc.c:1646 */ +#line 478 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), EQ); } -#line 2759 "src/parser.c" /* yacc.c:1646 */ +#line 2772 "src/parser.c" /* yacc.c:1667 */ break; case 43: -#line 476 "src/parser.y" /* yacc.c:1646 */ +#line 482 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), NEQ); } -#line 2767 "src/parser.c" /* yacc.c:1646 */ +#line 2780 "src/parser.c" /* yacc.c:1667 */ break; case 44: -#line 480 "src/parser.y" /* yacc.c:1646 */ +#line 486 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '<'); } -#line 2775 "src/parser.c" /* yacc.c:1646 */ +#line 2788 "src/parser.c" /* yacc.c:1667 */ break; case 45: -#line 484 "src/parser.y" /* yacc.c:1646 */ +#line 490 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '>'); } -#line 2783 "src/parser.c" /* yacc.c:1646 */ +#line 2796 "src/parser.c" /* yacc.c:1667 */ break; case 46: -#line 488 "src/parser.y" /* yacc.c:1646 */ +#line 494 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), LESSEQ); } -#line 2791 "src/parser.c" /* yacc.c:1646 */ +#line 2804 "src/parser.c" /* yacc.c:1667 */ break; case 47: -#line 492 "src/parser.y" /* yacc.c:1646 */ +#line 498 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), GREATEREQ); } -#line 2799 "src/parser.c" /* yacc.c:1646 */ +#line 2812 "src/parser.c" /* yacc.c:1667 */ break; case 48: -#line 496 "src/parser.y" /* yacc.c:1646 */ +#line 502 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 2807 "src/parser.c" /* yacc.c:1646 */ +#line 2820 "src/parser.c" /* yacc.c:1667 */ break; case 49: -#line 501 "src/parser.y" /* yacc.c:1646 */ +#line 507 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 2815 "src/parser.c" /* yacc.c:1646 */ +#line 2828 "src/parser.c" /* yacc.c:1667 */ break; case 50: -#line 504 "src/parser.y" /* yacc.c:1646 */ +#line 510 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -2831,11 +2844,11 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_import_meta((yyvsp[-2].blk), (yyvsp[-1].blk)); } } -#line 2835 "src/parser.c" /* yacc.c:1646 */ +#line 2848 "src/parser.c" /* yacc.c:1667 */ break; case 51: -#line 521 "src/parser.y" /* yacc.c:1646 */ +#line 527 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[-3].blk)); // XXX Make gen_import take only blocks and the int is_data so we @@ -2845,11 +2858,11 @@ YYLTYPE yylloc = yyloc_default; jv_free((yyvsp[0].literal)); jv_free(v); } -#line 2849 "src/parser.c" /* yacc.c:1646 */ +#line 2862 "src/parser.c" /* yacc.c:1667 */ break; case 52: -#line 530 "src/parser.y" /* yacc.c:1646 */ +#line 536 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[-2].blk)); (yyval.blk) = gen_import(jv_string_value(v), jv_string_value((yyvsp[0].literal)), 0); @@ -2857,22 +2870,22 @@ YYLTYPE yylloc = yyloc_default; jv_free((yyvsp[0].literal)); jv_free(v); } -#line 2861 "src/parser.c" /* yacc.c:1646 */ +#line 2874 "src/parser.c" /* yacc.c:1667 */ break; case 53: -#line 537 "src/parser.y" /* yacc.c:1646 */ +#line 543 "src/parser.y" /* yacc.c:1667 */ { jv v = block_const((yyvsp[0].blk)); (yyval.blk) = gen_import(jv_string_value(v), NULL, 0); block_free((yyvsp[0].blk)); jv_free(v); } -#line 2872 "src/parser.c" /* yacc.c:1646 */ +#line 2885 "src/parser.c" /* yacc.c:1667 */ break; case 54: -#line 545 "src/parser.y" /* yacc.c:1646 */ +#line 551 "src/parser.y" /* yacc.c:1667 */ { if (!block_is_const((yyvsp[0].blk))) { FAIL((yyloc), "Import path must be constant"); @@ -2882,182 +2895,182 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = (yyvsp[0].blk); } } -#line 2886 "src/parser.c" /* yacc.c:1646 */ +#line 2899 "src/parser.c" /* yacc.c:1667 */ break; case 55: -#line 556 "src/parser.y" /* yacc.c:1646 */ +#line 562 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_function(jv_string_value((yyvsp[-3].literal)), gen_noop(), (yyvsp[-1].blk)); jv_free((yyvsp[-3].literal)); } -#line 2895 "src/parser.c" /* yacc.c:1646 */ +#line 2908 "src/parser.c" /* yacc.c:1667 */ break; case 56: -#line 561 "src/parser.y" /* yacc.c:1646 */ +#line 567 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_function(jv_string_value((yyvsp[-6].literal)), (yyvsp[-4].blk), (yyvsp[-1].blk)); jv_free((yyvsp[-6].literal)); } -#line 2904 "src/parser.c" /* yacc.c:1646 */ +#line 2917 "src/parser.c" /* yacc.c:1667 */ break; case 57: -#line 567 "src/parser.y" /* yacc.c:1646 */ +#line 573 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 2912 "src/parser.c" /* yacc.c:1646 */ +#line 2925 "src/parser.c" /* yacc.c:1667 */ break; case 58: -#line 570 "src/parser.y" /* yacc.c:1646 */ +#line 576 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2920 "src/parser.c" /* yacc.c:1646 */ +#line 2933 "src/parser.c" /* yacc.c:1667 */ break; case 59: -#line 575 "src/parser.y" /* yacc.c:1646 */ +#line 581 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2929 "src/parser.c" /* yacc.c:1646 */ +#line 2942 "src/parser.c" /* yacc.c:1667 */ break; case 60: -#line 579 "src/parser.y" /* yacc.c:1646 */ +#line 585 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2938 "src/parser.c" /* yacc.c:1646 */ +#line 2951 "src/parser.c" /* yacc.c:1667 */ break; case 61: -#line 583 "src/parser.y" /* yacc.c:1646 */ +#line 589 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_param(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 2947 "src/parser.c" /* yacc.c:1646 */ +#line 2960 "src/parser.c" /* yacc.c:1667 */ break; case 62: -#line 590 "src/parser.y" /* yacc.c:1646 */ +#line 596 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("text"); } -#line 2953 "src/parser.c" /* yacc.c:1646 */ +#line 2966 "src/parser.c" /* yacc.c:1667 */ break; case 63: -#line 590 "src/parser.y" /* yacc.c:1646 */ +#line 596 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 2962 "src/parser.c" /* yacc.c:1646 */ +#line 2975 "src/parser.c" /* yacc.c:1667 */ break; case 64: -#line 594 "src/parser.y" /* yacc.c:1646 */ +#line 600 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = (yyvsp[-1].literal); } -#line 2968 "src/parser.c" /* yacc.c:1646 */ +#line 2981 "src/parser.c" /* yacc.c:1667 */ break; case 65: -#line 594 "src/parser.y" /* yacc.c:1646 */ +#line 600 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 2977 "src/parser.c" /* yacc.c:1646 */ +#line 2990 "src/parser.c" /* yacc.c:1667 */ break; case 66: -#line 601 "src/parser.y" /* yacc.c:1646 */ +#line 607 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const(jv_string("")); } -#line 2985 "src/parser.c" /* yacc.c:1646 */ +#line 2998 "src/parser.c" /* yacc.c:1667 */ break; case 67: -#line 604 "src/parser.y" /* yacc.c:1646 */ +#line 610 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-1].blk), gen_const((yyvsp[0].literal)), '+'); } -#line 2993 "src/parser.c" /* yacc.c:1646 */ +#line 3006 "src/parser.c" /* yacc.c:1667 */ break; case 68: -#line 607 "src/parser.y" /* yacc.c:1646 */ +#line 613 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_binop((yyvsp[-3].blk), gen_format((yyvsp[-1].blk), jv_copy((yyvsp[-4].literal))), '+'); } -#line 3001 "src/parser.c" /* yacc.c:1646 */ +#line 3014 "src/parser.c" /* yacc.c:1667 */ break; case 69: -#line 613 "src/parser.y" /* yacc.c:1646 */ +#line 619 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 3009 "src/parser.c" /* yacc.c:1646 */ +#line 3022 "src/parser.c" /* yacc.c:1667 */ break; case 70: -#line 616 "src/parser.y" /* yacc.c:1646 */ +#line 622 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 3017 "src/parser.c" /* yacc.c:1646 */ +#line 3030 "src/parser.c" /* yacc.c:1667 */ break; case 71: -#line 621 "src/parser.y" /* yacc.c:1646 */ +#line 627 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3025 "src/parser.c" /* yacc.c:1646 */ +#line 3038 "src/parser.c" /* yacc.c:1667 */ break; case 72: -#line 624 "src/parser.y" /* yacc.c:1646 */ +#line 630 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 3033 "src/parser.c" /* yacc.c:1646 */ +#line 3046 "src/parser.c" /* yacc.c:1667 */ break; case 73: -#line 627 "src/parser.y" /* yacc.c:1646 */ +#line 633 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3041 "src/parser.c" /* yacc.c:1646 */ +#line 3054 "src/parser.c" /* yacc.c:1667 */ break; case 74: -#line 633 "src/parser.y" /* yacc.c:1646 */ +#line 639 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3049 "src/parser.c" /* yacc.c:1646 */ +#line 3062 "src/parser.c" /* yacc.c:1667 */ break; case 75: -#line 636 "src/parser.y" /* yacc.c:1646 */ +#line 642 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call("recurse", gen_noop()); } -#line 3057 "src/parser.c" /* yacc.c:1646 */ +#line 3070 "src/parser.c" /* yacc.c:1667 */ break; case 76: -#line 639 "src/parser.y" /* yacc.c:1646 */ +#line 645 "src/parser.y" /* yacc.c:1667 */ { jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[0].literal))); // impossible symbol (yyval.blk) = gen_location((yyloc), locations, @@ -3066,247 +3079,247 @@ YYLTYPE yylloc = yyloc_default; jv_free(v); jv_free((yyvsp[0].literal)); } -#line 3070 "src/parser.c" /* yacc.c:1646 */ +#line 3083 "src/parser.c" /* yacc.c:1667 */ break; case 77: -#line 647 "src/parser.y" /* yacc.c:1646 */ +#line 653 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "break requires a label to break to"); (yyval.blk) = gen_noop(); } -#line 3079 "src/parser.c" /* yacc.c:1646 */ +#line 3092 "src/parser.c" /* yacc.c:1667 */ break; case 78: -#line 651 "src/parser.y" /* yacc.c:1646 */ +#line 657 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-2].blk), gen_const((yyvsp[-1].literal))); } -#line 3087 "src/parser.c" /* yacc.c:1646 */ +#line 3100 "src/parser.c" /* yacc.c:1667 */ break; case 79: -#line 654 "src/parser.y" /* yacc.c:1646 */ +#line 660 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt(gen_noop(), gen_const((yyvsp[-1].literal))); } -#line 3095 "src/parser.c" /* yacc.c:1646 */ +#line 3108 "src/parser.c" /* yacc.c:1667 */ break; case 80: -#line 657 "src/parser.y" /* yacc.c:1646 */ +#line 663 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3103 "src/parser.c" /* yacc.c:1646 */ +#line 3116 "src/parser.c" /* yacc.c:1667 */ break; case 81: -#line 660 "src/parser.y" /* yacc.c:1646 */ +#line 666 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt(gen_noop(), (yyvsp[-1].blk)); } -#line 3111 "src/parser.c" /* yacc.c:1646 */ +#line 3124 "src/parser.c" /* yacc.c:1667 */ break; case 82: -#line 663 "src/parser.y" /* yacc.c:1646 */ +#line 669 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-1].blk), gen_const((yyvsp[0].literal))); } -#line 3119 "src/parser.c" /* yacc.c:1646 */ +#line 3132 "src/parser.c" /* yacc.c:1667 */ break; case 83: -#line 666 "src/parser.y" /* yacc.c:1646 */ +#line 672 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index(gen_noop(), gen_const((yyvsp[0].literal))); } -#line 3127 "src/parser.c" /* yacc.c:1646 */ +#line 3140 "src/parser.c" /* yacc.c:1667 */ break; case 84: -#line 669 "src/parser.y" /* yacc.c:1646 */ +#line 675 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3135 "src/parser.c" /* yacc.c:1646 */ +#line 3148 "src/parser.c" /* yacc.c:1667 */ break; case 85: -#line 672 "src/parser.y" /* yacc.c:1646 */ +#line 678 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index(gen_noop(), (yyvsp[0].blk)); } -#line 3143 "src/parser.c" /* yacc.c:1646 */ +#line 3156 "src/parser.c" /* yacc.c:1667 */ break; case 86: -#line 675 "src/parser.y" /* yacc.c:1646 */ +#line 681 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3152 "src/parser.c" /* yacc.c:1646 */ +#line 3165 "src/parser.c" /* yacc.c:1667 */ break; case 87: -#line 679 "src/parser.y" /* yacc.c:1646 */ +#line 685 "src/parser.y" /* yacc.c:1667 */ { jv_free((yyvsp[-1].literal)); FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3162 "src/parser.c" /* yacc.c:1646 */ +#line 3175 "src/parser.c" /* yacc.c:1667 */ break; case 88: -#line 685 "src/parser.y" /* yacc.c:1646 */ +#line 691 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-4].blk), (yyvsp[-2].blk)); } -#line 3170 "src/parser.c" /* yacc.c:1646 */ +#line 3183 "src/parser.c" /* yacc.c:1667 */ break; case 89: -#line 688 "src/parser.y" /* yacc.c:1646 */ +#line 694 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3178 "src/parser.c" /* yacc.c:1646 */ +#line 3191 "src/parser.c" /* yacc.c:1667 */ break; case 90: -#line 691 "src/parser.y" /* yacc.c:1646 */ +#line 697 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index_opt((yyvsp[-5].blk), (yyvsp[-2].blk)); } -#line 3186 "src/parser.c" /* yacc.c:1646 */ +#line 3199 "src/parser.c" /* yacc.c:1667 */ break; case 91: -#line 694 "src/parser.y" /* yacc.c:1646 */ +#line 700 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_index((yyvsp[-4].blk), (yyvsp[-1].blk)); } -#line 3194 "src/parser.c" /* yacc.c:1646 */ +#line 3207 "src/parser.c" /* yacc.c:1667 */ break; case 92: -#line 697 "src/parser.y" /* yacc.c:1646 */ +#line 703 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH_OPT)); } -#line 3202 "src/parser.c" /* yacc.c:1646 */ +#line 3215 "src/parser.c" /* yacc.c:1667 */ break; case 93: -#line 700 "src/parser.y" /* yacc.c:1646 */ +#line 706 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = block_join((yyvsp[-2].blk), gen_op_simple(EACH)); } -#line 3210 "src/parser.c" /* yacc.c:1646 */ +#line 3223 "src/parser.c" /* yacc.c:1667 */ break; case 94: -#line 703 "src/parser.y" /* yacc.c:1646 */ +#line 709 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-6].blk), (yyvsp[-4].blk), (yyvsp[-2].blk), INDEX_OPT); } -#line 3218 "src/parser.c" /* yacc.c:1646 */ +#line 3231 "src/parser.c" /* yacc.c:1667 */ break; case 95: -#line 706 "src/parser.y" /* yacc.c:1646 */ +#line 712 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), gen_const(jv_null()), INDEX_OPT); } -#line 3226 "src/parser.c" /* yacc.c:1646 */ +#line 3239 "src/parser.c" /* yacc.c:1667 */ break; case 96: -#line 709 "src/parser.y" /* yacc.c:1646 */ +#line 715 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), gen_const(jv_null()), (yyvsp[-2].blk), INDEX_OPT); } -#line 3234 "src/parser.c" /* yacc.c:1646 */ +#line 3247 "src/parser.c" /* yacc.c:1667 */ break; case 97: -#line 712 "src/parser.y" /* yacc.c:1646 */ +#line 718 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), INDEX); } -#line 3242 "src/parser.c" /* yacc.c:1646 */ +#line 3255 "src/parser.c" /* yacc.c:1667 */ break; case 98: -#line 715 "src/parser.y" /* yacc.c:1646 */ +#line 721 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), (yyvsp[-2].blk), gen_const(jv_null()), INDEX); } -#line 3250 "src/parser.c" /* yacc.c:1646 */ +#line 3263 "src/parser.c" /* yacc.c:1667 */ break; case 99: -#line 718 "src/parser.y" /* yacc.c:1646 */ +#line 724 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), gen_const(jv_null()), (yyvsp[-1].blk), INDEX); } -#line 3258 "src/parser.c" /* yacc.c:1646 */ +#line 3271 "src/parser.c" /* yacc.c:1667 */ break; case 100: -#line 721 "src/parser.y" /* yacc.c:1646 */ +#line 727 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const((yyvsp[0].literal)); } -#line 3266 "src/parser.c" /* yacc.c:1646 */ +#line 3279 "src/parser.c" /* yacc.c:1667 */ break; case 101: -#line 724 "src/parser.y" /* yacc.c:1646 */ +#line 730 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3274 "src/parser.c" /* yacc.c:1646 */ +#line 3287 "src/parser.c" /* yacc.c:1667 */ break; case 102: -#line 727 "src/parser.y" /* yacc.c:1646 */ +#line 733 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_format(gen_noop(), (yyvsp[0].literal)); } -#line 3282 "src/parser.c" /* yacc.c:1646 */ +#line 3295 "src/parser.c" /* yacc.c:1667 */ break; case 103: -#line 730 "src/parser.y" /* yacc.c:1646 */ +#line 736 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-1].blk); } -#line 3290 "src/parser.c" /* yacc.c:1646 */ +#line 3303 "src/parser.c" /* yacc.c:1667 */ break; case 104: -#line 733 "src/parser.y" /* yacc.c:1646 */ +#line 739 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_collect((yyvsp[-1].blk)); } -#line 3298 "src/parser.c" /* yacc.c:1646 */ +#line 3311 "src/parser.c" /* yacc.c:1667 */ break; case 105: -#line 736 "src/parser.y" /* yacc.c:1646 */ +#line 742 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_const(jv_array()); } -#line 3306 "src/parser.c" /* yacc.c:1646 */ +#line 3319 "src/parser.c" /* yacc.c:1667 */ break; case 106: -#line 739 "src/parser.y" /* yacc.c:1646 */ +#line 745 "src/parser.y" /* yacc.c:1667 */ { block o = gen_const_object((yyvsp[-1].blk)); if (o.first != NULL) @@ -3314,20 +3327,20 @@ YYLTYPE yylloc = yyloc_default; else (yyval.blk) = BLOCK(gen_subexp(gen_const(jv_object())), (yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3318 "src/parser.c" /* yacc.c:1646 */ +#line 3331 "src/parser.c" /* yacc.c:1667 */ break; case 107: -#line 746 "src/parser.y" /* yacc.c:1646 */ +#line 752 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal)))); jv_free((yyvsp[0].literal)); } -#line 3327 "src/parser.c" /* yacc.c:1646 */ +#line 3340 "src/parser.c" /* yacc.c:1667 */ break; case 108: -#line 750 "src/parser.y" /* yacc.c:1646 */ +#line 756 "src/parser.y" /* yacc.c:1667 */ { if (strcmp(jv_string_value((yyvsp[0].literal)), "__loc__") == 0) { (yyval.blk) = gen_const(JV_OBJECT(jv_string("file"), jv_copy(locations->fname), @@ -3337,11 +3350,11 @@ YYLTYPE yylloc = yyloc_default; } jv_free((yyvsp[0].literal)); } -#line 3341 "src/parser.c" /* yacc.c:1646 */ +#line 3354 "src/parser.c" /* yacc.c:1667 */ break; case 109: -#line 759 "src/parser.y" /* yacc.c:1646 */ +#line 765 "src/parser.y" /* yacc.c:1667 */ { const char *s = jv_string_value((yyvsp[0].literal)); if (strcmp(s, "false") == 0) @@ -3354,198 +3367,198 @@ YYLTYPE yylloc = yyloc_default; (yyval.blk) = gen_location((yyloc), locations, gen_call(s, gen_noop())); jv_free((yyvsp[0].literal)); } -#line 3358 "src/parser.c" /* yacc.c:1646 */ +#line 3371 "src/parser.c" /* yacc.c:1667 */ break; case 110: -#line 771 "src/parser.y" /* yacc.c:1646 */ +#line 777 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_call(jv_string_value((yyvsp[-3].literal)), (yyvsp[-1].blk)); (yyval.blk) = gen_location((yylsp[-3]), locations, (yyval.blk)); jv_free((yyvsp[-3].literal)); } -#line 3368 "src/parser.c" /* yacc.c:1646 */ +#line 3381 "src/parser.c" /* yacc.c:1667 */ break; case 111: -#line 776 "src/parser.y" /* yacc.c:1646 */ +#line 782 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3374 "src/parser.c" /* yacc.c:1646 */ +#line 3387 "src/parser.c" /* yacc.c:1667 */ break; case 112: -#line 777 "src/parser.y" /* yacc.c:1646 */ +#line 783 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3380 "src/parser.c" /* yacc.c:1646 */ +#line 3393 "src/parser.c" /* yacc.c:1667 */ break; case 113: -#line 778 "src/parser.y" /* yacc.c:1646 */ +#line 784 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[-3].blk); } -#line 3386 "src/parser.c" /* yacc.c:1646 */ +#line 3399 "src/parser.c" /* yacc.c:1667 */ break; case 114: -#line 779 "src/parser.y" /* yacc.c:1646 */ +#line 785 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_noop(); } -#line 3392 "src/parser.c" /* yacc.c:1646 */ +#line 3405 "src/parser.c" /* yacc.c:1667 */ break; case 115: -#line 782 "src/parser.y" /* yacc.c:1646 */ +#line 788 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3400 "src/parser.c" /* yacc.c:1646 */ +#line 3413 "src/parser.c" /* yacc.c:1667 */ break; case 116: -#line 785 "src/parser.y" /* yacc.c:1646 */ +#line 791 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3408 "src/parser.c" /* yacc.c:1646 */ +#line 3421 "src/parser.c" /* yacc.c:1667 */ break; case 117: -#line 790 "src/parser.y" /* yacc.c:1646 */ +#line 796 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_lambda((yyvsp[0].blk)); } -#line 3416 "src/parser.c" /* yacc.c:1646 */ +#line 3429 "src/parser.c" /* yacc.c:1667 */ break; case 118: -#line 795 "src/parser.y" /* yacc.c:1646 */ +#line 801 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), gen_destructure_alt((yyvsp[0].blk))); } -#line 3424 "src/parser.c" /* yacc.c:1646 */ +#line 3437 "src/parser.c" /* yacc.c:1667 */ break; case 119: -#line 798 "src/parser.y" /* yacc.c:1646 */ +#line 804 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_destructure_alt((yyvsp[0].blk)); } -#line 3432 "src/parser.c" /* yacc.c:1646 */ +#line 3445 "src/parser.c" /* yacc.c:1667 */ break; case 120: -#line 803 "src/parser.y" /* yacc.c:1646 */ +#line 809 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3440 "src/parser.c" /* yacc.c:1646 */ +#line 3453 "src/parser.c" /* yacc.c:1667 */ break; case 121: -#line 806 "src/parser.y" /* yacc.c:1646 */ +#line 812 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3448 "src/parser.c" /* yacc.c:1646 */ +#line 3461 "src/parser.c" /* yacc.c:1667 */ break; case 122: -#line 811 "src/parser.y" /* yacc.c:1646 */ +#line 817 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 3457 "src/parser.c" /* yacc.c:1646 */ +#line 3470 "src/parser.c" /* yacc.c:1667 */ break; case 123: -#line 815 "src/parser.y" /* yacc.c:1646 */ +#line 821 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3465 "src/parser.c" /* yacc.c:1646 */ +#line 3478 "src/parser.c" /* yacc.c:1667 */ break; case 124: -#line 818 "src/parser.y" /* yacc.c:1646 */ +#line 824 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3473 "src/parser.c" /* yacc.c:1646 */ +#line 3486 "src/parser.c" /* yacc.c:1667 */ break; case 125: -#line 823 "src/parser.y" /* yacc.c:1646 */ +#line 829 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_array_matcher(gen_noop(), (yyvsp[0].blk)); } -#line 3481 "src/parser.c" /* yacc.c:1646 */ +#line 3494 "src/parser.c" /* yacc.c:1667 */ break; case 126: -#line 826 "src/parser.y" /* yacc.c:1646 */ +#line 832 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_array_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3489 "src/parser.c" /* yacc.c:1646 */ +#line 3502 "src/parser.c" /* yacc.c:1667 */ break; case 127: -#line 831 "src/parser.y" /* yacc.c:1646 */ +#line 837 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3497 "src/parser.c" /* yacc.c:1646 */ +#line 3510 "src/parser.c" /* yacc.c:1667 */ break; case 128: -#line 834 "src/parser.y" /* yacc.c:1646 */ +#line 840 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3505 "src/parser.c" /* yacc.c:1646 */ +#line 3518 "src/parser.c" /* yacc.c:1667 */ break; case 129: -#line 839 "src/parser.y" /* yacc.c:1646 */ +#line 845 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[0].literal)), gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal)))); } -#line 3513 "src/parser.c" /* yacc.c:1646 */ +#line 3526 "src/parser.c" /* yacc.c:1667 */ break; case 130: -#line 842 "src/parser.y" /* yacc.c:1646 */ +#line 848 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), BLOCK(gen_op_simple(DUP), gen_op_unbound(STOREV, jv_string_value((yyvsp[-2].literal))), (yyvsp[0].blk))); } -#line 3521 "src/parser.c" /* yacc.c:1646 */ +#line 3534 "src/parser.c" /* yacc.c:1667 */ break; case 131: -#line 845 "src/parser.y" /* yacc.c:1646 */ +#line 851 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3529 "src/parser.c" /* yacc.c:1646 */ +#line 3542 "src/parser.c" /* yacc.c:1667 */ break; case 132: -#line 848 "src/parser.y" /* yacc.c:1646 */ +#line 854 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3537 "src/parser.c" /* yacc.c:1646 */ +#line 3550 "src/parser.c" /* yacc.c:1667 */ break; case 133: -#line 851 "src/parser.y" /* yacc.c:1646 */ +#line 857 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_object_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3545 "src/parser.c" /* yacc.c:1646 */ +#line 3558 "src/parser.c" /* yacc.c:1667 */ break; case 134: -#line 854 "src/parser.y" /* yacc.c:1646 */ +#line 860 "src/parser.y" /* yacc.c:1667 */ { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -3554,276 +3567,276 @@ YYLTYPE yylloc = yyloc_default; jv_free(msg); (yyval.blk) = gen_object_matcher((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 3558 "src/parser.c" /* yacc.c:1646 */ +#line 3571 "src/parser.c" /* yacc.c:1667 */ break; case 135: -#line 862 "src/parser.y" /* yacc.c:1646 */ +#line 868 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 3567 "src/parser.c" /* yacc.c:1646 */ +#line 3580 "src/parser.c" /* yacc.c:1667 */ break; case 136: -#line 868 "src/parser.y" /* yacc.c:1646 */ +#line 874 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("as"); } -#line 3575 "src/parser.c" /* yacc.c:1646 */ +#line 3588 "src/parser.c" /* yacc.c:1667 */ break; case 137: -#line 871 "src/parser.y" /* yacc.c:1646 */ +#line 877 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("def"); } -#line 3583 "src/parser.c" /* yacc.c:1646 */ +#line 3596 "src/parser.c" /* yacc.c:1667 */ break; case 138: -#line 874 "src/parser.y" /* yacc.c:1646 */ +#line 880 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("module"); } -#line 3591 "src/parser.c" /* yacc.c:1646 */ +#line 3604 "src/parser.c" /* yacc.c:1667 */ break; case 139: -#line 877 "src/parser.y" /* yacc.c:1646 */ +#line 883 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("import"); } -#line 3599 "src/parser.c" /* yacc.c:1646 */ +#line 3612 "src/parser.c" /* yacc.c:1667 */ break; case 140: -#line 880 "src/parser.y" /* yacc.c:1646 */ +#line 886 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("include"); } -#line 3607 "src/parser.c" /* yacc.c:1646 */ +#line 3620 "src/parser.c" /* yacc.c:1667 */ break; case 141: -#line 883 "src/parser.y" /* yacc.c:1646 */ +#line 889 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("if"); } -#line 3615 "src/parser.c" /* yacc.c:1646 */ +#line 3628 "src/parser.c" /* yacc.c:1667 */ break; case 142: -#line 886 "src/parser.y" /* yacc.c:1646 */ +#line 892 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("then"); } -#line 3623 "src/parser.c" /* yacc.c:1646 */ +#line 3636 "src/parser.c" /* yacc.c:1667 */ break; case 143: -#line 889 "src/parser.y" /* yacc.c:1646 */ +#line 895 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("else"); } -#line 3631 "src/parser.c" /* yacc.c:1646 */ +#line 3644 "src/parser.c" /* yacc.c:1667 */ break; case 144: -#line 892 "src/parser.y" /* yacc.c:1646 */ +#line 898 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("elif"); } -#line 3639 "src/parser.c" /* yacc.c:1646 */ +#line 3652 "src/parser.c" /* yacc.c:1667 */ break; case 145: -#line 895 "src/parser.y" /* yacc.c:1646 */ +#line 901 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("reduce"); } -#line 3647 "src/parser.c" /* yacc.c:1646 */ +#line 3660 "src/parser.c" /* yacc.c:1667 */ break; case 146: -#line 898 "src/parser.y" /* yacc.c:1646 */ +#line 904 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("foreach"); } -#line 3655 "src/parser.c" /* yacc.c:1646 */ +#line 3668 "src/parser.c" /* yacc.c:1667 */ break; case 147: -#line 901 "src/parser.y" /* yacc.c:1646 */ +#line 907 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("end"); } -#line 3663 "src/parser.c" /* yacc.c:1646 */ +#line 3676 "src/parser.c" /* yacc.c:1667 */ break; case 148: -#line 904 "src/parser.y" /* yacc.c:1646 */ +#line 910 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("and"); } -#line 3671 "src/parser.c" /* yacc.c:1646 */ +#line 3684 "src/parser.c" /* yacc.c:1667 */ break; case 149: -#line 907 "src/parser.y" /* yacc.c:1646 */ +#line 913 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("or"); } -#line 3679 "src/parser.c" /* yacc.c:1646 */ +#line 3692 "src/parser.c" /* yacc.c:1667 */ break; case 150: -#line 910 "src/parser.y" /* yacc.c:1646 */ +#line 916 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("try"); } -#line 3687 "src/parser.c" /* yacc.c:1646 */ +#line 3700 "src/parser.c" /* yacc.c:1667 */ break; case 151: -#line 913 "src/parser.y" /* yacc.c:1646 */ +#line 919 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("catch"); } -#line 3695 "src/parser.c" /* yacc.c:1646 */ +#line 3708 "src/parser.c" /* yacc.c:1667 */ break; case 152: -#line 916 "src/parser.y" /* yacc.c:1646 */ +#line 922 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("label"); } -#line 3703 "src/parser.c" /* yacc.c:1646 */ +#line 3716 "src/parser.c" /* yacc.c:1667 */ break; case 153: -#line 919 "src/parser.y" /* yacc.c:1646 */ +#line 925 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("break"); } -#line 3711 "src/parser.c" /* yacc.c:1646 */ +#line 3724 "src/parser.c" /* yacc.c:1667 */ break; case 154: -#line 922 "src/parser.y" /* yacc.c:1646 */ +#line 928 "src/parser.y" /* yacc.c:1667 */ { (yyval.literal) = jv_string("__loc__"); } -#line 3719 "src/parser.c" /* yacc.c:1646 */ +#line 3732 "src/parser.c" /* yacc.c:1667 */ break; case 155: -#line 927 "src/parser.y" /* yacc.c:1646 */ +#line 933 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk)=gen_noop(); } -#line 3727 "src/parser.c" /* yacc.c:1646 */ +#line 3740 "src/parser.c" /* yacc.c:1667 */ break; case 156: -#line 930 "src/parser.y" /* yacc.c:1646 */ +#line 936 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3733 "src/parser.c" /* yacc.c:1646 */ +#line 3746 "src/parser.c" /* yacc.c:1667 */ break; case 157: -#line 931 "src/parser.y" /* yacc.c:1646 */ +#line 937 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk)=block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3739 "src/parser.c" /* yacc.c:1646 */ +#line 3752 "src/parser.c" /* yacc.c:1667 */ break; case 158: -#line 932 "src/parser.y" /* yacc.c:1646 */ +#line 938 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = (yyvsp[0].blk); } -#line 3745 "src/parser.c" /* yacc.c:1646 */ +#line 3758 "src/parser.c" /* yacc.c:1667 */ break; case 159: -#line 935 "src/parser.y" /* yacc.c:1646 */ +#line 941 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3753 "src/parser.c" /* yacc.c:1646 */ +#line 3766 "src/parser.c" /* yacc.c:1667 */ break; case 160: -#line 938 "src/parser.y" /* yacc.c:1646 */ +#line 944 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3761 "src/parser.c" /* yacc.c:1646 */ +#line 3774 "src/parser.c" /* yacc.c:1667 */ break; case 161: -#line 941 "src/parser.y" /* yacc.c:1646 */ +#line 947 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3769 "src/parser.c" /* yacc.c:1646 */ +#line 3782 "src/parser.c" /* yacc.c:1667 */ break; case 162: -#line 944 "src/parser.y" /* yacc.c:1646 */ +#line 950 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair((yyvsp[0].blk), BLOCK(gen_op_simple(POP), gen_op_simple(DUP2), gen_op_simple(DUP2), gen_op_simple(INDEX))); } -#line 3778 "src/parser.c" /* yacc.c:1646 */ +#line 3791 "src/parser.c" /* yacc.c:1667 */ break; case 163: -#line 948 "src/parser.y" /* yacc.c:1646 */ +#line 954 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[-2].literal)))), (yyvsp[0].blk)); } -#line 3787 "src/parser.c" /* yacc.c:1646 */ +#line 3800 "src/parser.c" /* yacc.c:1667 */ break; case 164: -#line 952 "src/parser.y" /* yacc.c:1646 */ +#line 958 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[0].literal)), gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal))))); } -#line 3796 "src/parser.c" /* yacc.c:1646 */ +#line 3809 "src/parser.c" /* yacc.c:1667 */ break; case 165: -#line 956 "src/parser.y" /* yacc.c:1646 */ +#line 962 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const((yyvsp[0].literal)), gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal))))); } -#line 3805 "src/parser.c" /* yacc.c:1646 */ +#line 3818 "src/parser.c" /* yacc.c:1667 */ break; case 166: -#line 960 "src/parser.y" /* yacc.c:1646 */ +#line 966 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 3814 "src/parser.c" /* yacc.c:1646 */ +#line 3827 "src/parser.c" /* yacc.c:1667 */ break; case 167: -#line 964 "src/parser.y" /* yacc.c:1646 */ +#line 970 "src/parser.y" /* yacc.c:1667 */ { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 3823 "src/parser.c" /* yacc.c:1646 */ +#line 3836 "src/parser.c" /* yacc.c:1667 */ break; case 168: -#line 968 "src/parser.y" /* yacc.c:1646 */ +#line 974 "src/parser.y" /* yacc.c:1667 */ { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -3832,20 +3845,20 @@ YYLTYPE yylloc = yyloc_default; jv_free(msg); (yyval.blk) = gen_dictpair((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 3836 "src/parser.c" /* yacc.c:1646 */ +#line 3849 "src/parser.c" /* yacc.c:1667 */ break; case 169: -#line 976 "src/parser.y" /* yacc.c:1646 */ +#line 982 "src/parser.y" /* yacc.c:1667 */ { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 3845 "src/parser.c" /* yacc.c:1646 */ +#line 3858 "src/parser.c" /* yacc.c:1667 */ break; -#line 3849 "src/parser.c" /* yacc.c:1646 */ +#line 3862 "src/parser.c" /* yacc.c:1667 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -3871,14 +3884,13 @@ YYLTYPE yylloc = yyloc_default; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -3961,14 +3973,11 @@ YYLTYPE yylloc = yyloc_default; | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -4034,6 +4043,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -4041,6 +4051,7 @@ YYLTYPE yylloc = yyloc_default; yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -4051,6 +4062,10 @@ YYLTYPE yylloc = yyloc_default; /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -4080,7 +4095,7 @@ YYLTYPE yylloc = yyloc_default; #endif return yyresult; } -#line 980 "src/parser.y" /* yacc.c:1906 */ +#line 986 "src/parser.y" /* yacc.c:1918 */ int jq_parse(struct locfile* locations, block* answer) { diff --git a/src/parser.h b/src/parser.h index b15c53aad4..4d14e954f9 100644 --- a/src/parser.h +++ b/src/parser.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_YY_SRC_PARSER_H_INCLUDED # define YY_YY_SRC_PARSER_H_INCLUDED /* Debug traces. */ @@ -40,7 +44,7 @@ extern int yydebug; #endif /* "%code requires" blocks. */ -#line 11 "src/parser.y" /* yacc.c:1909 */ +#line 11 "src/parser.y" /* yacc.c:1927 */ #include "locfile.h" struct lexer_param; @@ -57,7 +61,7 @@ struct lexer_param; } \ } while (0) -#line 61 "src/parser.h" /* yacc.c:1909 */ +#line 65 "src/parser.h" /* yacc.c:1927 */ /* Token type. */ #ifndef YYTOKENTYPE @@ -163,12 +167,12 @@ struct lexer_param; union YYSTYPE { -#line 31 "src/parser.y" /* yacc.c:1909 */ +#line 31 "src/parser.y" /* yacc.c:1927 */ jv literal; block blk; -#line 172 "src/parser.h" /* yacc.c:1909 */ +#line 176 "src/parser.h" /* yacc.c:1927 */ }; typedef union YYSTYPE YYSTYPE; diff --git a/src/parser.y b/src/parser.y index 6758102561..e223adab53 100644 --- a/src/parser.y +++ b/src/parser.y @@ -172,7 +172,7 @@ static jv check_object_key(block k) { char errbuf[15]; return jv_string_fmt("Cannot use %s (%s) as object key", jv_kind_name(block_const_kind(k)), - jv_dump_string_trunc(jv_copy(block_const(k)), errbuf, sizeof(errbuf))); + jv_dump_string_trunc(block_const(k), errbuf, sizeof(errbuf))); } return jv_invalid(); } @@ -216,19 +216,25 @@ static block constant_fold(block a, block b, int op) { jv res = jv_invalid(); if (block_const_kind(a) == JV_KIND_NUMBER) { - double na = jv_number_value(block_const(a)); - double nb = jv_number_value(block_const(b)); + jv jv_a = block_const(a); + jv jv_b = block_const(b); + + double na = jv_number_value(jv_a); + double nb = jv_number_value(jv_b); + + int cmp = jv_cmp(jv_a, jv_b); + switch (op) { case '+': res = jv_number(na + nb); break; case '-': res = jv_number(na - nb); break; case '*': res = jv_number(na * nb); break; case '/': res = jv_number(na / nb); break; - case EQ: res = (na == nb ? jv_true() : jv_false()); break; - case NEQ: res = (na != nb ? jv_true() : jv_false()); break; - case '<': res = (na < nb ? jv_true() : jv_false()); break; - case '>': res = (na > nb ? jv_true() : jv_false()); break; - case LESSEQ: res = (na <= nb ? jv_true() : jv_false()); break; - case GREATEREQ: res = (na >= nb ? jv_true() : jv_false()); break; + case EQ: res = (cmp == 0 ? jv_true() : jv_false()); break; + case NEQ: res = (cmp != 0 ? jv_true() : jv_false()); break; + case '<': res = (cmp < 0 ? jv_true() : jv_false()); break; + case '>': res = (cmp > 0 ? jv_true() : jv_false()); break; + case LESSEQ: res = (cmp <= 0 ? jv_true() : jv_false()); break; + case GREATEREQ: res = (cmp >= 0 ? jv_true() : jv_false()); break; default: break; } } else if (op == '+' && block_const_kind(a) == JV_KIND_STRING) { diff --git a/tests/jq.test b/tests/jq.test index a6a8d2194b..adc5788962 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1673,3 +1673,42 @@ false #null +# +# Tests to cover the new toliteral number functionality +# For an example see #1652 and other linked issues +# + +# We are backward and sanity compatible + +map(. == 1) +[1, 1.0, 1.000, 100e-2, 1e+0, 0.0001e4] +[true, true, true, true, true, true] + +# When no arithmetic is involved jq should preserve the literal value + +.[0] | tostring +[13911860366432393] +"13911860366432393" + +.x | tojson +{"x":13911860366432393} +"13911860366432393" + +13911860366432393 == 13911860366432392 +null +false + + +# Applying arithmetic to the value will truncate the result to double + +. - 10 +13911860366432393 +13911860366432382 + +.[0] - 10 +[13911860366432393] +13911860366432382 + +.x - 10 +{"x":13911860366432393} +13911860366432382 diff --git a/tests/local.supp b/tests/local.supp new file mode 100644 index 0000000000..8bb878b06c --- /dev/null +++ b/tests/local.supp @@ -0,0 +1,14 @@ +{ + macos valgrind 1 + Memcheck:Leak + match-leak-kinds: possible + fun:calloc + fun:map_images_nolock + ... + fun:_dyld_objc_notify_register + fun:_objc_init + fun:_os_object_init + fun:libdispatch_init + fun:libSystem_initializer + ... +} diff --git a/tests/setup b/tests/setup index 4a96574d4c..bb5f62be3e 100755 --- a/tests/setup +++ b/tests/setup @@ -14,7 +14,8 @@ JQ=$JQBASEDIR/jq if [ -z "${NO_VALGRIND-}" ] && which valgrind > /dev/null; then VALGRIND="valgrind --error-exitcode=1 --leak-check=full \ - --suppressions=$JQTESTDIR/onig.supp" + --suppressions=$JQTESTDIR/onig.supp \ + --suppressions=$JQTESTDIR/local.supp" VG_EXIT0=--error-exitcode=0 Q=-q else