diff --git a/src/compile.c b/src/compile.c
index 58d08573df..5645fa5f90 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -1034,43 +1034,40 @@ block gen_cond(block cond, block iftrue, block iffalse) {
BLOCK(gen_op_simple(POP), iffalse)));
}
-block gen_try_handler(block handler) {
- // Quite a pain just to hide jq's internal errors.
- return gen_cond(// `if type=="object" and .__jq
- gen_and(gen_call("_equal",
- BLOCK(gen_lambda(gen_const(jv_string("object"))),
- gen_lambda(gen_call("type", gen_noop())))),
- BLOCK(gen_subexp(gen_const(jv_string("__jq"))),
- gen_noop(),
- gen_op_simple(INDEX))),
- // `then error`
- gen_call("error", gen_noop()),
- // `else HANDLER end`
- handler);
-}
-
block gen_try(block exp, block handler) {
/*
- * Produce something like:
- * FORK_OPT
+ * Produce:
+ *
+ * TRY_BEGIN handler
*
- * JUMP
- *
+ * TRY_END
+ * JUMP past_handler
+ * handler:
+ * past_handler:
*
- * If this is not an internal try/catch, then catch and re-raise
- * internal errors to prevent them from leaking.
+ * If backtracks then TRY_BEGIN will backtrack.
*
- * The handler will only execute if we backtrack to the FORK_OPT with
- * an error (exception). If produces no value then FORK_OPT
- * will backtrack (propagate the `empty`, as it were. If
- * produces a value then we'll execute whatever bytecode follows this
- * sequence.
+ * If produces a value then we'll execute whatever bytecode follows
+ * this sequence. If that code raises an exception, then TRY_END will wrap
+ * and re-raise that exception, and TRY_BEGIN will unwrap and re-raise the
+ * exception (see jq_next()).
+ *
+ * If raises then the TRY_BEGIN will see a non-wrapped exception and
+ * will jump to the handler (note the TRY_END will not execute in this case),
+ * and if the handler produces any values, then we'll execute whatever
+ * bytecode follows this sequence. Note that TRY_END will not execute in
+ * this case, so if the handler raises an exception, or code past the handler
+ * raises an exception, then that exception won't be wrapped and re-raised,
+ * and the TRY_BEGIN will not catch it because it does not stack_save() when
+ * it branches to the handler.
*/
- if (!handler.first && !handler.last)
- // A hack to deal with `.` as the handler; we could use a real NOOP here
- handler = BLOCK(gen_op_simple(DUP), gen_op_simple(POP), handler);
- exp = BLOCK(exp, gen_op_target(JUMP, handler));
- return BLOCK(gen_op_target(FORK_OPT, exp), exp, handler);
+
+ if (block_is_noop(handler))
+ handler = BLOCK(gen_op_simple(DUP), gen_op_simple(POP));
+
+ block jump = gen_op_target(JUMP, handler);
+ return BLOCK(gen_op_target(TRY_BEGIN, jump), exp, gen_op_simple(TRY_END),
+ jump, handler);
}
block gen_label(const char *label, block exp) {
diff --git a/src/compile.h b/src/compile.h
index cccd661dcb..f690adc240 100644
--- a/src/compile.h
+++ b/src/compile.h
@@ -59,7 +59,6 @@ block gen_destructure(block var, block matcher, block body);
block gen_destructure_alt(block matcher);
block gen_cond(block cond, block iftrue, block iffalse);
-block gen_try_handler(block handler);
block gen_try(block exp, block handler);
block gen_label(const char *label, block exp);
diff --git a/src/execute.c b/src/execute.c
index 34bb63dc93..091ddbc355 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -348,6 +348,7 @@ jv jq_next(jq_state *jq) {
int raising;
int backtracking = !jq->initial_execution;
+
jq->initial_execution = 0;
assert(jv_get_kind(jq->error) == JV_KIND_NULL);
while (1) {
@@ -808,7 +809,59 @@ jv jq_next(jq_state *jq) {
break;
}
- case FORK_OPT:
+ case TRY_BEGIN:
+ stack_save(jq, pc - 1, stack_get_pos(jq));
+ pc++; // skip handler offset this time
+ break;
+
+ case TRY_END:
+ stack_save(jq, pc - 1, stack_get_pos(jq));
+ break;
+
+ case ON_BACKTRACK(TRY_BEGIN): {
+ if (!raising) {
+ /*
+ * `try EXP ...` -- EXP backtracked (e.g., EXP was `empty`), so we
+ * backtrack more:
+ */
+ jv_free(stack_pop(jq));
+ goto do_backtrack;
+ }
+
+ /*
+ * Else `(try EXP ... ) | EXP2` raised an error.
+ *
+ * If the error was wrapped in another error, then that means EXP2 raised
+ * the error. We unwrap it and re-raise it as it wasn't raised by EXP.
+ *
+ * See commentary in gen_try().
+ */
+ jv e = jv_invalid_get_msg(jv_copy(jq->error));
+ if (!jv_is_valid(e) && jv_invalid_has_msg(jv_copy(e))) {
+ set_error(jq, e);
+ goto do_backtrack;
+ }
+ jv_free(e);
+
+ /*
+ * Else we caught an error containing a non-error value, so we jump to
+ * the handler.
+ *
+ * See commentary in gen_try().
+ */
+ uint16_t offset = *pc++;
+ jv_free(stack_pop(jq)); // free the input
+ stack_push(jq, jv_invalid_get_msg(jq->error)); // push the error's message
+ jq->error = jv_null();
+ pc += offset;
+ break;
+ }
+ case ON_BACKTRACK(TRY_END):
+ // Wrap the error so the matching TRY_BEGIN doesn't catch it
+ if (raising)
+ set_error(jq, jv_invalid_with_msg(jv_copy(jq->error)));
+ goto do_backtrack;
+
case DESTRUCTURE_ALT:
case FORK: {
stack_save(jq, pc - 1, stack_get_pos(jq));
@@ -816,7 +869,6 @@ jv jq_next(jq_state *jq) {
break;
}
- case ON_BACKTRACK(FORK_OPT):
case ON_BACKTRACK(DESTRUCTURE_ALT): {
if (jv_is_valid(jq->error)) {
// `try EXP ...` backtracked here (no value, `empty`), so we backtrack more
diff --git a/src/opcode_list.h b/src/opcode_list.h
index 886131d7c6..06147f0ff7 100644
--- a/src/opcode_list.h
+++ b/src/opcode_list.h
@@ -11,9 +11,10 @@ OP(STORE_GLOBAL, GLOBAL, 0, 0)
OP(INDEX, NONE, 2, 1)
OP(INDEX_OPT, NONE, 2, 1)
OP(EACH, NONE, 1, 1)
-OP(EACH_OPT, NONE, 1, 1)
+OP(EACH_OPT, NONE, 1, 1)
OP(FORK, BRANCH, 0, 0)
-OP(FORK_OPT, BRANCH, 0, 0)
+OP(TRY_BEGIN, BRANCH, 0, 0)
+OP(TRY_END, NONE, 0, 0)
OP(JUMP, BRANCH, 0, 0)
OP(JUMP_F,BRANCH, 1, 0)
OP(BACKTRACK, NONE, 0, 0)
diff --git a/src/parser.c b/src/parser.c
index 45e03b06b6..e7c6a4ea00 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -965,23 +965,23 @@ static const yytype_int8 yytranslate[] =
static const yytype_int16 yyrline[] =
{
0, 312, 312, 315, 320, 323, 338, 341, 346, 349,
- 354, 358, 361, 365, 369, 373, 376, 381, 385, 389,
- 394, 401, 405, 409, 413, 417, 421, 425, 429, 433,
- 437, 441, 445, 449, 453, 457, 461, 465, 471, 477,
- 481, 485, 489, 493, 497, 501, 505, 509, 514, 517,
- 534, 543, 550, 558, 569, 574, 580, 583, 588, 592,
- 599, 599, 603, 603, 610, 613, 616, 622, 625, 628,
- 633, 636, 639, 645, 648, 651, 659, 663, 666, 669,
- 672, 675, 678, 681, 684, 687, 691, 697, 700, 703,
- 706, 709, 712, 715, 718, 721, 724, 727, 730, 733,
- 736, 739, 742, 745, 748, 751, 754, 757, 779, 783,
- 787, 790, 802, 807, 808, 809, 810, 813, 816, 821,
- 826, 829, 834, 837, 842, 846, 849, 854, 857, 862,
- 865, 870, 873, 876, 879, 882, 885, 893, 899, 902,
- 905, 908, 911, 914, 917, 920, 923, 926, 929, 932,
- 935, 938, 941, 944, 947, 950, 955, 958, 959, 960,
- 963, 966, 969, 972, 976, 980, 984, 988, 992, 996,
- 1004
+ 354, 358, 361, 365, 369, 373, 376, 381, 384, 387,
+ 392, 399, 403, 407, 411, 415, 419, 423, 427, 431,
+ 435, 439, 443, 447, 451, 455, 459, 463, 469, 475,
+ 479, 483, 487, 491, 495, 499, 503, 507, 512, 515,
+ 532, 541, 548, 556, 567, 572, 578, 581, 586, 590,
+ 597, 597, 601, 601, 608, 611, 614, 620, 623, 626,
+ 631, 634, 637, 643, 646, 649, 657, 661, 664, 667,
+ 670, 673, 676, 679, 682, 685, 689, 695, 698, 701,
+ 704, 707, 710, 713, 716, 719, 722, 725, 728, 731,
+ 734, 737, 740, 743, 746, 749, 752, 755, 777, 781,
+ 785, 788, 800, 805, 806, 807, 808, 811, 814, 819,
+ 824, 827, 832, 835, 840, 844, 847, 852, 855, 860,
+ 863, 868, 871, 874, 877, 880, 883, 891, 897, 900,
+ 903, 906, 909, 912, 915, 918, 921, 924, 927, 930,
+ 933, 936, 939, 942, 945, 948, 953, 956, 957, 958,
+ 961, 964, 967, 970, 974, 978, 982, 986, 990, 994,
+ 1002
};
#endif
@@ -2818,271 +2818,269 @@ YYLTYPE yylloc = yyloc_default;
case 17: /* Exp: "try" Exp "catch" Exp */
#line 381 "src/parser.y"
{
- //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, $4);
- (yyval.blk) = gen_try((yyvsp[-2].blk), gen_try_handler((yyvsp[0].blk)));
+ (yyval.blk) = gen_try((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2825 "src/parser.c"
+#line 2824 "src/parser.c"
break;
case 18: /* Exp: "try" Exp */
-#line 385 "src/parser.y"
+#line 384 "src/parser.y"
{
- //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, gen_op_simple(BACKTRACK));
(yyval.blk) = gen_try((yyvsp[0].blk), gen_op_simple(BACKTRACK));
}
-#line 2834 "src/parser.c"
+#line 2832 "src/parser.c"
break;
case 19: /* Exp: "try" Exp "catch" error */
-#line 389 "src/parser.y"
+#line 387 "src/parser.y"
{
FAIL((yyloc), "Possibly unterminated 'try' statement");
(yyval.blk) = (yyvsp[-2].blk);
}
-#line 2843 "src/parser.c"
+#line 2841 "src/parser.c"
break;
case 20: /* Exp: "label" BINDING '|' Exp */
-#line 394 "src/parser.y"
+#line 392 "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 2854 "src/parser.c"
+#line 2852 "src/parser.c"
break;
case 21: /* Exp: Exp '?' */
-#line 401 "src/parser.y"
+#line 399 "src/parser.y"
{
(yyval.blk) = gen_try((yyvsp[-1].blk), gen_op_simple(BACKTRACK));
}
-#line 2862 "src/parser.c"
+#line 2860 "src/parser.c"
break;
case 22: /* Exp: Exp '=' Exp */
-#line 405 "src/parser.y"
+#line 403 "src/parser.y"
{
(yyval.blk) = gen_call("_assign", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk))));
}
-#line 2870 "src/parser.c"
+#line 2868 "src/parser.c"
break;
case 23: /* Exp: Exp "or" Exp */
-#line 409 "src/parser.y"
+#line 407 "src/parser.y"
{
(yyval.blk) = gen_or((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2878 "src/parser.c"
+#line 2876 "src/parser.c"
break;
case 24: /* Exp: Exp "and" Exp */
-#line 413 "src/parser.y"
+#line 411 "src/parser.y"
{
(yyval.blk) = gen_and((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2886 "src/parser.c"
+#line 2884 "src/parser.c"
break;
case 25: /* Exp: Exp "//" Exp */
-#line 417 "src/parser.y"
+#line 415 "src/parser.y"
{
(yyval.blk) = gen_definedor((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2894 "src/parser.c"
+#line 2892 "src/parser.c"
break;
case 26: /* Exp: Exp "//=" Exp */
-#line 421 "src/parser.y"
+#line 419 "src/parser.y"
{
(yyval.blk) = gen_definedor_assign((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2902 "src/parser.c"
+#line 2900 "src/parser.c"
break;
case 27: /* Exp: Exp "|=" Exp */
-#line 425 "src/parser.y"
+#line 423 "src/parser.y"
{
(yyval.blk) = gen_call("_modify", BLOCK(gen_lambda((yyvsp[-2].blk)), gen_lambda((yyvsp[0].blk))));
}
-#line 2910 "src/parser.c"
+#line 2908 "src/parser.c"
break;
case 28: /* Exp: Exp '|' Exp */
-#line 429 "src/parser.y"
+#line 427 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2918 "src/parser.c"
+#line 2916 "src/parser.c"
break;
case 29: /* Exp: Exp ',' Exp */
-#line 433 "src/parser.y"
+#line 431 "src/parser.y"
{
(yyval.blk) = gen_both((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 2926 "src/parser.c"
+#line 2924 "src/parser.c"
break;
case 30: /* Exp: Exp '+' Exp */
-#line 437 "src/parser.y"
+#line 435 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '+');
}
-#line 2934 "src/parser.c"
+#line 2932 "src/parser.c"
break;
case 31: /* Exp: Exp "+=" Exp */
-#line 441 "src/parser.y"
+#line 439 "src/parser.y"
{
(yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '+');
}
-#line 2942 "src/parser.c"
+#line 2940 "src/parser.c"
break;
case 32: /* Exp: '-' Exp */
-#line 445 "src/parser.y"
+#line 443 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop()));
}
-#line 2950 "src/parser.c"
+#line 2948 "src/parser.c"
break;
case 33: /* Exp: Exp '-' Exp */
-#line 449 "src/parser.y"
+#line 447 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '-');
}
-#line 2958 "src/parser.c"
+#line 2956 "src/parser.c"
break;
case 34: /* Exp: Exp "-=" Exp */
-#line 453 "src/parser.y"
+#line 451 "src/parser.y"
{
(yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '-');
}
-#line 2966 "src/parser.c"
+#line 2964 "src/parser.c"
break;
case 35: /* Exp: Exp '*' Exp */
-#line 457 "src/parser.y"
+#line 455 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '*');
}
-#line 2974 "src/parser.c"
+#line 2972 "src/parser.c"
break;
case 36: /* Exp: Exp "*=" Exp */
-#line 461 "src/parser.y"
+#line 459 "src/parser.y"
{
(yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '*');
}
-#line 2982 "src/parser.c"
+#line 2980 "src/parser.c"
break;
case 37: /* Exp: Exp '/' Exp */
-#line 465 "src/parser.y"
+#line 463 "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 2992 "src/parser.c"
+#line 2990 "src/parser.c"
break;
case 38: /* Exp: Exp '%' Exp */
-#line 471 "src/parser.y"
+#line 469 "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 3002 "src/parser.c"
+#line 3000 "src/parser.c"
break;
case 39: /* Exp: Exp "/=" Exp */
-#line 477 "src/parser.y"
+#line 475 "src/parser.y"
{
(yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '/');
}
-#line 3010 "src/parser.c"
+#line 3008 "src/parser.c"
break;
case 40: /* Exp: Exp "%=" Exp */
-#line 481 "src/parser.y"
+#line 479 "src/parser.y"
{
(yyval.blk) = gen_update((yyvsp[-2].blk), (yyvsp[0].blk), '%');
}
-#line 3018 "src/parser.c"
+#line 3016 "src/parser.c"
break;
case 41: /* Exp: Exp "==" Exp */
-#line 485 "src/parser.y"
+#line 483 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), EQ);
}
-#line 3026 "src/parser.c"
+#line 3024 "src/parser.c"
break;
case 42: /* Exp: Exp "!=" Exp */
-#line 489 "src/parser.y"
+#line 487 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), NEQ);
}
-#line 3034 "src/parser.c"
+#line 3032 "src/parser.c"
break;
case 43: /* Exp: Exp '<' Exp */
-#line 493 "src/parser.y"
+#line 491 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '<');
}
-#line 3042 "src/parser.c"
+#line 3040 "src/parser.c"
break;
case 44: /* Exp: Exp '>' Exp */
-#line 497 "src/parser.y"
+#line 495 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), '>');
}
-#line 3050 "src/parser.c"
+#line 3048 "src/parser.c"
break;
case 45: /* Exp: Exp "<=" Exp */
-#line 501 "src/parser.y"
+#line 499 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), LESSEQ);
}
-#line 3058 "src/parser.c"
+#line 3056 "src/parser.c"
break;
case 46: /* Exp: Exp ">=" Exp */
-#line 505 "src/parser.y"
+#line 503 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-2].blk), (yyvsp[0].blk), GREATEREQ);
}
-#line 3066 "src/parser.c"
+#line 3064 "src/parser.c"
break;
case 47: /* Exp: Term */
-#line 509 "src/parser.y"
+#line 507 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3074 "src/parser.c"
+#line 3072 "src/parser.c"
break;
case 48: /* Import: ImportWhat ';' */
-#line 514 "src/parser.y"
+#line 512 "src/parser.y"
{
(yyval.blk) = (yyvsp[-1].blk);
}
-#line 3082 "src/parser.c"
+#line 3080 "src/parser.c"
break;
case 49: /* Import: ImportWhat Exp ';' */
-#line 517 "src/parser.y"
+#line 515 "src/parser.y"
{
if (!block_is_const((yyvsp[-1].blk))) {
FAIL((yyloc), "Module metadata must be constant");
@@ -3098,11 +3096,11 @@ YYLTYPE yylloc = yyloc_default;
(yyval.blk) = gen_import_meta((yyvsp[-2].blk), (yyvsp[-1].blk));
}
}
-#line 3102 "src/parser.c"
+#line 3100 "src/parser.c"
break;
case 50: /* ImportWhat: "import" ImportFrom "as" BINDING */
-#line 534 "src/parser.y"
+#line 532 "src/parser.y"
{
jv v = block_const((yyvsp[-2].blk));
// XXX Make gen_import take only blocks and the int is_data so we
@@ -3112,11 +3110,11 @@ YYLTYPE yylloc = yyloc_default;
jv_free((yyvsp[0].literal));
jv_free(v);
}
-#line 3116 "src/parser.c"
+#line 3114 "src/parser.c"
break;
case 51: /* ImportWhat: "import" ImportFrom "as" IDENT */
-#line 543 "src/parser.y"
+#line 541 "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);
@@ -3124,22 +3122,22 @@ YYLTYPE yylloc = yyloc_default;
jv_free((yyvsp[0].literal));
jv_free(v);
}
-#line 3128 "src/parser.c"
+#line 3126 "src/parser.c"
break;
case 52: /* ImportWhat: "include" ImportFrom */
-#line 550 "src/parser.y"
+#line 548 "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 3139 "src/parser.c"
+#line 3137 "src/parser.c"
break;
case 53: /* ImportFrom: String */
-#line 558 "src/parser.y"
+#line 556 "src/parser.y"
{
if (!block_is_const((yyvsp[0].blk))) {
FAIL((yyloc), "Import path must be constant");
@@ -3149,181 +3147,181 @@ YYLTYPE yylloc = yyloc_default;
(yyval.blk) = (yyvsp[0].blk);
}
}
-#line 3153 "src/parser.c"
+#line 3151 "src/parser.c"
break;
case 54: /* FuncDef: "def" IDENT ':' Exp ';' */
-#line 569 "src/parser.y"
+#line 567 "src/parser.y"
{
(yyval.blk) = gen_function(jv_string_value((yyvsp[-3].literal)), gen_noop(), (yyvsp[-1].blk));
jv_free((yyvsp[-3].literal));
}
-#line 3162 "src/parser.c"
+#line 3160 "src/parser.c"
break;
case 55: /* FuncDef: "def" IDENT '(' Params ')' ':' Exp ';' */
-#line 574 "src/parser.y"
+#line 572 "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 3171 "src/parser.c"
+#line 3169 "src/parser.c"
break;
case 56: /* Params: Param */
-#line 580 "src/parser.y"
+#line 578 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3179 "src/parser.c"
+#line 3177 "src/parser.c"
break;
case 57: /* Params: Params ';' Param */
-#line 583 "src/parser.y"
+#line 581 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3187 "src/parser.c"
+#line 3185 "src/parser.c"
break;
case 58: /* Param: BINDING */
-#line 588 "src/parser.y"
+#line 586 "src/parser.y"
{
(yyval.blk) = gen_param_regular(jv_string_value((yyvsp[0].literal)));
jv_free((yyvsp[0].literal));
}
-#line 3196 "src/parser.c"
+#line 3194 "src/parser.c"
break;
case 59: /* Param: IDENT */
-#line 592 "src/parser.y"
+#line 590 "src/parser.y"
{
(yyval.blk) = gen_param(jv_string_value((yyvsp[0].literal)));
jv_free((yyvsp[0].literal));
}
-#line 3205 "src/parser.c"
+#line 3203 "src/parser.c"
break;
case 60: /* @1: %empty */
-#line 599 "src/parser.y"
+#line 597 "src/parser.y"
{ (yyval.literal) = jv_string("text"); }
-#line 3211 "src/parser.c"
+#line 3209 "src/parser.c"
break;
case 61: /* String: QQSTRING_START @1 QQString QQSTRING_END */
-#line 599 "src/parser.y"
+#line 597 "src/parser.y"
{
(yyval.blk) = (yyvsp[-1].blk);
jv_free((yyvsp[-2].literal));
}
-#line 3220 "src/parser.c"
+#line 3218 "src/parser.c"
break;
case 62: /* @2: %empty */
-#line 603 "src/parser.y"
+#line 601 "src/parser.y"
{ (yyval.literal) = (yyvsp[-1].literal); }
-#line 3226 "src/parser.c"
+#line 3224 "src/parser.c"
break;
case 63: /* String: FORMAT QQSTRING_START @2 QQString QQSTRING_END */
-#line 603 "src/parser.y"
+#line 601 "src/parser.y"
{
(yyval.blk) = (yyvsp[-1].blk);
jv_free((yyvsp[-2].literal));
}
-#line 3235 "src/parser.c"
+#line 3233 "src/parser.c"
break;
case 64: /* QQString: %empty */
-#line 610 "src/parser.y"
+#line 608 "src/parser.y"
{
(yyval.blk) = gen_const(jv_string(""));
}
-#line 3243 "src/parser.c"
+#line 3241 "src/parser.c"
break;
case 65: /* QQString: QQString QQSTRING_TEXT */
-#line 613 "src/parser.y"
+#line 611 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-1].blk), gen_const((yyvsp[0].literal)), '+');
}
-#line 3251 "src/parser.c"
+#line 3249 "src/parser.c"
break;
case 66: /* QQString: QQString QQSTRING_INTERP_START Exp QQSTRING_INTERP_END */
-#line 616 "src/parser.y"
+#line 614 "src/parser.y"
{
(yyval.blk) = gen_binop((yyvsp[-3].blk), gen_format((yyvsp[-1].blk), jv_copy((yyvsp[-4].literal))), '+');
}
-#line 3259 "src/parser.c"
+#line 3257 "src/parser.c"
break;
case 67: /* ElseBody: "elif" Exp "then" Exp ElseBody */
-#line 622 "src/parser.y"
+#line 620 "src/parser.y"
{
(yyval.blk) = gen_cond((yyvsp[-3].blk), (yyvsp[-1].blk), (yyvsp[0].blk));
}
-#line 3267 "src/parser.c"
+#line 3265 "src/parser.c"
break;
case 68: /* ElseBody: "else" Exp "end" */
-#line 625 "src/parser.y"
+#line 623 "src/parser.y"
{
(yyval.blk) = (yyvsp[-1].blk);
}
-#line 3275 "src/parser.c"
+#line 3273 "src/parser.c"
break;
case 69: /* ElseBody: "end" */
-#line 628 "src/parser.y"
+#line 626 "src/parser.y"
{
(yyval.blk) = gen_noop();
}
-#line 3283 "src/parser.c"
+#line 3281 "src/parser.c"
break;
case 70: /* ExpD: ExpD '|' ExpD */
-#line 633 "src/parser.y"
+#line 631 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3291 "src/parser.c"
+#line 3289 "src/parser.c"
break;
case 71: /* ExpD: '-' ExpD */
-#line 636 "src/parser.y"
+#line 634 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[0].blk), gen_call("_negate", gen_noop()));
}
-#line 3299 "src/parser.c"
+#line 3297 "src/parser.c"
break;
case 72: /* ExpD: Term */
-#line 639 "src/parser.y"
+#line 637 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3307 "src/parser.c"
+#line 3305 "src/parser.c"
break;
case 73: /* Term: '.' */
-#line 645 "src/parser.y"
+#line 643 "src/parser.y"
{
(yyval.blk) = gen_noop();
}
-#line 3315 "src/parser.c"
+#line 3313 "src/parser.c"
break;
case 74: /* Term: ".." */
-#line 648 "src/parser.y"
+#line 646 "src/parser.y"
{
(yyval.blk) = gen_call("recurse", gen_noop());
}
-#line 3323 "src/parser.c"
+#line 3321 "src/parser.c"
break;
case 75: /* Term: "break" BINDING */
-#line 651 "src/parser.y"
+#line 649 "src/parser.y"
{
jv v = jv_string_fmt("*label-%s", jv_string_value((yyvsp[0].literal))); // impossible symbol
(yyval.blk) = gen_location((yyloc), locations,
@@ -3332,263 +3330,263 @@ YYLTYPE yylloc = yyloc_default;
jv_free(v);
jv_free((yyvsp[0].literal));
}
-#line 3336 "src/parser.c"
+#line 3334 "src/parser.c"
break;
case 76: /* Term: "break" error */
-#line 659 "src/parser.y"
+#line 657 "src/parser.y"
{
FAIL((yyloc), "break requires a label to break to");
(yyval.blk) = gen_noop();
}
-#line 3345 "src/parser.c"
+#line 3343 "src/parser.c"
break;
case 77: /* Term: Term FIELD '?' */
-#line 663 "src/parser.y"
+#line 661 "src/parser.y"
{
(yyval.blk) = gen_index_opt((yyvsp[-2].blk), gen_const((yyvsp[-1].literal)));
}
-#line 3353 "src/parser.c"
+#line 3351 "src/parser.c"
break;
case 78: /* Term: FIELD '?' */
-#line 666 "src/parser.y"
+#line 664 "src/parser.y"
{
(yyval.blk) = gen_index_opt(gen_noop(), gen_const((yyvsp[-1].literal)));
}
-#line 3361 "src/parser.c"
+#line 3359 "src/parser.c"
break;
case 79: /* Term: Term '.' String '?' */
-#line 669 "src/parser.y"
+#line 667 "src/parser.y"
{
(yyval.blk) = gen_index_opt((yyvsp[-3].blk), (yyvsp[-1].blk));
}
-#line 3369 "src/parser.c"
+#line 3367 "src/parser.c"
break;
case 80: /* Term: '.' String '?' */
-#line 672 "src/parser.y"
+#line 670 "src/parser.y"
{
(yyval.blk) = gen_index_opt(gen_noop(), (yyvsp[-1].blk));
}
-#line 3377 "src/parser.c"
+#line 3375 "src/parser.c"
break;
case 81: /* Term: Term FIELD */
-#line 675 "src/parser.y"
+#line 673 "src/parser.y"
{
(yyval.blk) = gen_index((yyvsp[-1].blk), gen_const((yyvsp[0].literal)));
}
-#line 3385 "src/parser.c"
+#line 3383 "src/parser.c"
break;
case 82: /* Term: FIELD */
-#line 678 "src/parser.y"
+#line 676 "src/parser.y"
{
(yyval.blk) = gen_index(gen_noop(), gen_const((yyvsp[0].literal)));
}
-#line 3393 "src/parser.c"
+#line 3391 "src/parser.c"
break;
case 83: /* Term: Term '.' String */
-#line 681 "src/parser.y"
+#line 679 "src/parser.y"
{
(yyval.blk) = gen_index((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3401 "src/parser.c"
+#line 3399 "src/parser.c"
break;
case 84: /* Term: '.' String */
-#line 684 "src/parser.y"
+#line 682 "src/parser.y"
{
(yyval.blk) = gen_index(gen_noop(), (yyvsp[0].blk));
}
-#line 3409 "src/parser.c"
+#line 3407 "src/parser.c"
break;
case 85: /* Term: '.' error */
-#line 687 "src/parser.y"
+#line 685 "src/parser.y"
{
FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields");
(yyval.blk) = gen_noop();
}
-#line 3418 "src/parser.c"
+#line 3416 "src/parser.c"
break;
case 86: /* Term: '.' IDENT error */
-#line 691 "src/parser.y"
+#line 689 "src/parser.y"
{
jv_free((yyvsp[-1].literal));
FAIL((yyloc), "try .[\"field\"] instead of .field for unusually named fields");
(yyval.blk) = gen_noop();
}
-#line 3428 "src/parser.c"
+#line 3426 "src/parser.c"
break;
case 87: /* Term: Term '[' Exp ']' '?' */
-#line 697 "src/parser.y"
+#line 695 "src/parser.y"
{
(yyval.blk) = gen_index_opt((yyvsp[-4].blk), (yyvsp[-2].blk));
}
-#line 3436 "src/parser.c"
+#line 3434 "src/parser.c"
break;
case 88: /* Term: Term '[' Exp ']' */
-#line 700 "src/parser.y"
+#line 698 "src/parser.y"
{
(yyval.blk) = gen_index((yyvsp[-3].blk), (yyvsp[-1].blk));
}
-#line 3444 "src/parser.c"
+#line 3442 "src/parser.c"
break;
case 89: /* Term: Term '.' '[' Exp ']' '?' */
-#line 703 "src/parser.y"
+#line 701 "src/parser.y"
{
(yyval.blk) = gen_index_opt((yyvsp[-5].blk), (yyvsp[-2].blk));
}
-#line 3452 "src/parser.c"
+#line 3450 "src/parser.c"
break;
case 90: /* Term: Term '.' '[' Exp ']' */
-#line 706 "src/parser.y"
+#line 704 "src/parser.y"
{
(yyval.blk) = gen_index((yyvsp[-4].blk), (yyvsp[-1].blk));
}
-#line 3460 "src/parser.c"
+#line 3458 "src/parser.c"
break;
case 91: /* Term: Term '[' ']' '?' */
-#line 709 "src/parser.y"
+#line 707 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH_OPT));
}
-#line 3468 "src/parser.c"
+#line 3466 "src/parser.c"
break;
case 92: /* Term: Term '[' ']' */
-#line 712 "src/parser.y"
+#line 710 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-2].blk), gen_op_simple(EACH));
}
-#line 3476 "src/parser.c"
+#line 3474 "src/parser.c"
break;
case 93: /* Term: Term '.' '[' ']' '?' */
-#line 715 "src/parser.y"
+#line 713 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-4].blk), gen_op_simple(EACH_OPT));
}
-#line 3484 "src/parser.c"
+#line 3482 "src/parser.c"
break;
case 94: /* Term: Term '.' '[' ']' */
-#line 718 "src/parser.y"
+#line 716 "src/parser.y"
{
(yyval.blk) = block_join((yyvsp[-3].blk), gen_op_simple(EACH));
}
-#line 3492 "src/parser.c"
+#line 3490 "src/parser.c"
break;
case 95: /* Term: Term '[' Exp ':' Exp ']' '?' */
-#line 721 "src/parser.y"
+#line 719 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-6].blk), (yyvsp[-4].blk), (yyvsp[-2].blk), INDEX_OPT);
}
-#line 3500 "src/parser.c"
+#line 3498 "src/parser.c"
break;
case 96: /* Term: Term '[' Exp ':' ']' '?' */
-#line 724 "src/parser.y"
+#line 722 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), gen_const(jv_null()), INDEX_OPT);
}
-#line 3508 "src/parser.c"
+#line 3506 "src/parser.c"
break;
case 97: /* Term: Term '[' ':' Exp ']' '?' */
-#line 727 "src/parser.y"
+#line 725 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-5].blk), gen_const(jv_null()), (yyvsp[-2].blk), INDEX_OPT);
}
-#line 3516 "src/parser.c"
+#line 3514 "src/parser.c"
break;
case 98: /* Term: Term '[' Exp ':' Exp ']' */
-#line 730 "src/parser.y"
+#line 728 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-5].blk), (yyvsp[-3].blk), (yyvsp[-1].blk), INDEX);
}
-#line 3524 "src/parser.c"
+#line 3522 "src/parser.c"
break;
case 99: /* Term: Term '[' Exp ':' ']' */
-#line 733 "src/parser.y"
+#line 731 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-4].blk), (yyvsp[-2].blk), gen_const(jv_null()), INDEX);
}
-#line 3532 "src/parser.c"
+#line 3530 "src/parser.c"
break;
case 100: /* Term: Term '[' ':' Exp ']' */
-#line 736 "src/parser.y"
+#line 734 "src/parser.y"
{
(yyval.blk) = gen_slice_index((yyvsp[-4].blk), gen_const(jv_null()), (yyvsp[-1].blk), INDEX);
}
-#line 3540 "src/parser.c"
+#line 3538 "src/parser.c"
break;
case 101: /* Term: LITERAL */
-#line 739 "src/parser.y"
+#line 737 "src/parser.y"
{
(yyval.blk) = gen_const((yyvsp[0].literal));
}
-#line 3548 "src/parser.c"
+#line 3546 "src/parser.c"
break;
case 102: /* Term: String */
-#line 742 "src/parser.y"
+#line 740 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3556 "src/parser.c"
+#line 3554 "src/parser.c"
break;
case 103: /* Term: FORMAT */
-#line 745 "src/parser.y"
+#line 743 "src/parser.y"
{
(yyval.blk) = gen_format(gen_noop(), (yyvsp[0].literal));
}
-#line 3564 "src/parser.c"
+#line 3562 "src/parser.c"
break;
case 104: /* Term: '(' Exp ')' */
-#line 748 "src/parser.y"
+#line 746 "src/parser.y"
{
(yyval.blk) = (yyvsp[-1].blk);
}
-#line 3572 "src/parser.c"
+#line 3570 "src/parser.c"
break;
case 105: /* Term: '[' Exp ']' */
-#line 751 "src/parser.y"
+#line 749 "src/parser.y"
{
(yyval.blk) = gen_collect((yyvsp[-1].blk));
}
-#line 3580 "src/parser.c"
+#line 3578 "src/parser.c"
break;
case 106: /* Term: '[' ']' */
-#line 754 "src/parser.y"
+#line 752 "src/parser.y"
{
(yyval.blk) = gen_const(jv_array());
}
-#line 3588 "src/parser.c"
+#line 3586 "src/parser.c"
break;
case 107: /* Term: '{' MkDict '}' */
-#line 757 "src/parser.y"
+#line 755 "src/parser.y"
{
block o = gen_const_object((yyvsp[-1].blk));
if (o.first != NULL)
@@ -3596,37 +3594,37 @@ YYLTYPE yylloc = yyloc_default;
else
(yyval.blk) = BLOCK(gen_subexp(gen_const(jv_object())), (yyvsp[-1].blk), gen_op_simple(POP));
}
-#line 3600 "src/parser.c"
+#line 3598 "src/parser.c"
break;
case 108: /* Term: '$' '$' '$' BINDING */
-#line 779 "src/parser.y"
+#line 777 "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 3609 "src/parser.c"
+#line 3607 "src/parser.c"
break;
case 109: /* Term: BINDING */
-#line 783 "src/parser.y"
+#line 781 "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 3618 "src/parser.c"
+#line 3616 "src/parser.c"
break;
case 110: /* Term: "$__loc__" */
-#line 787 "src/parser.y"
+#line 785 "src/parser.y"
{
(yyval.blk) = gen_loc_object(&(yyloc), locations);
}
-#line 3626 "src/parser.c"
+#line 3624 "src/parser.c"
break;
case 111: /* Term: IDENT */
-#line 790 "src/parser.y"
+#line 788 "src/parser.y"
{
const char *s = jv_string_value((yyvsp[0].literal));
if (strcmp(s, "false") == 0)
@@ -3639,198 +3637,198 @@ YYLTYPE yylloc = yyloc_default;
(yyval.blk) = gen_location((yyloc), locations, gen_call(s, gen_noop()));
jv_free((yyvsp[0].literal));
}
-#line 3643 "src/parser.c"
+#line 3641 "src/parser.c"
break;
case 112: /* Term: IDENT '(' Args ')' */
-#line 802 "src/parser.y"
+#line 800 "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 3653 "src/parser.c"
+#line 3651 "src/parser.c"
break;
case 113: /* Term: '(' error ')' */
-#line 807 "src/parser.y"
+#line 805 "src/parser.y"
{ (yyval.blk) = gen_noop(); }
-#line 3659 "src/parser.c"
+#line 3657 "src/parser.c"
break;
case 114: /* Term: '[' error ']' */
-#line 808 "src/parser.y"
+#line 806 "src/parser.y"
{ (yyval.blk) = gen_noop(); }
-#line 3665 "src/parser.c"
+#line 3663 "src/parser.c"
break;
case 115: /* Term: Term '[' error ']' */
-#line 809 "src/parser.y"
+#line 807 "src/parser.y"
{ (yyval.blk) = (yyvsp[-3].blk); }
-#line 3671 "src/parser.c"
+#line 3669 "src/parser.c"
break;
case 116: /* Term: '{' error '}' */
-#line 810 "src/parser.y"
+#line 808 "src/parser.y"
{ (yyval.blk) = gen_noop(); }
-#line 3677 "src/parser.c"
+#line 3675 "src/parser.c"
break;
case 117: /* Args: Arg */
-#line 813 "src/parser.y"
+#line 811 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3685 "src/parser.c"
+#line 3683 "src/parser.c"
break;
case 118: /* Args: Args ';' Arg */
-#line 816 "src/parser.y"
+#line 814 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3693 "src/parser.c"
+#line 3691 "src/parser.c"
break;
case 119: /* Arg: Exp */
-#line 821 "src/parser.y"
+#line 819 "src/parser.y"
{
(yyval.blk) = gen_lambda((yyvsp[0].blk));
}
-#line 3701 "src/parser.c"
+#line 3699 "src/parser.c"
break;
case 120: /* RepPatterns: RepPatterns "?//" Pattern */
-#line 826 "src/parser.y"
+#line 824 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-2].blk), gen_destructure_alt((yyvsp[0].blk)));
}
-#line 3709 "src/parser.c"
+#line 3707 "src/parser.c"
break;
case 121: /* RepPatterns: Pattern */
-#line 829 "src/parser.y"
+#line 827 "src/parser.y"
{
(yyval.blk) = gen_destructure_alt((yyvsp[0].blk));
}
-#line 3717 "src/parser.c"
+#line 3715 "src/parser.c"
break;
case 122: /* Patterns: RepPatterns "?//" Pattern */
-#line 834 "src/parser.y"
+#line 832 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3725 "src/parser.c"
+#line 3723 "src/parser.c"
break;
case 123: /* Patterns: Pattern */
-#line 837 "src/parser.y"
+#line 835 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3733 "src/parser.c"
+#line 3731 "src/parser.c"
break;
case 124: /* Pattern: BINDING */
-#line 842 "src/parser.y"
+#line 840 "src/parser.y"
{
(yyval.blk) = gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal)));
jv_free((yyvsp[0].literal));
}
-#line 3742 "src/parser.c"
+#line 3740 "src/parser.c"
break;
case 125: /* Pattern: '[' ArrayPats ']' */
-#line 846 "src/parser.y"
+#line 844 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP));
}
-#line 3750 "src/parser.c"
+#line 3748 "src/parser.c"
break;
case 126: /* Pattern: '{' ObjPats '}' */
-#line 849 "src/parser.y"
+#line 847 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-1].blk), gen_op_simple(POP));
}
-#line 3758 "src/parser.c"
+#line 3756 "src/parser.c"
break;
case 127: /* ArrayPats: Pattern */
-#line 854 "src/parser.y"
+#line 852 "src/parser.y"
{
(yyval.blk) = gen_array_matcher(gen_noop(), (yyvsp[0].blk));
}
-#line 3766 "src/parser.c"
+#line 3764 "src/parser.c"
break;
case 128: /* ArrayPats: ArrayPats ',' Pattern */
-#line 857 "src/parser.y"
+#line 855 "src/parser.y"
{
(yyval.blk) = gen_array_matcher((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3774 "src/parser.c"
+#line 3772 "src/parser.c"
break;
case 129: /* ObjPats: ObjPat */
-#line 862 "src/parser.y"
+#line 860 "src/parser.y"
{
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3782 "src/parser.c"
+#line 3780 "src/parser.c"
break;
case 130: /* ObjPats: ObjPats ',' ObjPat */
-#line 865 "src/parser.y"
+#line 863 "src/parser.y"
{
(yyval.blk) = BLOCK((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3790 "src/parser.c"
+#line 3788 "src/parser.c"
break;
case 131: /* ObjPat: BINDING */
-#line 870 "src/parser.y"
+#line 868 "src/parser.y"
{
(yyval.blk) = gen_object_matcher(gen_const((yyvsp[0].literal)), gen_op_unbound(STOREV, jv_string_value((yyvsp[0].literal))));
}
-#line 3798 "src/parser.c"
+#line 3796 "src/parser.c"
break;
case 132: /* ObjPat: BINDING ':' Pattern */
-#line 873 "src/parser.y"
+#line 871 "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 3806 "src/parser.c"
+#line 3804 "src/parser.c"
break;
case 133: /* ObjPat: IDENT ':' Pattern */
-#line 876 "src/parser.y"
+#line 874 "src/parser.y"
{
(yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk));
}
-#line 3814 "src/parser.c"
+#line 3812 "src/parser.c"
break;
case 134: /* ObjPat: Keyword ':' Pattern */
-#line 879 "src/parser.y"
+#line 877 "src/parser.y"
{
(yyval.blk) = gen_object_matcher(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk));
}
-#line 3822 "src/parser.c"
+#line 3820 "src/parser.c"
break;
case 135: /* ObjPat: String ':' Pattern */
-#line 882 "src/parser.y"
+#line 880 "src/parser.y"
{
(yyval.blk) = gen_object_matcher((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 3830 "src/parser.c"
+#line 3828 "src/parser.c"
break;
case 136: /* ObjPat: '(' Exp ')' ':' Pattern */
-#line 885 "src/parser.y"
+#line 883 "src/parser.y"
{
jv msg = check_object_key((yyvsp[-3].blk));
if (jv_is_valid(msg)) {
@@ -3839,268 +3837,268 @@ YYLTYPE yylloc = yyloc_default;
jv_free(msg);
(yyval.blk) = gen_object_matcher((yyvsp[-3].blk), (yyvsp[0].blk));
}
-#line 3843 "src/parser.c"
+#line 3841 "src/parser.c"
break;
case 137: /* ObjPat: error ':' Pattern */
-#line 893 "src/parser.y"
+#line 891 "src/parser.y"
{
FAIL((yyloc), "May need parentheses around object key expression");
(yyval.blk) = (yyvsp[0].blk);
}
-#line 3852 "src/parser.c"
+#line 3850 "src/parser.c"
break;
case 138: /* Keyword: "as" */
-#line 899 "src/parser.y"
+#line 897 "src/parser.y"
{
(yyval.literal) = jv_string("as");
}
-#line 3860 "src/parser.c"
+#line 3858 "src/parser.c"
break;
case 139: /* Keyword: "def" */
-#line 902 "src/parser.y"
+#line 900 "src/parser.y"
{
(yyval.literal) = jv_string("def");
}
-#line 3868 "src/parser.c"
+#line 3866 "src/parser.c"
break;
case 140: /* Keyword: "module" */
-#line 905 "src/parser.y"
+#line 903 "src/parser.y"
{
(yyval.literal) = jv_string("module");
}
-#line 3876 "src/parser.c"
+#line 3874 "src/parser.c"
break;
case 141: /* Keyword: "import" */
-#line 908 "src/parser.y"
+#line 906 "src/parser.y"
{
(yyval.literal) = jv_string("import");
}
-#line 3884 "src/parser.c"
+#line 3882 "src/parser.c"
break;
case 142: /* Keyword: "include" */
-#line 911 "src/parser.y"
+#line 909 "src/parser.y"
{
(yyval.literal) = jv_string("include");
}
-#line 3892 "src/parser.c"
+#line 3890 "src/parser.c"
break;
case 143: /* Keyword: "if" */
-#line 914 "src/parser.y"
+#line 912 "src/parser.y"
{
(yyval.literal) = jv_string("if");
}
-#line 3900 "src/parser.c"
+#line 3898 "src/parser.c"
break;
case 144: /* Keyword: "then" */
-#line 917 "src/parser.y"
+#line 915 "src/parser.y"
{
(yyval.literal) = jv_string("then");
}
-#line 3908 "src/parser.c"
+#line 3906 "src/parser.c"
break;
case 145: /* Keyword: "else" */
-#line 920 "src/parser.y"
+#line 918 "src/parser.y"
{
(yyval.literal) = jv_string("else");
}
-#line 3916 "src/parser.c"
+#line 3914 "src/parser.c"
break;
case 146: /* Keyword: "elif" */
-#line 923 "src/parser.y"
+#line 921 "src/parser.y"
{
(yyval.literal) = jv_string("elif");
}
-#line 3924 "src/parser.c"
+#line 3922 "src/parser.c"
break;
case 147: /* Keyword: "reduce" */
-#line 926 "src/parser.y"
+#line 924 "src/parser.y"
{
(yyval.literal) = jv_string("reduce");
}
-#line 3932 "src/parser.c"
+#line 3930 "src/parser.c"
break;
case 148: /* Keyword: "foreach" */
-#line 929 "src/parser.y"
+#line 927 "src/parser.y"
{
(yyval.literal) = jv_string("foreach");
}
-#line 3940 "src/parser.c"
+#line 3938 "src/parser.c"
break;
case 149: /* Keyword: "end" */
-#line 932 "src/parser.y"
+#line 930 "src/parser.y"
{
(yyval.literal) = jv_string("end");
}
-#line 3948 "src/parser.c"
+#line 3946 "src/parser.c"
break;
case 150: /* Keyword: "and" */
-#line 935 "src/parser.y"
+#line 933 "src/parser.y"
{
(yyval.literal) = jv_string("and");
}
-#line 3956 "src/parser.c"
+#line 3954 "src/parser.c"
break;
case 151: /* Keyword: "or" */
-#line 938 "src/parser.y"
+#line 936 "src/parser.y"
{
(yyval.literal) = jv_string("or");
}
-#line 3964 "src/parser.c"
+#line 3962 "src/parser.c"
break;
case 152: /* Keyword: "try" */
-#line 941 "src/parser.y"
+#line 939 "src/parser.y"
{
(yyval.literal) = jv_string("try");
}
-#line 3972 "src/parser.c"
+#line 3970 "src/parser.c"
break;
case 153: /* Keyword: "catch" */
-#line 944 "src/parser.y"
+#line 942 "src/parser.y"
{
(yyval.literal) = jv_string("catch");
}
-#line 3980 "src/parser.c"
+#line 3978 "src/parser.c"
break;
case 154: /* Keyword: "label" */
-#line 947 "src/parser.y"
+#line 945 "src/parser.y"
{
(yyval.literal) = jv_string("label");
}
-#line 3988 "src/parser.c"
+#line 3986 "src/parser.c"
break;
case 155: /* Keyword: "break" */
-#line 950 "src/parser.y"
+#line 948 "src/parser.y"
{
(yyval.literal) = jv_string("break");
}
-#line 3996 "src/parser.c"
+#line 3994 "src/parser.c"
break;
case 156: /* MkDict: %empty */
-#line 955 "src/parser.y"
+#line 953 "src/parser.y"
{
(yyval.blk)=gen_noop();
}
-#line 4004 "src/parser.c"
+#line 4002 "src/parser.c"
break;
case 157: /* MkDict: MkDictPair */
-#line 958 "src/parser.y"
+#line 956 "src/parser.y"
{ (yyval.blk) = (yyvsp[0].blk); }
-#line 4010 "src/parser.c"
+#line 4008 "src/parser.c"
break;
case 158: /* MkDict: MkDictPair ',' MkDict */
-#line 959 "src/parser.y"
+#line 957 "src/parser.y"
{ (yyval.blk)=block_join((yyvsp[-2].blk), (yyvsp[0].blk)); }
-#line 4016 "src/parser.c"
+#line 4014 "src/parser.c"
break;
case 159: /* MkDict: error ',' MkDict */
-#line 960 "src/parser.y"
+#line 958 "src/parser.y"
{ (yyval.blk) = (yyvsp[0].blk); }
-#line 4022 "src/parser.c"
+#line 4020 "src/parser.c"
break;
case 160: /* MkDictPair: IDENT ':' ExpD */
-#line 963 "src/parser.y"
+#line 961 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk));
}
-#line 4030 "src/parser.c"
+#line 4028 "src/parser.c"
break;
case 161: /* MkDictPair: Keyword ':' ExpD */
-#line 966 "src/parser.y"
+#line 964 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_const((yyvsp[-2].literal)), (yyvsp[0].blk));
}
-#line 4038 "src/parser.c"
+#line 4036 "src/parser.c"
break;
case 162: /* MkDictPair: String ':' ExpD */
-#line 969 "src/parser.y"
+#line 967 "src/parser.y"
{
(yyval.blk) = gen_dictpair((yyvsp[-2].blk), (yyvsp[0].blk));
}
-#line 4046 "src/parser.c"
+#line 4044 "src/parser.c"
break;
case 163: /* MkDictPair: String */
-#line 972 "src/parser.y"
+#line 970 "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 4055 "src/parser.c"
+#line 4053 "src/parser.c"
break;
case 164: /* MkDictPair: BINDING ':' ExpD */
-#line 976 "src/parser.y"
+#line 974 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_location((yyloc), locations, gen_op_unbound(LOADV, jv_string_value((yyvsp[-2].literal)))),
(yyvsp[0].blk));
}
-#line 4064 "src/parser.c"
+#line 4062 "src/parser.c"
break;
case 165: /* MkDictPair: BINDING */
-#line 980 "src/parser.y"
+#line 978 "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 4073 "src/parser.c"
+#line 4071 "src/parser.c"
break;
case 166: /* MkDictPair: IDENT */
-#line 984 "src/parser.y"
+#line 982 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))),
gen_index(gen_noop(), gen_const((yyvsp[0].literal))));
}
-#line 4082 "src/parser.c"
+#line 4080 "src/parser.c"
break;
case 167: /* MkDictPair: "$__loc__" */
-#line 988 "src/parser.y"
+#line 986 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_const(jv_string("__loc__")),
gen_loc_object(&(yyloc), locations));
}
-#line 4091 "src/parser.c"
+#line 4089 "src/parser.c"
break;
case 168: /* MkDictPair: Keyword */
-#line 992 "src/parser.y"
+#line 990 "src/parser.y"
{
(yyval.blk) = gen_dictpair(gen_const(jv_copy((yyvsp[0].literal))),
gen_index(gen_noop(), gen_const((yyvsp[0].literal))));
}
-#line 4100 "src/parser.c"
+#line 4098 "src/parser.c"
break;
case 169: /* MkDictPair: '(' Exp ')' ':' ExpD */
-#line 996 "src/parser.y"
+#line 994 "src/parser.y"
{
jv msg = check_object_key((yyvsp[-3].blk));
if (jv_is_valid(msg)) {
@@ -4109,20 +4107,20 @@ YYLTYPE yylloc = yyloc_default;
jv_free(msg);
(yyval.blk) = gen_dictpair((yyvsp[-3].blk), (yyvsp[0].blk));
}
-#line 4113 "src/parser.c"
+#line 4111 "src/parser.c"
break;
case 170: /* MkDictPair: error ':' ExpD */
-#line 1004 "src/parser.y"
+#line 1002 "src/parser.y"
{
FAIL((yyloc), "May need parentheses around object key expression");
(yyval.blk) = (yyvsp[0].blk);
}
-#line 4122 "src/parser.c"
+#line 4120 "src/parser.c"
break;
-#line 4126 "src/parser.c"
+#line 4124 "src/parser.c"
default: break;
}
@@ -4351,7 +4349,7 @@ YYLTYPE yylloc = yyloc_default;
return yyresult;
}
-#line 1008 "src/parser.y"
+#line 1006 "src/parser.y"
int jq_parse(struct locfile* locations, block* answer) {
diff --git a/src/parser.y b/src/parser.y
index 6924ad34dc..7599d9f2f4 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -379,11 +379,9 @@ Term "as" Patterns '|' Exp {
} |
"try" Exp "catch" Exp {
- //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, $4);
- $$ = gen_try($2, gen_try_handler($4));
+ $$ = gen_try($2, $4);
} |
"try" Exp {
- //$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, gen_op_simple(BACKTRACK));
$$ = gen_try($2, gen_op_simple(BACKTRACK));
} |
"try" Exp "catch" error {
diff --git a/tests/jq.test b/tests/jq.test
index da35e9a84c..2cc16bdbcf 100644
--- a/tests/jq.test
+++ b/tests/jq.test
@@ -1834,3 +1834,58 @@ null
debug
1
1
+
+# try/catch catches more than it should #1859
+"foo" | try ((try . catch "caught too much") | error) catch "caught just right"
+null
+"caught just right"
+
+.[]|(try (if .=="hi" then . else error end) catch empty) | "\(.) there!"
+["hi","ho"]
+"hi there!"
+
+try (["hi","ho"]|.[]|(try . catch (if .=="ho" then "BROKEN"|error else empty end)) | if .=="ho" then error else "\(.) there!" end) catch "caught outside \(.)"
+null
+"hi there!"
+"caught outside ho"
+
+.[]|(try . catch (if .=="ho" then "BROKEN"|error else empty end)) | if .=="ho" then error else "\(.) there!" end
+["hi","ho"]
+"hi there!"
+
+try (try error catch "inner catch \(.)") catch "outer catch \(.)"
+"foo"
+"inner catch foo"
+
+try ((try error catch "inner catch \(.)")|error) catch "outer catch \(.)"
+"foo"
+"outer catch inner catch foo"
+
+# Also #1859, but from #1885
+first(.?,.?)
+null
+null
+
+# Also #1859, but from #2140
+{foo: "bar"} | .foo |= .?
+null
+{"foo": "bar"}
+
+# Also #1859, but from #2220
+. |= try 2
+1
+2
+
+. |= try 2 catch 3
+1
+2
+
+.[] |= try tonumber
+["1", "2a", "3", 4]
+[1, 3, 4]
+
+# Also 1859, but from 2073
+any(keys[]|tostring?;true)
+{"a":"1","b":"2","c":"3"}
+true
+