Commit 94dbfc454886ee8206a71efbb3fb384f41482212

Thomas de Grivel 2023-03-04T02:00:03

wip

diff --git a/libc3/cfn.c b/libc3/cfn.c
new file mode 100644
index 0000000..6eba261
--- /dev/null
+++ b/libc3/cfn.c
@@ -0,0 +1,92 @@
+/* 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 "cfn.h"
+
+s_tag * cfn_apply (s_cfn *cfn, s_list *args) {
+  ffi_type **arg_types;
+  void **arg_values;
+  ffi_cif cif;
+  sw i;
+  sw num_args;
+  void* result;
+  ffi_type* result_type;
+  num_args = list_length(args);
+  if (! num_args) {
+    /* TODO */
+    assert(! "todo");
+    err(1, "todo");
+    return NULL;
+  }
+  if (! (arg_types = malloc(sizeof(ffi_type *) * num_args)))
+    err(1, "cfn_apply");
+  if (! (arg_values = malloc(sizeof(void *) * num_args)))
+    err(1, "cfn_apply");
+  while (args) {
+    switch (args->tag.type.type) {
+    case TAG_S8:
+      arg_types[num_args] = &ffi_type_sint;
+      arg_values[num_args] = args->data;
+      num_args++;
+      break;
+    case FLOAT:
+      arg_types[num_args] = &ffi_type_float;
+      arg_values[num_args] = args->data;
+      num_args++;
+      break;
+    case STRING:
+      arg_types[num_args] = &ffi_type_pointer;
+      arg_values[num_args] = &args->data;
+      num_args++;
+      break;
+    }
+
+    args = args->next;
+  }
+
+  ffi_type** final_arg_types = malloc(sizeof(ffi_type*) * num_args);
+  void** final_arg_values = malloc(sizeof(void*) * num_args);
+
+  for (int i = 0; i < num_args; i++) {
+    final_arg_types[i] = arg_types[i];
+    final_arg_values[i] = arg_values[i];
+  }
+
+  ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, num_args, NULL, final_arg_types);
+
+  switch (((Node*)fn_ptr)->tag) {
+  case INT:
+    result_type = &ffi_type_sint;
+    break;
+  case FLOAT:
+    result_type = &ffi_type_float;
+    break;
+  case STRING:
+    result_type = &ffi_type_pointer;
+    break;
+  }
+
+  ffi_call(&cif, ((Node*)fn_ptr)->data, result, final_arg_values);
+
+  free(final_arg_types);
+  free(final_arg_values);
+
+  if (((Node*)fn_ptr)->tag == STRING) {
+    char* result_copy = strdup(result);
+    free_result(result, ((Node*)fn_ptr)->tag);
+    result = result_copy;
+  }
+
+  return result;
+}
+#endif /* CFN_H */
diff --git a/libc3/cfn.h b/libc3/cfn.h
new file mode 100644
index 0000000..0c5a90a
--- /dev/null
+++ b/libc3/cfn.h
@@ -0,0 +1,23 @@
+/* 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 CFN_H
+#define CFN_H
+
+#include "types.h"
+
+/* stack-allocation compatible functions */
+s_cfn * cfn_init (s_cfn *cfn);
+void cfn_clean (s_cfn *cfn);
+
+#endif /* CFN_H */
diff --git a/libc3/types.h b/libc3/types.h
index 279a8dd..6261e22 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -57,6 +57,7 @@ typedef enum {
   TAG_CALL,
   TAG_CALL_FN,
   TAG_CALL_MACRO,
+  TAG_CFN,
   TAG_CHARACTER,
   TAG_F32,
   TAG_F64,
@@ -86,6 +87,7 @@ typedef struct binding                 s_binding;
 typedef struct buf                     s_buf;
 typedef struct buf_save                s_buf_save;
 typedef struct call                    s_call;
+typedef struct cfn                     s_cfn;
 typedef struct env                     s_env;
 typedef struct error_handler           s_error_handler;
 typedef struct fact                    s_fact;
@@ -110,6 +112,7 @@ typedef struct sym                     s_sym;
 typedef struct sym_list                s_sym_list;
 typedef struct tag                     s_tag;
 typedef struct tuple                   s_tuple;
+typedef struct type_list               s_type_list;
 typedef struct unwind_protect          s_unwind_protect;
 
 /* unions */
@@ -136,6 +139,11 @@ struct buf_save {
   uw wpos;
 };
 
+struct cfn {
+  const s_sym *name;
+  void *p;
+};
+
 struct fact {
   const s_tag *subject;
   const s_tag *predicate;
@@ -204,6 +212,11 @@ struct tuple {
   s_tag *tag;
 };
 
+struct type_list {
+  e_tag_type type;
+  s_type_list *next;
+};
+
 struct unwind_protect {
   jmp_buf buf;
   jmp_buf *jmp;
@@ -283,6 +296,7 @@ struct sym {
 union tag_data {
   bool         bool;
   s_call       call;
+  s_cfn       *cfn;
   character    character;
   f32          f32;
   f64          f64;