From cf4b48c7ba30cb30e116b523cff036ea481459f6 Mon Sep 17 00:00:00 2001 From: "Leonid S. Usov" Date: Fri, 19 Oct 2018 21:57:41 +0300 Subject: [PATCH] Save literal value of the parsed number to preserve it for the output Extend jv_number to use decNumber for storing number literals. Any math operations on the numbers will truncate them to double precision. Comparisons when both numbers are literal numbers will compare them without truncation. Delay conversion of numbers to doubles until a math operation is performed, to preserve precision. A literal jv_number will only need conversion to double once, and will reuse the resultant double on subsequent conversions. Outputting literal jv_numbers preserves the original precision. Add strong pthread requirement to manage contexts/allocations for converting numbers between their decNumber, string, and double formats. --- .gitignore | 1 + Makefile.am | 12 +- configure.ac | 14 +- docs/content/manual/v1.6/manual.yml | 48 ++ src/builtin.c | 29 +- src/execute.c | 15 +- src/jq_test.c | 73 +- src/jv.c | 651 ++++++++++++----- src/jv.h | 5 +- src/jv_aux.c | 39 +- src/jv_dtoa_tsd.c | 46 ++ src/jv_dtoa_tsd.h | 4 + src/jv_parse.c | 23 +- src/jv_print.c | 37 +- src/jv_type_private.h | 7 + src/parser.c | 1029 ++++++++++++++------------- src/parser.h | 16 +- src/parser.y | 24 +- tests/jq.test | 39 + tests/local.supp | 14 + tests/setup | 3 +- 21 files changed, 1374 insertions(+), 755 deletions(-) create mode 100644 src/jv_dtoa_tsd.c create mode 100644 src/jv_dtoa_tsd.h create mode 100644 src/jv_type_private.h create mode 100644 tests/local.supp 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