txlyre 1 week geleden
bovenliggende
commit
9de9944418
4 gewijzigde bestanden met toevoegingen van 403 en 304 verwijderingen
  1. 63 10
      qirt.c
  2. 7 0
      qirt.h
  3. 296 288
      qistd.c
  4. 37 6
      std.qi

+ 63 - 10
qirt.c

@@ -1606,11 +1606,13 @@ qi_value_t *qi_deref(qi_state_t *state, qi_value_t *value) {
   if (value->type == QI_REFERENCE) {
     qi_mutex_lock(value->value.ref.scope->mutex);
 
-    qi_symbol_t *symbol = qi_table_get(value->value.ref.scope->scope, value->value.ref.name);
+    qi_symbol_t *symbol =
+        qi_table_get(value->value.ref.scope->scope, value->value.ref.name);
     if (!symbol) {
       qi_mutex_unlock(value->value.ref.scope->mutex);
 
-      qi_throw_format(state, "reference to undefined symbol: '%s'", value->value.ref.name);
+      qi_throw_format(state, "reference to undefined symbol: '%s'",
+                      value->value.ref.name);
     }
 
     qi_value_t *r = symbol->value;
@@ -1626,7 +1628,8 @@ leave:
   return 0;
 }
 
-qi_value_t *qi_set_ref(qi_state_t *state, qi_bool is_pf, qi_value_t *ref, qi_value_t *value) {
+qi_value_t *qi_set_ref(qi_state_t *state, qi_bool is_pf, qi_value_t *ref,
+                       qi_value_t *value) {
   qi_value_t *meta;
   qi_bool fail = false;
 
@@ -1639,13 +1642,15 @@ qi_value_t *qi_set_ref(qi_state_t *state, qi_bool is_pf, qi_value_t *ref, qi_val
   if (ref->type == QI_REFERENCE) {
     qi_mutex_lock(ref->value.ref.scope->mutex);
 
-    qi_symbol_t *symbol = qi_table_get(ref->value.ref.scope->scope, ref->value.ref.name);
+    qi_symbol_t *symbol =
+        qi_table_get(ref->value.ref.scope->scope, ref->value.ref.name);
 
     if (symbol) {
       if (symbol->is_constant) {
         qi_mutex_unlock(ref->value.ref.scope->mutex);
 
-        qi_throw_format(state, "redeclaration of constant symbol (by reference): '%s'",
+        qi_throw_format(state,
+                        "redeclaration of constant symbol (by reference): '%s'",
                         ref->value.ref.name);
       }
 
@@ -2132,16 +2137,41 @@ leave:
   return NULL;
 }
 
+qi_bool qi_is_iter(qi_state_t *state, qi_value_t *value) {
+  return qi_get_method(state, value, "__begin") != NULL &&
+         qi_get_method(state, value, "__next") != NULL &&
+         qi_get_method(state, value, "__end") != NULL;
+}
+
 qi_value_t *qi_iter(qi_state_t *state, qi_value_t *value) {
+  if (qi_is_iter(state, value))
+    return qi_iter_begin(state, value);
+
   qi_value_t *meta;
   qi_bool fail = false;
-  if ((meta = qi_call_meta(state, &fail, value, "__iter", 1, value)))
-    return qi_iter(state, meta);
+  if ((meta = qi_call_meta(state, &fail, value, "__iter", 1, value))) {
+    if (!qi_is_iter(state, meta))
+      qi_throw_format(state, "__iter returned not an iterator (%s)",
+                      _qi_type(state, meta));
+
+    return meta;
+  }
 
   if (fail)
-    qi_throw_format(state, "cannot iterate %s", _qi_type(state, value));
+    goto leave;
+
+  if (value->type == QI_LIST || value->type == QI_TUPLE ||
+      value->type == QI_BYTES || value->type == QI_TABLE) {
+    qi_list_t *pargs = qi_list_make_n(1);
+    qi_list_data(pargs, 0) = value;
+
+    return qi_call(state, state->listiterator, pargs);
+  }
 
-  return qi_to_list(state, value);
+leave:
+  qi_throw_format(state, "cannot iterate %s", _qi_type(state, value));
+
+  return NULL;
 }
 
 qi_value_t *qi_index(qi_state_t *state, qi_value_t *value, qi_value_t *index) {
@@ -4316,12 +4346,31 @@ qi_value_t *qi_builtin_table(qi_state_t *state, qi_size_t pargc,
 }
 
 qi_value_t *qi_builtin_ref(qi_state_t *state, qi_size_t pargc,
-                             qi_list_t *pargs) {
+                           qi_list_t *pargs) {
   qi_value_t *a = qi_list_data(pargs, 0);
 
   return qi_to_ref(state, a);
 }
 
+qi_value_t *qi_builtin_iter(qi_state_t *state, qi_size_t pargc,
+                            qi_list_t *pargs) {
+  qi_value_t *a = qi_list_data(pargs, 0);
+
+  return qi_iter(state, a);
+}
+
+qi_value_t *qi_builtin_iter_next(qi_state_t *state, qi_size_t pargc,
+                                 qi_list_t *pargs) {
+  qi_value_t *a = qi_list_data(pargs, 0);
+
+  if (!qi_is_iter(state, a))
+    qi_throw_format(state,
+                    "expected first argument to be an iterator, but got: %s",
+                    _qi_type(state, a));
+
+  return qi_iter_next(state, a);
+}
+
 qi_value_t *qi_builtin_deref(qi_state_t *state, qi_size_t pargc,
                              qi_list_t *pargs) {
   qi_value_t *a = qi_list_data(pargs, 0);
@@ -4567,6 +4616,8 @@ static void qi_state_setup(qi_state_t *state) {
   qi_add_builtin(state, "tuple", 1, qi_builtin_tuple);
   qi_add_builtin(state, "table", 1, qi_builtin_table);
   qi_add_builtin(state, "ref", 1, qi_builtin_ref);
+  qi_add_builtin(state, "iter", 1, qi_builtin_iter);
+  qi_add_builtin(state, "iter_next", 1, qi_builtin_iter_next);
 
   qi_add_builtin(state, "deref", 1, qi_builtin_deref);
   qi_add_builtin(state, "ref_set", 2, qi_builtin_ref_set);
@@ -4585,6 +4636,8 @@ static void qi_state_setup(qi_state_t *state) {
   state->_debug_data = NULL;
 
   qi_init_std(state);
+
+  state->listiterator = qi_get(state, "ListIterator");
 }
 
 static void _qi_state_init(qi_state_t **state, qi_bool enable_debug) {

+ 7 - 0
qirt.h

@@ -177,6 +177,8 @@ struct _qi_state_t {
   qi_value_t *nnumbers[8];
   qi_value_t *numbers[256];
 
+  qi_value_t *listiterator;
+
   qi_table_t *pseudomethods;
   void *pseudomethods_mutex;
 
@@ -352,6 +354,10 @@ struct _qi_symbol_t {
       qi_mutex_unlock((value)->mutex);                                         \
   }
 
+#define qi_iter_begin(state, v) (qi_call((state), (qi_get_method((state), (v), "__begin")), qi_list_push(qi_list_make(), (v))))
+#define qi_iter_end(state, v) (_qi_truthy((state), qi_call((state), (qi_get_method((state), (v), "__end")), qi_list_push(qi_list_make(), (v)))))
+#define qi_iter_next(state, v) (qi_call((state), (qi_get_method((state), (v), "__next")), qi_list_push(qi_list_make(), (v))))
+
 void *qi_malloc(qi_size_t size);
 void *qi_malloc_atomic(qi_size_t size);
 void *qi_realloc(void *old_ptr, qi_size_t size);
@@ -430,6 +436,7 @@ size_t _qi_length(qi_state_t *state, qi_value_t *value);
 qi_value_t *qi_del(qi_state_t *state, qi_value_t *value, qi_value_t *index);
 qi_bool _qi_truthy(qi_state_t *state, qi_value_t *value);
 qi_value_t *qi_cast(qi_state_t *state, qi_type_t type, qi_value_t *value);
+qi_bool qi_is_iter(qi_state_t *state, qi_value_t *value);
 qi_value_t *qi_iter(qi_state_t *state, qi_value_t *value);
 qi_value_t *qi_index(qi_state_t *state, qi_value_t *value, qi_value_t *index);
 qi_value_t *qi_index_set(qi_state_t *state, qi_bool is_pf, qi_value_t *value,

File diff suppressed because it is too large
+ 296 - 288
qistd.c


+ 37 - 6
std.qi

@@ -62,6 +62,9 @@ func is_defined(name) {
   inline `qi_bool b = qi_find(state, qi_get(state, "name")->value.string) != NULL`
   inline `return qi_make_boolean(state, b)`
 }
+func is_table(a) {
+  inline `return qi_make_boolean(state, qi_get(state, "a")->type == QI_TABLE)`
+}
 func list_remove(l, x, first=false) {
   if type(l) != "list"
     throw "expected first argument to be: list, but got: " + type(l)
@@ -432,14 +435,19 @@ func __class_wrapper(n, p, t, mt, st): return Object({
     "__call": func (this, pargs) use (n, p) {
         var t = {}
         var mt = { "__type": func (this) use (n): n }
-        for var other of p {
-            t += other.t
-            mt += other.mt
+        if p {
+          var i = 0
+          while i < len(p) {
+            t += p[i].t
+            mt += p[i].mt
+
+            i += 1
+          }
         }
         t += this.t
         mt += this.mt
         mt.super = this.super
-        obj = set_meta_table(t, mt)
+        var obj = set_meta_table(t, mt)
         if "constructor" in mt
           func_call(mt.constructor, [obj] + pargs)
         return obj
@@ -538,6 +546,29 @@ class AssertionError(Error)
 func assert(cond, msg=AssertionError())
   if !cond
     throw msg
+class ListIterator { 
+    constructor(this, l) {
+        this.l = list(l)
+
+        this.i = 0
+        this.z = len(this.l)
+    }
+
+    __str(this): "<ListIterator>"
+
+    __begin(this) {
+        this.i = 0
+        
+        return this
+    }
+
+    __next(this) {
+        if this.i < this.z
+          return this.l[this.i++]
+    }
+
+    __end(this): this.i >= this.z
+}
 class OrderedTable {
     __data__ = nil
 
@@ -621,7 +652,7 @@ class OrderedTable {
         return d
     }
 
-    __iter (this): this.keys()
+    __iter (this): ListIterator(this.keys())
     __len (this): len(this.__data__)
 
     __in (this, k) {
@@ -669,4 +700,4 @@ class OrderedTable {
 
         this.__data__.push((k, v))
     }
-}
+}

Some files were not shown because too many files changed in this diff