|
@@ -555,12 +555,20 @@ static char *qi_buffer_read(qi_buffer_t *buf) {
|
|
|
return buf->str;
|
|
|
}
|
|
|
|
|
|
-void qi_add_defer(qi_state_t *state, qi_ssize_t index, qi_defer_t defer) {
|
|
|
+void _qi_add_defer(qi_state_t *state, qi_ssize_t index, qi_defer_t defer, qi_bool is_local) {
|
|
|
if (qi_list_empty(state->scopes))
|
|
|
return;
|
|
|
|
|
|
qi_scope_t *scope = NULL;
|
|
|
|
|
|
+ if (is_local) {
|
|
|
+ scope = qi_list_last(state->scopes);
|
|
|
+
|
|
|
+ qi_list_insert(scope->defers, index, (void *)defer);
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
for (ssize_t i = state->scopes->length - 1; i >= 0; i--) {
|
|
|
qi_scope_t *tmp = qi_list_index(state->scopes, i);
|
|
|
|
|
@@ -1318,12 +1326,11 @@ qi_trap_t *qi_set_trap(qi_state_t *state, qi_defer_t finally) {
|
|
|
trap->finally = finally;
|
|
|
trap->scope = qi_list_last(state->scopes);
|
|
|
trap->scopes_count = qi_list_length(state->scopes);
|
|
|
- trap->calltrace_size =
|
|
|
- !__debug_enabled ? 0 : qi_list_length(state->calltrace);
|
|
|
+ trap->calltrace_size = qi_list_length(state->calltrace);
|
|
|
|
|
|
qi_list_push(state->traps, trap);
|
|
|
|
|
|
- qi_add_defer(state, 0, __qi_unset_trap);
|
|
|
+ qi_add_local_defer(state, 0, __qi_unset_trap);
|
|
|
|
|
|
return trap;
|
|
|
}
|
|
@@ -1337,11 +1344,9 @@ void qi_unset_trap(qi_state_t *state, qi_trap_t *trap) {
|
|
|
i < k; i++)
|
|
|
qi_old_scope(state);
|
|
|
|
|
|
- if (__debug_enabled)
|
|
|
- for (size_t i = 0,
|
|
|
- k = qi_list_length(state->calltrace) - trap->calltrace_size;
|
|
|
- i < k; i++)
|
|
|
- qi_list_pop(state->calltrace);
|
|
|
+ for (size_t i = 0, k = qi_list_length(state->calltrace) - trap->calltrace_size;
|
|
|
+ i < k; i++)
|
|
|
+ qi_list_pop(state->calltrace);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2163,6 +2168,9 @@ static qi_value_t *_qi_call(qi_state_t *state, qi_value_t *value,
|
|
|
qi_throw_format(state, "cannot call %s", _qi_type(state, value));
|
|
|
}
|
|
|
|
|
|
+ if (qi_list_length(state->calltrace) >= state->rlimit)
|
|
|
+ qi_throw_format(state, "max. recursion depth limit reached (%zu)", state->rlimit);
|
|
|
+
|
|
|
if (value->value.function._this) {
|
|
|
qi_list_t *temp = !pargs ? qi_list_make() : qi_list_copy(pargs);
|
|
|
qi_list_insert(temp, 0, value->value.function._this);
|
|
@@ -2179,8 +2187,7 @@ static qi_value_t *_qi_call(qi_state_t *state, qi_value_t *value,
|
|
|
value->value.function.name, value->value.function.pargc,
|
|
|
pargc);
|
|
|
|
|
|
- if (__debug_enabled)
|
|
|
- qi_push_trace(state, value, debug_data);
|
|
|
+ qi_push_trace(state, value, debug_data);
|
|
|
|
|
|
if (!value->value.function.is_builtin) {
|
|
|
qi_new_sticky_scope(state);
|
|
@@ -2200,8 +2207,7 @@ static qi_value_t *_qi_call(qi_state_t *state, qi_value_t *value,
|
|
|
if (!value->value.function.is_builtin)
|
|
|
qi_old_scope(state);
|
|
|
|
|
|
- if (__debug_enabled)
|
|
|
- qi_pop_trace(state);
|
|
|
+ qi_pop_trace(state);
|
|
|
|
|
|
return result;
|
|
|
}
|
|
@@ -2939,8 +2945,7 @@ static qi_state_t *qi_state_clone(qi_state_t *state) {
|
|
|
newstate->scopes = qi_list_copy(state->scopes);
|
|
|
qi_set_barrier(newstate);
|
|
|
|
|
|
- if (__debug_enabled)
|
|
|
- newstate->calltrace = qi_list_copy(state->calltrace);
|
|
|
+ newstate->calltrace = qi_list_copy(state->calltrace);
|
|
|
|
|
|
return newstate;
|
|
|
}
|
|
@@ -4109,10 +4114,8 @@ static void qi_state_setup(qi_state_t *state) {
|
|
|
state->scopes = qi_list_make();
|
|
|
qi_new_sticky_scope(state);
|
|
|
|
|
|
- if (__debug_enabled)
|
|
|
- state->calltrace = qi_list_make();
|
|
|
- else
|
|
|
- state->calltrace = NULL;
|
|
|
+ state->calltrace = qi_list_make();
|
|
|
+ state->rlimit = QI_DEFAULT_RLIMIT;
|
|
|
|
|
|
qi_decl_const(state, "nil", state->nil);
|
|
|
qi_decl_const(state, "true", state->_true);
|