diff --git a/libc3/cfn.c b/libc3/cfn.c
index a88b983..03a71e3 100644
--- a/libc3/cfn.c
+++ b/libc3/cfn.c
@@ -30,6 +30,7 @@ void * cfn_tag_to_ffi_value (s_tag *tag, const s_sym *type);
s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
{
s_list *a;
+ void **arg_pointers = NULL;
void **arg_values = NULL;
u8 arity;
s_list *cfn_arg_type;
@@ -39,6 +40,7 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
s_tag tmp;
s_tag tmp2;
assert(cfn);
+ assert(cfn->arity == cfn->cif.nargs);
num_args = list_length(args);
arity = cfn->arity - (cfn->arg_result ? 1 : 0);
if (arity != num_args) {
@@ -52,6 +54,8 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
/* make result point to tmp value */
result = cfn_tag_to_ffi_value(&tmp, cfn->result_type);
if (cfn->arity) {
+ if (! (arg_pointers = calloc(sizeof(void *), cfn->arity + 1)))
+ err(1, "cfn_apply");
if (! (arg_values = calloc(sizeof(void *), cfn->arity + 1)))
err(1, "cfn_apply");
cfn_arg_type = cfn->arg_types;
@@ -59,10 +63,21 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
while (cfn_arg_type) {
assert(cfn_arg_type->tag.type.type == TAG_SYM);
if (cfn_arg_type->tag.data.sym == sym_1("&result"))
- arg_values[i] = cfn_tag_to_ffi_value(&tmp2, cfn->result_type);
+ if (cfn->cif.rtype == &ffi_type_pointer) {
+ arg_pointers[i] = cfn_tag_to_ffi_value(&tmp2, cfn->result_type);
+ arg_values[i] = &arg_pointers[i];
+ }
+ else
+ arg_values[i] = cfn_tag_to_ffi_value(&tmp2, cfn->result_type);
else {
- arg_values[i] = cfn_tag_to_ffi_value(&a->tag,
- cfn_arg_type->tag.data.sym);
+ if (cfn->cif.arg_types[i] == &ffi_type_pointer) {
+ arg_pointers[i] = cfn_tag_to_ffi_value(&a->tag,
+ cfn_arg_type->tag.data.sym);
+ arg_values[i] = &arg_pointers[i];
+ }
+ else
+ arg_values[i] = cfn_tag_to_ffi_value(&a->tag,
+ cfn_arg_type->tag.data.sym);
a = list_next(a);
}
cfn_arg_type = list_next(cfn_arg_type);
@@ -82,6 +97,7 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
warnx("cfn_apply: NULL function pointer");
tag_init_void(dest);
}
+ free(arg_pointers);
free(arg_values);
return dest;
}
@@ -101,6 +117,7 @@ s_cfn * cfn_copy (const s_cfn *cfn, s_cfn *dest)
dest->arg_result = cfn->arg_result;
list_copy(cfn->arg_types, &dest->arg_types);
dest->arity = cfn->arity;
+ dest->cif = cfn->cif;
dest->result_type = cfn->result_type;
dest->ptr = cfn->ptr;
return dest;
@@ -129,6 +146,7 @@ s_cfn * cfn_set_type (s_cfn *cfn, s_list *arg_type,
sw arity;
u8 i = 0;
ffi_type *result_ffi_type;
+ ffi_status status;
assert(cfn);
if (! (result_ffi_type = cfn_sym_to_ffi_type(result_type, NULL)))
return NULL;
@@ -159,9 +177,20 @@ s_cfn * cfn_set_type (s_cfn *cfn, s_list *arg_type,
cfn->arg_types = arg_type;
cfn->arity = arity;
cfn->result_type = result_type;
- ffi_prep_cif(&cfn->cif, FFI_DEFAULT_ABI, cfn->arity, result_ffi_type,
- arg_ffi_type);
- free(arg_ffi_type);
+ status = ffi_prep_cif(&cfn->cif, FFI_DEFAULT_ABI, cfn->arity, result_ffi_type,
+ arg_ffi_type);
+ if (status == FFI_BAD_TYPEDEF) {
+ warnx("cfn_set_type: ffi_prep_cif: FFI_BAD_TYPEDEF");
+ return NULL;
+ }
+ if (status == FFI_BAD_ABI) {
+ warnx("cfn_set_type: ffi_prep_cif: FFI_BAD_ABI");
+ return NULL;
+ }
+ if (status != FFI_OK) {
+ warnx("cfn_set_type: ffi_prep_cif: unknown error");
+ return NULL;
+ }
return cfn;
}
@@ -252,7 +281,7 @@ e_tag_type cfn_sym_to_tag_type (const s_sym *sym)
if (sym == sym_1("sym"))
return TAG_SYM;
if (sym == sym_1("tag"))
- return TAG_PTAG;
+ return TAG_VOID;
if (sym == sym_1("tuple"))
return TAG_TUPLE;
assert(! "cfn_sym_to_tag_type: unknown type");
diff --git a/libc3/tag.c b/libc3/tag.c
index 60250a7..5fd59ca 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -478,10 +478,267 @@ void tag_delete (s_tag *tag)
s_tag * tag_div (const s_tag *a, const s_tag *b, s_tag *dest)
{
- (void) a;
- (void) b;
- (void) dest;
- return NULL;
+ 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 divide %s by %s",
+ tag_type_to_string(a->type.type),
+ tag_type_to_string(b->type.type));
}
s_tag * tag_f32 (s_tag *tag, f32 x)
@@ -918,10 +1175,267 @@ s_tag * tag_list_1 (s_tag *tag, const s8 *p)
s_tag * tag_mul (const s_tag *a, const s_tag *b, s_tag *dest)
{
- (void) a;
- (void) b;
- (void) dest;
- return NULL;
+ 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 multiply %s by %s",
+ tag_type_to_string(a->type.type),
+ tag_type_to_string(b->type.type));
}
s_tag * tag_new ()
@@ -990,10 +1504,267 @@ s_tag * tag_str_1 (s_tag *tag, s8 *free, const s8 *p)
s_tag * tag_sub (const s_tag *a, const s_tag *b, s_tag *dest)
{
- (void) a;
- (void) b;
- (void) dest;
- return NULL;
+ 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_s8(dest, a->data.u8 - b->data.u8);
+ case TAG_U16:
+ return tag_init_s16(dest, a->data.u8 - b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.u8 - b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(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_s16(dest, a->data.u16 - b->data.u8);
+ case TAG_U16:
+ return tag_init_s16(dest, a->data.u16 - b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.u16 - b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(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_s32(dest, a->data.u32 - b->data.u8);
+ case TAG_U16:
+ return tag_init_s32(dest, a->data.u32 - b->data.u16);
+ case TAG_U32:
+ return tag_init_s32(dest, a->data.u32 - b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(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_s64(dest, a->data.u64 - b->data.u8);
+ case TAG_U16:
+ return tag_init_s64(dest, a->data.u64 - b->data.u16);
+ case TAG_U32:
+ return tag_init_s64(dest, a->data.u64 - b->data.u32);
+ case TAG_U64:
+ return tag_init_s64(dest, a->data.u64 - b->data.u64);
+ default:
+ goto ko;
+ }
+ default:
+ goto ko;
+ }
+ ko:
+ errx(1, "cannot subtract %s by %s",
+ tag_type_to_string(a->type.type),
+ tag_type_to_string(b->type.type));
}
s_tag * tag_sym (s_tag *tag, const s_sym *x)
diff --git a/test/ic3/op.out.expected b/test/ic3/op.out.expected
index dc3a265..21d9409 100644
--- a/test/ic3/op.out.expected
+++ b/test/ic3/op.out.expected
@@ -4,5 +4,5 @@ quote 1 + 2 / 3 * 4
quote 1 + 2 / 3 * 4 - 5
3
1
-4
--1
+1
+-4