Commit 17a1ef11a1d761ccba3c0a94699a6ec4061f0732

Thomas de Grivel 2024-07-13T12:01:55

libc3: fix access, facts: error handling

diff --git a/.ic3_history b/.ic3_history
index c04bdbf..f2b12a4 100644
--- a/.ic3_history
+++ b/.ic3_history
@@ -1,9 +1,3 @@
-Plop.sq(4)
-defmodule Plop do def a = 1 end
-Plop.a
-(Sw) 123\
-(Sw) 123
-(Sw) 123/2
 (Sw) 123 / 2
 defmodule Plop do def a = 1 end
 Plop.a
@@ -97,3 +91,9 @@ quote [{:a, 1}, {:b, 2}]
 abc.def
 %{a: 1}
 %{a: 1}.a
+test = fn (list, args) { List.map(list, fn (e) { access(args, e)})}
+test([a, b, c], %{a: 1, b: 2, c: 3})
+test([:a, :b, :c], %{a: 1, b: 2, c: 3})
+a = %{a: 1}
+b = %{b: 2}
+a.a + b.b
diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index 1416cd4..f2b12a4 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -1,11 +1,3 @@
-  def sq = fn (x) { x + x }
-end
-Plop.sq(4)
-defmodule Plop do def a = 1 end
-Plop.a
-(Sw) 123\
-(Sw) 123
-(Sw) 123/2
 (Sw) 123 / 2
 defmodule Plop do def a = 1 end
 Plop.a
@@ -95,4 +87,13 @@ quote [a: 1, b: 2]
 quote [{:a, 1}, {:b, 2}]
 %C3.Operator{}
 %GL.Vertex{}
-%C3.Operator{}
+123.456
+abc.def
+%{a: 1}
+%{a: 1}.a
+test = fn (list, args) { List.map(list, fn (e) { access(args, e)})}
+test([a, b, c], %{a: 1, b: 2, c: 3})
+test([:a, :b, :c], %{a: 1, b: 2, c: 3})
+a = %{a: 1}
+b = %{b: 2}
+a.a + b.b
diff --git a/libc3/env.c b/libc3/env.c
index 7321a9b..c32d951 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -605,7 +605,11 @@ bool env_eval_call_fn_args (s_env *env, const s_fn *fn,
       args_final = args;
     }
     while (clause) {
-      frame_init(&frame, env->frame);
+      if (! frame_init(&frame, env->frame)) {
+        list_delete_all(env->search_modules);
+        env->search_modules = search_modules;
+        return false;
+      }
       env->frame = &frame;
       if (env_eval_equal_list(env, fn->macro || fn->special_operator,
                               clause->pattern, args_final, &tmp))
diff --git a/libc3/facts.c b/libc3/facts.c
index 9e61ad4..8ba4eb2 100644
--- a/libc3/facts.c
+++ b/libc3/facts.c
@@ -321,6 +321,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
                       "  version: 1}\n")) <= 0) {
     err_write_1("facts_load: invalid or missing header: ");
     err_puts(path->ptr.pchar);
+    assert(! "facts_load: invalid or missing header");
     return -1;
   }
   result += r;
@@ -342,6 +343,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
       err_inspect_u64(&line);
       err_write_1(": ");
       err_puts(path->ptr.pchar);
+      assert(! "facts_load: invalid fact");
       goto ko;
     }
     result += r;
@@ -351,6 +353,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
       err_inspect_u64(&line);
       err_write_1(": ");
       err_puts(path->ptr.pchar);
+      assert(! "facts_load: missing newline");
       goto ko;
     }
     result += r;
@@ -360,6 +363,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
       err_inspect_u64(&line);
       err_write_1(": ");
       err_puts(path->ptr.pchar);
+      assert(! "facts_load: invalid fact");
       goto ko;
     }
     fact_r(&fact_eval, &fact_eval_r);
@@ -371,6 +375,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
 	err_inspect_u64(&line);
 	err_write_1(": ");
 	err_puts(path->ptr.pchar);
+	assert(! "facts_load: failed to replace fact");
 	goto ko;
       }
     }
@@ -382,6 +387,7 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
 	err_inspect_u64(&line);
 	err_write_1(": ");
 	err_puts(path->ptr.pchar);
+	assert(! "facts_load: failed to add fact");
 	goto ko;
       }
     }
diff --git a/libc3/facts_cursor.c b/libc3/facts_cursor.c
index 40a5551..f7b691c 100644
--- a/libc3/facts_cursor.c
+++ b/libc3/facts_cursor.c
@@ -16,6 +16,7 @@
 #include "facts_cursor.h"
 #include "skiplist__fact.h"
 #include "skiplist_node__fact.h"
+#include "sym.h"
 #include "tag.h"
 #include "var.h"
 
@@ -125,10 +126,12 @@ const s_fact ** facts_cursor_next (s_facts_cursor *cursor,
                                    const s_fact **dest)
 {
   const s_fact *fact;
+  const s_sym *type;
   assert(cursor);
   if (! facts_cursor_lock(cursor))
     return NULL;
   if (cursor->node) {
+  next:
     cursor->node = SKIPLIST_NODE_NEXT__fact(cursor->node, 0);
     if (cursor->node &&
         cursor->index->compare(&cursor->end, cursor->node->fact) < 0)
@@ -148,16 +151,31 @@ const s_fact ** facts_cursor_next (s_facts_cursor *cursor,
   fact = cursor->node->fact;
   if (cursor->var_subject) {
     tag_var(cursor->var_subject, cursor->var_subject_type);
+    if (! tag_type(fact->subject, &type))
+      goto ko;
+    if (cursor->var_subject_type != &g_sym_Tag &&
+        cursor->var_subject_type != type)
+      goto next;
     if (! var_set(cursor->var_subject, fact->subject))
       goto ko;
   }
   if (cursor->var_predicate) {
     tag_var(cursor->var_predicate, cursor->var_predicate_type);
+    if (! tag_type(fact->predicate, &type))
+      goto ko;
+    if (cursor->var_predicate_type != &g_sym_Tag &&
+        cursor->var_predicate_type != type)
+      goto next;
     if (! var_set(cursor->var_predicate, fact->predicate))
       goto ko;
   }
   if (cursor->var_object) {
     tag_var(cursor->var_object, cursor->var_object_type);
+    if (! tag_type(fact->object, &type))
+      goto ko;
+    if (cursor->var_object_type != &g_sym_Tag &&
+        cursor->var_object_type != type)
+      goto next;
     if (! var_set(cursor->var_object, fact->object))
       goto ko;
   }
diff --git a/libc3/frame.c b/libc3/frame.c
index adda70c..4f73b30 100644
--- a/libc3/frame.c
+++ b/libc3/frame.c
@@ -48,13 +48,25 @@ s_frame * frame_delete (s_frame *frame)
 
 void frame_delete_all (s_frame *frame)
 {
-  while (frame)
-    frame = frame_delete(frame);
+  s_frame *f;
+  f = frame;
+  while (f)
+    f = frame_delete(f);
 }
 
 const s_tag * frame_get (const s_frame *frame, const s_sym *sym)
 {
-  return binding_get(frame->bindings, sym);
+  const s_frame *f;
+  const s_tag *result;
+  assert(sym);
+  f = frame;
+  while (f) {
+    result = binding_get(frame->bindings, sym);
+    if (result)
+      return result;
+    f = f->next;
+  }
+  return NULL;
 }
 
 s_frame * frame_init (s_frame *frame, s_frame *next)
@@ -72,5 +84,9 @@ s_frame * frame_new (s_frame *next)
   frame = alloc(sizeof(s_frame));
   if (! frame)
     return NULL;
-  return frame_init(frame, next);
+  if (! frame_init(frame, next)) {
+    free(frame);
+    return NULL;
+  }
+  return frame;
 }
diff --git a/libc3/var.c b/libc3/var.c
index e2bf728..da4d0a8 100644
--- a/libc3/var.c
+++ b/libc3/var.c
@@ -86,6 +86,7 @@ s_tag * var_set (s_tag *var, const s_tag *value)
       err_inspect_sym(&var_type);
       err_write_1(" != ");
       err_inspect_sym(&value_type);
+      err_write_1("\n");
       assert(! "var_set: type mismatch");
       return NULL;
     }