From 0673dee1b38db5d49ae3f8cda0ba53fa4021c3ba Mon Sep 17 00:00:00 2001 From: William Langford Date: Fri, 17 Aug 2018 22:47:13 -0400 Subject: Fix destructuring alternation Attempting to use the existing FORK_OPT opcode resulted in difficulty knowing when to pop an error message off the stack and when not to. This commit makes DESTRUCTURE_ALT a real opcode that is identical to FORK_OPT, except for never pushing the error message onto the stack when continuing from an error backtrack. Some small changes were necessary to the DUP/POP behavior surrounding destructuring to accomodate this. --- src/execute.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/execute.c') diff --git a/src/execute.c b/src/execute.c index d5672165..8eb41cc7 100644 --- a/src/execute.c +++ b/src/execute.c @@ -799,21 +799,27 @@ jv jq_next(jq_state *jq) { } case FORK_OPT: + case DESTRUCTURE_ALT: case FORK: { stack_save(jq, pc - 1, stack_get_pos(jq)); pc++; // skip offset this time break; } - case ON_BACKTRACK(FORK_OPT): { + 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 jv_free(stack_pop(jq)); goto do_backtrack; } // `try EXP ...` exception caught in EXP - jv_free(stack_pop(jq)); // free the input - stack_push(jq, jv_invalid_get_msg(jq->error)); // push the error's message + // DESTRUCTURE_ALT doesn't want the error message on the stack, + // as we would just want to throw it away anyway. + if (opcode != ON_BACKTRACK(DESTRUCTURE_ALT)) { + 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(); uint16_t offset = *pc++; pc += offset; -- cgit v1.2.3