diff --git a/lib/c3/0.1/c3.facts b/lib/c3/0.1/c3.facts
index f9c992b..3231808 100644
--- a/lib/c3/0.1/c3.facts
+++ b/lib/c3/0.1/c3.facts
@@ -9,19 +9,19 @@
{C3, :symbol, C3.*}
{C3, :symbol, C3./}
{C3, :symbol, C3.first}
-{C3.+, :cfn, cfn :tag "tag_add" (:tag, :tag)}
+{C3.+, :cfn, cfn :tag "tag_add" (:tag, :tag, :tag)}
{C3.+, :is_a, :operator}
{C3.+, :operator_precedence, 1}
{C3.+, :operator_associativity, :left}
-{C3.-, :cfn, cfn :tag "tag_sub" (:tag, :tag)}
+{C3.-, :cfn, cfn :tag "tag_sub" (:tag, :tag, :tag)}
{C3.-, :is_a, :operator}
{C3.-, :operator_precedence, 1}
{C3.-, :operator_associativity, :left}
-{C3.*, :cfn, cfn :tag "tag_mul" (:tag, :tag)}
+{C3.*, :cfn, cfn :tag "tag_mul" (:tag, :tag, :tag)}
{C3.*, :is_a, :operator}
{C3.*, :operator_precedence, 2}
{C3.*, :operator_associativity, :left}
-{C3./, :cfn, cfn :tag "tag_div" (:tag, :tag)}
+{C3./, :cfn, cfn :tag "tag_div" (:tag, :tag, :tag)}
{C3./, :is_a, :operator}
{C3./, :operator_precedence, 2}
{C3./, :operator_associativity, :left}
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 05d9360..197ee95 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -317,6 +317,7 @@ sw buf_parse_cfn (s_buf *buf, s_cfn *dest)
goto restore;
result += r;
tmp.arity = list_length(tmp.arg_types);
+ cfn_link(&tmp);
*dest = tmp;
r = result;
goto clean;
diff --git a/libc3/cfn.c b/libc3/cfn.c
index 4780568..d26c9aa 100644
--- a/libc3/cfn.c
+++ b/libc3/cfn.c
@@ -12,6 +12,7 @@
* THIS SOFTWARE.
*/
#include <assert.h>
+#include <dlfcn.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
@@ -87,6 +88,14 @@ s_cfn * cfn_init (s_cfn *cfn)
return cfn;
}
+s_cfn * cfn_link (s_cfn *cfn)
+{
+ assert(cfn);
+ if (! (cfn->p = (void (*) (void)) dlsym(RTLD_DEFAULT, cfn->name.ptr.ps8)))
+ errx(1, "cfn_link: %s: %s", cfn->name.ptr.ps8, dlerror());
+ return cfn;
+}
+
s_cfn * cfn_set_type (s_cfn *cfn, s_list *arg_type,
const s_sym *result_type)
{
diff --git a/libc3/cfn.h b/libc3/cfn.h
index 2ddf28a..3aa3f7e 100644
--- a/libc3/cfn.h
+++ b/libc3/cfn.h
@@ -24,4 +24,7 @@ void cfn_clean (s_cfn *cfn);
s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest);
s_cfn * cfn_copy (const s_cfn *cfn, s_cfn *dest);
+/* modifiers */
+s_cfn * cfn_link (s_cfn *cfn);
+
#endif /* CFN_H */
diff --git a/libc3/tag.c b/libc3/tag.c
index 57c8045..9300d1d 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -27,6 +27,271 @@ s_tag * tag_1 (s_tag *tag, const s8 *p)
return tag_init_1(tag, p);
}
+s_tag * tag_add (const s_tag *a, const s_tag *b, s_tag *dest)
+{
+ assert(a);
+ assert(b);
+ assert(dest);
+ switch (a->type.type) {
+ case TAG_F32:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.f32 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.f32 + b->data.f64);
+ case TAG_S8:
+ return tag_init_f32(dest, a->data.f32 + b->data.s8);
+ case TAG_S16:
+ return tag_init_f32(dest, a->data.f32 + b->data.s16);
+ case TAG_S32:
+ return tag_init_f32(dest, a->data.f32 + b->data.s32);
+ case TAG_S64:
+ return tag_init_f32(dest, a->data.f32 + b->data.s64);
+ case TAG_U8:
+ return tag_init_f32(dest, a->data.f32 + b->data.u8);
+ case TAG_U16:
+ return tag_init_f32(dest, a->data.f32 + b->data.u16);
+ case TAG_U32:
+ return tag_init_f32(dest, a->data.f32 + b->data.u32);
+ case TAG_U64:
+ return tag_init_f32(dest, a->data.f32 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_F64:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f64(dest, a->data.f64 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.f64 + b->data.f64);
+ case TAG_S8:
+ return tag_init_f64(dest, a->data.f64 + b->data.s8);
+ case TAG_S16:
+ return tag_init_f64(dest, a->data.f64 + b->data.s16);
+ case TAG_S32:
+ return tag_init_f64(dest, a->data.f64 + b->data.s32);
+ case TAG_S64:
+ return tag_init_f64(dest, a->data.f64 + b->data.s64);
+ case TAG_U8:
+ return tag_init_f64(dest, a->data.f64 + b->data.u8);
+ case TAG_U16:
+ return tag_init_f64(dest, a->data.f64 + b->data.u16);
+ case TAG_U32:
+ return tag_init_f64(dest, a->data.f64 + b->data.u32);
+ case TAG_U64:
+ return tag_init_f64(dest, a->data.f64 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_S8:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.s8 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.s8 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s8(dest, a->data.s8 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s16(dest, a->data.s8 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.s8 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.s8 + b->data.s64);
+ case TAG_U8:
+ return tag_init_s8(dest, a->data.s8 + b->data.u8);
+ case TAG_U16:
+ return tag_init_s16(dest, a->data.s8 + b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.s8 + b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(dest, a->data.s8 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_S16:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.s16 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.s16 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s16(dest, a->data.s16 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s16(dest, a->data.s16 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.s16 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.s16 + b->data.s64);
+ case TAG_U8:
+ return tag_init_s16(dest, a->data.s16 + b->data.u8);
+ case TAG_U16:
+ return tag_init_s16(dest, a->data.s16 + b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.s16 + b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(dest, a->data.s16 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_S32:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.s32 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.s32 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s32(dest, a->data.s32 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s32(dest, a->data.s32 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.s32 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.s32 + b->data.s64);
+ case TAG_U8:
+ return tag_init_s32(dest, a->data.s32 + b->data.u8);
+ case TAG_U16:
+ return tag_init_s32(dest, a->data.s32 + b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.s32 + b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(dest, a->data.s32 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_S64:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.s64 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.s64 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s32(dest, a->data.s64 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s32(dest, a->data.s64 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.s64 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.s64 + b->data.s64);
+ case TAG_U8:
+ return tag_init_s32(dest, a->data.s64 + b->data.u8);
+ case TAG_U16:
+ return tag_init_s32(dest, a->data.s64 + b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.s64 + b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(dest, a->data.s64 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_U8:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.u8 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.u8 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s8(dest, a->data.u8 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s16(dest, a->data.u8 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.u8 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.u8 + b->data.s64);
+ case TAG_U8:
+ return tag_init_u8(dest, a->data.u8 + b->data.u8);
+ case TAG_U16:
+ return tag_init_u16(dest, a->data.u8 + b->data.u16);
+ case TAG_U32:
+ return tag_init_u32(dest, a->data.u8 + b->data.u32);
+ case TAG_U64:
+ return tag_init_u64(dest, a->data.u8 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_U16:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.u16 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.u16 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s16(dest, a->data.u16 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s16(dest, a->data.u16 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.u16 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.u16 + b->data.s64);
+ case TAG_U8:
+ return tag_init_u16(dest, a->data.u16 + b->data.u8);
+ case TAG_U16:
+ return tag_init_u16(dest, a->data.u16 + b->data.u16);
+ case TAG_U32:
+ return tag_init_u32(dest, a->data.u16 + b->data.u32);
+ case TAG_U64:
+ return tag_init_u64(dest, a->data.u16 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_U32:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.u32 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.u32 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s32(dest, a->data.u32 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s32(dest, a->data.u32 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s32(dest, a->data.u32 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.u32 + b->data.s64);
+ case TAG_U8:
+ return tag_init_u32(dest, a->data.u32 + b->data.u8);
+ case TAG_U16:
+ return tag_init_u32(dest, a->data.u32 + b->data.u16);
+ case TAG_U32:
+ return tag_init_u32(dest, a->data.u32 + b->data.u32);
+ case TAG_U64:
+ return tag_init_u64(dest, a->data.u32 + b->data.u64);
+ default:
+ goto ko;
+ }
+ case TAG_U64:
+ switch (b->type.type) {
+ case TAG_F32:
+ return tag_init_f32(dest, a->data.u64 + b->data.f32);
+ case TAG_F64:
+ return tag_init_f64(dest, a->data.u64 + b->data.f64);
+ case TAG_S8:
+ return tag_init_s64(dest, a->data.u64 + b->data.s8);
+ case TAG_S16:
+ return tag_init_s64(dest, a->data.u64 + b->data.s16);
+ case TAG_S32:
+ return tag_init_s64(dest, a->data.u64 + b->data.s32);
+ case TAG_S64:
+ return tag_init_s64(dest, a->data.u64 + b->data.s64);
+ case TAG_U8:
+ return tag_init_u64(dest, a->data.u64 + b->data.u8);
+ case TAG_U16:
+ return tag_init_u64(dest, a->data.u64 + b->data.u16);
+ case TAG_U32:
+ return tag_init_u64(dest, a->data.u64 + b->data.u32);
+ case TAG_U64:
+ return tag_init_u64(dest, a->data.u64 + b->data.u64);
+ default:
+ goto ko;
+ }
+ default:
+ goto ko;
+ }
+ ko:
+ errx(1, "cannot add %s to %s",
+ tag_type_to_string(a->type.type),
+ tag_type_to_string(b->type.type));
+}
+
s_tag * tag_bool (s_tag *tag, bool b)
{
assert(tag);
@@ -759,6 +1024,39 @@ ffi_type tag_to_ffi_type(const s_tag *tag)
return ffi_type_void;
}
+s8 * tag_type_to_string (e_tag_type type)
+{
+ switch (type) {
+ case TAG_VOID: return "void";
+ case TAG_BOOL: return "bool";
+ case TAG_CALL: return "call";
+ case TAG_CALL_FN: return "call_fn";
+ case TAG_CALL_MACRO: return "call_macro";
+ case TAG_CFN: return "cfn";
+ case TAG_CHARACTER: return "character";
+ case TAG_F32: return "f32";
+ case TAG_F64: return "f64";
+ case TAG_FN: return "fn";
+ case TAG_IDENT: return "ident";
+ case TAG_INTEGER: return "integer";
+ case TAG_S64: return "s64";
+ case TAG_S32: return "s32";
+ case TAG_S16: return "s16";
+ case TAG_S8: return "s8";
+ case TAG_U8: return "u8";
+ case TAG_U16: return "u16";
+ case TAG_U32: return "u32";
+ case TAG_U64: return "u64";
+ case TAG_LIST: return "list";
+ case TAG_PTAG: return "ptag";
+ case TAG_QUOTE: return "quote";
+ case TAG_STR: return "str";
+ case TAG_SYM: return "sym";
+ case TAG_TUPLE: return "tuple";
+ case TAG_VAR: return "var";
+ }
+}
+
s_tag * tag_u8 (s_tag *tag, u8 x)
{
assert(tag);
diff --git a/libc3/tag.h b/libc3/tag.h
index ed23870..e9502b1 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -97,6 +97,7 @@ e_bool tag_is_unbound_var (const s_tag *tag);
s8 tag_number_compare (const s_tag *a, const s_tag *b);
sw tag_size (const s_tag *tag);
sw tag_type_size (e_tag_type type);
+s8 * tag_type_to_string (e_tag_type type);
/* Modifiers */
s_tag * tag_1 (s_tag *tag, const s8 *p);
@@ -136,4 +137,7 @@ s_tag * tag_var (s_tag *tag);
s_tag * tag_void (s_tag *tag);
ffi_type tag_to_ffi_type(const s_tag *tag);
+/* operators */
+s_tag * tag_add (const s_tag *a, const s_tag *b, s_tag *dest);
+
#endif /* STR_H */