Commit 0c264e5d406d923848bfb17a1747a51dd0dc7953

Thomas de Grivel 2024-07-04T14:22:44

fix return bug in env_def operator fix def clean

diff --git a/libc3/env.c b/libc3/env.c
index 6324ca8..1fbd0af 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -217,12 +217,54 @@ s_tag * env_def (s_env *env, const s_call *call, s_tag *dest)
       tag_clean(&tag_value);
       return NULL;
     }
-    tag_init_ident(dest, &tag_ident.data.ident);
+    if (tag_ident.data.ident.module == env->current_defmodule &&
+        tag_ident.data.ident.sym == &g_sym_clean) {
+      if (! env_def_clean(env, env->current_defmodule, &tag_value)) {
+        tag_clean(&tag_value);
+        return NULL;
+      }
+    }
   }
   tag_clean(&tag_value);
+  tag_init_ident(dest, &tag_ident.data.ident);
   return dest;
 }
 
+const s_sym * env_def_clean (s_env *env, const s_sym *module,
+                             const s_tag *clean)
+{
+  const s_struct_type *st;
+  s_tag tag_module_name;
+  s_tag tag_st;
+  s_tag tag_struct_type;
+  if (! env_struct_type_find(env, module, &st))
+    return NULL;
+  if (! st) {
+    err_write_1("env_def_clean: module ");
+    err_inspect_sym(&module);
+    err_write_1(": struct type not found");
+    assert(! "env_def_clean: module struct type not found");
+    return NULL;
+  }
+  if (clean->type != TAG_CFN) {
+    err_write_1("env_def_clean: module ");
+    err_inspect_sym(&module);
+    err_write_1(": clean method must be a Cfn");
+    assert(! "env_def_clean: module clean method must be a Cfn");
+    return NULL;
+  }
+  tag_init_sym(&tag_module_name, module);
+  tag_init_struct_type_update_clean(&tag_st, st, &clean->data.cfn);
+  tag_init_sym(&tag_struct_type, &g_sym_struct_type);
+  if (! facts_replace_tags(&env->facts, &tag_module_name,
+                           &tag_struct_type, &tag_st)) {
+    tag_clean(&tag_st);
+    return NULL;
+  }
+  tag_clean(&tag_st);
+  return module;
+}
+
 s_tag * env_defmodule (s_env *env, const s_sym **name,
                        const s_block *block, s_tag *dest)
 {
diff --git a/libc3/env.h b/libc3/env.h
index 3bd50b8..59ecf2e 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -43,6 +43,8 @@ bool           env_sym_search_modules (s_env *env,
 
 /* Operators. */
 s_tag *       env_def (s_env *env, const s_call *call, s_tag *dest);
+const s_sym * env_def_clean (s_env *env, const s_sym *module,
+                             const s_tag *tag_clean);
 s_tag *       env_defmodule (s_env *env, const s_sym **name,
                              const s_block *block, s_tag *dest);
 s_tag *       env_defoperator (s_env *env, const s_sym **name,
diff --git a/libc3/list_init.c b/libc3/list_init.c
index 3a802d2..eefb738 100644
--- a/libc3/list_init.c
+++ b/libc3/list_init.c
@@ -425,6 +425,20 @@ s_list * list_init_struct_type (s_list *list, const s_sym *module,
   return list;
 }
 
+s_list * list_init_struct_type_update_clean (s_list *list,
+                                             const s_struct_type *st,
+                                             const s_cfn *clean,
+                                             s_list *next)
+{
+  s_list tmp;
+  assert(list);
+  list_init(&tmp, next);
+  if (! tag_init_struct_type_update_clean(&tmp.tag, st, clean))
+    return NULL;
+  *list = tmp;
+  return list;
+}
+
 s_list * list_init_sw (s_list *list, sw i, s_list *next)
 {
   s_list tmp;
@@ -1018,6 +1032,21 @@ s_list * list_new_struct_type (const s_sym *module, const s_list *spec,
   return list;
 }
 
+s_list * list_new_struct_type_update_clean (const s_struct_type *st,
+                                            const s_cfn *clean,
+                                            s_list *next)
+{
+  s_list *list;
+  list = list_new(next);
+  if (! list)
+    return NULL;
+  if (! tag_init_struct_type_update_clean(&list->tag, st, clean)) {
+    free(list);
+    return NULL;
+  }
+  return list;
+}
+
 s_list * list_new_sw (sw i, s_list *next)
 {
   s_list *list;
diff --git a/libc3/list_init.h b/libc3/list_init.h
index 078ce91..c67ffac 100644
--- a/libc3/list_init.h
+++ b/libc3/list_init.h
@@ -56,6 +56,10 @@ s_list * list_init_struct_with_data (s_list *list, const s_sym *module,
                                      void *data, s_list *next);
 s_list * list_init_struct_type (s_list *list, const s_sym *module,
                                 const s_list *spec, s_list *next);
+s_list * list_init_struct_type_update_clean (s_list *list,
+                                             const s_struct_type *st,
+                                             const s_cfn *clean,
+                                             s_list *next);
 s_list * list_init_sw (s_list *list, sw i, s_list *next);
 s_list * list_init_sym (s_list *list, const s_sym *sym, s_list *next);
 s_list * list_init_tuple (s_list *list, uw count, s_list *next);
@@ -116,6 +120,9 @@ s_list * list_new_struct_with_data (const s_sym *module, void *data,
                                     s_list *next);
 s_list * list_new_struct_type (const s_sym *module, const s_list *spec,
                                s_list *next);
+s_list * list_new_struct_type_update_clean (const s_struct_type *st,
+                                            const s_cfn *clean,
+                                            s_list *next);
 s_list * list_new_sw (sw i, s_list *next);
 s_list * list_new_sym (const s_sym *sym, s_list *next);
 s_list * list_new_tuple (uw count, s_list *next);
@@ -172,6 +179,9 @@ s_list * list_struct_with_data (s_list *list, const s_sym *module,
                                 void *data);
 s_list * list_struct_type (s_list *list, const s_sym *module,
                            const s_list *spec);
+s_list * list_struct_type_update_clean (s_list *list,
+                                        const s_struct_type *st,
+                                        const s_cfn *clean);
 s_list * list_sw (s_list *list, sw i);
 s_list * list_sym (s_list *list, const s_sym *sym);
 s_list * list_tuple (s_list *list, uw count);
diff --git a/libc3/struct_type.c b/libc3/struct_type.c
index 82fd432..56ebb9e 100644
--- a/libc3/struct_type.c
+++ b/libc3/struct_type.c
@@ -157,6 +157,21 @@ s_struct_type * struct_type_init_cast (s_struct_type *st,
   return NULL;
 }
 
+s_struct_type * struct_type_init_update_clean (s_struct_type *st,
+                                               const s_struct_type *src,
+                                               const s_cfn *clean)
+{
+  s_struct_type tmp = {0};
+  assert(st);
+  assert(src);
+  assert(clean);
+  if (! struct_type_init_copy(&tmp, src))
+    return NULL;
+  tmp.clean = (f_clean) clean->ptr.f;
+  *st = tmp;
+  return st;
+}
+
 s_struct_type * struct_type_init_copy (s_struct_type *st,
                                        const s_struct_type *src)
 {
diff --git a/libc3/struct_type.h b/libc3/struct_type.h
index 42d487c..f73e46b 100644
--- a/libc3/struct_type.h
+++ b/libc3/struct_type.h
@@ -32,6 +32,9 @@ s_struct_type * struct_type_init (s_struct_type *st,
 s_struct_type * struct_type_init_cast (s_struct_type *st,
                                        const s_sym * const *type,
                                        const s_tag *src);
+s_struct_type * struct_type_init_update_clean (s_struct_type *st,
+                                               const s_struct_type *src,
+                                               const s_cfn *clean);
 s_struct_type * struct_type_init_copy (s_struct_type *st,
                                        const s_struct_type *src);
 
diff --git a/libc3/tag_init.c b/libc3/tag_init.c
index 10e992d..447201e 100644
--- a/libc3/tag_init.c
+++ b/libc3/tag_init.c
@@ -417,6 +417,19 @@ s_tag * tag_init_struct_type (s_tag *tag, const s_sym *module,
   return tag;
 }
 
+s_tag * tag_init_struct_type_update_clean (s_tag *tag,
+                                           const s_struct_type *st,
+                                           const s_cfn *clean)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tmp.type = TAG_STRUCT_TYPE;
+  if (! struct_type_init_update_clean(&tmp.data.struct_type, st, clean))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_init_sw (s_tag *tag, sw i)
 {
   s_tag tmp = {0};
@@ -1009,6 +1022,22 @@ s_tag * tag_new_struct_type (const s_sym *module, const s_list *spec)
   return tag;
 }
 
+s_tag * tag_new_struct_type_update_clean (const s_struct_type *st,
+                                          const s_cfn *clean)
+{
+  s_tag *tag;
+  tag = alloc(sizeof(s_tag));
+  if (! tag)
+    return NULL;
+  tag->type = TAG_STRUCT_TYPE;
+  if (! struct_type_init_update_clean(&tag->data.struct_type, st,
+                                      clean)) {
+    free(tag);
+    return NULL;
+  }
+  return tag;
+}
+
 s_tag * tag_new_sw (sw i)
 {
   s_tag *tag;
@@ -1575,6 +1604,20 @@ s_tag * tag_struct_type (s_tag *tag, const s_sym *module,
   return tag;
 }
 
+s_tag * tag_struct_type_update_clean (s_tag *tag,
+                                      const s_struct_type *st,
+                                      const s_cfn *clean)
+{
+  s_tag tmp = {0};
+  assert(tag);
+  tag_clean(tag);
+  tmp.type = TAG_STRUCT_TYPE;
+  if (! struct_type_init_update_clean(&tmp.data.struct_type, st, clean))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
 s_tag * tag_sw (s_tag *tag, sw i)
 {
   s_tag tmp = {0};
diff --git a/libc3/tag_init.h b/libc3/tag_init.h
index def8015..78bc924 100644
--- a/libc3/tag_init.h
+++ b/libc3/tag_init.h
@@ -45,6 +45,9 @@ s_tag * tag_init_struct_with_data (s_tag *tag, const s_sym *module,
                                    void *data);
 s_tag * tag_init_struct_type (s_tag *tag, const s_sym *module,
                               const s_list *spec);
+s_tag * tag_init_struct_type_update_clean (s_tag *tag,
+                                           const s_struct_type *st,
+                                           const s_cfn *clean);
 s_tag * tag_init_sw (s_tag *tag, sw i);
 s_tag * tag_init_sym (s_tag *tag, const s_sym *sym);
 s_tag * tag_init_tuple (s_tag *tag, uw count);
@@ -98,6 +101,8 @@ s_tag * tag_new_str_empty (void);
 s_tag * tag_new_struct (const s_sym *module);
 s_tag * tag_new_struct_with_data (const s_sym *module, void *data);
 s_tag * tag_new_struct_type (const s_sym *module, const s_list *spec);
+s_tag * tag_new_struct_type_update_clean (const s_struct_type *st,
+                                          const s_cfn *clean);
 s_tag * tag_new_sw (sw i);
 s_tag * tag_new_sym (const s_sym *sym);
 s_tag * tag_new_tuple (uw count);
@@ -153,6 +158,9 @@ s_tag * tag_struct_with_data (s_tag *tag, const s_sym *module,
                               void *data);
 s_tag * tag_struct_type (s_tag *tag, const s_sym *module,
                          const s_list *spec);
+s_tag * tag_struct_type_update_clean (s_tag *tag,
+                                      const s_struct_type *st,
+                                      const s_cfn *clean);
 s_tag * tag_sw (s_tag *tag, sw i);
 s_tag * tag_sym (s_tag *tag, const s_sym *sym);
 s_tag * tag_tuple (s_tag *tag, uw count);
diff --git a/libc3/tag_init.rb b/libc3/tag_init.rb
index a6ef7c2..fc427e5 100644
--- a/libc3/tag_init.rb
+++ b/libc3/tag_init.rb
@@ -380,6 +380,10 @@ class TagInitList
        TagInit.new("struct_type", "TAG_STRUCT_TYPE", :init_mode_init,
                    [Arg.new("const s_sym *", "module"),
                     Arg.new("const s_list *", "spec")]),
+       TagInit.new("struct_type", "update_clean", "TAG_STRUCT_TYPE",
+                   :init_mode_init,
+                   [Arg.new("const s_struct_type *", "st"),
+                    Arg.new("const s_cfn *", "clean")]),
        TagInit.new("sw", "TAG_SW", :init_mode_direct,
                    [Arg.new("sw", "i")]),
        TagInit.new("sym", "TAG_SYM", :init_mode_direct,