Commit 01f284de7360b3874dc992b270735b8a7aec3e46

Thomas de Grivel 2024-05-21T16:01:39

wip var_set bug

diff --git a/libc3/compare.c b/libc3/compare.c
index f168b78..1453132 100644
--- a/libc3/compare.c
+++ b/libc3/compare.c
@@ -183,6 +183,7 @@ s8 compare_fact_unbound_var_count (const s_fact *a,
 {
   u8 a_count;
   u8 b_count;
+  bool unbound;
   if (a == b)
     return 0;
   if (!a)
@@ -191,17 +192,29 @@ s8 compare_fact_unbound_var_count (const s_fact *a,
     return 1;
   a_count = 0;
   b_count = 0;
-  if (tag_is_unbound_var(a->subject))
+  if (! tag_is_unbound_var(a->subject, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     a_count++;
-  if (tag_is_unbound_var(a->predicate))
+  if (! tag_is_unbound_var(a->predicate, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     a_count++;
-  if (tag_is_unbound_var(a->object))
+  if (! tag_is_unbound_var(a->object, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     a_count++;
-  if (tag_is_unbound_var(b->subject))
+  if (! tag_is_unbound_var(b->subject, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     b_count++;
-  if (tag_is_unbound_var(b->predicate))
+  if (! tag_is_unbound_var(b->predicate, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     b_count++;
-  if (tag_is_unbound_var(b->object))
+  if (! tag_is_unbound_var(b->object, &unbound))
+    return COMPARE_ERROR;
+  if (unbound)
     b_count++;
   return compare_u8(a_count, b_count);
 }
diff --git a/libc3/compare.h b/libc3/compare.h
index f891d7b..c55e859 100644
--- a/libc3/compare.h
+++ b/libc3/compare.h
@@ -15,6 +15,11 @@
 
 #include "types.h"
 
+#define COMPARE_ERROR ((s8) -2)
+#define COMPARE_LT    ((s8) -1)
+#define COMPARE_EQ    ((s8)  0)
+#define COMPARE_GT    ((s8)  1)
+
 #define COMPARE_PROTOTYPE(type)                     \
   s8 compare_##type (type a, type b)
 
diff --git a/libc3/facts_spec.c b/libc3/facts_spec.c
index 536d335..988c2b6 100644
--- a/libc3/facts_spec.c
+++ b/libc3/facts_spec.c
@@ -63,6 +63,7 @@ p_facts_spec facts_spec_sort (p_facts_spec spec)
   uw count;
   uw i = 0;
   uw j;
+  s8 r;
   assert(spec);
   count = facts_spec_count_facts(spec);
   if (count > 0)
@@ -71,8 +72,11 @@ p_facts_spec facts_spec_sort (p_facts_spec spec)
       while (j < count - i - 1) {
         a = spec + j * 4;
         b = spec + (j + 1) * 4;
-        if (compare_fact_unbound_var_count((s_fact *) a,
-                                           (s_fact *) b) > 0) {
+        r = compare_fact_unbound_var_count((s_fact *) a,
+                                           (s_fact *) b);
+        if (r == COMPARE_ERROR)
+          return NULL;
+        if (r > 0) {
           s_tag *swap[3];
           swap[0] = a[0];
           swap[1] = a[1];
diff --git a/libc3/facts_with.c b/libc3/facts_with.c
index c8e26b7..930c686 100644
--- a/libc3/facts_with.c
+++ b/libc3/facts_with.c
@@ -147,6 +147,7 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
                                   s_tag *predicate,
                                   s_tag *object)
 {
+  bool unbound;
   s_tag *var_subject = NULL;
   s_tag *var_predicate = NULL;
   s_tag *var_object = NULL;
@@ -155,11 +156,17 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
   assert(subject);
   assert(predicate);
   assert(object);
-  if (tag_is_unbound_var(subject))
+  if (! tag_is_unbound_var(subject, &unbound))
+    return NULL;
+  if (unbound)
     var_subject = subject;
-  if (tag_is_unbound_var(predicate))
+  if (! tag_is_unbound_var(predicate, &unbound))
+    return NULL;
+  if (unbound)
     var_predicate = predicate;
-  if (tag_is_unbound_var(object))
+  if (! tag_is_unbound_var(object, &unbound))
+    return NULL;
+  if (unbound)
     var_object = object;
   if (var_subject && var_predicate && var_object)
     return facts_with_0(facts, cursor, var_subject, var_predicate,
diff --git a/libc3/facts_with_cursor.c b/libc3/facts_with_cursor.c
index 279cc38..b0e8183 100644
--- a/libc3/facts_with_cursor.c
+++ b/libc3/facts_with_cursor.c
@@ -50,9 +50,10 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
     err_puts("facts_with_cursor_next: pthread_mutex_lock");
     assert(! "facts_with_cursor_next: pthread_mutex_lock");
     exit(1);
+    return NULL;
   }
   if (! cursor->facts_count)
-    goto ko;
+    goto not_found;
   if (cursor->level == cursor->facts_count) {
     level = &cursor->levels[cursor->facts_count - 1];
 #ifdef DEBUG_FACTS
@@ -85,7 +86,7 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
     cursor->level--;
     if (! cursor->level) {
       cursor->facts_count = 0;
-      goto ko;
+      goto not_found;
     }
     cursor->level--;
   }
@@ -97,9 +98,10 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
       else
         parent_spec = cursor->spec;
       level->spec = facts_spec_new_expand(parent_spec);
-      facts_with_tags(cursor->facts, &level->cursor,
-                      level->spec[0], level->spec[1],
-                      level->spec[2]);
+      if (! facts_with_tags(cursor->facts, &level->cursor,
+                            level->spec[0], level->spec[1],
+                            level->spec[2]))
+        goto ko;
     }
 #ifdef DEBUG_FACTS
     buf_write_1(&g_c3_env.err, "[debug] cursor->level=");
@@ -126,7 +128,7 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
     level->spec = NULL;
     if (! cursor->level) {
       cursor->facts_count = 0;
-      goto ko;
+      goto not_found;
     }
     cursor->level--;
   }
@@ -137,6 +139,14 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
   }
   *dest = fact;
   return dest;
+ not_found:
+  if (pthread_mutex_unlock(&cursor->mutex)) {
+    err_puts("facts_with_cursor_next: pthread_mutex_unlock");
+    assert(! "facts_with_cursor_next: pthread_mutex_unlock");
+    exit(1);
+  }
+  *dest = NULL;
+  return dest;
  ko:
   if (pthread_mutex_unlock(&cursor->mutex)) {
     err_puts("facts_with_cursor_next: pthread_mutex_unlock");
diff --git a/libc3/tag.c b/libc3/tag.c
index efe0688..d04f68d 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -652,9 +652,16 @@ bool tag_is_number (const s_tag *tag)
   return false;
 }
 
-bool tag_is_unbound_var (const s_tag *tag)
+bool * tag_is_unbound_var (const s_tag *tag, bool *dest)
 {
-  return (tag && tag->type == TAG_VAR);
+  assert(tag);
+  if (! tag) {
+    err_puts("tag_is_unbound_var: NULL tag");
+    assert(! "tag_is_unbound_var: NULL tag");
+    return NULL;
+  }
+  *dest = tag->type == TAG_VAR;
+  return dest;
 }
 
 bool tag_is_zero(const s_tag *tag)
diff --git a/libc3/tag.h b/libc3/tag.h
index 3e103a5..7edb651 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -48,7 +48,7 @@ s_str *        tag_inspect (const s_tag *tag, s_str *dest);
 bool           tag_ident_is_bound (const s_tag *tag);
 bool           tag_is_bound_var (const s_tag *tag);
 bool           tag_is_number (const s_tag *tag);
-bool           tag_is_unbound_var (const s_tag *tag);
+bool *         tag_is_unbound_var (const s_tag *tag, bool *dest);
 bool           tag_is_zero(const s_tag *tag);
 s8             tag_number_compare (const s_tag *a, const s_tag *b);
 const s_tag *  tag_resolve_cow (const s_tag *tag);
diff --git a/libc3/types.h b/libc3/types.h
index 0f2609b..7ab9cfa 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -191,12 +191,12 @@ typedef union tag_data u_tag_data;
 typedef union tag_type u_tag_type;
 
 /* typedefs */
-typedef u32            character;
-typedef s_tag      **p_facts_spec;
-typedef s_tag       *t_facts_spec[];
-typedef SHA1_CTX     t_hash;
-typedef const s_tag *p_tag;
-typedef u64          t_skiplist_height;
+typedef u32           character;
+typedef s_tag       **p_facts_spec;
+typedef s_tag        *t_facts_spec[];
+typedef SHA1_CTX      t_hash;
+typedef const s_tag  *p_tag;
+typedef u64           t_skiplist_height;
 
 /* function typedefs */
 typedef void (* f_clean) (void *x);