Commit 74b7f1e6420b2a9b4d6d5a21b8b96b5e002a6cb3

Thomas de Grivel 2024-05-18T20:48:23

env_defstruct

diff --git a/libc3/c3_main.h b/libc3/c3_main.h
index 45a5a0e..55a3efc 100644
--- a/libc3/c3_main.h
+++ b/libc3/c3_main.h
@@ -43,6 +43,7 @@ s_tag * c3_defoperator (const s_sym **name, const s_sym **sym,
                         u8 operator_precedence,
                         const s_sym **operator_associativity,
                         s_tag *dest);
+s_tag * c3_defstruct (const s_list *spec);
 void ** c3_dlopen (const s_str *path, void **dest);
 void    c3_exit (sw code);
 s_tag * c3_pin (const s_tag *a, s_tag *dest);
diff --git a/libc3/env.c b/libc3/env.c
index d3451fa..603d538 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -239,32 +239,24 @@ s_tag * env_defoperator (s_env *env, const s_sym **name,
   return dest;
 }
 
-const s_sym * env_defstruct (s_env *env, const s_sym *module)
+const s_sym * env_defstruct (s_env *env, const s_list *spec)
 {
   s_struct_type *st;
-  s_list *st_spec;
   s_tag tag_module_name;
   s_tag tag_st = {0};
   s_tag tag_struct_type;
-  tag_init_sym(&tag_module_name, module);
-  if (env_struct_type_get_spec(env, module, &st_spec)) {
-    tag_init_sym(&tag_struct_type, &g_sym_struct_type);
-    tag_st.type = TAG_STRUCT_TYPE;
-    st = &tag_st.data.struct_type;
-    if (! struct_type_init(st, module, st_spec)) {
-      list_delete_all(st_spec);
-      return NULL;
-    }
-    st->clean = env_struct_type_get_clean(env, module);
-    if (! facts_replace_tags(&env->facts, &tag_module_name,
-                             &tag_struct_type, &tag_st)) {
+  tag_init_sym(&tag_module_name, env->current_defmodule);
+  tag_init_sym(&tag_struct_type, &g_sym_struct_type);
+  tag_st.type = TAG_STRUCT_TYPE;
+  st = &tag_st.data.struct_type;
+  if (! struct_type_init(st, env->current_defmodule, spec))
+    return NULL;
+  if (! facts_replace_tags(&env->facts, &tag_module_name,
+                           &tag_struct_type, &tag_st)) {
       struct_type_clean(st);
-      list_delete_all(st_spec);
       return NULL;
-    }
-    list_delete_all(st_spec);
   }
-  return module;
+  return env->current_defmodule;
 }
 
 void env_error_f (s_env *env, const char *fmt, ...)
@@ -1875,8 +1867,10 @@ bool env_module_load (s_env *env, const s_sym *module, s_facts *facts)
                            &tag_time))
     goto rollback;
   tag_clean(&tag_time);
-  if (! env_defstruct(env, module))
-    goto rollback;
+  if (env_struct_type_has_spec(env, module)) {
+    if (! env_module_load_defstruct(env, module))
+      goto rollback;
+  }
   env_module_is_loading_set(env, module, false);
   return true;
  rollback:
@@ -1887,6 +1881,35 @@ bool env_module_load (s_env *env, const s_sym *module, s_facts *facts)
   return false;
 }
 
+const s_sym * env_module_load_defstruct (s_env *env,
+                                         const s_sym *module)
+{
+  s_struct_type *st;
+  s_list *st_spec;
+  s_tag tag_module_name;
+  s_tag tag_st = {0};
+  s_tag tag_struct_type;
+  if (! env_struct_type_get_spec(env, module, &st_spec))
+    return NULL;
+  tag_st.type = TAG_STRUCT_TYPE;
+  st = &tag_st.data.struct_type;
+  if (! struct_type_init(st, module, st_spec)) {
+    list_delete_all(st_spec);
+    return NULL;
+  }
+  st->clean = env_struct_type_get_clean(env, module);
+  tag_init_sym(&tag_module_name, module);
+  tag_init_sym(&tag_struct_type, &g_sym_struct_type);
+  if (! facts_replace_tags(&env->facts, &tag_module_name,
+                           &tag_struct_type, &tag_st)) {
+    struct_type_clean(st);
+    list_delete_all(st_spec);
+    return NULL;
+  }
+  list_delete_all(st_spec);
+  return module;
+}
+
 bool env_module_maybe_reload (s_env *env, const s_sym *module,
                               s_facts *facts)
 {
@@ -2318,7 +2341,6 @@ s_list ** env_struct_type_get_spec (s_env *env,
                                     const s_sym *module,
                                     s_list **dest)
 {
-  s_facts_with_cursor cursor;
   s_fact *found;
   s_tag tag_defstruct;
   s_tag tag_module;
@@ -2330,20 +2352,17 @@ s_list ** env_struct_type_get_spec (s_env *env,
   tag_init_sym(&tag_defstruct, &g_sym_defstruct);
   tag_init_sym(&tag_module, module);
   tag_init_var(&tag_var);
-  if (! env_module_maybe_reload(env, module, &env->facts))
-    return NULL;
-  facts_with(&env->facts, &cursor, (t_facts_spec) {
-      &tag_module, &tag_defstruct, &tag_var, NULL, NULL });
-  found = facts_with_cursor_next(&cursor);
+  found = facts_find_fact_by_tags(&env->facts, &tag_module,
+                                  &tag_defstruct, &tag_var);
   if (! found) {
-    facts_with_cursor_clean(&cursor);
+    err_write_1("env_struct_type_get_spec: ");
+    err_inspect_sym(&module);
+    err_puts(": defstruct not found");
+    assert(! "env_struct_type_get_spec: defstruct not found");
     return NULL;
   }
-  if (! env_eval_tag(env, found->object, &tmp)) {
-    facts_with_cursor_clean(&cursor);
+  if (! env_eval_tag(env, found->object, &tmp))
     return NULL;
-  }
-  facts_with_cursor_clean(&cursor);
   if (tmp.type != TAG_LIST ||
       ! list_is_plist(tmp.data.list)) {
     err_write_1("env_get_struct_type_spec: module ");
@@ -2356,6 +2375,24 @@ s_list ** env_struct_type_get_spec (s_env *env,
   return dest;
 }
 
+bool env_struct_type_has_spec (s_env *env, const s_sym *module)
+{
+  s_fact *found;
+  s_tag tag_defstruct;
+  s_tag tag_module;
+  s_tag tag_var;
+  assert(env);
+  assert(module);
+  tag_init_sym(&tag_defstruct, &g_sym_defstruct);
+  tag_init_sym(&tag_module, module);
+  tag_init_var(&tag_var);
+  found = facts_find_fact_by_tags(&env->facts, &tag_module,
+                                  &tag_defstruct, &tag_var);
+  if (! found)
+    return false;
+  return true;
+}
+
 bool env_tag_ident_is_bound (const s_env *env, const s_tag *tag,
                              s_facts *facts)
 {
diff --git a/libc3/env.h b/libc3/env.h
index abc3cd5..128da91 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -45,6 +45,9 @@ s_tag *       env_defoperator (s_env *env, const s_sym **name,
                                u8 operator_precedence,
                                const s_sym **operator_associativity,
                                s_tag *dest);
+const s_sym * env_defstruct (s_env *env, const s_list *spec);
+const s_sym * env_module_load_defstruct (s_env *env,
+                                         const s_sym *module);
 bool          env_eval_array (s_env *env, const s_array *array,
                               s_array *dest);
 bool          env_eval_array_tag (s_env *env, const s_array *array,
@@ -190,6 +193,8 @@ f_clean       env_struct_type_get_clean (s_env *env,
                                          const s_sym *module);
 s_list **     env_struct_type_get_spec (s_env *env, const s_sym *module,
                                         s_list **dest);
+bool          env_struct_type_has_spec (s_env *env,
+                                        const s_sym *module);
 bool          env_tag_ident_is_bound (const s_env *env,
                                       const s_tag *tag,
                                       s_facts *facts);