Commit d8e2c25ede42c0d47fcdbf4ff562fe36d5afe63b

Thomas de Grivel 2024-04-04T19:48:43

wip defoperator (struct)

diff --git a/Makefile b/Makefile
index ad9727c..2ee88b5 100644
--- a/Makefile
+++ b/Makefile
@@ -194,8 +194,9 @@ lldb_test:
 	${MAKE} debug
 	${MAKE} -C test lldb_test
 
-test: build
 test:
+	${MAKE} -C libc3 build
+	${MAKE} -C ic3 build
 	${MAKE} -C test test
 	if ${HAVE_ASAN}; then ${MAKE} test_asan; fi
 
diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index 3e9a609..2308239 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -97,3 +97,4 @@ type((Integer) 10)
 type((Integer) 0)
 (Sw) 10
 (Uw) 10
+def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
diff --git a/lib/c3/0.1/c3/operator.facts b/lib/c3/0.1/c3/operator.facts
index 7f878c8..38e879f 100644
--- a/lib/c3/0.1/c3/operator.facts
+++ b/lib/c3/0.1/c3/operator.facts
@@ -1,4 +1,4 @@
 %{module: C3.Facts.Dump,
   version: 1}
 replace {C3.Operator, :is_a, :module}
-replace {C3.Operator, :defstruct, [sym: :+, symbol_value: ?, operator_precedence: 0, operator_associativity: :left]}
+replace {C3.Operator, :defstruct, [sym: :+, symbol_value: (Tag) ?, operator_precedence: 0, operator_associativity: :left]}
diff --git a/libc3/env.c b/libc3/env.c
index e56c29d..cc0abbf 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -71,6 +71,7 @@ void env_clean (s_env *env)
 
 s_tag * env_def (s_env *env, const s_call *call, s_tag *dest)
 {
+  s_struct *s;
   s_tag tag_ident;
   s_tag tag_module;
   s_tag tag_symbol;
@@ -94,15 +95,36 @@ s_tag * env_def (s_env *env, const s_call *call, s_tag *dest)
                            &tag_ident.data.ident);
   tag_init_sym(&tag_module, tag_ident.data.ident.module);
   tag_init_sym(&tag_symbol, &g_sym_symbol);
-  tag_init_sym(&tag_symbol_value, &g_sym_symbol_value);
-  env_eval_tag(env, &list_next(call->arguments)->tag, &tag_value);
   if (! facts_add_tags(&env->facts, &tag_module, &tag_symbol,
                        &tag_ident))
     return NULL;
-  if (! facts_replace_tags(&env->facts, &tag_ident, &tag_symbol_value,
-                           &tag_value))
-    return NULL;
-  tag_init_ident(dest, &tag_ident.data.ident);
+  env_eval_tag(env, &list_next(call->arguments)->tag, &tag_value);
+  if (tag_value.type == TAG_STRUCT &&
+      (s = &tag_value.data.struct_) &&
+      s->type->module == &g_sym_C3__Operator) {
+    if (! env_defoperator(env, &tag_ident.data.ident.sym,
+                          struct_get_sym(&tag_value.data.struct_,
+                                         &g_sym_sym),
+                          struct_get_tag(&tag_value.data.struct_,
+                                         &g_sym_symbol_value),
+                          struct_get_u8(&tag_value.data.struct_,
+                                        &g_sym_operator_precedence),
+                          struct_get_sym(&tag_value.data.struct_,
+                                         &g_sym_operator_associativity),
+                          dest)) {
+      tag_clean(&tag_value);
+      return NULL;
+    }
+  }
+  else {
+    tag_init_sym(&tag_symbol_value, &g_sym_symbol_value);
+    if (! facts_replace_tags(&env->facts, &tag_ident, &tag_symbol_value,
+                             &tag_value)) {
+      tag_clean(&tag_value);
+      return NULL;
+    }
+    tag_init_ident(dest, &tag_ident.data.ident);
+  }
   tag_clean(&tag_value);
   return dest;
 }
diff --git a/libc3/struct.c b/libc3/struct.c
index a2e1ac3..2d6e522 100644
--- a/libc3/struct.c
+++ b/libc3/struct.c
@@ -91,6 +91,32 @@ bool struct_find_key_index (const s_struct *s, const s_sym *key,
   return false;
 }
 
+void * struct_get (s_struct *s, const s_sym *key)
+{
+  uw i = 0;
+  assert(s);
+  assert(key);
+  if (! struct_find_key_index(s, key, &i))
+    return NULL;
+  assert(i < s->type->map.count);
+  return (u8 *) s->data + s->type->offset[i];
+}
+
+const s_sym ** struct_get_sym (s_struct *s, const s_sym *key)
+{
+  return (const s_sym **) struct_get(s, key);
+}
+
+s_tag * struct_get_tag (s_struct *s, const s_sym *key)
+{
+  return (s_tag *) struct_get(s, key);
+}
+
+u8 struct_get_u8 (s_struct *s, const s_sym *key)
+{
+  return *(u8 *) struct_get(s, key);
+}
+
 s_struct * struct_init (s_struct *s, const s_sym *module)
 {
   s_struct tmp = {0};
diff --git a/libc3/struct.h b/libc3/struct.h
index c6f7d9a..e921d5a 100644
--- a/libc3/struct.h
+++ b/libc3/struct.h
@@ -47,7 +47,11 @@ s_struct * struct_set (s_struct *s, const s_sym *key,
                        const s_tag *value);
 
 /* Observers. */
-bool struct_find_key_index (const s_struct *s, const s_sym *key,
-                            uw *dest);
+bool           struct_find_key_index (const s_struct *s, const s_sym *key,
+                                      uw *dest);
+void *         struct_get (s_struct *s, const s_sym *key);
+const s_sym ** struct_get_sym (s_struct *s, const s_sym *key);
+s_tag *        struct_get_tag (s_struct *s, const s_sym *key);
+u8             struct_get_u8 (s_struct *s, const s_sym *key);
 
 #endif /* LIBC3_STRUCT_H */
diff --git a/libc3/sym.c b/libc3/sym.c
index 857fb02..f1cf9c8 100644
--- a/libc3/sym.c
+++ b/libc3/sym.c
@@ -29,6 +29,7 @@ const s_sym g_sym_Array           = {{{NULL},  5, {"Array"}}};
 const s_sym g_sym_Block           = {{{NULL},  5, {"Block"}}};
 const s_sym g_sym_Bool            = {{{NULL},  4, {"Bool"}}};
 const s_sym g_sym_C3              = {{{NULL},  2, {"C3"}}};
+const s_sym g_sym_C3__Operator    = {{{NULL}, 11, {"C3.Operator"}}};
 const s_sym g_sym_Call            = {{{NULL},  4, {"Call"}}};
 const s_sym g_sym_Cfn             = {{{NULL},  3, {"Cfn"}}};
 const s_sym g_sym_Character       = {{{NULL},  9, {"Character"}}};
@@ -97,6 +98,7 @@ const s_sym g_sym_rx              = {{{NULL},  2, {"rx"}}};
 const s_sym g_sym_special_operator =
   {{{NULL}, 16, {"special_operator"}}};
 const s_sym g_sym_struct_type     = {{{NULL}, 11, {"struct_type"}}};
+const s_sym g_sym_sym             = {{{NULL},  3, {"sym"}}};
 const s_sym g_sym_symbol          = {{{NULL},  6, {"symbol"}}};
 const s_sym g_sym_symbol_value    = {{{NULL}, 12, {"symbol_value"}}};
 const s_sym g_sym_then            = {{{NULL},  4, {"then"}}};
@@ -297,6 +299,7 @@ void sym_init_g_sym (void)
   sym_register(&g_sym_Block, NULL);
   sym_register(&g_sym_Bool, NULL);
   sym_register(&g_sym_C3, NULL);
+  sym_register(&g_sym_C3__Operator, NULL);
   sym_register(&g_sym_Call, NULL);
   sym_register(&g_sym_Cfn, NULL);
   sym_register(&g_sym_Character, NULL);
@@ -362,6 +365,7 @@ void sym_init_g_sym (void)
   sym_register(&g_sym_rx, NULL);
   sym_register(&g_sym_special_operator, NULL);
   sym_register(&g_sym_struct_type, NULL);
+  sym_register(&g_sym_sym, NULL);
   sym_register(&g_sym_symbol, NULL);
   sym_register(&g_sym_symbol_value, NULL);
   sym_register(&g_sym_then, NULL);
diff --git a/libc3/sym.h b/libc3/sym.h
index 8ac5f8e..f5599e0 100644
--- a/libc3/sym.h
+++ b/libc3/sym.h
@@ -34,6 +34,7 @@ extern const s_sym g_sym_Array;
 extern const s_sym g_sym_Block;
 extern const s_sym g_sym_Bool;
 extern const s_sym g_sym_C3;
+extern const s_sym g_sym_C3__Operator;
 extern const s_sym g_sym_Call;
 extern const s_sym g_sym_Cfn;
 extern const s_sym g_sym_Character;
@@ -99,6 +100,7 @@ extern const s_sym g_sym_rwx;
 extern const s_sym g_sym_rx;
 extern const s_sym g_sym_special_operator;
 extern const s_sym g_sym_struct_type;
+extern const s_sym g_sym_sym;
 extern const s_sym g_sym_symbol;
 extern const s_sym g_sym_symbol_value;
 extern const s_sym g_sym_then;
diff --git a/test/ic3/cast.in b/test/ic3/cast.in
index 3ddc0fe..5623c00 100644
--- a/test/ic3/cast.in
+++ b/test/ic3/cast.in
@@ -28,3 +28,7 @@ quote (Sym) "Abc"
 (Sym) "Abc"
 quote (Sym) "abc"
 (Sym) "abc"
+quote (Tag) ?
+(Tag) ?
+quote (U8) ?
+(U8) ?
diff --git a/test/ic3/defoperator.in b/test/ic3/defoperator.in
index e25b395..5a859e2 100644
--- a/test/ic3/defoperator.in
+++ b/test/ic3/defoperator.in
@@ -1,5 +1,5 @@
-quote defoperator :operator_muul :**** cfn Tag "tag_mul" (Tag, Tag, Result) 11 :left
-defoperator :operator_muul :**** cfn Tag "tag_mul" (Tag, Tag, Result) 11 :left
+quote def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
+def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
 quote 4 **** 4
 4 **** 4
 quote 4 **** 4 **** 4
diff --git a/test/ic3/defoperator.out.expected b/test/ic3/defoperator.out.expected
index db5e566..eb89716 100644
--- a/test/ic3/defoperator.out.expected
+++ b/test/ic3/defoperator.out.expected
@@ -1,9 +1,4 @@
-def operator_muul = %C3.Operator{
-  sym: :****,
-  symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result),
-  operator_precedence: 11,
-  operator_associativity: :left
-}
+def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
 C3.operator_muul
 4 **** 4
 16
diff --git a/test/ic3/var.in b/test/ic3/var.in
new file mode 100644
index 0000000..138a3bc
--- /dev/null
+++ b/test/ic3/var.in
@@ -0,0 +1,4 @@
+quote (Tag) ?
+(Tag) ?
+quote (U8) ?
+(U8) ?
diff --git a/test/ic3/var.out.expected b/test/ic3/var.out.expected
new file mode 100644
index 0000000..906df4f
--- /dev/null
+++ b/test/ic3/var.out.expected
@@ -0,0 +1,4 @@
+(Tag) ?
+?
+(U8) ?
+(U8) ?
diff --git a/test/ic3/var.ret.expected b/test/ic3/var.ret.expected
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/ic3/var.ret.expected
@@ -0,0 +1 @@
+0