Commit 80cb8e95f792dfc5030e34132fac2e78d94b8926

Thomas de Grivel 2024-11-18T11:20:30

Facts.collect_with

diff --git a/.ikc3_history b/.ikc3_history
index 41f55dc..dd1066c 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,4 +1,3 @@
-1 + 1
 1 + 100000000000000000000000000000000000000000000000000000000
 type(1 + 100000000000000000000000000000000000000000000000000000000)
 type(1 + 1)
@@ -97,3 +96,4 @@ Time.from_str("1970-01-01 00:00:00")
 Time.from_str("2024-10-31 23:00:00")
 Time.to_str(Time.from_str("2024-10-31 23:00:00"))
 List.map([1, 2, 3], fn (x) { x * 2 })
+Facts.collect_with(Facts.env_db(), [[op = ?, :is_a, :operator]], fn (fact) { op })
diff --git a/lib/kc3/0.1/facts.kc3 b/lib/kc3/0.1/facts.kc3
index 2098edc..f25c2b7 100644
--- a/lib/kc3/0.1/facts.kc3
+++ b/lib/kc3/0.1/facts.kc3
@@ -17,6 +17,9 @@ defmodule Facts do
 
   def cast = cfn Tag "tag_init_cast_struct" (Result, Sym, Tag)
 
+  def collect_with = cfn Tag "kc3_facts_collect_with" (Facts, List,
+    Fn, Result)
+
   def collect_with_tags = cfn Tag "kc3_facts_collect_with_tags" (Facts,
     Tag, Tag, Tag, Fn, Result)
 
diff --git a/libkc3/env.c b/libkc3/env.c
index 27b351a..20b74fc 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -2124,6 +2124,65 @@ s_fact_w * env_fact_w_eval (s_env *env, const s_fact_w *fact,
   return dest;
 }
 
+s_tag * env_facts_collect_with (s_env *env, s_facts *facts,
+                                s_list **spec,
+                                s_fn *callback, s_tag *dest)
+{
+  s_list *arguments;
+  s_facts_with_cursor cursor = {0};
+  const s_fact *fact = NULL;
+  s_fact_w *fact_w = NULL;
+  s_list **l;
+  s_list  *list;
+  s_tag tmp = {0};
+  assert(env);
+  assert(facts);
+  assert(spec);
+  assert(callback);
+  assert(dest);
+  if (! (arguments = list_new_struct(&g_sym_FactW, NULL)))
+    return NULL;
+  if (! struct_allocate(&arguments->tag.data.struct_)) {
+    list_delete_all(arguments);
+    return NULL;
+  }
+  fact_w = arguments->tag.data.struct_.data;
+  if (! facts_with_list(facts, &cursor, *spec))
+    return NULL;
+  list = NULL;
+  l = &list;
+  while (1) {
+    if (! facts_with_cursor_next(&cursor, &fact))
+      goto clean;
+    if (! fact)
+      goto ok;
+    fact_w_clean(fact_w);
+    if (! fact_w_init_fact(fact_w, fact))
+      goto clean;
+    *l = list_new(NULL);
+    if (! env_eval_call_fn_args(env, callback, arguments, &(*l)->tag)) {
+      goto clean;
+    }
+    l = &(*l)->next.data.list;
+  }
+ ok:
+  list_delete_all(arguments);
+  tmp.type = TAG_LIST;
+  tmp.data.list = list;
+  if (false) {
+    err_write_1("env_facts_first_with: ");
+    err_inspect_tag(&tmp);
+    err_write_1("\n");
+  }
+  *dest = tmp;
+  return dest;
+ clean:
+  facts_with_cursor_clean(&cursor);
+  tag_clean(&tmp);
+  list_delete_all(arguments);
+  return NULL;  
+}
+
 s_tag * env_facts_collect_with_tags (s_env *env, s_facts *facts,
                                      s_tag *subject,
                                      s_tag *predicate,
@@ -2158,7 +2217,6 @@ s_tag * env_facts_collect_with_tags (s_env *env, s_facts *facts,
       goto clean;
     *l = list_new(NULL);
     if (! env_eval_call_fn_args(env, callback, arguments, &(*l)->tag)) {
-      fact_w_clean(fact_w);
       goto clean;
     }
     l = &(*l)->next.data.list;
diff --git a/libkc3/env.h b/libkc3/env.h
index c96245b..b3242f0 100644
--- a/libkc3/env.h
+++ b/libkc3/env.h
@@ -61,6 +61,9 @@ s_tag *        env_defoperator (s_env *env, const s_sym * const *name,
 const s_sym *  env_defstruct (s_env *env, const s_list *spec);
 s_fact_w *     env_fact_w_eval (s_env *env, const s_fact_w *fact,
 	         	       s_fact_w *dest);
+s_tag *        env_facts_collect_with (s_env *env, s_facts *facts,
+                                       s_list **spec, s_fn *callback,
+                                       s_tag *dest);
 s_tag *        env_facts_collect_with_tags (s_env *env, s_facts *facts,
                                             s_tag *subject,
                                             s_tag *predicate,
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index 3615f3a..5824153 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -248,6 +248,13 @@ bool * kc3_facts_add_tags (s_facts *facts, const s_tag *subject,
   return dest;
 }
 
+s_tag * kc3_facts_collect_with (s_facts *facts, s_list **spec,
+                                s_fn *callback, s_tag *dest)
+{
+  return env_facts_collect_with(&g_kc3_env, facts, spec, callback,
+                                dest);
+}
+
 s_tag * kc3_facts_collect_with_tags (s_facts *facts,
                                      s_tag *subject,
                                      s_tag *predicate,
diff --git a/libkc3/kc3_main.h b/libkc3/kc3_main.h
index 2a962e4..3bb6617 100644
--- a/libkc3/kc3_main.h
+++ b/libkc3/kc3_main.h
@@ -77,6 +77,8 @@ bool *       kc3_facts_add_tags (s_facts *facts, const s_tag *subject,
                                  const s_tag *predicate,
                                  const s_tag *object,
                                  bool *dest);
+s_tag *      kc3_facts_collect_with (s_facts *facts, s_list **spec,
+                                     s_fn *callback, s_tag *dest);
 s_tag *      kc3_facts_collect_with_tags (s_facts *facts,
                                           s_tag *subject,
                                           s_tag *predicate,