Commit 29a543e0ae64d8bc9e7e6d86467299897dc426b2

Thomas de Grivel 2023-08-12T09:08:08

fix call

diff --git a/libc3/env.c b/libc3/env.c
index e0afa1c..8cb4038 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -147,6 +147,7 @@ bool env_eval_call_fn (s_env *env, const s_call *call, s_tag *dest)
   s_list *args = NULL;
   s_frame frame;
   s_fn *fn;
+  s_fn *fn2;
   s_tag tag;
   s_list *tmp = NULL;
   assert(env);
@@ -156,23 +157,30 @@ bool env_eval_call_fn (s_env *env, const s_call *call, s_tag *dest)
   assert(fn);
   frame_init(&frame, env->frame);
   env->frame = &frame;
+  fn2 = fn;
   if (call->arguments) {
     if (! env_eval_call_arguments(env, call->arguments, &args)) {
       env->frame = frame_clean(&frame);
       return false;
     }
-    if (! env_eval_equal_list(env, fn->pattern, args, &tmp)) {
+    while (fn2 && ! env_eval_equal_list(env, fn2->pattern, args, &tmp))
+      fn2 = fn2->next_clause;
+    if (! fn2) {
       err_puts("env_eval_call_fn: no clause matching.\nTried clauses :\n");
-      err_inspect_list(fn->pattern);
+      fn2 = fn;
+      while (fn2) {
+        err_inspect_fn_pattern(fn2->pattern);
+        fn2 = fn2->next_clause;
+      }
       err_puts("\nArguments :\n");
-      err_inspect_list(args);
+      err_inspect_fn_pattern(args);
       err_puts("\n");
       list_delete_all(args);
       env->frame = frame_clean(&frame);
       return false;
     }
   }
-  if (! env_eval_progn(env, fn->algo, &tag)) {
+  if (! env_eval_progn(env, fn2->algo, &tag)) {
     list_delete_all(args);
     list_delete_all(tmp);
     env->frame = frame_clean(&frame);
@@ -300,9 +308,9 @@ bool env_eval_call_special_operator (s_env *env, const s_call *call,
   env->frame = &frame;
   if (! env_eval_equal_list(env, fn->pattern, call->arguments, &tmp)) {
     err_puts("env_eval_call_fn: no clause matching.\nTried clauses :\n");
-    err_inspect_list(fn->pattern);
+    err_inspect_fn_pattern(fn->pattern);
     err_puts("\nArguments :\n");
-    err_inspect_list(call->arguments);
+    err_inspect_fn_pattern(call->arguments);
     err_puts("\n");
     env->frame = frame_clean(&frame);
     return false;
diff --git a/libc3/io.c b/libc3/io.c
index c9225b6..7ee1db0 100644
--- a/libc3/io.c
+++ b/libc3/io.c
@@ -23,6 +23,14 @@ sw err_inspect (const s_tag *tag)
   return r;
 }
 
+sw err_inspect_fn_pattern (const s_list *list)
+{
+  sw r;
+  r = buf_inspect_fn_pattern(&g_c3_env.err, list);
+  buf_flush(&g_c3_env.err);
+  return r;
+}
+
 sw err_inspect_list (const s_list *list)
 {
   sw r;
diff --git a/libc3/io.h b/libc3/io.h
index 99624cd..7c52705 100644
--- a/libc3/io.h
+++ b/libc3/io.h
@@ -17,6 +17,7 @@
 
 /* error output */
 sw err_inspect (const s_tag *tag);
+sw err_inspect_fn_pattern (const s_list *list);
 sw err_inspect_list (const s_list *list);
 sw err_puts (const s8 *s);
 
diff --git a/test/ic3/fn.in b/test/ic3/fn.in
index 5d4daf3..a16d710 100644
--- a/test/ic3/fn.in
+++ b/test/ic3/fn.in
@@ -6,11 +6,15 @@ quote fn {
   ((x | _y)) { x }
   (_) { :error }
 }
-fn (x) { x }
-fn (x, _y) { x }
-fn ((x | _y)) { x }
-fn {
+a = fn (x) { x }
+a(1)
+b = fn (x, _y) { x }
+b(1, 2)
+c = fn ((x | _y)) { x }
+c((1, 2))
+d = fn {
   (()) { :error }
   ((x | _y)) { x }
-  (_) { :error }
+  (_) { :error2 }
 }
+d((1, 2))
diff --git a/test/ic3/fn.out.expected b/test/ic3/fn.out.expected
index 5d4daf3..9ef8205 100644
--- a/test/ic3/fn.out.expected
+++ b/test/ic3/fn.out.expected
@@ -7,10 +7,14 @@ quote fn {
   (_) { :error }
 }
 fn (x) { x }
+1
 fn (x, _y) { x }
+1
 fn ((x | _y)) { x }
+1
 fn {
   (()) { :error }
   ((x | _y)) { x }
-  (_) { :error }
+  (_) { :error2 }
 }
+1