Commit ddd5a4beb0f6b90671e25c0c7b3d023c84ebf178

Thomas de Grivel 2023-03-14T22:21:35

wip cfn

diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 7f8fc28..7d3f7bd 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -60,15 +60,18 @@ sw buf_parse_call (s_buf *buf, s_call *dest)
   sw r;
   sw result = 0;
   s_buf_save save;
+  s_call tmp;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  if ((r = buf_parse_ident(buf, &dest->ident)) <= 0)
+  call_init(&tmp);
+  if ((r = buf_parse_ident(buf, &tmp.ident)) <= 0)
     goto clean;
   result += r;
-  if ((r = buf_parse_call_args_paren(buf, dest)) <= 0)
+  if ((r = buf_parse_call_args_paren(buf, &tmp)) <= 0)
     goto restore;
   result += r;
+  *dest = tmp;
   r = result;
   goto clean;
  restore:
diff --git a/libc3/call.c b/libc3/call.c
index 6ec7833..f47c006 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -32,14 +32,15 @@ s_call * call_copy (const s_call *src, s_call *dest)
   assert(dest);
   ident_copy(&src->ident, &dest->ident);
   list_copy(src->arguments, &dest->arguments);
+  dest->cfn = src->cfn;
+  dest->fn = src->fn;
   return dest;
 }
 
 s_call * call_init (s_call *call)
 {
   assert(call);
-  call->cfn = NULL;
-  call->fn = NULL;
+  bzero(call, sizeof(s_call));
   return call;
 }
 
@@ -47,7 +48,8 @@ s_call * call_init_1 (s_call *call, const s8 *p)
 {
   s_buf buf;
   buf_init_1(&buf, p);
-  buf_parse_call(&buf, call);
+  if (buf_parse_call(&buf, call) != (sw) strlen(p))
+    errx(1, "invalid call: %s", p);
   buf_clean(&buf);
   return call;
 }
diff --git a/libc3/env.c b/libc3/env.c
index 88eb1d0..4533c74 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -90,7 +90,7 @@ bool env_eval_call (s_env *env, const s_call *call, s_tag *dest)
   assert(env);
   assert(call);
   assert(dest);
-  c = *call;
+  call_copy(call, &c);
   ident_resolve_module(&c.ident, env);
   tag_init_1(    &tag_cfn,      ":cfn");
   tag_init_1(    &tag_fn,       ":fn");
@@ -141,6 +141,7 @@ bool env_eval_call (s_env *env, const s_call *call, s_tag *dest)
   else
     result = env_eval_call_fn(env, &c, dest);
   facts_with_cursor_clean(&cursor);
+  call_clean(&c);
   return result;
 }
 
diff --git a/test/buf_parse_test.c b/test/buf_parse_test.c
index 9e00090..07a8d3e 100644
--- a/test/buf_parse_test.c
+++ b/test/buf_parse_test.c
@@ -18,6 +18,7 @@
 #include "../libc3/buf.h"
 #include "../libc3/buf_parse.h"
 #include "../libc3/call.h"
+#include "../libc3/cfn.h"
 #include "../libc3/fn.h"
 #include "../libc3/list.h"
 #include "../libc3/str.h"
@@ -50,6 +51,18 @@
     test_context(NULL);                                                \
   } while (0)
 
+#define BUF_PARSE_TEST_CFN(test)                                       \
+  do {                                                                 \
+    s_buf buf;                                                         \
+    s_cfn dest;                                                        \
+    test_context("buf_parse_cfn(" # test ")");                         \
+    buf_init_1(&buf, (test));                                          \
+    TEST_EQ(buf_parse_cfn(&buf, &dest), strlen(test));                 \
+    cfn_clean(&dest);                                                  \
+    buf_clean(&buf);                                                   \
+    test_context(NULL);                                                \
+  } while (0)
+
 #define BUF_PARSE_TEST_CHARACTER(test, expected)                       \
   do {                                                                 \
     s_buf buf;                                                         \
@@ -284,6 +297,19 @@
     test_context(NULL);                                                \
   } while (0)
 
+#define BUF_PARSE_TEST_NOT_CFN(test)                                   \
+  do {                                                                 \
+    s_buf buf;                                                         \
+    s_cfn dest;                                                        \
+    bzero(&dest, sizeof(dest));                                        \
+    test_context("buf_parse_cfn(" # test ") -> 0");                    \
+    buf_init_1(&buf, (test));                                          \
+    TEST_EQ(buf_parse_cfn(&buf, &dest), 0);                            \
+    TEST_EQ(buf.rpos, 0);                                              \
+    buf_clean(&buf);                                                   \
+    test_context(NULL);                                                \
+  } while (0)
+
 #define BUF_PARSE_TEST_NOT_CHARACTER(test)                             \
   do {                                                                 \
     s_buf buf;                                                         \
@@ -588,6 +614,7 @@
 
 void buf_parse_test_bool ();
 void buf_parse_test_call ();
+void buf_parse_test_cfn ();
 void buf_parse_test_character ();
 void buf_parse_test_digit_bin ();
 void buf_parse_test_digit_hex ();
@@ -635,6 +662,7 @@ void buf_parse_test ()
   buf_parse_test_tag();
   buf_parse_test_tuple();
   buf_parse_test_ident();
+  buf_parse_test_cfn();
 }
 
 void buf_parse_test_bool ()
@@ -682,6 +710,20 @@ void buf_parse_test_call ()
   BUF_PARSE_TEST_CALL("a(B.c(D.e(f, g), H.i(j, k)))");
 }
 
+void buf_parse_test_cfn ()
+{
+  BUF_PARSE_TEST_NOT_CFN("0");
+  BUF_PARSE_TEST_NOT_CFN("9");
+  BUF_PARSE_TEST_NOT_CFN("A");
+  BUF_PARSE_TEST_NOT_CFN("Z");
+  BUF_PARSE_TEST_NOT_CFN("a");
+  BUF_PARSE_TEST_NOT_CFN("z");
+  BUF_PARSE_TEST_NOT_CFN("cfn 0 1 (2)");
+  BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag)");
+  BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag, :tag)");
+  BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag, :tag, :tag)");
+}
+
 void buf_parse_test_character ()
 {
   BUF_PARSE_TEST_NOT_CHARACTER("\x01");