Commit 2d771fb81879b9f6ff5e7e147ae2a546148e164a

Thomas de Grivel 2024-04-11T18:05:44

wip env_eval_fn

diff --git a/libc3/env.c b/libc3/env.c
index 3d87197..7a5840c 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -33,6 +33,7 @@
 #include "facts_with_cursor.h"
 #include "file.h"
 #include "fn.h"
+#include "fn_clause.h"
 #include "frame.h"
 #include "ident.h"
 #include "io.h"
@@ -1318,6 +1319,75 @@ bool env_eval_struct (s_env *env, const s_struct *s, s_tag *dest)
   return false;
 }
 
+bool env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest)
+{
+  uw i;
+  s_block     *src_block;
+  s_fn_clause *src_clause;
+  s_list      *src_pattern;
+  s_tag       *src_tag;
+  s_tag         tmp = {0};
+  s_block      *tmp_block;
+  s_fn_clause **tmp_clause;
+  s_fn         *tmp_fn;
+  s_list      **tmp_pattern;
+  s_tag        *tmp_tag;
+  assert(env);
+  assert(fn);
+  assert(dest);
+  (void) env;
+  tmp.type = TAG_FN;
+  tmp_fn = &tmp.data.fn;
+  src_clause = fn->clauses;
+  tmp_clause = &tmp_fn->clauses;
+  while (src_clause) {
+    *tmp_clause = fn_clause_new(NULL);
+    src_pattern = src_clause->pattern;
+    tmp_pattern = &(*tmp_clause)->pattern;
+    while (src_pattern) {
+      *tmp_pattern = list_new(NULL);
+      if (! env_eval_fn_tag(env, &src_pattern->tag,
+                            &(*tmp_pattern)->tag))
+        goto ko;
+      src_pattern = list_next(src_pattern);
+      tmp_pattern = &(*tmp_pattern)->next.data.list;
+    }
+    src_block = &src_clause->algo;
+    tmp_block = &(*tmp_clause)->algo;
+    if (! block_init(tmp_block, src_block->count))
+      goto ko;
+    tmp_block->short_form = src_block->short_form;
+    i = 0;
+    while (i < src_block->count) {
+      src_tag = src_block->tag + i;
+      tmp_tag = tmp_block->tag + i;
+      if (! env_eval_fn_tag(env, src_tag, tmp_tag))
+        goto ko;
+      i++;
+    }
+    src_clause = src_clause->next_clause;
+    tmp_clause = &(*tmp_clause)->next_clause;
+  }
+  tmp_fn->macro = fn->macro;
+  tmp_fn->special_operator = fn->special_operator;
+  *dest = tmp;
+  return true;
+ ko:
+  fn_clean(&tmp.data.fn);
+  return false;
+}
+
+bool env_eval_fn_tag (s_env *env, const s_tag *tag, s_tag *dest)
+{
+  assert(env);
+  assert(tag);
+  assert(dest);
+  (void) env;
+  if (! tag_init_copy(dest, tag))
+    return false;
+  return true;
+}
+
 bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
 {
   assert(env);
@@ -1334,6 +1404,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
     return env_eval_call(env, &tag->data.call, dest);
   case TAG_COMPLEX:
     return env_eval_complex(env, tag->data.complex, dest);
+  case TAG_FN:
+    return env_eval_fn(env, &tag->data.fn, dest);
   case TAG_IDENT:
     return env_eval_ident(env, &tag->data.ident, dest);
   case TAG_LIST:
@@ -1355,7 +1427,6 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
   case TAG_F64:
   case TAG_F128:
   case TAG_FACT:
-  case TAG_FN:
   case TAG_INTEGER:
   case TAG_RATIO:
   case TAG_PTAG:
diff --git a/libc3/env.h b/libc3/env.h
index 51f3f5c..acdb0f8 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -71,6 +71,8 @@ bool          env_eval_equal_tuple (s_env *env, bool macro,
                                     const s_tuple *a, const s_tuple *b,
                                     s_tuple *dest);
 bool          env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest);
+bool          env_eval_fn_tag (s_env *env, const s_tag *tag,
+                               s_tag *dest);
 bool          env_eval_fn_call (s_env *env, const s_fn *fn,
                                 const s_list *arguments, s_tag *dest);
 bool          env_eval_ident (s_env *env, const s_ident *ident,
diff --git a/libc3/list_init.c b/libc3/list_init.c
index fac1925..d4d9c91 100644
--- a/libc3/list_init.c
+++ b/libc3/list_init.c
@@ -129,6 +129,17 @@ s_list * list_init_f128 (s_list *list, f128 f, s_list *next)
   return list;
 }
 
+s_list * list_init_fn_copy (s_list *list, const s_fn *fn, s_list *next)
+{
+  s_list tmp;
+  assert(list);
+  list_init(&tmp, next);
+  if (! tag_init_fn_copy(&tmp.tag, fn))
+    return NULL;
+  *list = tmp;
+  return list;
+}
+
 s_list * list_init_ident (s_list *list, const s_ident *ident, 
                           s_list *next)
 {
@@ -655,6 +666,19 @@ s_list * list_new_f128 (f128 f, s_list *next)
   return list;
 }
 
+s_list * list_new_fn_copy (const s_fn *fn, s_list *next)
+{
+  s_list *list;
+  list = list_new(next);
+  if (! list)
+    return NULL;
+  if (! tag_init_fn_copy(&list->tag, fn)) {
+    free(list);
+    return NULL;
+  }
+  return list;
+}
+
 s_list * list_new_ident (const s_ident *ident, s_list *next)
 {
   s_list *list;
diff --git a/libc3/list_init.h b/libc3/list_init.h
index 8bc30e1..d12d3e7 100644
--- a/libc3/list_init.h
+++ b/libc3/list_init.h
@@ -18,6 +18,7 @@ s_list * list_init_complex (s_list *list, s_complex *c, s_list *next);
 s_list * list_init_f32 (s_list *list, f32 f, s_list *next);
 s_list * list_init_f64 (s_list *list, f64 f, s_list *next);
 s_list * list_init_f128 (s_list *list, f128 f, s_list *next);
+s_list * list_init_fn_copy (s_list *list, const s_fn *fn, s_list *next);
 s_list * list_init_ident (s_list *list, const s_ident *ident, 
                           s_list *next);
 s_list * list_init_ident_1 (s_list *list, const char *p, s_list *next);
@@ -83,6 +84,7 @@ s_list * list_new_complex (s_complex *c, s_list *next);
 s_list * list_new_f32 (f32 f, s_list *next);
 s_list * list_new_f64 (f64 f, s_list *next);
 s_list * list_new_f128 (f128 f, s_list *next);
+s_list * list_new_fn_copy (const s_fn *fn, s_list *next);
 s_list * list_new_ident (const s_ident *ident, s_list *next);
 s_list * list_new_ident_1 (const char *p, s_list *next);
 s_list * list_new_integer_1 (const char *p, s_list *next);
@@ -139,6 +141,7 @@ s_list * list_complex (s_list *list, s_complex *c);
 s_list * list_f32 (s_list *list, f32 f);
 s_list * list_f64 (s_list *list, f64 f);
 s_list * list_f128 (s_list *list, f128 f);
+s_list * list_fn_copy (s_list *list, const s_fn *fn);
 s_list * list_ident (s_list *list, const s_ident *ident);
 s_list * list_ident_1 (s_list *list, const char *p);
 s_list * list_integer_1 (s_list *list, const char *p);
diff --git a/libc3/tag_init.c b/libc3/tag_init.c
index 042e8b2..64cf500 100644
--- a/libc3/tag_init.c
+++ b/libc3/tag_init.c
@@ -122,6 +122,17 @@ s_tag * tag_init_f128 (s_tag *tag, f128 f)
   return tag;
 }
 
+s_tag * tag_init_fn_copy (s_tag *tag, const s_fn *fn)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tmp.type = TAG_FN;
+  if (! fn_init_copy(&tmp.data.fn, fn))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_init_ident (s_tag *tag, const s_ident *ident)
 {
   s_tag tmp = {0};
@@ -623,6 +634,20 @@ s_tag * tag_new_f128 (f128 f)
   return tag;
 }
 
+s_tag * tag_new_fn_copy (const s_fn *fn)
+{
+  s_tag *tag;
+  tag = alloc(sizeof(s_tag));
+  if (! tag)
+    return NULL;
+  tag->type = TAG_FN;
+  if (! fn_init_copy(&tag->data.fn, fn)) {
+    free(tag);
+    return NULL;
+  }
+  return tag;
+}
+
 s_tag * tag_new_ident (const s_ident *ident)
 {
   s_tag *tag;
@@ -1199,6 +1224,18 @@ s_tag * tag_f128 (s_tag *tag, f128 f)
   return tag;
 }
 
+s_tag * tag_fn_copy (s_tag *tag, const s_fn *fn)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tag_clean(tag);
+  tmp.type = TAG_FN;
+  if (! fn_init_copy(&tmp.data.fn, fn))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_ident (s_tag *tag, const s_ident *ident)
 {
   s_tag tmp = {0};
diff --git a/libc3/tag_init.h b/libc3/tag_init.h
index 39c2c05..873add5 100644
--- a/libc3/tag_init.h
+++ b/libc3/tag_init.h
@@ -16,6 +16,7 @@ s_tag * tag_init_complex (s_tag *tag, s_complex *c);
 s_tag * tag_init_f32 (s_tag *tag, f32 f);
 s_tag * tag_init_f64 (s_tag *tag, f64 f);
 s_tag * tag_init_f128 (s_tag *tag, f128 f);
+s_tag * tag_init_fn_copy (s_tag *tag, const s_fn *fn);
 s_tag * tag_init_ident (s_tag *tag, const s_ident *ident);
 s_tag * tag_init_ident_1 (s_tag *tag, const char *p);
 s_tag * tag_init_integer_1 (s_tag *tag, const char *p);
@@ -68,6 +69,7 @@ s_tag * tag_new_complex (s_complex *c);
 s_tag * tag_new_f32 (f32 f);
 s_tag * tag_new_f64 (f64 f);
 s_tag * tag_new_f128 (f128 f);
+s_tag * tag_new_fn_copy (const s_fn *fn);
 s_tag * tag_new_ident (const s_ident *ident);
 s_tag * tag_new_ident_1 (const char *p);
 s_tag * tag_new_integer_1 (const char *p);
@@ -120,6 +122,7 @@ s_tag * tag_complex (s_tag *tag, s_complex *c);
 s_tag * tag_f32 (s_tag *tag, f32 f);
 s_tag * tag_f64 (s_tag *tag, f64 f);
 s_tag * tag_f128 (s_tag *tag, f128 f);
+s_tag * tag_fn_copy (s_tag *tag, const s_fn *fn);
 s_tag * tag_ident (s_tag *tag, const s_ident *ident);
 s_tag * tag_ident_1 (s_tag *tag, const char *p);
 s_tag * tag_integer_1 (s_tag *tag, const char *p);
diff --git a/libc3/tag_init.rb b/libc3/tag_init.rb
index 17c398f..6ab6d11 100644
--- a/libc3/tag_init.rb
+++ b/libc3/tag_init.rb
@@ -321,6 +321,8 @@ class TagInitList
                    [Arg.new("f64", "f")]),
        TagInit.new("f128", "TAG_F128", :init_mode_direct,
                    [Arg.new("f128", "f")]),
+       TagInit.new("fn", "copy", "TAG_FN", :init_mode_init,
+                   [Arg.new("const s_fn *", "fn")]),
        TagInit.new("ident", "TAG_IDENT", :init_mode_direct,
                    [Arg.new("const s_ident *", "ident")]),
        TagInit1.new("ident", "1", "TAG_IDENT", :init_mode_init),