diff --git a/libc3/buf.c b/libc3/buf.c
index ebf2342..8c3b661 100644
--- a/libc3/buf.c
+++ b/libc3/buf.c
@@ -765,7 +765,7 @@ sw buf_vf (s_buf *buf, const char *fmt, va_list ap)
return r;
}
-sw buf_write_1 (s_buf *buf, s8 *p)
+sw buf_write_1 (s_buf *buf, const s8 *p)
{
s_str stra;
str_init_1(&stra, NULL, p);
diff --git a/libc3/buf.h b/libc3/buf.h
index c7fdf89..2b0e412 100644
--- a/libc3/buf.h
+++ b/libc3/buf.h
@@ -89,7 +89,7 @@ sw buf_str_to_hex (s_buf *buf, const s_str *src);
sw buf_str_to_hex_size (const s_str *src);
sw buf_u8_to_hex (s_buf *buf, u8 x);
sw buf_vf (s_buf *buf, const char *fmt, va_list ap);
-sw buf_write_1 (s_buf *buf, s8 *p);
+sw buf_write_1 (s_buf *buf, const s8 *p);
sw buf_write_character_utf8 (s_buf *buf, character c);
sw buf_write_f32 (s_buf *buf, f32 x);
sw buf_write_f64 (s_buf *buf, f64 x);
diff --git a/libc3/c3.h b/libc3/c3.h
index 7f8abe1..1e1a10e 100644
--- a/libc3/c3.h
+++ b/libc3/c3.h
@@ -36,6 +36,7 @@
#include "hash.h"
#include "ident.h"
#include "integer.h"
+#include "io.h"
#include "list.h"
#include "module.h"
#include "quote.h"
diff --git a/libc3/env.c b/libc3/env.c
index 7913a1e..fc8af05 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -134,6 +134,9 @@ bool env_eval_call_arguments (s_env *env, s_list *args, s_list **dest)
*t = list_new();
if (! env_eval_tag(env, &args->tag, &(*t)->tag)) {
list_delete_all(tmp);
+ err_puts("env_eval_call_arguments: invalid argument: ");
+ err_inspect(&args->tag);
+ err_puts("\n");
return false;
}
t = &(*t)->next.data.list;
@@ -163,6 +166,11 @@ bool env_eval_call_fn (s_env *env, const s_call *call, s_tag *dest)
return false;
}
if (! env_eval_equal_list(env, fn->pattern, args, &tmp)) {
+ err_puts("env_eval_call_fn: no clause matching.\nTried clauses :\n");
+ err_inspect_list(fn->pattern);
+ err_puts("\nArguments :\n");
+ err_inspect_list(args);
+ err_puts("\n");
list_delete_all(args);
env->frame = frame_clean(&frame);
return false;
@@ -197,6 +205,8 @@ bool env_eval_call_macro (s_env *env, const s_call *call, s_tag *dest)
bool env_eval_equal_list (s_env *env, const s_list *a, const s_list *b,
s_list **dest)
{
+ s_list *a_next;
+ s_list *b_next;
s_list *tmp;
s_list **t;
t = &tmp;
@@ -212,8 +222,15 @@ bool env_eval_equal_list (s_env *env, const s_list *a, const s_list *b,
*t = list_new();
if (! env_eval_equal_tag(env, &a->tag, &b->tag, &(*t)->tag))
goto ko;
- a = list_next(a);
- b = list_next(b);
+ a_next = list_next(a);
+ b_next = list_next(b);
+ if (! a_next || ! b_next) {
+ if (! env_eval_equal_tag(env, &a->next, &b->next, &(*t)->next))
+ goto ko;
+ break;
+ }
+ a = a_next;
+ b = b_next;
t = &(*t)->next.data.list;
}
ok:
diff --git a/libc3/io.c b/libc3/io.c
new file mode 100644
index 0000000..34d7914
--- /dev/null
+++ b/libc3/io.c
@@ -0,0 +1,57 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software excepted
+ * on Apple computers 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 "buf.h"
+#include "buf_inspect.h"
+#include "env.h"
+#include "io.h"
+
+sw err_inspect (const s_tag *tag)
+{
+ sw r;
+ r = buf_inspect_tag(&g_c3_env.err, tag);
+ buf_flush(&g_c3_env.err);
+ return r;
+}
+
+sw err_inspect_list (const s_list *list)
+{
+ sw r;
+ r = buf_inspect_list(&g_c3_env.err, list);
+ buf_flush(&g_c3_env.err);
+ return r;
+}
+
+sw err_puts (const s8 *s)
+{
+ sw r;
+ r = buf_write_1(&g_c3_env.err, s);
+ buf_flush(&g_c3_env.err);
+ return r;
+}
+
+sw io_inspect (const s_tag *tag)
+{
+ sw r;
+ r = buf_inspect_tag(&g_c3_env.out, tag);
+ buf_flush(&g_c3_env.out);
+ return r;
+}
+
+sw io_puts (const s8 *s)
+{
+ sw r;
+ r = buf_write_1(&g_c3_env.out, s);
+ buf_flush(&g_c3_env.out);
+ return r;
+}
diff --git a/libc3/io.h b/libc3/io.h
new file mode 100644
index 0000000..5989385
--- /dev/null
+++ b/libc3/io.h
@@ -0,0 +1,28 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software excepted
+ * on Apple computers 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.
+ */
+#ifndef IO_H
+#define IO_H
+
+#include "types.h"
+
+/* error output */
+sw err_inspect (const s_tag *tag);
+sw err_inspect_list (const s_list *list);
+sw err_puts (const s8 *s);
+
+/* standard output */
+sw io_inspect (const s_tag *tag);
+sw io_puts (const s8 *s);
+
+#endif /* IO_H */
diff --git a/libc3/sources.mk b/libc3/sources.mk
index 576ad3f..a3dec1f 100644
--- a/libc3/sources.mk
+++ b/libc3/sources.mk
@@ -31,6 +31,7 @@ HEADERS = \
hash.h \
ident.h \
integer.h \
+ io.h \
list.h \
log.h \
module.h \
@@ -81,6 +82,7 @@ SOURCES = \
hash.c \
ident.c \
integer.c \
+ io.c \
list.c \
log.c \
module.c \
@@ -129,6 +131,7 @@ LO_SOURCES = \
hash.c \
ident.c \
integer.c \
+ io.c \
list.c \
log.c \
module.c \
diff --git a/libc3/sources.sh b/libc3/sources.sh
index 40e3a5a..a4196f9 100644
--- a/libc3/sources.sh
+++ b/libc3/sources.sh
@@ -1,4 +1,4 @@
# sources.sh generated by update_sources
-HEADERS='arg.h binding.h bool.h buf.h buf_file.h buf_inspect.h buf_parse.h buf_parse_c.h buf_save.h c3.h c_types.h call.h character.h compare.h config.h env.h error.h error_handler.h eval.h fact.h facts.h facts_cursor.h facts_spec.h facts_spec_cursor.h facts_with.h facts_with_cursor.h fn.h frame.h hash.h ident.h integer.h list.h log.h module.h quote.h set__fact.h set__tag.h set_cursor__fact.h set_cursor__tag.h set_item__fact.h set_item__tag.h sha1.h skiplist__fact.h skiplist_node__fact.h str.h sym.h tag.h tuple.h types.h ucd.h '
-SOURCES='arg.c binding.c bool.c buf.c buf_file.c buf_inspect.c buf_parse.c buf_parse_c.c buf_save.c c3.c call.c character.c compare.c env.c error.c error_handler.c eval.c fact.c facts.c facts_cursor.c facts_spec.c facts_spec_cursor.c facts_with.c facts_with_cursor.c fn.c frame.c hash.c ident.c integer.c list.c log.c module.c quote.c set__fact.c set__tag.c set_cursor__fact.c set_cursor__tag.c set_item__fact.c set_item__tag.c skiplist__fact.c skiplist_node__fact.c str.c sym.c tag.c tuple.c ucd.c '
-LO_SOURCES='arg.c binding.c bool.c buf.c buf_file.c buf_inspect.c buf_parse.c buf_parse_c.c buf_save.c c3.c call.c character.c compare.c env.c error.c error_handler.c eval.c fact.c facts.c facts_cursor.c facts_spec.c facts_spec_cursor.c facts_with.c facts_with_cursor.c fn.c frame.c hash.c ident.c integer.c list.c log.c module.c quote.c set__fact.c set__tag.c set_cursor__fact.c set_cursor__tag.c set_item__fact.c set_item__tag.c skiplist__fact.c skiplist_node__fact.c str.c sym.c tag.c tuple.c ucd.c ../libtommath/bn_cutoffs.c ../libtommath/bn_mp_2expt.c ../libtommath/bn_mp_abs.c ../libtommath/bn_mp_add.c ../libtommath/bn_mp_add_d.c ../libtommath/bn_mp_and.c ../libtommath/bn_mp_clamp.c ../libtommath/bn_mp_clear.c ../libtommath/bn_mp_clear_multi.c ../libtommath/bn_mp_cmp.c ../libtommath/bn_mp_cmp_d.c ../libtommath/bn_mp_cmp_mag.c ../libtommath/bn_mp_cnt_lsb.c ../libtommath/bn_mp_complement.c ../libtommath/bn_mp_copy.c ../libtommath/bn_mp_count_bits.c ../libtommath/bn_mp_div.c ../libtommath/bn_mp_div_2.c ../libtommath/bn_mp_div_2d.c ../libtommath/bn_mp_div_3.c ../libtommath/bn_mp_div_d.c ../libtommath/bn_mp_dr_is_modulus.c ../libtommath/bn_mp_dr_reduce.c ../libtommath/bn_mp_dr_setup.c ../libtommath/bn_mp_error_to_string.c ../libtommath/bn_mp_exch.c ../libtommath/bn_mp_exptmod.c ../libtommath/bn_mp_gcd.c ../libtommath/bn_mp_get_i32.c ../libtommath/bn_mp_get_i64.c ../libtommath/bn_mp_get_mag_u32.c ../libtommath/bn_mp_get_mag_u64.c ../libtommath/bn_mp_grow.c ../libtommath/bn_mp_init.c ../libtommath/bn_mp_init_copy.c ../libtommath/bn_mp_init_multi.c ../libtommath/bn_mp_init_size.c ../libtommath/bn_mp_invmod.c ../libtommath/bn_mp_lcm.c ../libtommath/bn_mp_lshd.c ../libtommath/bn_mp_mod.c ../libtommath/bn_mp_mod_2d.c ../libtommath/bn_mp_montgomery_calc_normalization.c ../libtommath/bn_mp_montgomery_reduce.c ../libtommath/bn_mp_montgomery_setup.c ../libtommath/bn_mp_mul.c ../libtommath/bn_mp_mul_2.c ../libtommath/bn_mp_mul_2d.c ../libtommath/bn_mp_mul_d.c ../libtommath/bn_mp_mulmod.c ../libtommath/bn_mp_neg.c ../libtommath/bn_mp_or.c ../libtommath/bn_mp_radix_size.c ../libtommath/bn_mp_reduce.c ../libtommath/bn_mp_reduce_2k.c ../libtommath/bn_mp_reduce_2k_l.c ../libtommath/bn_mp_reduce_2k_setup.c ../libtommath/bn_mp_reduce_2k_setup_l.c ../libtommath/bn_mp_reduce_is_2k.c ../libtommath/bn_mp_reduce_is_2k_l.c ../libtommath/bn_mp_reduce_setup.c ../libtommath/bn_mp_rshd.c ../libtommath/bn_mp_set.c ../libtommath/bn_mp_sqr.c ../libtommath/bn_mp_sqrt.c ../libtommath/bn_mp_sub.c ../libtommath/bn_mp_sub_d.c ../libtommath/bn_mp_xor.c ../libtommath/bn_mp_zero.c ../libtommath/bn_s_mp_add.c ../libtommath/bn_s_mp_balance_mul.c ../libtommath/bn_s_mp_exptmod.c ../libtommath/bn_s_mp_exptmod_fast.c ../libtommath/bn_s_mp_invmod_fast.c ../libtommath/bn_s_mp_invmod_slow.c ../libtommath/bn_s_mp_karatsuba_mul.c ../libtommath/bn_s_mp_karatsuba_sqr.c ../libtommath/bn_s_mp_montgomery_reduce_fast.c ../libtommath/bn_s_mp_mul_digs.c ../libtommath/bn_s_mp_mul_digs_fast.c ../libtommath/bn_s_mp_mul_high_digs.c ../libtommath/bn_s_mp_mul_high_digs_fast.c ../libtommath/bn_s_mp_rand_platform.c ../libtommath/bn_s_mp_sqr.c ../libtommath/bn_s_mp_sqr_fast.c ../libtommath/bn_s_mp_sub.c ../libtommath/bn_s_mp_toom_mul.c ../libtommath/bn_s_mp_toom_sqr.c '
+HEADERS='arg.h binding.h bool.h buf.h buf_file.h buf_inspect.h buf_parse.h buf_parse_c.h buf_save.h c3.h c_types.h call.h character.h compare.h config.h env.h error.h error_handler.h eval.h fact.h facts.h facts_cursor.h facts_spec.h facts_spec_cursor.h facts_with.h facts_with_cursor.h fn.h frame.h hash.h ident.h integer.h io.h list.h log.h module.h quote.h set__fact.h set__tag.h set_cursor__fact.h set_cursor__tag.h set_item__fact.h set_item__tag.h sha1.h skiplist__fact.h skiplist_node__fact.h str.h sym.h tag.h tuple.h types.h ucd.h '
+SOURCES='arg.c binding.c bool.c buf.c buf_file.c buf_inspect.c buf_parse.c buf_parse_c.c buf_save.c c3.c call.c character.c compare.c env.c error.c error_handler.c eval.c fact.c facts.c facts_cursor.c facts_spec.c facts_spec_cursor.c facts_with.c facts_with_cursor.c fn.c frame.c hash.c ident.c integer.c io.c list.c log.c module.c quote.c set__fact.c set__tag.c set_cursor__fact.c set_cursor__tag.c set_item__fact.c set_item__tag.c skiplist__fact.c skiplist_node__fact.c str.c sym.c tag.c tuple.c ucd.c '
+LO_SOURCES='arg.c binding.c bool.c buf.c buf_file.c buf_inspect.c buf_parse.c buf_parse_c.c buf_save.c c3.c call.c character.c compare.c env.c error.c error_handler.c eval.c fact.c facts.c facts_cursor.c facts_spec.c facts_spec_cursor.c facts_with.c facts_with_cursor.c fn.c frame.c hash.c ident.c integer.c io.c list.c log.c module.c quote.c set__fact.c set__tag.c set_cursor__fact.c set_cursor__tag.c set_item__fact.c set_item__tag.c skiplist__fact.c skiplist_node__fact.c str.c sym.c tag.c tuple.c ucd.c ../libtommath/bn_cutoffs.c ../libtommath/bn_mp_2expt.c ../libtommath/bn_mp_abs.c ../libtommath/bn_mp_add.c ../libtommath/bn_mp_add_d.c ../libtommath/bn_mp_and.c ../libtommath/bn_mp_clamp.c ../libtommath/bn_mp_clear.c ../libtommath/bn_mp_clear_multi.c ../libtommath/bn_mp_cmp.c ../libtommath/bn_mp_cmp_d.c ../libtommath/bn_mp_cmp_mag.c ../libtommath/bn_mp_cnt_lsb.c ../libtommath/bn_mp_complement.c ../libtommath/bn_mp_copy.c ../libtommath/bn_mp_count_bits.c ../libtommath/bn_mp_div.c ../libtommath/bn_mp_div_2.c ../libtommath/bn_mp_div_2d.c ../libtommath/bn_mp_div_3.c ../libtommath/bn_mp_div_d.c ../libtommath/bn_mp_dr_is_modulus.c ../libtommath/bn_mp_dr_reduce.c ../libtommath/bn_mp_dr_setup.c ../libtommath/bn_mp_error_to_string.c ../libtommath/bn_mp_exch.c ../libtommath/bn_mp_exptmod.c ../libtommath/bn_mp_gcd.c ../libtommath/bn_mp_get_i32.c ../libtommath/bn_mp_get_i64.c ../libtommath/bn_mp_get_mag_u32.c ../libtommath/bn_mp_get_mag_u64.c ../libtommath/bn_mp_grow.c ../libtommath/bn_mp_init.c ../libtommath/bn_mp_init_copy.c ../libtommath/bn_mp_init_multi.c ../libtommath/bn_mp_init_size.c ../libtommath/bn_mp_invmod.c ../libtommath/bn_mp_lcm.c ../libtommath/bn_mp_lshd.c ../libtommath/bn_mp_mod.c ../libtommath/bn_mp_mod_2d.c ../libtommath/bn_mp_montgomery_calc_normalization.c ../libtommath/bn_mp_montgomery_reduce.c ../libtommath/bn_mp_montgomery_setup.c ../libtommath/bn_mp_mul.c ../libtommath/bn_mp_mul_2.c ../libtommath/bn_mp_mul_2d.c ../libtommath/bn_mp_mul_d.c ../libtommath/bn_mp_mulmod.c ../libtommath/bn_mp_neg.c ../libtommath/bn_mp_or.c ../libtommath/bn_mp_radix_size.c ../libtommath/bn_mp_reduce.c ../libtommath/bn_mp_reduce_2k.c ../libtommath/bn_mp_reduce_2k_l.c ../libtommath/bn_mp_reduce_2k_setup.c ../libtommath/bn_mp_reduce_2k_setup_l.c ../libtommath/bn_mp_reduce_is_2k.c ../libtommath/bn_mp_reduce_is_2k_l.c ../libtommath/bn_mp_reduce_setup.c ../libtommath/bn_mp_rshd.c ../libtommath/bn_mp_set.c ../libtommath/bn_mp_sqr.c ../libtommath/bn_mp_sqrt.c ../libtommath/bn_mp_sub.c ../libtommath/bn_mp_sub_d.c ../libtommath/bn_mp_xor.c ../libtommath/bn_mp_zero.c ../libtommath/bn_s_mp_add.c ../libtommath/bn_s_mp_balance_mul.c ../libtommath/bn_s_mp_exptmod.c ../libtommath/bn_s_mp_exptmod_fast.c ../libtommath/bn_s_mp_invmod_fast.c ../libtommath/bn_s_mp_invmod_slow.c ../libtommath/bn_s_mp_karatsuba_mul.c ../libtommath/bn_s_mp_karatsuba_sqr.c ../libtommath/bn_s_mp_montgomery_reduce_fast.c ../libtommath/bn_s_mp_mul_digs.c ../libtommath/bn_s_mp_mul_digs_fast.c ../libtommath/bn_s_mp_mul_high_digs.c ../libtommath/bn_s_mp_mul_high_digs_fast.c ../libtommath/bn_s_mp_rand_platform.c ../libtommath/bn_s_mp_sqr.c ../libtommath/bn_s_mp_sqr_fast.c ../libtommath/bn_s_mp_sub.c ../libtommath/bn_s_mp_toom_mul.c ../libtommath/bn_s_mp_toom_sqr.c '
diff --git a/test/env_test.c b/test/env_test.c
index 3972be5..40e4c50 100644
--- a/test/env_test.c
+++ b/test/env_test.c
@@ -14,6 +14,7 @@
#include "../libc3/compare.h"
#include "../libc3/env.h"
#include "../libc3/frame.h"
+#include "../libc3/sym.h"
#include "../libc3/tag.h"
#include "test.h"
@@ -51,11 +52,42 @@ void env_test_eval_equal_tag ()
tag_1(&y, "[1, 2]"), &z));
TEST_ASSERT(frame_get(&frame, x.data.ident.sym));
TEST_EQ(compare_tag(&z, &y), 0);
+ tag_clean(&z);
+ env.frame = frame_clean(&frame);
+ env_clean(&env);
+ env_init(&env);
+ env.frame = frame_init(&frame, env.frame);
+ test_context("[] = []");
+ TEST_ASSERT(env_eval_equal_tag(&env, tag_1(&x, "[]"),
+ tag_1(&y, "[]"), &z));
+ TEST_EQ(compare_tag(&z, &y), 0);
+ tag_clean(&z);
+ env.frame = frame_clean(&frame);
+ env_clean(&env);
+ env_init(&env);
+ env.frame = frame_init(&frame, env.frame);
+ test_context("x = [1, 2]");
+ TEST_ASSERT(env_eval_equal_tag(&env, tag_1(&x, "[a, b]"),
+ tag_1(&y, "[1, 2]"), &z));
+ TEST_ASSERT(frame_get(&frame, sym_1("a")));
+ TEST_ASSERT(frame_get(&frame, sym_1("b")));
+ TEST_EQ(compare_tag(&z, &y), 0);
+ tag_clean(&z);
+ env.frame = frame_clean(&frame);
+ env_clean(&env);
+ env_init(&env);
+ env.frame = frame_init(&frame, env.frame);
+ test_context("x = [1, 2]");
+ TEST_ASSERT(env_eval_equal_tag(&env, tag_1(&x, "[a | b]"),
+ tag_1(&y, "[1, 2]"), &z));
+ TEST_ASSERT(frame_get(&frame, sym_1("a")));
+ TEST_ASSERT(frame_get(&frame, sym_1("b")));
+ TEST_EQ(compare_tag(&z, &y), 0);
+ tag_clean(&z);
env.frame = frame_clean(&frame);
env_clean(&env);
tag_clean(&x);
tag_clean(&y);
- tag_clean(&z);
test_context(NULL);
}