|
@@ -559,7 +559,24 @@ void qi_add_defer(qi_state_t *state, qi_ssize_t index, qi_defer_t defer) {
|
|
|
if (qi_list_empty(state->scopes))
|
|
|
return;
|
|
|
|
|
|
- qi_scope_t *scope = qi_list_last(state->scopes);
|
|
|
+ qi_scope_t *scope = NULL;
|
|
|
+
|
|
|
+ for (ssize_t i = state->scopes->length - 1; i >= 0; i--) {
|
|
|
+ qi_scope_t *tmp = qi_list_index(state->scopes, i);
|
|
|
+
|
|
|
+ if (i == 0 || tmp->is_sticky) {
|
|
|
+ scope = tmp;
|
|
|
+
|
|
|
+ break;
|
|
|
+ } else if (tmp->is_barrier)
|
|
|
+ break;
|
|
|
+
|
|
|
+ scope = tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!scope)
|
|
|
+ scope = qi_list_last(state->scopes);
|
|
|
+
|
|
|
qi_list_insert(scope->defers, index, (void *)defer);
|
|
|
}
|
|
|
|
|
@@ -582,12 +599,19 @@ void qi_new_scope(qi_state_t *state) {
|
|
|
scope->defers = qi_list_make();
|
|
|
|
|
|
scope->is_barrier = false;
|
|
|
+ scope->is_sticky = false;
|
|
|
|
|
|
scope->mutex = qi_mutex_create();
|
|
|
|
|
|
qi_list_push(state->scopes, scope);
|
|
|
}
|
|
|
|
|
|
+void qi_new_sticky_scope(qi_state_t *state) {
|
|
|
+ qi_new_scope(state);
|
|
|
+
|
|
|
+ ((qi_scope_t *)qi_list_last(state->scopes))->is_sticky = true;
|
|
|
+}
|
|
|
+
|
|
|
static void qi_scope_run_defers(qi_state_t *state, qi_scope_t *scope) {
|
|
|
qi_mutex_lock(scope->mutex);
|
|
|
|
|
@@ -2141,7 +2165,7 @@ static qi_value_t *_qi_call(qi_state_t *state, qi_value_t *value,
|
|
|
qi_push_trace(state, value, debug_data);
|
|
|
|
|
|
if (!value->value.function.is_builtin) {
|
|
|
- qi_new_scope(state);
|
|
|
+ qi_new_sticky_scope(state);
|
|
|
|
|
|
qi_decl_const(state, "it", value);
|
|
|
qi_decl(state, "arguments",
|
|
@@ -4062,7 +4086,7 @@ static void qi_state_setup(qi_state_t *state) {
|
|
|
|
|
|
state->traps = qi_list_make();
|
|
|
state->scopes = qi_list_make();
|
|
|
- qi_new_scope(state);
|
|
|
+ qi_new_sticky_scope(state);
|
|
|
|
|
|
if (__debug_enabled)
|
|
|
state->calltrace = qi_list_make();
|