diff --git a/libc3/buf_inspect.c b/libc3/buf_inspect.c
index 51c6220..6c06872 100644
--- a/libc3/buf_inspect.c
+++ b/libc3/buf_inspect.c
@@ -643,7 +643,7 @@ sw buf_inspect_fn (s_buf *buf, const s_fn *fn)
if ((r = buf_write_1(buf, "{\n")) < 0)
return r;
result += r;
- while (fn) {
+ while (clause) {
if ((r = buf_write_1(buf, " ")) < 0)
return r;
result += r;
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index bbe3a6e..3b7068c 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -1164,6 +1164,7 @@ sw buf_parse_fn (s_buf *buf, s_fn *dest)
*tail = fn_clause_new(NULL);
if ((r = buf_parse_fn_clause(buf, *tail)) <= 0)
goto restore;
+ result += r;
tail = &(*tail)->next_clause;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
diff --git a/libc3/fn.c b/libc3/fn.c
index abe9257..a150e5f 100644
--- a/libc3/fn.c
+++ b/libc3/fn.c
@@ -13,9 +13,12 @@
#include <assert.h>
#include <err.h>
#include <stdlib.h>
+#include <string.h>
#include <strings.h>
#include "arg.h"
#include "binding.h"
+#include "buf.h"
+#include "buf_parse.h"
#include "fn.h"
#include "fn_clause.h"
#include "list.h"
@@ -47,6 +50,18 @@ s_fn * fn_init (s_fn *fn)
return fn;
}
+s_fn * fn_init_1 (s_fn *fn, s8 *p)
+{
+ s_buf buf;
+ sw r;
+ assert(fn);
+ buf_init_1(&buf, p);
+ if ((r = buf_parse_fn(&buf, fn)) != (sw) strlen(p))
+ errx(1, "fn_init_1: buf_parse_fn(%s) %ld != %lu", p, r, strlen(p));
+ buf_clean(&buf);
+ return fn;
+}
+
s_fn * fn_new ()
{
s_fn *fn;
diff --git a/libc3/fn.h b/libc3/fn.h
index 5ce397a..80b146a 100644
--- a/libc3/fn.h
+++ b/libc3/fn.h
@@ -24,6 +24,7 @@
/* stack-allocation compatible functions */
void fn_clean (s_fn *fn);
s_fn * fn_init (s_fn *fn);
+s_fn * fn_init_1 (s_fn *fn, s8 *p);
/* constructors */
s_fn * fn_new ();
diff --git a/test/fn_test.c b/test/fn_test.c
new file mode 100644
index 0000000..e3e229e
--- /dev/null
+++ b/test/fn_test.c
@@ -0,0 +1,41 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <string.h>
+#include "../libc3/fn.h"
+#include "test.h"
+
+#define FN_TEST_INIT_1(test) \
+ do { \
+ TEST_EQ(fn_init_1(&f, (test)), &f); \
+ fn_clean(&f); \
+ } while (0)
+
+TEST_CASE_PROTOTYPE(fn_init_1);
+
+void fn_test ();
+
+void fn_test ()
+{
+ TEST_CASE_RUN(fn_init_1);
+}
+
+TEST_CASE(fn_init_1)
+{
+ s_fn f;
+ FN_TEST_INIT_1("fn (x) { x }");
+ FN_TEST_INIT_1("fn (x) { x * 2 }");
+ FN_TEST_INIT_1("fn (x, y) { x + y }");
+ FN_TEST_INIT_1("fn { (x) { x } (x, y) { x + y } }");
+ FN_TEST_INIT_1("fn { (()) { :error } ((x | _y)) { x } (_) { :error } }");
+}
+TEST_CASE_END(fn_init_1)
diff --git a/test/libc3_test.c b/test/libc3_test.c
index b1590ee..51fd8e9 100644
--- a/test/libc3_test.c
+++ b/test/libc3_test.c
@@ -27,6 +27,7 @@ void fact_test ();
void facts_test ();
void facts_cursor_test ();
void facts_with_test ();
+void fn_test ();
void ident_test ();
void list_test ();
void set__fact_test ();
@@ -94,6 +95,10 @@ int main (int argc, char **argv)
fprintf(stderr, "\ntuple\n");
tuple_test();
}
+ if (test_target("fn")) {
+ fprintf(stderr, "\nfn\n");
+ fn_test();
+ }
if (test_target("call")) {
fprintf(stderr, "\ncall\n");
call_test();
diff --git a/test/sources.mk b/test/sources.mk
index 35344ec..a908ad3 100644
--- a/test/sources.mk
+++ b/test/sources.mk
@@ -23,6 +23,7 @@ SOURCES = \
facts_cursor_test.c \
facts_test.c \
facts_with_test.c \
+ fn_test.c \
hash_test.c \
ident_test.c \
libc3_test.c \
diff --git a/test/sources.sh b/test/sources.sh
index dccfc9e..4d8d5cf 100644
--- a/test/sources.sh
+++ b/test/sources.sh
@@ -1,2 +1,2 @@
# sources.sh generated by update_sources
-SOURCES='array_test.c bool_test.c buf_file_test.c buf_inspect_test.c buf_parse_test.c buf_parse_test_s16.c buf_parse_test_s32.c buf_parse_test_s64.c buf_parse_test_s8.c buf_parse_test_u16.c buf_parse_test_u32.c buf_parse_test_u64.c buf_parse_test_u8.c buf_test.c call_test.c cfn_test.c character_test.c compare_test.c env_test.c fact_test.c facts_cursor_test.c facts_test.c facts_with_test.c hash_test.c ident_test.c libc3_test.c list_test.c set__fact_test.c set__tag_test.c skiplist__fact_test.c str_test.c sym_test.c tag_test.c test.c tuple_test.c types_test.c '
+SOURCES='array_test.c bool_test.c buf_file_test.c buf_inspect_test.c buf_parse_test.c buf_parse_test_s16.c buf_parse_test_s32.c buf_parse_test_s64.c buf_parse_test_s8.c buf_parse_test_u16.c buf_parse_test_u32.c buf_parse_test_u64.c buf_parse_test_u8.c buf_test.c call_test.c cfn_test.c character_test.c compare_test.c env_test.c fact_test.c facts_cursor_test.c facts_test.c facts_with_test.c fn_test.c hash_test.c ident_test.c libc3_test.c list_test.c set__fact_test.c set__tag_test.c skiplist__fact_test.c str_test.c sym_test.c tag_test.c test.c tuple_test.c types_test.c '