txlyre пре 3 недеља
родитељ
комит
ea93f68bca
4 измењених фајлова са 286 додато и 255 уклоњено
  1. 22 19
      qirt.c
  2. 9 2
      qirt.h
  3. 251 232
      qistd.c
  4. 4 2
      std.qi

+ 22 - 19
qirt.c

@@ -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);

+ 9 - 2
qirt.h

@@ -150,6 +150,9 @@ struct _qi_value_t {
   } value;
 };
 
+
+#define QI_DEFAULT_RLIMIT 1000
+
 struct _qi_state_t {
   qi_value_t *nil;
   qi_value_t *_true;
@@ -178,6 +181,8 @@ struct _qi_state_t {
   qi_list_t *scopes;
   qi_list_t *calltrace;
 
+  size_t rlimit;
+
   const char *_debug_data;
 };
 
@@ -229,7 +234,7 @@ struct _qi_trap_t {
     if (setjmp(trap->label)) {                                                 \
       qi_unset_trap(state, trap);                                              \
       if (trap->finally)                                                       \
-        qi_add_defer(state, 0, trap->finally);                                 \
+        qi_add_local_defer(state, 0, trap->finally);                                 \
       handle;                                                                  \
       if (trap->finally) {                                                     \
         qi_pop_defer(state, 0);                                                \
@@ -365,7 +370,9 @@ qi_table_t *qi_table_set(qi_table_t *table, char *key, void *value);
 qi_list_t *qi_table_keys(qi_table_t *table);
 qi_bool qi_table_delete(qi_table_t *table, char *key);
 qi_table_t *qi_table_copy(qi_table_t *table);
-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);
+#define qi_add_defer(state, index, defer) (_qi_add_defer((state), (index), (defer), false))
+#define qi_add_local_defer(state, index, defer) (_qi_add_defer((state), (index), (defer), true))
 qi_defer_t qi_pop_defer(qi_state_t *state, qi_ssize_t index);
 void qi_new_scope(qi_state_t *state);
 void qi_new_sticky_scope(qi_state_t *state);

Разлика између датотеке није приказан због своје велике величине
+ 251 - 232
qistd.c


+ 4 - 2
std.qi

@@ -146,8 +146,8 @@ func list_unshift(l, x) {
 set_pseudomethod("list.shift", list_shift)
 set_pseudomethod("list.unshift", list_unshift)
 func slice(l) {
-  if type(l) !in ("list", "string", "bytes")
-    throw "expected first argument to be: list, string or bytes, but got: " + type(l)
+  if type(l) !in ("list", "string", "bytes", "ustr")
+    throw "expected first argument to be: list, string, bytes or ustr, but got: " + type(l)
   var r = []
   if len(arguments) == 2 {
     var f = arguments[1]
@@ -174,6 +174,8 @@ func slice(l) {
     return list_join(r)
   elif type(l) == "bytes"
     return bytes(r)
+  elif type(l) == "ustr"
+    return ustr(r)
   return r
 }
 set_pseudomethod("list.slice", slice)

Неке датотеке нису приказане због велике количине промена