Skip to content

Commit

Permalink
Fix try/catch (fix jqlang#1859)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicowilliams committed Apr 3, 2019
1 parent 036c38e commit 5bd9985
Showing 1 changed file with 31 additions and 1 deletion.
32 changes: 31 additions & 1 deletion src/execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ struct forkpoint {
int path_len, subexp_nest;
jv value_at_path;
uint16_t* return_address;
uint16_t* call_address; /* for tr/catch */
};

struct stack_pos {
Expand All @@ -274,6 +275,7 @@ void stack_save(jq_state *jq, uint16_t* retaddr, struct stack_pos sp){
fork->value_at_path = jv_copy(jq->value_at_path);
fork->subexp_nest = jq->subexp_nest;
fork->return_address = retaddr;
fork->call_address = 0;
jq->stk_top = sp.saved_data_stack;
jq->curr_frame = sp.saved_curr_frame;
}
Expand Down Expand Up @@ -339,6 +341,7 @@ uint16_t* stack_restore(jq_state *jq){
}

struct forkpoint* fork = stack_block(&jq->stk, jq->fork_top);
uint16_t* call_address = fork->call_address;
uint16_t* retaddr = fork->return_address;
jq->stk_top = fork->saved_data_stack;
jq->curr_frame = fork->saved_curr_frame;
Expand All @@ -353,6 +356,11 @@ uint16_t* stack_restore(jq_state *jq){
jq->value_at_path = fork->value_at_path;
jq->subexp_nest = fork->subexp_nest;
jq->fork_top = stack_pop_block(&jq->stk, jq->fork_top, sizeof(struct forkpoint));
if (jq->fork_top) {
fork = stack_block(&jq->stk, jq->fork_top);
if (!fork->call_address || fork->call_address < call_address)
fork->call_address = call_address;
}
return retaddr;
}

Expand Down Expand Up @@ -438,6 +446,7 @@ jv jq_next(jq_state *jq) {
}
assert(pc);

uint16_t *error_source = 0;
int raising;
int backtracking = !jq->initial_execution;
jq->initial_execution = 0;
Expand Down Expand Up @@ -896,6 +905,12 @@ jv jq_next(jq_state *jq) {
jq->finished = 1;
return jv_invalid();
}
if (!jv_is_valid(jq->error) && jq->fork_top && jq->curr_frame > jq->fork_top) {
struct forkpoint* frk = stack_block(&jq->stk, jq->fork_top);
error_source = frk->call_address;
} else {
error_source = pc;
}
backtracking = 1;
break;
}
Expand All @@ -915,17 +930,22 @@ jv jq_next(jq_state *jq) {
jv_free(stack_pop(jq));
goto do_backtrack;
}

uint16_t offset = *pc++;

// `try EXP ...` exception caught in EXP
// 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
if (error_source > (pc + offset))
goto do_backtrack;
stack_push(jq, jv_invalid_get_msg(jq->error)); // push the error's message
} else {
error_source = 0;
jv_free(jq->error);
}
jq->error = jv_null();
uint16_t offset = *pc++;
pc += offset;
break;
}
Expand All @@ -937,6 +957,10 @@ jv jq_next(jq_state *jq) {
}

case CALL_BUILTIN: {
if (jq->fork_top && jq->curr_frame > jq->fork_top) {
struct forkpoint* frk = stack_block(&jq->stk, jq->fork_top);
frk->call_address = pc;
}
int nargs = *pc++;
jv top = stack_pop(jq);
jv* in = cfunc_input;
Expand Down Expand Up @@ -976,6 +1000,10 @@ jv jq_next(jq_state *jq) {

case TAIL_CALL_JQ:
case CALL_JQ: {
if (jq->fork_top && jq->curr_frame > jq->fork_top) {
struct forkpoint* frk = stack_block(&jq->stk, jq->fork_top);
frk->call_address = pc;
}
/*
* Bytecode layout here:
*
Expand Down Expand Up @@ -1246,6 +1274,8 @@ jv jq_next(jq_state *jq) {
case ON_BACKTRACK(CORET):
case ON_BACKTRACK(RET): {
// resumed after top-level return
if (!jv_is_valid(jq->error))
error_source = pc;
goto do_backtrack;
}
}
Expand Down

0 comments on commit 5bd9985

Please sign in to comment.