diff --git a/src/builtin.c b/src/builtin.c index 26205f91..793b5976 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -383,7 +383,7 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) { static jv f_divide(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) { - if (jv_number_value(b) == 0.0 && jv_number_value(a) != 0.0) + if (jv_number_value(b) == 0.0) return type_error2(a, b, "cannot be divided because the divisor is zero"); jv r = jv_number(jv_number_value(a) / jv_number_value(b)); jv_free(a); @@ -396,14 +396,22 @@ static jv f_divide(jq_state *jq, jv input, jv a, jv b) { } } +#define dtoi(n) ((n) < INTMAX_MIN ? INTMAX_MIN : -(n) < INTMAX_MIN ? INTMAX_MAX : (intmax_t)(n)) static jv f_mod(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) { - intmax_t bi = (intmax_t)jv_number_value(b); + double na = jv_number_value(a); + double nb = jv_number_value(b); + if (isnan(na) || isnan(nb)) { + jv_free(a); + jv_free(b); + return jv_number(NAN); + } + intmax_t bi = dtoi(nb); if (bi == 0) return type_error2(a, b, "cannot be divided (remainder) because the divisor is zero"); // Check if the divisor is -1 to avoid overflow when the dividend is INTMAX_MIN. - jv r = jv_number(bi == -1 ? 0 : (intmax_t)jv_number_value(a) % bi); + jv r = jv_number(bi == -1 ? 0 : dtoi(na) % bi); jv_free(a); jv_free(b); return r; @@ -411,6 +419,7 @@ static jv f_mod(jq_state *jq, jv input, jv a, jv b) { return type_error2(a, b, "cannot be divided (remainder)"); } } +#undef dtoi static jv f_equal(jq_state *jq, jv input, jv a, jv b) { jv_free(input); diff --git a/src/compile.c b/src/compile.c index 4af74ff6..492340b1 100644 --- a/src/compile.c +++ b/src/compile.c @@ -172,12 +172,6 @@ int block_is_const(block b) { return (block_is_single(b) && (b.first->op == LOADK || b.first->op == PUSHK_UNDER)); } -int block_is_const_inf(block b) { - return (block_is_single(b) && b.first->op == LOADK && - jv_get_kind(b.first->imm.constant) == JV_KIND_NUMBER && - isinf(jv_number_value(b.first->imm.constant))); -} - jv_kind block_const_kind(block b) { assert(block_is_const(b)); return jv_get_kind(b.first->imm.constant); diff --git a/src/compile.h b/src/compile.h index f690adc2..03cb54f5 100644 --- a/src/compile.h +++ b/src/compile.h @@ -22,7 +22,6 @@ block gen_op_simple(opcode op); block gen_const(jv constant); block gen_const_global(jv constant, const char *name); int block_is_const(block b); -int block_is_const_inf(block b); jv_kind block_const_kind(block b); jv block_const(block b); block gen_op_target(opcode op, block target); diff --git a/src/parser.c b/src/parser.c index 541cef84..fc1a978c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -497,7 +497,16 @@ static block constant_fold(block a, block b, int 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 '/': + if (nb == 0.0) return gen_noop(); + res = jv_number(na / nb); + break; + case '%': +#define is_unsafe_double(n) (isnan(n) || (n) < INTMAX_MIN || -(n) < INTMAX_MIN) + if (is_unsafe_double(na) || is_unsafe_double(nb) || (intmax_t)nb == 0) return gen_noop(); +#undef is_unsafe_double + res = jv_number((intmax_t)na % (intmax_t)nb); + 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; @@ -574,7 +583,7 @@ static block gen_loc_object(location *loc, struct locfile *locations) { } -#line 578 "src/parser.c" +#line 587 "src/parser.c" #ifdef short @@ -964,24 +973,24 @@ static const yytype_int8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 313, 313, 316, 321, 324, 339, 342, 347, 350, - 355, 359, 362, 366, 370, 374, 377, 382, 385, 388, - 393, 400, 404, 408, 412, 416, 420, 424, 428, 432, - 436, 440, 444, 448, 452, 456, 460, 464, 470, 476, - 480, 484, 488, 492, 496, 500, 504, 508, 513, 516, - 533, 542, 549, 557, 568, 573, 579, 582, 587, 591, - 598, 603, 607, 607, 614, 617, 620, 626, 629, 632, - 637, 640, 643, 649, 652, 655, 663, 667, 670, 673, - 676, 679, 682, 685, 688, 691, 695, 701, 704, 707, - 710, 713, 716, 719, 722, 725, 728, 731, 734, 737, - 740, 743, 746, 749, 752, 755, 758, 761, 783, 787, - 791, 794, 806, 811, 812, 813, 814, 817, 820, 825, - 830, 833, 838, 841, 846, 850, 853, 858, 861, 866, - 869, 874, 877, 880, 883, 886, 889, 897, 903, 906, - 909, 912, 915, 918, 921, 924, 927, 930, 933, 936, - 939, 942, 945, 948, 951, 954, 959, 962, 963, 964, - 967, 970, 973, 976, 980, 985, 989, 993, 997, 1001, - 1009 + 0, 322, 322, 325, 330, 333, 348, 351, 356, 359, + 364, 368, 371, 375, 379, 383, 386, 391, 394, 397, + 402, 409, 413, 417, 421, 425, 429, 433, 437, 441, + 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, + 485, 489, 493, 497, 501, 505, 509, 513, 518, 521, + 538, 547, 554, 562, 573, 578, 584, 587, 592, 596, + 603, 608, 612, 612, 619, 622, 625, 631, 634, 637, + 642, 645, 648, 654, 657, 660, 668, 672, 675, 678, + 681, 684, 687, 690, 693, 696, 700, 706, 709, 712, + 715, 718, 721, 724, 727, 730, 733, 736, 739, 742, + 745, 748, 751, 754, 757, 760, 763, 766, 788, 792, + 796, 799, 811, 816, 817, 818, 819, 822, 825, 830, + 835, 838, 843, 846, 851, 855, 858, 863, 866, 871, + 874, 879, 882, 885, 888, 891, 894, 902, 908, 911, + 914, 917, 920, 923, 926, 929, 932, 935, 938, 941, + 944, 947, 950, 953, 956, 959, 964, 967, 968, 969, + 972, 975, 978, 981, 985, 990, 994, 998, 1002, 1006, + 1014 }; #endif @@ -2195,199 +2204,199 @@ yydestruct (const char *yymsg, case YYSYMBOL_IDENT: /* IDENT */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2199 "src/parser.c" +#line 2208 "src/parser.c" break; case YYSYMBOL_FIELD: /* FIELD */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2205 "src/parser.c" +#line 2214 "src/parser.c" break; case YYSYMBOL_BINDING: /* BINDING */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2211 "src/parser.c" +#line 2220 "src/parser.c" break; case YYSYMBOL_LITERAL: /* LITERAL */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2217 "src/parser.c" +#line 2226 "src/parser.c" break; case YYSYMBOL_FORMAT: /* FORMAT */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2223 "src/parser.c" +#line 2232 "src/parser.c" break; case YYSYMBOL_QQSTRING_TEXT: /* QQSTRING_TEXT */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2229 "src/parser.c" +#line 2238 "src/parser.c" break; case YYSYMBOL_Module: /* Module */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2235 "src/parser.c" +#line 2244 "src/parser.c" break; case YYSYMBOL_Imports: /* Imports */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2241 "src/parser.c" +#line 2250 "src/parser.c" break; case YYSYMBOL_FuncDefs: /* FuncDefs */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2247 "src/parser.c" +#line 2256 "src/parser.c" break; case YYSYMBOL_Exp: /* Exp */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2253 "src/parser.c" +#line 2262 "src/parser.c" break; case YYSYMBOL_Import: /* Import */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2259 "src/parser.c" +#line 2268 "src/parser.c" break; case YYSYMBOL_ImportWhat: /* ImportWhat */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2265 "src/parser.c" +#line 2274 "src/parser.c" break; case YYSYMBOL_ImportFrom: /* ImportFrom */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2271 "src/parser.c" +#line 2280 "src/parser.c" break; case YYSYMBOL_FuncDef: /* FuncDef */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2277 "src/parser.c" +#line 2286 "src/parser.c" break; case YYSYMBOL_Params: /* Params */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2283 "src/parser.c" +#line 2292 "src/parser.c" break; case YYSYMBOL_Param: /* Param */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2289 "src/parser.c" +#line 2298 "src/parser.c" break; case YYSYMBOL_NoFormat: /* NoFormat */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2295 "src/parser.c" +#line 2304 "src/parser.c" break; case YYSYMBOL_String: /* String */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2301 "src/parser.c" +#line 2310 "src/parser.c" break; case YYSYMBOL_QQString: /* QQString */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2307 "src/parser.c" +#line 2316 "src/parser.c" break; case YYSYMBOL_ElseBody: /* ElseBody */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2313 "src/parser.c" +#line 2322 "src/parser.c" break; case YYSYMBOL_ExpD: /* ExpD */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2319 "src/parser.c" +#line 2328 "src/parser.c" break; case YYSYMBOL_Term: /* Term */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2325 "src/parser.c" +#line 2334 "src/parser.c" break; case YYSYMBOL_Args: /* Args */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2331 "src/parser.c" +#line 2340 "src/parser.c" break; case YYSYMBOL_Arg: /* Arg */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2337 "src/parser.c" +#line 2346 "src/parser.c" break; case YYSYMBOL_RepPatterns: /* RepPatterns */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2343 "src/parser.c" +#line 2352 "src/parser.c" break; case YYSYMBOL_Patterns: /* Patterns */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2349 "src/parser.c" +#line 2358 "src/parser.c" break; case YYSYMBOL_Pattern: /* Pattern */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2355 "src/parser.c" +#line 2364 "src/parser.c" break; case YYSYMBOL_ArrayPats: /* ArrayPats */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2361 "src/parser.c" +#line 2370 "src/parser.c" break; case YYSYMBOL_ObjPats: /* ObjPats */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2367 "src/parser.c" +#line 2376 "src/parser.c" break; case YYSYMBOL_ObjPat: /* ObjPat */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2373 "src/parser.c" +#line 2382 "src/parser.c" break; case YYSYMBOL_Keyword: /* Keyword */ #line 36 "src/parser.y" { jv_free(((*yyvaluep).literal)); } -#line 2379 "src/parser.c" +#line 2388 "src/parser.c" break; case YYSYMBOL_MkDict: /* MkDict */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2385 "src/parser.c" +#line 2394 "src/parser.c" break; case YYSYMBOL_MkDictPair: /* MkDictPair */ #line 37 "src/parser.y" { block_free(((*yyvaluep).blk)); } -#line 2391 "src/parser.c" +#line 2400 "src/parser.c" break; default: @@ -2691,31 +2700,31 @@ yyreduce: switch (yyn) { case 2: /* TopLevel: Module Imports Exp */ -#line 313 "src/parser.y" +#line 322 "src/parser.y" { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), gen_op_simple(TOP), (yyvsp[0].blk)); } -#line 2699 "src/parser.c" +#line 2708 "src/parser.c" break; case 3: /* TopLevel: Module Imports FuncDefs */ -#line 316 "src/parser.y" +#line 325 "src/parser.y" { *answer = BLOCK((yyvsp[-2].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2707 "src/parser.c" +#line 2716 "src/parser.c" break; case 4: /* Module: %empty */ -#line 321 "src/parser.y" +#line 330 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 2715 "src/parser.c" +#line 2724 "src/parser.c" break; case 5: /* Module: "module" Exp ';' */ -#line 324 "src/parser.y" +#line 333 "src/parser.y" { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -2729,364 +2738,360 @@ yyreduce: (yyval.blk) = gen_module((yyvsp[-1].blk)); } } -#line 2733 "src/parser.c" +#line 2742 "src/parser.c" break; case 6: /* Imports: %empty */ -#line 339 "src/parser.y" +#line 348 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 2741 "src/parser.c" +#line 2750 "src/parser.c" break; case 7: /* Imports: Import Imports */ -#line 342 "src/parser.y" +#line 351 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2749 "src/parser.c" +#line 2758 "src/parser.c" break; case 8: /* FuncDefs: %empty */ -#line 347 "src/parser.y" +#line 356 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 2757 "src/parser.c" +#line 2766 "src/parser.c" break; case 9: /* FuncDefs: FuncDef FuncDefs */ -#line 350 "src/parser.y" +#line 359 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2765 "src/parser.c" +#line 2774 "src/parser.c" break; case 10: /* Exp: FuncDef Exp */ -#line 355 "src/parser.y" +#line 364 "src/parser.y" { (yyval.blk) = block_bind_referenced((yyvsp[-1].blk), (yyvsp[0].blk), OP_IS_CALL_PSEUDO); } -#line 2773 "src/parser.c" +#line 2782 "src/parser.c" break; case 11: /* Exp: Term "as" Patterns '|' Exp */ -#line 359 "src/parser.y" +#line 368 "src/parser.y" { (yyval.blk) = gen_destructure((yyvsp[-4].blk), (yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2781 "src/parser.c" +#line 2790 "src/parser.c" break; case 12: /* Exp: "reduce" Term "as" Patterns '(' Exp ';' Exp ')' */ -#line 362 "src/parser.y" +#line 371 "src/parser.y" { (yyval.blk) = gen_reduce((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2789 "src/parser.c" +#line 2798 "src/parser.c" break; case 13: /* Exp: "foreach" Term "as" Patterns '(' Exp ';' Exp ';' Exp ')' */ -#line 366 "src/parser.y" +#line 375 "src/parser.y" { (yyval.blk) = gen_foreach((yyvsp[-9].blk), (yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 2797 "src/parser.c" +#line 2806 "src/parser.c" break; case 14: /* Exp: "foreach" Term "as" Patterns '(' Exp ';' Exp ')' */ -#line 370 "src/parser.y" +#line 379 "src/parser.y" { (yyval.blk) = gen_foreach((yyvsp[-7].blk), (yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), gen_noop()); } -#line 2805 "src/parser.c" +#line 2814 "src/parser.c" break; case 15: /* Exp: "if" Exp "then" Exp ElseBody */ -#line 374 "src/parser.y" +#line 383 "src/parser.y" { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 2813 "src/parser.c" - break; - - case 16: /* Exp: "if" Exp "then" error */ -#line 377 "src/parser.y" - { - FAIL((yyloc), "Possibly unterminated 'if' statement"); - (yyval.blk) = (yyvsp[-2].blk); -} #line 2822 "src/parser.c" break; + case 16: /* Exp: "if" Exp "then" error */ +#line 386 "src/parser.y" + { + FAIL((yyloc), "Possibly unterminated 'if' statement"); + (yyval.blk) = (yyvsp[-2].blk); +} +#line 2831 "src/parser.c" + break; + case 17: /* Exp: "try" Exp "catch" Exp */ -#line 382 "src/parser.y" +#line 391 "src/parser.y" { (yyval.blk) = gen_try((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2830 "src/parser.c" +#line 2839 "src/parser.c" break; case 18: /* Exp: "try" Exp */ -#line 385 "src/parser.y" +#line 394 "src/parser.y" { (yyval.blk) = gen_try((yyvsp[0].blk), gen_op_simple(BACKTRACK)); } -#line 2838 "src/parser.c" - break; - - case 19: /* Exp: "try" Exp "catch" error */ -#line 388 "src/parser.y" - { - FAIL((yyloc), "Possibly unterminated 'try' statement"); - (yyval.blk) = (yyvsp[-2].blk); -} #line 2847 "src/parser.c" break; + case 19: /* Exp: "try" Exp "catch" error */ +#line 397 "src/parser.y" + { + FAIL((yyloc), "Possibly unterminated 'try' statement"); + (yyval.blk) = (yyvsp[-2].blk); +} +#line 2856 "src/parser.c" + break; + case 20: /* Exp: "label" BINDING '|' Exp */ -#line 393 "src/parser.y" +#line 402 "src/parser.y" { 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 2858 "src/parser.c" +#line 2867 "src/parser.c" break; case 21: /* Exp: Exp '?' */ -#line 400 "src/parser.y" +#line 409 "src/parser.y" { (yyval.blk) = gen_try((yyvsp[-1].blk), gen_op_simple(BACKTRACK)); } -#line 2866 "src/parser.c" +#line 2875 "src/parser.c" break; case 22: /* Exp: Exp '=' Exp */ -#line 404 "src/parser.y" +#line 413 "src/parser.y" { (yyval.blk) = gen_call("_assign", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2874 "src/parser.c" +#line 2883 "src/parser.c" break; case 23: /* Exp: Exp "or" Exp */ -#line 408 "src/parser.y" +#line 417 "src/parser.y" { (yyval.blk) = gen_or((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2882 "src/parser.c" +#line 2891 "src/parser.c" break; case 24: /* Exp: Exp "and" Exp */ -#line 412 "src/parser.y" +#line 421 "src/parser.y" { (yyval.blk) = gen_and((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2890 "src/parser.c" +#line 2899 "src/parser.c" break; case 25: /* Exp: Exp "//" Exp */ -#line 416 "src/parser.y" +#line 425 "src/parser.y" { (yyval.blk) = gen_definedor((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2898 "src/parser.c" +#line 2907 "src/parser.c" break; case 26: /* Exp: Exp "//=" Exp */ -#line 420 "src/parser.y" +#line 429 "src/parser.y" { (yyval.blk) = gen_definedor_assign((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2906 "src/parser.c" +#line 2915 "src/parser.c" break; case 27: /* Exp: Exp "|=" Exp */ -#line 424 "src/parser.y" +#line 433 "src/parser.y" { (yyval.blk) = gen_call("_modify", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk)))); } -#line 2914 "src/parser.c" +#line 2923 "src/parser.c" break; case 28: /* Exp: Exp '|' Exp */ -#line 428 "src/parser.y" +#line 437 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2922 "src/parser.c" +#line 2931 "src/parser.c" break; case 29: /* Exp: Exp ',' Exp */ -#line 432 "src/parser.y" +#line 441 "src/parser.y" { (yyval.blk) = gen_both((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 2930 "src/parser.c" +#line 2939 "src/parser.c" break; case 30: /* Exp: Exp '+' Exp */ -#line 436 "src/parser.y" +#line 445 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2938 "src/parser.c" +#line 2947 "src/parser.c" break; case 31: /* Exp: Exp "+=" Exp */ -#line 440 "src/parser.y" +#line 449 "src/parser.y" { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '+'); } -#line 2946 "src/parser.c" +#line 2955 "src/parser.c" break; case 32: /* Exp: '-' Exp */ -#line 444 "src/parser.y" +#line 453 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 2954 "src/parser.c" +#line 2963 "src/parser.c" break; case 33: /* Exp: Exp '-' Exp */ -#line 448 "src/parser.y" +#line 457 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2962 "src/parser.c" +#line 2971 "src/parser.c" break; case 34: /* Exp: Exp "-=" Exp */ -#line 452 "src/parser.y" +#line 461 "src/parser.y" { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '-'); } -#line 2970 "src/parser.c" +#line 2979 "src/parser.c" break; case 35: /* Exp: Exp '*' Exp */ -#line 456 "src/parser.y" +#line 465 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2978 "src/parser.c" +#line 2987 "src/parser.c" break; case 36: /* Exp: Exp "*=" Exp */ -#line 460 "src/parser.y" +#line 469 "src/parser.y" { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '*'); } -#line 2986 "src/parser.c" +#line 2995 "src/parser.c" break; case 37: /* Exp: Exp '/' Exp */ -#line 464 "src/parser.y" +#line 473 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '/'); - if (block_is_const_inf((yyval.blk))) - FAIL((yyloc), "Division by zero?"); } -#line 2996 "src/parser.c" +#line 3003 "src/parser.c" break; case 38: /* Exp: Exp '%' Exp */ -#line 470 "src/parser.y" +#line 477 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '%'); - if (block_is_const_inf((yyval.blk))) - FAIL((yyloc), "Remainder by zero?"); } -#line 3006 "src/parser.c" +#line 3011 "src/parser.c" break; case 39: /* Exp: Exp "/=" Exp */ -#line 476 "src/parser.y" +#line 481 "src/parser.y" { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '/'); } -#line 3014 "src/parser.c" +#line 3019 "src/parser.c" break; case 40: /* Exp: Exp "%=" Exp */ -#line 480 "src/parser.y" +#line 485 "src/parser.y" { (yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '%'); } -#line 3022 "src/parser.c" +#line 3027 "src/parser.c" break; case 41: /* Exp: Exp "==" Exp */ -#line 484 "src/parser.y" +#line 489 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), EQ); } -#line 3030 "src/parser.c" +#line 3035 "src/parser.c" break; case 42: /* Exp: Exp "!=" Exp */ -#line 488 "src/parser.y" +#line 493 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), NEQ); } -#line 3038 "src/parser.c" +#line 3043 "src/parser.c" break; case 43: /* Exp: Exp '<' Exp */ -#line 492 "src/parser.y" +#line 497 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '<'); } -#line 3046 "src/parser.c" +#line 3051 "src/parser.c" break; case 44: /* Exp: Exp '>' Exp */ -#line 496 "src/parser.y" +#line 501 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '>'); } -#line 3054 "src/parser.c" +#line 3059 "src/parser.c" break; case 45: /* Exp: Exp "<=" Exp */ -#line 500 "src/parser.y" +#line 505 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), LESSEQ); } -#line 3062 "src/parser.c" +#line 3067 "src/parser.c" break; case 46: /* Exp: Exp ">=" Exp */ -#line 504 "src/parser.y" +#line 509 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), GREATEREQ); } -#line 3070 "src/parser.c" +#line 3075 "src/parser.c" break; case 47: /* Exp: Term */ -#line 508 "src/parser.y" +#line 513 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3078 "src/parser.c" +#line 3083 "src/parser.c" break; case 48: /* Import: ImportWhat ';' */ -#line 513 "src/parser.y" +#line 518 "src/parser.y" { (yyval.blk) = (yyvsp[-1].blk); } -#line 3086 "src/parser.c" +#line 3091 "src/parser.c" break; case 49: /* Import: ImportWhat Exp ';' */ -#line 516 "src/parser.y" +#line 521 "src/parser.y" { if (!block_is_const((yyvsp[-1].blk))) { FAIL((yyloc), "Module metadata must be constant"); @@ -3102,11 +3107,11 @@ yyreduce: (yyval.blk) = gen_import_meta((yyvsp[-2].blk), (yyvsp[-1].blk)); } } -#line 3106 "src/parser.c" +#line 3111 "src/parser.c" break; case 50: /* ImportWhat: "import" ImportFrom "as" BINDING */ -#line 533 "src/parser.y" +#line 538 "src/parser.y" { jv v = block_const((yyvsp[-2].blk)); // XXX Make gen_import take only blocks and the int is_data so we @@ -3116,11 +3121,11 @@ yyreduce: jv_free((yyvsp[0].literal)); jv_free(v); } -#line 3120 "src/parser.c" +#line 3125 "src/parser.c" break; case 51: /* ImportWhat: "import" ImportFrom "as" IDENT */ -#line 542 "src/parser.y" +#line 547 "src/parser.y" { jv v = block_const((yyvsp[-2].blk)); (yyval.blk) = gen_import(jv_string_value(v), jv_string_value((yyvsp[0].literal)), 0); @@ -3128,22 +3133,22 @@ yyreduce: jv_free((yyvsp[0].literal)); jv_free(v); } -#line 3132 "src/parser.c" +#line 3137 "src/parser.c" break; case 52: /* ImportWhat: "include" ImportFrom */ -#line 549 "src/parser.y" +#line 554 "src/parser.y" { 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 3143 "src/parser.c" +#line 3148 "src/parser.c" break; case 53: /* ImportFrom: String */ -#line 557 "src/parser.y" +#line 562 "src/parser.y" { if (!block_is_const((yyvsp[0].blk))) { FAIL((yyloc), "Import path must be constant"); @@ -3153,183 +3158,183 @@ yyreduce: (yyval.blk) = (yyvsp[0].blk); } } -#line 3157 "src/parser.c" +#line 3162 "src/parser.c" break; case 54: /* FuncDef: "def" IDENT ':' Exp ';' */ -#line 568 "src/parser.y" +#line 573 "src/parser.y" { (yyval.blk) = gen_function(jv_string_value((yyvsp[-3].literal)), gen_noop(), (yyvsp[-1].blk)); jv_free((yyvsp[-3].literal)); } -#line 3166 "src/parser.c" +#line 3171 "src/parser.c" break; case 55: /* FuncDef: "def" IDENT '(' Params ')' ':' Exp ';' */ -#line 573 "src/parser.y" +#line 578 "src/parser.y" { (yyval.blk) = gen_function(jv_string_value((yyvsp[-6].literal)), (yyvsp[-4].blk), (yyvsp[-1].blk)); jv_free((yyvsp[-6].literal)); } -#line 3175 "src/parser.c" +#line 3180 "src/parser.c" break; case 56: /* Params: Param */ -#line 579 "src/parser.y" +#line 584 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3183 "src/parser.c" +#line 3188 "src/parser.c" break; case 57: /* Params: Params ';' Param */ -#line 582 "src/parser.y" +#line 587 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3191 "src/parser.c" +#line 3196 "src/parser.c" break; case 58: /* Param: BINDING */ -#line 587 "src/parser.y" +#line 592 "src/parser.y" { (yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 3200 "src/parser.c" +#line 3205 "src/parser.c" break; case 59: /* Param: IDENT */ -#line 591 "src/parser.y" +#line 596 "src/parser.y" { (yyval.blk) = gen_param(jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 3209 "src/parser.c" +#line 3214 "src/parser.c" break; case 60: /* NoFormat: %empty */ -#line 598 "src/parser.y" +#line 603 "src/parser.y" { (yyval.literal) = jv_string("text"); } -#line 3217 "src/parser.c" +#line 3222 "src/parser.c" break; case 61: /* String: QQSTRING_START NoFormat QQString QQSTRING_END */ -#line 603 "src/parser.y" +#line 608 "src/parser.y" { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 3226 "src/parser.c" +#line 3231 "src/parser.c" break; case 62: /* @1: %empty */ -#line 607 "src/parser.y" +#line 612 "src/parser.y" { (yyval.literal) = (yyvsp[-1].literal); } -#line 3232 "src/parser.c" +#line 3237 "src/parser.c" break; case 63: /* String: FORMAT QQSTRING_START @1 QQString QQSTRING_END */ -#line 607 "src/parser.y" +#line 612 "src/parser.y" { (yyval.blk) = (yyvsp[-1].blk); jv_free((yyvsp[-2].literal)); } -#line 3241 "src/parser.c" +#line 3246 "src/parser.c" break; case 64: /* QQString: %empty */ -#line 614 "src/parser.y" +#line 619 "src/parser.y" { (yyval.blk) = gen_const(jv_string("")); } -#line 3249 "src/parser.c" +#line 3254 "src/parser.c" break; case 65: /* QQString: QQString QQSTRING_TEXT */ -#line 617 "src/parser.y" +#line 622 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-1].blk), gen_const((yyvsp[0].literal)), '+'); } -#line 3257 "src/parser.c" +#line 3262 "src/parser.c" break; case 66: /* QQString: QQString QQSTRING_INTERP_START Exp QQSTRING_INTERP_END */ -#line 620 "src/parser.y" +#line 625 "src/parser.y" { (yyval.blk) = gen_binop((yyvsp[-3].blk), gen_format((yyvsp[-1].blk), jv_copy((yyvsp[-4].literal))), '+'); } -#line 3265 "src/parser.c" +#line 3270 "src/parser.c" break; case 67: /* ElseBody: "elif" Exp "then" Exp ElseBody */ -#line 626 "src/parser.y" +#line 631 "src/parser.y" { (yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk)); } -#line 3273 "src/parser.c" +#line 3278 "src/parser.c" break; case 68: /* ElseBody: "else" Exp "end" */ -#line 629 "src/parser.y" +#line 634 "src/parser.y" { (yyval.blk) = (yyvsp[-1].blk); } -#line 3281 "src/parser.c" +#line 3286 "src/parser.c" break; case 69: /* ElseBody: "end" */ -#line 632 "src/parser.y" +#line 637 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 3289 "src/parser.c" +#line 3294 "src/parser.c" break; case 70: /* ExpD: ExpD '|' ExpD */ -#line 637 "src/parser.y" +#line 642 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3297 "src/parser.c" +#line 3302 "src/parser.c" break; case 71: /* ExpD: '-' ExpD */ -#line 640 "src/parser.y" +#line 645 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop())); } -#line 3305 "src/parser.c" +#line 3310 "src/parser.c" break; case 72: /* ExpD: Term */ -#line 643 "src/parser.y" +#line 648 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3313 "src/parser.c" +#line 3318 "src/parser.c" break; case 73: /* Term: '.' */ -#line 649 "src/parser.y" +#line 654 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 3321 "src/parser.c" +#line 3326 "src/parser.c" break; case 74: /* Term: ".." */ -#line 652 "src/parser.y" +#line 657 "src/parser.y" { (yyval.blk) = gen_call("recurse", gen_noop()); } -#line 3329 "src/parser.c" +#line 3334 "src/parser.c" break; case 75: /* Term: "break" BINDING */ -#line 655 "src/parser.y" +#line 660 "src/parser.y" { jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[0].literal))); // impossible symbol (yyval.blk) = gen_location((yyloc), locations, @@ -3338,263 +3343,263 @@ yyreduce: jv_free(v); jv_free((yyvsp[0].literal)); } -#line 3342 "src/parser.c" +#line 3347 "src/parser.c" break; case 76: /* Term: "break" error */ -#line 663 "src/parser.y" +#line 668 "src/parser.y" { FAIL((yyloc), "break requires a label to break to"); (yyval.blk) = gen_noop(); } -#line 3351 "src/parser.c" +#line 3356 "src/parser.c" break; case 77: /* Term: Term FIELD '?' */ -#line 667 "src/parser.y" +#line 672 "src/parser.y" { (yyval.blk) = gen_index_opt((yyvsp[-2].blk), gen_const((yyvsp[-1].literal))); } -#line 3359 "src/parser.c" +#line 3364 "src/parser.c" break; case 78: /* Term: FIELD '?' */ -#line 670 "src/parser.y" +#line 675 "src/parser.y" { (yyval.blk) = gen_index_opt(gen_noop(), gen_const((yyvsp[-1].literal))); } -#line 3367 "src/parser.c" +#line 3372 "src/parser.c" break; case 79: /* Term: Term '.' String '?' */ -#line 673 "src/parser.y" +#line 678 "src/parser.y" { (yyval.blk) = gen_index_opt((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3375 "src/parser.c" +#line 3380 "src/parser.c" break; case 80: /* Term: '.' String '?' */ -#line 676 "src/parser.y" +#line 681 "src/parser.y" { (yyval.blk) = gen_index_opt(gen_noop(), (yyvsp[-1].blk)); } -#line 3383 "src/parser.c" +#line 3388 "src/parser.c" break; case 81: /* Term: Term FIELD */ -#line 679 "src/parser.y" +#line 684 "src/parser.y" { (yyval.blk) = gen_index((yyvsp[-1].blk), gen_const((yyvsp[0].literal))); } -#line 3391 "src/parser.c" +#line 3396 "src/parser.c" break; case 82: /* Term: FIELD */ -#line 682 "src/parser.y" +#line 687 "src/parser.y" { (yyval.blk) = gen_index(gen_noop(), gen_const((yyvsp[0].literal))); } -#line 3399 "src/parser.c" +#line 3404 "src/parser.c" break; case 83: /* Term: Term '.' String */ -#line 685 "src/parser.y" +#line 690 "src/parser.y" { (yyval.blk) = gen_index((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3407 "src/parser.c" +#line 3412 "src/parser.c" break; case 84: /* Term: '.' String */ -#line 688 "src/parser.y" +#line 693 "src/parser.y" { (yyval.blk) = gen_index(gen_noop(), (yyvsp[0].blk)); } -#line 3415 "src/parser.c" +#line 3420 "src/parser.c" break; case 85: /* Term: '.' error */ -#line 691 "src/parser.y" +#line 696 "src/parser.y" { FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3424 "src/parser.c" +#line 3429 "src/parser.c" break; case 86: /* Term: '.' IDENT error */ -#line 695 "src/parser.y" +#line 700 "src/parser.y" { jv_free((yyvsp[-1].literal)); FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields"); (yyval.blk) = gen_noop(); } -#line 3434 "src/parser.c" +#line 3439 "src/parser.c" break; case 87: /* Term: Term '[' Exp ']' '?' */ -#line 701 "src/parser.y" +#line 706 "src/parser.y" { (yyval.blk) = gen_index_opt((yyvsp[-4].blk), (yyvsp[-2].blk)); } -#line 3442 "src/parser.c" +#line 3447 "src/parser.c" break; case 88: /* Term: Term '[' Exp ']' */ -#line 704 "src/parser.y" +#line 709 "src/parser.y" { (yyval.blk) = gen_index((yyvsp[-3].blk), (yyvsp[-1].blk)); } -#line 3450 "src/parser.c" +#line 3455 "src/parser.c" break; case 89: /* Term: Term '.' '[' Exp ']' '?' */ -#line 707 "src/parser.y" +#line 712 "src/parser.y" { (yyval.blk) = gen_index_opt((yyvsp[-5].blk), (yyvsp[-2].blk)); } -#line 3458 "src/parser.c" +#line 3463 "src/parser.c" break; case 90: /* Term: Term '.' '[' Exp ']' */ -#line 710 "src/parser.y" +#line 715 "src/parser.y" { (yyval.blk) = gen_index((yyvsp[-4].blk), (yyvsp[-1].blk)); } -#line 3466 "src/parser.c" +#line 3471 "src/parser.c" break; case 91: /* Term: Term '[' ']' '?' */ -#line 713 "src/parser.y" +#line 718 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH_OPT)); } -#line 3474 "src/parser.c" +#line 3479 "src/parser.c" break; case 92: /* Term: Term '[' ']' */ -#line 716 "src/parser.y" +#line 721 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-2].blk), gen_op_simple(EACH)); } -#line 3482 "src/parser.c" +#line 3487 "src/parser.c" break; case 93: /* Term: Term '.' '[' ']' '?' */ -#line 719 "src/parser.y" +#line 724 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-4].blk), gen_op_simple(EACH_OPT)); } -#line 3490 "src/parser.c" +#line 3495 "src/parser.c" break; case 94: /* Term: Term '.' '[' ']' */ -#line 722 "src/parser.y" +#line 727 "src/parser.y" { (yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH)); } -#line 3498 "src/parser.c" +#line 3503 "src/parser.c" break; case 95: /* Term: Term '[' Exp ':' Exp ']' '?' */ -#line 725 "src/parser.y" +#line 730 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-6].blk), (yyvsp[-4].blk), (yyvsp[-2].blk), INDEX_OPT); } -#line 3506 "src/parser.c" +#line 3511 "src/parser.c" break; case 96: /* Term: Term '[' Exp ':' ']' '?' */ -#line 728 "src/parser.y" +#line 733 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), gen_const(jv_null()), INDEX_OPT); } -#line 3514 "src/parser.c" +#line 3519 "src/parser.c" break; case 97: /* Term: Term '[' ':' Exp ']' '?' */ -#line 731 "src/parser.y" +#line 736 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), gen_const(jv_null()), (yyvsp[-2].blk), INDEX_OPT); } -#line 3522 "src/parser.c" +#line 3527 "src/parser.c" break; case 98: /* Term: Term '[' Exp ':' Exp ']' */ -#line 734 "src/parser.y" +#line 739 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), INDEX); } -#line 3530 "src/parser.c" +#line 3535 "src/parser.c" break; case 99: /* Term: Term '[' Exp ':' ']' */ -#line 737 "src/parser.y" +#line 742 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), (yyvsp[-2].blk), gen_const(jv_null()), INDEX); } -#line 3538 "src/parser.c" +#line 3543 "src/parser.c" break; case 100: /* Term: Term '[' ':' Exp ']' */ -#line 740 "src/parser.y" +#line 745 "src/parser.y" { (yyval.blk) = gen_slice_index((yyvsp[-4].blk), gen_const(jv_null()), (yyvsp[-1].blk), INDEX); } -#line 3546 "src/parser.c" +#line 3551 "src/parser.c" break; case 101: /* Term: LITERAL */ -#line 743 "src/parser.y" +#line 748 "src/parser.y" { (yyval.blk) = gen_const((yyvsp[0].literal)); } -#line 3554 "src/parser.c" +#line 3559 "src/parser.c" break; case 102: /* Term: String */ -#line 746 "src/parser.y" +#line 751 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3562 "src/parser.c" +#line 3567 "src/parser.c" break; case 103: /* Term: FORMAT */ -#line 749 "src/parser.y" +#line 754 "src/parser.y" { (yyval.blk) = gen_format(gen_noop(), (yyvsp[0].literal)); } -#line 3570 "src/parser.c" +#line 3575 "src/parser.c" break; case 104: /* Term: '(' Exp ')' */ -#line 752 "src/parser.y" +#line 757 "src/parser.y" { (yyval.blk) = (yyvsp[-1].blk); } -#line 3578 "src/parser.c" +#line 3583 "src/parser.c" break; case 105: /* Term: '[' Exp ']' */ -#line 755 "src/parser.y" +#line 760 "src/parser.y" { (yyval.blk) = gen_collect((yyvsp[-1].blk)); } -#line 3586 "src/parser.c" +#line 3591 "src/parser.c" break; case 106: /* Term: '[' ']' */ -#line 758 "src/parser.y" +#line 763 "src/parser.y" { (yyval.blk) = gen_const(jv_array()); } -#line 3594 "src/parser.c" +#line 3599 "src/parser.c" break; case 107: /* Term: '{' MkDict '}' */ -#line 761 "src/parser.y" +#line 766 "src/parser.y" { block o = gen_const_object((yyvsp[-1].blk)); if (o.first != NULL) @@ -3602,37 +3607,37 @@ yyreduce: else (yyval.blk) = BLOCK(gen_subexp(gen_const(jv_object())), (yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3606 "src/parser.c" +#line 3611 "src/parser.c" break; case 108: /* Term: '$' '$' '$' BINDING */ -#line 783 "src/parser.y" +#line 788 "src/parser.y" { (yyval.blk) = gen_location((yyloc), locations, gen_op_unbound(LOADVN, jv_string_value((yyvsp[0].literal)))); jv_free((yyvsp[0].literal)); } -#line 3615 "src/parser.c" +#line 3620 "src/parser.c" break; case 109: /* Term: BINDING */ -#line 787 "src/parser.y" +#line 792 "src/parser.y" { (yyval.blk) = gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal)))); jv_free((yyvsp[0].literal)); } -#line 3624 "src/parser.c" +#line 3629 "src/parser.c" break; case 110: /* Term: "$__loc__" */ -#line 791 "src/parser.y" +#line 796 "src/parser.y" { (yyval.blk) = gen_loc_object(&(yyloc), locations); } -#line 3632 "src/parser.c" +#line 3637 "src/parser.c" break; case 111: /* Term: IDENT */ -#line 794 "src/parser.y" +#line 799 "src/parser.y" { const char *s = jv_string_value((yyvsp[0].literal)); if (strcmp(s, "false") == 0) @@ -3645,198 +3650,198 @@ yyreduce: (yyval.blk) = gen_location((yyloc), locations, gen_call(s, gen_noop())); jv_free((yyvsp[0].literal)); } -#line 3649 "src/parser.c" +#line 3654 "src/parser.c" break; case 112: /* Term: IDENT '(' Args ')' */ -#line 806 "src/parser.y" +#line 811 "src/parser.y" { (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 3659 "src/parser.c" +#line 3664 "src/parser.c" break; case 113: /* Term: '(' error ')' */ -#line 811 "src/parser.y" +#line 816 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 3665 "src/parser.c" +#line 3670 "src/parser.c" break; case 114: /* Term: '[' error ']' */ -#line 812 "src/parser.y" +#line 817 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 3671 "src/parser.c" +#line 3676 "src/parser.c" break; case 115: /* Term: Term '[' error ']' */ -#line 813 "src/parser.y" +#line 818 "src/parser.y" { (yyval.blk) = (yyvsp[-3].blk); } -#line 3677 "src/parser.c" +#line 3682 "src/parser.c" break; case 116: /* Term: '{' error '}' */ -#line 814 "src/parser.y" +#line 819 "src/parser.y" { (yyval.blk) = gen_noop(); } -#line 3683 "src/parser.c" +#line 3688 "src/parser.c" break; case 117: /* Args: Arg */ -#line 817 "src/parser.y" +#line 822 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3691 "src/parser.c" +#line 3696 "src/parser.c" break; case 118: /* Args: Args ';' Arg */ -#line 820 "src/parser.y" +#line 825 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3699 "src/parser.c" +#line 3704 "src/parser.c" break; case 119: /* Arg: Exp */ -#line 825 "src/parser.y" +#line 830 "src/parser.y" { (yyval.blk) = gen_lambda((yyvsp[0].blk)); } -#line 3707 "src/parser.c" +#line 3712 "src/parser.c" break; case 120: /* RepPatterns: RepPatterns "?//" Pattern */ -#line 830 "src/parser.y" +#line 835 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-2].blk), gen_destructure_alt((yyvsp[0].blk))); } -#line 3715 "src/parser.c" +#line 3720 "src/parser.c" break; case 121: /* RepPatterns: Pattern */ -#line 833 "src/parser.y" +#line 838 "src/parser.y" { (yyval.blk) = gen_destructure_alt((yyvsp[0].blk)); } -#line 3723 "src/parser.c" +#line 3728 "src/parser.c" break; case 122: /* Patterns: RepPatterns "?//" Pattern */ -#line 838 "src/parser.y" +#line 843 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3731 "src/parser.c" +#line 3736 "src/parser.c" break; case 123: /* Patterns: Pattern */ -#line 841 "src/parser.y" +#line 846 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3739 "src/parser.c" +#line 3744 "src/parser.c" break; case 124: /* Pattern: BINDING */ -#line 846 "src/parser.y" +#line 851 "src/parser.y" { (yyval.blk) = gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal))); jv_free((yyvsp[0].literal)); } -#line 3748 "src/parser.c" +#line 3753 "src/parser.c" break; case 125: /* Pattern: '[' ArrayPats ']' */ -#line 850 "src/parser.y" +#line 855 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3756 "src/parser.c" +#line 3761 "src/parser.c" break; case 126: /* Pattern: '{' ObjPats '}' */ -#line 853 "src/parser.y" +#line 858 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP)); } -#line 3764 "src/parser.c" +#line 3769 "src/parser.c" break; case 127: /* ArrayPats: Pattern */ -#line 858 "src/parser.y" +#line 863 "src/parser.y" { (yyval.blk) = gen_array_matcher(gen_noop(), (yyvsp[0].blk)); } -#line 3772 "src/parser.c" +#line 3777 "src/parser.c" break; case 128: /* ArrayPats: ArrayPats ',' Pattern */ -#line 861 "src/parser.y" +#line 866 "src/parser.y" { (yyval.blk) = gen_array_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3780 "src/parser.c" +#line 3785 "src/parser.c" break; case 129: /* ObjPats: ObjPat */ -#line 866 "src/parser.y" +#line 871 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 3788 "src/parser.c" +#line 3793 "src/parser.c" break; case 130: /* ObjPats: ObjPats ',' ObjPat */ -#line 869 "src/parser.y" +#line 874 "src/parser.y" { (yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3796 "src/parser.c" +#line 3801 "src/parser.c" break; case 131: /* ObjPat: BINDING */ -#line 874 "src/parser.y" +#line 879 "src/parser.y" { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[0].literal)), gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal)))); } -#line 3804 "src/parser.c" +#line 3809 "src/parser.c" break; case 132: /* ObjPat: BINDING ':' Pattern */ -#line 877 "src/parser.y" +#line 882 "src/parser.y" { (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 3812 "src/parser.c" +#line 3817 "src/parser.c" break; case 133: /* ObjPat: IDENT ':' Pattern */ -#line 880 "src/parser.y" +#line 885 "src/parser.y" { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3820 "src/parser.c" +#line 3825 "src/parser.c" break; case 134: /* ObjPat: Keyword ':' Pattern */ -#line 883 "src/parser.y" +#line 888 "src/parser.y" { (yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 3828 "src/parser.c" +#line 3833 "src/parser.c" break; case 135: /* ObjPat: String ':' Pattern */ -#line 886 "src/parser.y" +#line 891 "src/parser.y" { (yyval.blk) = gen_object_matcher((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 3836 "src/parser.c" +#line 3841 "src/parser.c" break; case 136: /* ObjPat: '(' Exp ')' ':' Pattern */ -#line 889 "src/parser.y" +#line 894 "src/parser.y" { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -3845,269 +3850,269 @@ yyreduce: jv_free(msg); (yyval.blk) = gen_object_matcher((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 3849 "src/parser.c" +#line 3854 "src/parser.c" break; case 137: /* ObjPat: error ':' Pattern */ -#line 897 "src/parser.y" +#line 902 "src/parser.y" { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 3858 "src/parser.c" +#line 3863 "src/parser.c" break; case 138: /* Keyword: "as" */ -#line 903 "src/parser.y" +#line 908 "src/parser.y" { (yyval.literal) = jv_string("as"); } -#line 3866 "src/parser.c" +#line 3871 "src/parser.c" break; case 139: /* Keyword: "def" */ -#line 906 "src/parser.y" +#line 911 "src/parser.y" { (yyval.literal) = jv_string("def"); } -#line 3874 "src/parser.c" +#line 3879 "src/parser.c" break; case 140: /* Keyword: "module" */ -#line 909 "src/parser.y" +#line 914 "src/parser.y" { (yyval.literal) = jv_string("module"); } -#line 3882 "src/parser.c" +#line 3887 "src/parser.c" break; case 141: /* Keyword: "import" */ -#line 912 "src/parser.y" +#line 917 "src/parser.y" { (yyval.literal) = jv_string("import"); } -#line 3890 "src/parser.c" +#line 3895 "src/parser.c" break; case 142: /* Keyword: "include" */ -#line 915 "src/parser.y" +#line 920 "src/parser.y" { (yyval.literal) = jv_string("include"); } -#line 3898 "src/parser.c" +#line 3903 "src/parser.c" break; case 143: /* Keyword: "if" */ -#line 918 "src/parser.y" +#line 923 "src/parser.y" { (yyval.literal) = jv_string("if"); } -#line 3906 "src/parser.c" +#line 3911 "src/parser.c" break; case 144: /* Keyword: "then" */ -#line 921 "src/parser.y" +#line 926 "src/parser.y" { (yyval.literal) = jv_string("then"); } -#line 3914 "src/parser.c" +#line 3919 "src/parser.c" break; case 145: /* Keyword: "else" */ -#line 924 "src/parser.y" +#line 929 "src/parser.y" { (yyval.literal) = jv_string("else"); } -#line 3922 "src/parser.c" +#line 3927 "src/parser.c" break; case 146: /* Keyword: "elif" */ -#line 927 "src/parser.y" +#line 932 "src/parser.y" { (yyval.literal) = jv_string("elif"); } -#line 3930 "src/parser.c" +#line 3935 "src/parser.c" break; case 147: /* Keyword: "reduce" */ -#line 930 "src/parser.y" +#line 935 "src/parser.y" { (yyval.literal) = jv_string("reduce"); } -#line 3938 "src/parser.c" +#line 3943 "src/parser.c" break; case 148: /* Keyword: "foreach" */ -#line 933 "src/parser.y" +#line 938 "src/parser.y" { (yyval.literal) = jv_string("foreach"); } -#line 3946 "src/parser.c" +#line 3951 "src/parser.c" break; case 149: /* Keyword: "end" */ -#line 936 "src/parser.y" +#line 941 "src/parser.y" { (yyval.literal) = jv_string("end"); } -#line 3954 "src/parser.c" +#line 3959 "src/parser.c" break; case 150: /* Keyword: "and" */ -#line 939 "src/parser.y" +#line 944 "src/parser.y" { (yyval.literal) = jv_string("and"); } -#line 3962 "src/parser.c" +#line 3967 "src/parser.c" break; case 151: /* Keyword: "or" */ -#line 942 "src/parser.y" +#line 947 "src/parser.y" { (yyval.literal) = jv_string("or"); } -#line 3970 "src/parser.c" +#line 3975 "src/parser.c" break; case 152: /* Keyword: "try" */ -#line 945 "src/parser.y" +#line 950 "src/parser.y" { (yyval.literal) = jv_string("try"); } -#line 3978 "src/parser.c" +#line 3983 "src/parser.c" break; case 153: /* Keyword: "catch" */ -#line 948 "src/parser.y" +#line 953 "src/parser.y" { (yyval.literal) = jv_string("catch"); } -#line 3986 "src/parser.c" +#line 3991 "src/parser.c" break; case 154: /* Keyword: "label" */ -#line 951 "src/parser.y" +#line 956 "src/parser.y" { (yyval.literal) = jv_string("label"); } -#line 3994 "src/parser.c" +#line 3999 "src/parser.c" break; case 155: /* Keyword: "break" */ -#line 954 "src/parser.y" +#line 959 "src/parser.y" { (yyval.literal) = jv_string("break"); } -#line 4002 "src/parser.c" +#line 4007 "src/parser.c" break; case 156: /* MkDict: %empty */ -#line 959 "src/parser.y" +#line 964 "src/parser.y" { (yyval.blk)=gen_noop(); } -#line 4010 "src/parser.c" +#line 4015 "src/parser.c" break; case 157: /* MkDict: MkDictPair */ -#line 962 "src/parser.y" +#line 967 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 4016 "src/parser.c" +#line 4021 "src/parser.c" break; case 158: /* MkDict: MkDictPair ',' MkDict */ -#line 963 "src/parser.y" +#line 968 "src/parser.y" { (yyval.blk)=block_join((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 4022 "src/parser.c" +#line 4027 "src/parser.c" break; case 159: /* MkDict: error ',' MkDict */ -#line 964 "src/parser.y" +#line 969 "src/parser.y" { (yyval.blk) = (yyvsp[0].blk); } -#line 4028 "src/parser.c" +#line 4033 "src/parser.c" break; case 160: /* MkDictPair: IDENT ':' ExpD */ -#line 967 "src/parser.y" +#line 972 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 4036 "src/parser.c" +#line 4041 "src/parser.c" break; case 161: /* MkDictPair: Keyword ':' ExpD */ -#line 970 "src/parser.y" +#line 975 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk)); } -#line 4044 "src/parser.c" +#line 4049 "src/parser.c" break; case 162: /* MkDictPair: String ':' ExpD */ -#line 973 "src/parser.y" +#line 978 "src/parser.y" { (yyval.blk) = gen_dictpair((yyvsp[-2].blk), (yyvsp[0].blk)); } -#line 4052 "src/parser.c" +#line 4057 "src/parser.c" break; case 163: /* MkDictPair: String */ -#line 976 "src/parser.y" +#line 981 "src/parser.y" { (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 4061 "src/parser.c" +#line 4066 "src/parser.c" break; case 164: /* MkDictPair: BINDING ':' ExpD */ -#line 980 "src/parser.y" +#line 985 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[-2].literal)))), (yyvsp[0].blk)); jv_free((yyvsp[-2].literal)); } -#line 4071 "src/parser.c" +#line 4076 "src/parser.c" break; case 165: /* MkDictPair: BINDING */ -#line 985 "src/parser.y" +#line 990 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const((yyvsp[0].literal)), gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[0].literal))))); } -#line 4080 "src/parser.c" +#line 4085 "src/parser.c" break; case 166: /* MkDictPair: IDENT */ -#line 989 "src/parser.y" +#line 994 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 4089 "src/parser.c" +#line 4094 "src/parser.c" break; case 167: /* MkDictPair: "$__loc__" */ -#line 993 "src/parser.y" +#line 998 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const(jv_string("__loc__")), gen_loc_object(&(yyloc), locations)); } -#line 4098 "src/parser.c" +#line 4103 "src/parser.c" break; case 168: /* MkDictPair: Keyword */ -#line 997 "src/parser.y" +#line 1002 "src/parser.y" { (yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))), gen_index(gen_noop(), gen_const((yyvsp[0].literal)))); } -#line 4107 "src/parser.c" +#line 4112 "src/parser.c" break; case 169: /* MkDictPair: '(' Exp ')' ':' ExpD */ -#line 1001 "src/parser.y" +#line 1006 "src/parser.y" { jv msg = check_object_key((yyvsp[-3].blk)); if (jv_is_valid(msg)) { @@ -4116,20 +4121,20 @@ yyreduce: jv_free(msg); (yyval.blk) = gen_dictpair((yyvsp[-3].blk), (yyvsp[0].blk)); } -#line 4120 "src/parser.c" +#line 4125 "src/parser.c" break; case 170: /* MkDictPair: error ':' ExpD */ -#line 1009 "src/parser.y" +#line 1014 "src/parser.y" { FAIL((yyloc), "May need parentheses around object key expression"); (yyval.blk) = (yyvsp[0].blk); } -#line 4129 "src/parser.c" +#line 4134 "src/parser.c" break; -#line 4133 "src/parser.c" +#line 4138 "src/parser.c" default: break; } @@ -4358,7 +4363,7 @@ yyreturnlab: return yyresult; } -#line 1013 "src/parser.y" +#line 1018 "src/parser.y" int jq_parse(struct locfile* locations, block* answer) { diff --git a/src/parser.y b/src/parser.y index f23f5953..94ede7c4 100644 --- a/src/parser.y +++ b/src/parser.y @@ -230,7 +230,16 @@ static block constant_fold(block a, block b, int 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 '/': + if (nb == 0.0) return gen_noop(); + res = jv_number(na / nb); + break; + case '%': +#define is_unsafe_to_int_cast(n) (isnan(n) || (n) < INTMAX_MIN || -(n) < INTMAX_MIN) + if (is_unsafe_to_int_cast(na) || is_unsafe_to_int_cast(nb) || (intmax_t)nb == 0) return gen_noop(); +#undef is_unsafe_to_int_cast + res = jv_number((intmax_t)na % (intmax_t)nb); + 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; @@ -463,14 +472,10 @@ Exp "*=" Exp { Exp '/' Exp { $$ = gen_binop($1, $3, '/'); - if (block_is_const_inf($$)) - FAIL(@$, "Division by zero?"); } | Exp '%' Exp { $$ = gen_binop($1, $3, '%'); - if (block_is_const_inf($$)) - FAIL(@$, "Remainder by zero?"); } | Exp "/=" Exp { diff --git a/tests/jq.test b/tests/jq.test index 55630a5a..73cf93d0 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -556,9 +556,13 @@ null null 172 -[(infinite, -infinite) % (1, -1)] +[(infinite, -infinite) % (1, -1, infinite)] null -[0,0,0,0] +[0,0,0,0,0,-1] + +[nan % 1, 1 % nan | isnan] +null +[true,true] 1 + tonumber + ("10" | tonumber) 4 @@ -1664,18 +1668,21 @@ try (1/.) catch . 0 "number (1) and number (0) cannot be divided because the divisor is zero" -0/0, (0 as $x | $x/0) | isnan +try (1/0) catch . 0 -true -true +"number (1) and number (0) cannot be divided because the divisor is zero" + +try (0/0) catch . +0 +"number (0) and number (0) cannot be divided because the divisor is zero" try (1%.) catch . 0 "number (1) and number (0) cannot be divided (remainder) because the divisor is zero" -%%FAIL -1/0 -jq: error: Division by zero? at , line 1: +try (1%0) catch . +0 +"number (1) and number (0) cannot be divided (remainder) because the divisor is zero" # Basic numbers tests: integers, powers of two [range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2|round] == $powers diff --git a/tests/shtest b/tests/shtest index a644b574..3ed22c30 100755 --- a/tests/shtest +++ b/tests/shtest @@ -30,47 +30,67 @@ $VALGRIND $Q $JQ -Rne '[inputs] == ["a\u0000b", "c\u0000d", "e"]' $d/input # String constant folding (addition only) nref=$($VALGRIND $Q $JQ -n --debug-dump-disasm '"foo"' | wc -l) +n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '"foo" + "bar"' | wc -l) +if [ $n -ne $nref ]; then + echo "Constant expression folding for strings didn't work" + exit 1 +fi -# Numeric constant folding (not all ops yet) +# Numeric constant folding (binary operators) n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '1+1' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '1-1' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '2*3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9/3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 +fi +n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9%3' | wc -l) +if [ $n -ne $nref ]; then + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9==3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9!=3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 +fi +n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9<3' | wc -l) +if [ $n -ne $nref ]; then + echo "Constant expression folding for numbers didn't work" + exit 1 +fi +n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9>3' | wc -l) +if [ $n -ne $nref ]; then + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9<=3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi n=$($VALGRIND $Q $JQ -n --debug-dump-disasm '9>=3' | wc -l) if [ $n -ne $nref ]; then - echo "Constant expression folding for strings didn't work" - exit 1 + echo "Constant expression folding for numbers didn't work" + exit 1 fi ## Test JSON sequence support