Commit 5bf34e91015502c1d3e3113920ec23594d1b5af0

Thomas de Grivel 2024-02-14T18:46:47

wip

diff --git a/README.md b/README.md
index a7bd184..25c43e2 100644
--- a/README.md
+++ b/README.md
@@ -293,7 +293,7 @@ Script interpreter. Works the same as ic3 but is not interactive.
      - height function `(TAG_VOID: 0, TAG_TUPLE: max(height(tuple->tags)))`
      - has_ident
      - collect_idents
-   - macros
+   - DONE macros
    - modules
      - defmodule
      - def
@@ -321,7 +321,9 @@ Script interpreter. Works the same as ic3 but is not interactive.
        - ffi ?
          - libdwarf
    - control structures
-     - if / when / unless
+     - if
+     - when
+     - unless
      - switch/case/cond
      - while
    - quote
diff --git a/lib/c3/0.1/c3.facts b/lib/c3/0.1/c3.facts
index 7de6335..2604539 100644
--- a/lib/c3/0.1/c3.facts
+++ b/lib/c3/0.1/c3.facts
@@ -199,3 +199,6 @@ add {C3, :symbol, C3.fib}
 replace {C3.fib, :fn, fn { (0) { 1 }
                            (1) { 1 }
                            (x) { fib(x - 1) + fib(x - 2) } }}
+add {C3, :symbol, C3.if}
+replace {C3.if, :is_a, :macro}
+replace {C3.if, :cfn, cfn Tag "c3_if" (Tag, Tag, Tag, Result)
\ No newline at end of file
diff --git a/libc3/c3.c b/libc3/c3.c
index c3b5930..1ed8a1b 100644
--- a/libc3/c3.c
+++ b/libc3/c3.c
@@ -15,11 +15,13 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include "bool.h"
 #include "buf.h"
 #include "c3_main.h"
 #include "env.h"
 #include "str.h"
 #include "sym.h"
+#include "tag.h"
 
 const s_str g_c3_base_binary = {{NULL}, 2, {"01"}};
 const s_str g_c3_base_octal = {{NULL}, 8, {"01234567"}};
@@ -76,6 +78,29 @@ s_str * c3_getenv (const s_str *name, s_str *dest)
   return str_init_1(dest, NULL, p);
 }
 
+/* Special operator. */
+s_tag * c3_if (const s_tag *cond, const s_tag *then, const s_tag *else_,
+               s_tag *dest)
+{
+  bool b;
+  s_tag tmp;
+  if (! env_eval_tag(&g_c3_env, cond, &tmp))
+    return NULL;
+  if (! bool_init_cast(&b, &tmp)) {
+    tag_clean(&tmp);
+    return NULL;
+  }
+  tag_clean(&tmp);
+  if (b) {
+    if (! env_eval_tag(&g_c3_env, then, dest))
+      return NULL;
+    return dest;
+  }
+  if (! env_eval_tag(&g_c3_env, else_, dest))
+    return NULL;
+  return dest;
+}
+
 s_env * c3_init (s_env *env, int argc, char **argv)
 {
   if (! env)
diff --git a/libc3/c3_main.h b/libc3/c3_main.h
index 596599c..0fde3b7 100644
--- a/libc3/c3_main.h
+++ b/libc3/c3_main.h
@@ -32,6 +32,10 @@ void c3_clean (s_env *env);
 /* Observers. */
 s_str * c3_getenv (const s_str *name, s_str *dest);
 
+/* Special operators. */
+s_tag * c3_if (const s_tag *cond, const s_tag *then,
+               const s_tag *else_, s_tag *dest);
+
 /* debug */
 void c3_break (void);