Commit 08be39f58dd9779d8b22a8a9116300a9f136991a

Thomas de Grivel 2024-01-05T18:12:59

struct

diff --git a/libc3/compare.c b/libc3/compare.c
index c7d62f2..9761e10 100644
--- a/libc3/compare.c
+++ b/libc3/compare.c
@@ -14,6 +14,7 @@
 #include <err.h>
 #include <string.h>
 #include "compare.h"
+#include "data.h"
 #include "integer.h"
 #include "list.h"
 #include "tag.h"
@@ -388,6 +389,60 @@ s8 compare_str (const s_str *a, const s_str *b)
   return 0;
 }
 
+s8 compare_struct (const s_struct *a, const s_struct *b)
+{
+  uw i;
+  int r;
+  const s_sym *type;
+  assert(a);
+  assert(b);
+  if (a == b)
+    return 0;
+  r = compare_struct_type(a->type, b->type);
+  if (r)
+    return r;
+  if (! a->data && ! b->data) {
+    if (a->tag == b->tag)
+      return 0;
+    i = 0;
+    while (i < a->type->map.count) {
+      r = compare_tag(a->tag + i, b->tag + i);
+      if (r)
+        return r;
+    }
+  }
+  if (a->data == b->data)
+    return 0;
+  if (! a->data)
+    return -1;
+  if (! b->data)
+    return 1;
+  while (i < a->type->map.count) {
+    tag_type(a->type->map.value + i, &type);
+    r = data_compare(type, (s8 *) a->data + a->type->offset[i],
+                     (s8 *) b->data + b->type->offset[i]);
+    if (r)
+      return r;
+  }
+  return 0;
+}
+
+s8 compare_struct_type (const s_struct_type *a, const s_struct_type *b)
+{
+  int r;
+  assert(a);
+  assert(b);
+  if (a == b)
+    return 0;
+  r = compare_sym(a->module, b->module);
+  if (r)
+    return r;
+  r = compare_map(&a->map, &b->map);
+  if (r)
+    return r;
+  return 0;
+}
+
 s8 compare_sym (const s_sym *a, const s_sym *b)
 {
   if (a == b)
diff --git a/libc3/compare.h b/libc3/compare.h
index bb6db50..8c91c6e 100644
--- a/libc3/compare.h
+++ b/libc3/compare.h
@@ -18,6 +18,7 @@
 #define COMPARE_PROTOTYPE(type)                     \
   s8 compare_##type (type a, type b)
 
+s8 compare_array (const s_array *a, const s_array *b);
 s8 compare_bool (bool a, bool b);
 s8 compare_call (const s_call *a, const s_call *b);
 s8 compare_cfn (const s_cfn *a, const s_cfn *b);
@@ -38,11 +39,13 @@ s8 compare_integer_u64 (const s_integer *a, u64 b);
 s8 compare_list (const s_list *a, const s_list *b);
 s8 compare_map (const s_map *a, const s_map *b);
 s8 compare_ptag (const p_tag a, const p_tag b);
+s8 compare_ptr (const void *a, const void *b);
 s8 compare_quote (const s_quote *a, const s_quote *b);
 COMPARE_PROTOTYPE(s8);
 COMPARE_PROTOTYPE(s16);
 COMPARE_PROTOTYPE(s32);
 COMPARE_PROTOTYPE(s64);
+COMPARE_PROTOTYPE(sw);
 s8 compare_str (const s_str *a, const s_str *b);
 s8 compare_struct (const s_struct *a, const s_struct *b);
 s8 compare_struct_type (const s_struct_type *a, const s_struct_type *b);
@@ -53,5 +56,6 @@ COMPARE_PROTOTYPE(u8);
 COMPARE_PROTOTYPE(u16);
 COMPARE_PROTOTYPE(u32);
 COMPARE_PROTOTYPE(u64);
+COMPARE_PROTOTYPE(uw);
 
 #endif /* LIBC3_COMPARE_H */
diff --git a/libc3/data.c b/libc3/data.c
index 136cb47..66b3f51 100644
--- a/libc3/data.c
+++ b/libc3/data.c
@@ -313,6 +313,93 @@ bool data_clean (const s_sym *type, void *data)
   return false;
 }
 
+bool data_compare (const s_sym *type, const void *a, const void *b)
+{
+  const s_struct_type *st;
+  if (type == sym_1("Array"))
+    return compare_array(a, b);
+  if (type == sym_1("Bool"))
+    return compare_bool(*(bool *) a, *(bool *) b);
+  if (type == sym_1("Call"))
+    return compare_call(a, b);
+  if (type == sym_1("Cfn"))
+    return compare_cfn(a, b);
+  if (type == sym_1("Character"))
+    return compare_character(*(character *) a, *(character *) b);
+  if (type == sym_1("F32"))
+    return compare_f32(*(f64 *) a, *(f64 *) b);
+  if (type == sym_1("F64"))
+    return compare_f64(*(f64 *) a, *(f64 *) b);
+  if (type == sym_1("Fact"))
+    return compare_fact(a, b);
+  if (type == sym_1("Fn"))
+    return compare_fn(a, b);
+  if (type == sym_1("Ident"))
+    return compare_ident(a, b);
+  if (type == sym_1("Integer"))
+    return compare_integer(a, b);
+  if (type == sym_1("List"))
+    return compare_list(a, b);
+  if (type == sym_1("Ptag"))
+    return compare_ptag(a, b);
+  if (type == sym_1("Ptr"))
+    return compare_ptr(a, b);
+  if (type == sym_1("PtrFree"))
+    return compare_ptr(a, b);
+  if (type == sym_1("Quote"))
+    return compare_quote(a, b);
+  if (type == sym_1("S8"))
+    return compare_s8(*(s8 *) a, *(s8 *) b);
+  if (type == sym_1("S16"))
+    return compare_s16(*(s16 *) a, *(s16 *) b);
+  if (type == sym_1("S32"))
+    return compare_s32(*(s32 *) a, *(s32 *) b);
+  if (type == sym_1("S64"))
+    return compare_s64(*(s64 *) a, *(s64 *) b);
+  if (type == sym_1("Str"))
+    return compare_str(a, b);
+  if (type == sym_1("Struct"))
+    return compare_struct(a, b);
+  if (type == sym_1("Sw"))
+    return compare_sw(*(sw *) a, *(sw *) b);
+  if (type == sym_1("Sym"))
+    return compare_sym(a, b);
+  if (type == sym_1("Tuple"))
+    return compare_tuple(a, b);
+  if (type == sym_1("U8"))
+    return compare_u8(*(u8 *) a, *(u8 *) b);
+  if (type == sym_1("U16"))
+    return compare_u16(*(u16 *) a, *(u16 *) b);
+  if (type == sym_1("U32"))
+    return compare_u32(*(u32 *) a, *(u32 *) b);
+  if (type == sym_1("U64"))
+    return compare_u64(*(u64 *) a, *(u64 *) b);
+  if (type == sym_1("Uw"))
+    return compare_uw(*(uw *) a, *(uw *) b);
+  if (type == sym_1("Var"))
+    return compare_ptr(a, b);
+  if (type == sym_1("Void"))
+    return 0;
+  /*
+  if (sym_is_array_type(type)) {
+  */
+  st = struct_type_find(type);
+  if (st) {
+    s_struct sa = {0};
+    s_struct sb = {0};
+    sa.type = st;
+    sa.data = (void *) a;
+    sb.type = st;
+    sb.data = (void *) a;
+    return compare_struct(&sa, &sb);
+  }
+  err_write_1("data_compare: unknown type: ");
+  err_inspect_sym(&type);
+  err_write_1("\n");
+  assert(! "data_compare: unknown type");
+  return false;
+}
+
 bool data_hash_update (const s_sym *type, t_hash *hash, const void *data)
 {
   const s_struct_type *st;
diff --git a/libc3/data.h b/libc3/data.h
index ed0d0c5..8843394 100644
--- a/libc3/data.h
+++ b/libc3/data.h
@@ -24,6 +24,7 @@
 sw     data_buf_inspect (const s_sym *type, s_buf *buf, const void *v);
 sw     data_buf_inspect_size (const s_sym *type, const void *v);
 bool   data_clean (const s_sym *type, void *v);
+bool   data_compare (const s_sym *type, const void *a, const void *b);
 bool   data_hash_update (const s_sym *type, t_hash *hash,
                          const void *s);
 void * data_init_cast (const s_sym *type, void *v, const s_tag *src);
diff --git a/libc3/env.c b/libc3/env.c
index 6266f76..4dd22fe 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -689,17 +689,27 @@ bool env_eval_struct (s_env *env, const s_struct *s, s_tag *dest)
     return false;
   i = 0;
   while (i < t->type->map.count) {
-    if (! tag_type(t->type->map.value + i, &type) ||
-        ! env_eval_tag(env, s->tag + i, &tag))
+    if (! tag_type(t->type->map.value + i, &type))
       goto ko;
-    if (! data_init_cast(type, (s8 *) t->data + t->type->offset[i],
-                         &tag)) {
-      warnx("env_eval_struct:"
-            " invalid type %s for key %s, expected %s.",
-            tag_type_to_string(tag.type),
-            t->type->map.key[i].data.sym->str.ptr.ps8,
-            tag_type_to_string(t->type->map.value[i].type));
-      goto ko_tag;
+    if (s->tag) {
+      if (! env_eval_tag(env, s->tag + i, &tag))
+        goto ko;
+      if (! data_init_cast(type, (s8 *) t->data + t->type->offset[i],
+                           &tag)) {
+        warnx("env_eval_struct:"
+              " invalid type %s for key %s, expected %s.",
+              tag_type_to_string(tag.type),
+              t->type->map.key[i].data.sym->str.ptr.ps8,
+              tag_type_to_string(t->type->map.value[i].type));
+        goto ko_tag;
+      }
+      tag_clean(&tag);
+    }
+    else {
+      const void *value;
+      if (! tag_to_const_pointer(t->type->map.value + i, type, &value))
+        goto ko;
+      data_init_copy(type, (s8 *) t->data + t->type->offset[i], value);
     }
     i++;
   }
diff --git a/libc3/types.h b/libc3/types.h
index 3bbd936..45bc68c 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -245,11 +245,11 @@ struct quote {
   s_tag *tag;
 };
 
-struct struct_type {
-  const s_sym *module;
-  s_map map;
-  uw *offset;
-  uw size;
+struct struct_ {
+  void *data;
+  s_tag *tag;
+  bool free_data;
+  const s_struct_type *type;
 };
 
 struct sym_list {
@@ -316,11 +316,11 @@ struct str {
   u_ptr   ptr;         /**< Pointer to memory. */
 };
 
-struct struct_ {
-  void *data;
-  s_tag *tag;
-  bool free_data;
-  const s_struct_type *type;
+struct struct_type {
+  const s_sym *module;
+  s_map map;
+  uw *offset;
+  uw size;
 };
 
 /* 3 */
diff --git a/test/ic3/struct.out.expected b/test/ic3/struct.out.expected
index fd4317b..f907a63 100644
--- a/test/ic3/struct.out.expected
+++ b/test/ic3/struct.out.expected
@@ -2,9 +2,5 @@
 0.0
 %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}
 %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}
-[position:  %GL.Point3D{x: 0.0, y: 0.0, z: 0.0},
- normal:    %GL.Point3D{x: 0.0, y: 0.0, z: 0.0},
- tex_coord: %GL.Point2D{x: 0.0, y: 0.0}]
-[position:  %GL.Point3D{x: 0.0, y: 0.0, z: 0.0},
- normal:    %GL.Point3D{x: 0.0, y: 0.0, z: 0.0},
- tex_coord: %GL.Point2D{x: 0.0, y: 0.0}]
+[position: %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}, normal: %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}, tex_coord: %GL.Point2D{x: 0.0, y: 0.0}]
+[position: %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}, normal: %GL.Point3D{x: 0.0, y: 0.0, z: 0.0}, tex_coord: %GL.Point2D{x: 0.0, y: 0.0}]