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,