Commit 51dfeda820aaf38e0fc1a759e608cbbde90c0e88

Thomas de Grivel 2023-03-03T23:33:00

multiple clause functions

diff --git a/lib/c3/0.1/c3.facts b/lib/c3/0.1/c3.facts
index 998aacf..b7cab56 100644
--- a/lib/c3/0.1/c3.facts
+++ b/lib/c3/0.1/c3.facts
@@ -5,5 +5,9 @@
 {C3, :name, "C3"}
 {C3, :path, "c3.facts"}
 {C3, :symbol, C3.first}
-{C3.first, :fn, fn ([a | _b]) { a }}
-%{hash: 0xD3CCC8472829759D}
+{C3.first, :fn, fn {
+ ([a | _b]) { a }
+ ({a, b}) { a }
+ ({a, b, c}) { a }
+}}
+%{hash: 0xED618BE2629E5F67}
diff --git a/libc3/buf_inspect.c b/libc3/buf_inspect.c
index 18cc6b6..66a3d80 100644
--- a/libc3/buf_inspect.c
+++ b/libc3/buf_inspect.c
@@ -235,10 +235,13 @@ sw buf_inspect_fn (s_buf *buf, const s_fn *fn)
       return r;
     result += r;
     while (fn) {
+      if ((r = buf_write_1(buf, "  ")) < 0)
+        return r;
+      result += r;
       if ((r = buf_inspect_fn_clause(buf, fn)) < 0)
         return r;
       result += r;
-      if ((r = buf_write_1(buf, "\n  ")) < 0)
+      if ((r = buf_write_1(buf, "\n")) < 0)
         return r;
       result += r;
       fn = fn->next_clause;
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 67388a0..c6370e5 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -442,6 +442,9 @@ sw buf_parse_fn (s_buf *buf, s_fn **dest)
     goto restore;
   if (r > 0) {
     result += r;
+    if ((r = buf_ignore_spaces(buf)) <= 0)
+      goto restore;
+    result += r;
     while (1) {
       *tail = fn_new(NULL);
       if ((r = buf_parse_fn_clause(buf, *tail)) <= 0)
@@ -485,18 +488,19 @@ sw buf_parse_fn_clause (s_buf *buf, s_fn *dest)
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  bzero(&tmp, sizeof(s_fn));
+  fn_init(&tmp, NULL);
   if ((r = buf_parse_fn_pattern(buf, &tmp.pattern)) <= 0) {
     warnx("buf_parse_fn: invalid pattern");
     goto restore;
   }
-  tmp.arity = list_length(tmp.pattern);
   result += r;
+  tmp.arity = list_length(tmp.pattern);
   if ((r = buf_ignore_spaces(buf)) < 0)
     goto restore;
   result += r;
   if ((r = buf_parse_fn_algo(buf, &tmp.algo)) <= 0) {
     buf_inspect_fn(&g_c3_env.err, &tmp);
+    buf_flush(&g_c3_env.err);
     warnx("buf_parse_fn: invalid program");
     goto restore;
   }
@@ -517,7 +521,7 @@ sw buf_parse_fn_algo (s_buf *buf, s_list **dest)
   sw r;
   sw result = 0;
   s_buf_save save;
-  s_list **t;
+  s_list **tail;
   s_tag tag;
   s_list *tmp = NULL;
   assert(buf);
@@ -529,16 +533,16 @@ sw buf_parse_fn_algo (s_buf *buf, s_list **dest)
   if ((r = buf_ignore_spaces(buf)) < 0)
     goto restore;
   result += r;
-  t = &tmp;
+  tail = &tmp;
   while (1) {
     if ((r = buf_parse_tag(buf, &tag)) < 0)
       goto restore;
     if (! r)
       break;
     result += r;
-    *t = list_new();
-    (*t)->tag = tag;
-    t = &(*t)->next.data.list;
+    *tail = list_new();
+    (*tail)->tag = tag;
+    tail = &(*tail)->next.data.list;
     if ((r = buf_ignore_spaces(buf)) < 0)
       goto restore;
     result += r;
@@ -569,9 +573,9 @@ sw buf_parse_fn_pattern (s_buf *buf, s_list **dest)
   sw r;
   sw result = 0;
   s_buf_save save;
-  s_list **t;
   s_tag tag;
   s_list *tmp = NULL;
+  s_list **tail = &tmp;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
@@ -581,14 +585,13 @@ sw buf_parse_fn_pattern (s_buf *buf, s_list **dest)
   if ((r = buf_ignore_spaces(buf)) < 0)
     goto restore;
   result += r;
-  t = &tmp;
   while (1) {
     if ((r = buf_parse_tag(buf, &tag)) <= 0)
       goto restore;
     result += r;
-    *t = list_new();
-    (*t)->tag = tag;
-    t = &(*t)->next.data.list;
+    *tail = list_new();
+    (*tail)->tag = tag;
+    tail = &(*tail)->next.data.list;
     if ((r = buf_ignore_spaces(buf)) < 0)
       goto restore;
     result += r;