Commit 0602ff4fd433084b68e82b894f43b8ad59b150fd

Thomas de Grivel 2024-08-17T14:35:17

facts_with

diff --git a/.ikc3_history b/.ikc3_history
index ece84e2..7a1e2de 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,7 +1,3 @@
-server = Socket.listen("192.168.2.50", "58000")
-server_client = Socket.Buf.accept(server)
-req = HTTP.Request.buf_parse(server_client.buf_rw.r)
-%HTTP.Response{}
 Struct.offset(%HTTP.Response{}, :message)
 Sym.type_size(Str)
 Struct.offset(%HTTP.Response{}, :message)
@@ -97,4 +93,7 @@ Facts.with_tags(Facts.env_facts(), ?, ?, ?, fn (fact) { puts(fact); void })
 Facts.with_tags(Facts.env_facts(), KC3, ?, ?, fn (fact) { puts(fact); void })
 Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact); void })
 Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); void })
-
+Facts.with(Facts.env_facts(), [[KC3, :operator, ?]], fn (fact) { puts(fact.object); void })
+Facts.with(Facts.env_facts(), [[KC3, ?, ?]], fn (fact) { puts(fact.object); void })
+Facts.with(Facts.env_facts(), [[KC3, :load_time, ?]], fn (fact) { puts(fact.object); void })
+Facts.with(Facts.env_facts(), [[?, :load_time, ?]], fn (fact) { puts(fact.object); void })
diff --git a/lib/kc3/0.1/facts.kc3 b/lib/kc3/0.1/facts.kc3
index 8ef12d7..ab19de8 100644
--- a/lib/kc3/0.1/facts.kc3
+++ b/lib/kc3/0.1/facts.kc3
@@ -17,6 +17,10 @@ defmodule Facts do
   # env_facts() -> facts
   def env_facts = cfn Ptr "kc3_env_facts" ()
 
+  # with(facts, [[?, ?, ?]], fn (fact) {result}) -> result
+  def with = cfn Tag "kc3_facts_with" (Facts, List, Fn,
+    Result)
+
   # with_tags(facts, subject, predicate, object,
   #           fn (fact) {result}) -> result
   def with_tags = cfn Tag "kc3_facts_with_tags" (Facts, Tag, Tag, Tag,
diff --git a/libkc3/env.c b/libkc3/env.c
index 469160a..06e8c2c 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -2014,6 +2014,47 @@ s_fact_w * env_fact_w_eval (s_env *env, const s_fact_w *fact,
   return dest;
 }
 
+s_tag * env_facts_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_tag tmp = {0};
+  if (! (arguments = list_new_struct(&g_sym_FactW, NULL)))
+    return NULL;
+  if (! struct_allocate(&arguments->tag.data.struct_))
+    return NULL;
+  fact_w = arguments->tag.data.struct_.data;
+  if (! facts_with_list(facts, &cursor, *spec))
+    return NULL;
+  while (1) {
+    if (! facts_with_cursor_next(&cursor, &fact))
+      goto clean;
+    if (! fact) {
+      goto ok;
+    }
+    tag_clean(&tmp);
+    fact_w_init_fact(fact_w, fact);
+    if (! env_eval_call_fn_args(env, callback, arguments, &tmp)) {
+      fact_w_clean(fact_w);
+      goto clean;
+    }
+    fact_w_clean(fact_w);
+    fact_w_init(fact_w);
+  }
+ ok:
+  list_delete_all(arguments);
+  *dest = tmp;
+  return dest;
+ clean:
+  tag_clean(&tmp);
+  fact_w_clean(fact_w);
+  list_delete_all(arguments);
+  return NULL;
+}
+
 s_tag * env_facts_with_tags (s_env *env, s_facts *facts, s_tag *subject,
                              s_tag *predicate, s_tag *object,
                              s_fn *callback, s_tag *dest)
diff --git a/libkc3/env.h b/libkc3/env.h
index 4e3e3f3..b683f0f 100644
--- a/libkc3/env.h
+++ b/libkc3/env.h
@@ -179,6 +179,8 @@ bool          env_eval_tuple (s_env *env, const s_tuple *tuple,
 bool          env_eval_void (s_env *env, const void *_, s_tag *dest);
 s_fact_w *    env_fact_w_eval (s_env *env, const s_fact_w *fact,
 			       s_fact_w *dest);
+s_tag *       env_facts_with (s_env *env, s_facts *facts, s_list **spec,
+                              s_fn *callback, s_tag *dest);
 s_tag *       env_facts_with_tags (s_env *env, s_facts *facts,
                                    s_tag *subject, s_tag *predicate,
                                    s_tag *object, s_fn *callback,
diff --git a/libkc3/facts_spec.c b/libkc3/facts_spec.c
index d003e3e..d029e50 100644
--- a/libkc3/facts_spec.c
+++ b/libkc3/facts_spec.c
@@ -16,6 +16,7 @@
 #include "fact.h"
 #include "facts_spec.h"
 #include "facts_spec_cursor.h"
+#include "list.h"
 #include "tag.h"
 
 uw facts_spec_count_facts (p_facts_spec spec)
@@ -56,6 +57,47 @@ p_facts_spec facts_spec_new_expand (p_facts_spec spec)
   return NULL;
 }
 
+p_facts_spec facts_spec_new_list (s_list *spec)
+{
+  uw c;
+  uw count = 1;
+  p_facts_spec new;
+  p_facts_spec n;
+  s_list *s;
+  s_list *t;
+  assert(spec);
+  if (! spec)
+    return NULL;
+  s = spec;
+  while (s) {
+    if (s->tag.type != TAG_LIST ||
+        (c = list_length(s->tag.data.list)) < 3 ||
+        (c - 1) % 2) {
+      err_puts("facts_spec_new_list: invalid spec");
+      assert(! "facts_spec_new_list: invalid spec");
+      return NULL;
+    }
+    count += c + 1;
+    s = list_next(s);
+  }
+  new = alloc(count * sizeof(s_tag *));
+  if (! new)
+    return NULL;
+  n = new;
+  s = spec;
+  while (s) {
+    t = s->tag.data.list;
+    while (t) {
+      *n++ = &t->tag;
+      t = list_next(t);
+    }
+    *n++ = NULL;
+    s = list_next(s);
+  }
+  *n = NULL;
+  return new;
+}
+
 p_facts_spec facts_spec_sort (p_facts_spec spec)
 {
   s_tag **a;
diff --git a/libkc3/facts_spec.h b/libkc3/facts_spec.h
index b268545..dbea2f8 100644
--- a/libkc3/facts_spec.h
+++ b/libkc3/facts_spec.h
@@ -29,6 +29,7 @@
 
 /* Constructors */
 p_facts_spec facts_spec_new_expand (p_facts_spec spec);
+p_facts_spec facts_spec_new_list (s_list *spec);
 
 /* Destructor */
 #define facts_spec_delete free
diff --git a/libkc3/facts_with.c b/libkc3/facts_with.c
index 790e3b9..c34e1d3 100644
--- a/libkc3/facts_with.c
+++ b/libkc3/facts_with.c
@@ -142,6 +142,22 @@ s_facts_cursor * facts_with_3 (s_facts *facts,
   return facts_cursor_init(facts, cursor, facts->index_spo, &fact, &fact);
 }
 
+s_facts_with_cursor * facts_with_list (s_facts *facts,
+                                       s_facts_with_cursor *cursor,
+                                       s_list *spec)
+{
+  p_facts_spec s;
+  assert(facts);
+  assert(cursor);
+  assert(spec);
+  if (! (s = facts_spec_new_list(spec))) {
+    err_puts("facts_with_list: facts_spec_new_list");
+    assert(! "facts_with_list: facts_spec_new_list");
+    return NULL;
+  }
+  return facts_with(facts, cursor, s);
+}
+
 s_facts_cursor * facts_with_tags (s_facts *facts,
                                   s_facts_cursor *cursor,
                                   s_tag *subject,
diff --git a/libkc3/facts_with.h b/libkc3/facts_with.h
index 072166f..793198a 100644
--- a/libkc3/facts_with.h
+++ b/libkc3/facts_with.h
@@ -40,6 +40,10 @@ s_facts_cursor * facts_with_3 (s_facts *facts,
                                const s_tag *predicate,
                                const s_tag *object);
 
+s_facts_with_cursor * facts_with_list (s_facts *facts,
+                                       s_facts_with_cursor *cursor,
+                                       s_list *spec);
+
 s_facts_cursor * facts_with_tags (s_facts *facts,
                                   s_facts_cursor *cursor,
                                   s_tag *subject,
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index a877cef..560fecd 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -190,6 +190,12 @@ uw * kc3_facts_next_id (uw *dest)
   return dest;
 }
 
+s_tag * kc3_facts_with (s_facts *facts, s_list **spec,
+                        s_fn *callback, s_tag *dest)
+{
+  return env_facts_with(&g_kc3_env, facts, spec, callback, dest);
+}
+
 s_tag * kc3_facts_with_tags (s_facts *facts, s_tag *subject,
                              s_tag *predicate, s_tag *object,
                              s_fn *callback, s_tag *dest)
diff --git a/libkc3/kc3_main.h b/libkc3/kc3_main.h
index c5d1777..25d2f7e 100644
--- a/libkc3/kc3_main.h
+++ b/libkc3/kc3_main.h
@@ -57,6 +57,8 @@ void **   kc3_dlopen (const s_str *path, void **dest);
 s_facts * kc3_env_facts (void);
 sw        kc3_errno (void);
 void      kc3_exit (sw code);
+s_tag *   kc3_facts_with (s_facts *facts, s_list **spec,
+                          s_fn *callback, s_tag *dest);
 s_tag *   kc3_facts_with_tags (s_facts *facts, s_tag *subject,
                                s_tag *predicate, s_tag *object,
                                s_fn *callback, s_tag *dest);