Commit def9a1d2003e2d3b6a694636e2c5afa69cf94691

Thomas de Grivel 2024-07-14T14:50:40

fix struct_access

diff --git a/.ic3_history b/.ic3_history
index f2b12a4..1b017bd 100644
--- a/.ic3_history
+++ b/.ic3_history
@@ -1,3 +1,6 @@
+(Sw) 123\
+(Sw) 123
+(Sw) 123/2
 (Sw) 123 / 2
 defmodule Plop do def a = 1 end
 Plop.a
@@ -91,9 +94,6 @@ quote [{:a, 1}, {:b, 2}]
 abc.def
 %{a: 1}
 %{a: 1}.a
-test = fn (list, args) { List.map(list, fn (e) { access(args, e)})}
-test([a, b, c], %{a: 1, b: 2, c: 3})
-test([:a, :b, :c], %{a: 1, b: 2, c: 3})
-a = %{a: 1}
-b = %{b: 2}
-a.a + b.b
+x = %C3.Operator{}
+x.sym
+quote x.sym
diff --git a/README.md b/README.md
index 7f7c29d..b7ad6f9 100644
--- a/README.md
+++ b/README.md
@@ -483,8 +483,8 @@ Script interpreter. Works the same as ic3 but is not interactive.
    - operators dispatch
      - list of matching operators (facts_with)
    - access
-     - buf_parse_call_access (Tag "." Sym)
-     - access (Tag, Sym) => Tag
+     - DONE buf_parse_call_access (Tag "." Sym)
+     - DONE access (Tag, Sym) => Tag
    - base-specific big floats
    - macro cast `(Macro) fn (x) { x }`
    - pretty printer
diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index f2b12a4..1b017bd 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -1,3 +1,6 @@
+(Sw) 123\
+(Sw) 123
+(Sw) 123/2
 (Sw) 123 / 2
 defmodule Plop do def a = 1 end
 Plop.a
@@ -91,9 +94,6 @@ quote [{:a, 1}, {:b, 2}]
 abc.def
 %{a: 1}
 %{a: 1}.a
-test = fn (list, args) { List.map(list, fn (e) { access(args, e)})}
-test([a, b, c], %{a: 1, b: 2, c: 3})
-test([:a, :b, :c], %{a: 1, b: 2, c: 3})
-a = %{a: 1}
-b = %{b: 2}
-a.a + b.b
+x = %C3.Operator{}
+x.sym
+quote x.sym
diff --git a/libc3/map.c b/libc3/map.c
index 597f2e0..aa7116f 100644
--- a/libc3/map.c
+++ b/libc3/map.c
@@ -75,6 +75,21 @@ s_tag * map_get (const s_map *map, const s_tag *key, s_tag *value)
   return NULL;
 }
 
+const s_sym ** map_get_type (const s_map *map, const s_tag *key,
+                             const s_sym **dest)
+{
+  uw i = 0;
+  while (i < map->count) {
+    if (compare_tag(key, map->key + i) == 0)
+      return tag_type(map->value + i, dest);
+    i++;
+  }
+  err_write_1("map_get_type: ");
+  err_inspect_tag(key);
+  err_puts(": key not found");
+  return NULL;
+}
+
 s_map * map_init (s_map *map, uw count)
 {
   s_map tmp = {0};
diff --git a/libc3/map.h b/libc3/map.h
index 3ee47ed..7670994 100644
--- a/libc3/map.h
+++ b/libc3/map.h
@@ -30,17 +30,20 @@ s_map * map_new (uw size);
 s_map * map_new_1 (const char *p);
 s_map * map_new_from_lists (const s_list *keys, const s_list *values);
 
-/* Modifiers */
+/* Operators. */
 s_map * map_set (s_map *map, const s_tag *key, const s_tag *value);
 s_map * map_sort (s_map *map);
 
-/* Operators */
-s_tag * map_access (const s_map *map, const s_sym *key, s_tag *value);
-s_map * map_cast (const s_tag *tag, s_map *map);
-s_tag * map_get (const s_map *map, const s_tag *key, s_tag *dest);
-s_map * map_update (const s_map *map, const s_tag *key,
-                    const s_tag *value, s_map *dest);
-s_map * map_update_list (const s_map *map, const s_list *alist,
-                         s_map *dest);
+/* Observers. */
+s_tag *        map_access (const s_map *map, const s_sym *key,
+                           s_tag *value);
+s_map *        map_cast (const s_tag *tag, s_map *map);
+s_tag *        map_get (const s_map *map, const s_tag *key, s_tag *dest);
+const s_sym ** map_get_type (const s_map *map, const s_tag *key,
+                             const s_sym **dest);
+s_map *        map_update (const s_map *map, const s_tag *key,
+                           const s_tag *value, s_map *dest);
+s_map *        map_update_list (const s_map *map, const s_list *alist,
+                                s_map *dest);
 
 #endif /* LIBC3_MAP_H */
diff --git a/libc3/struct.c b/libc3/struct.c
index 9e52df1..5870379 100644
--- a/libc3/struct.c
+++ b/libc3/struct.c
@@ -25,12 +25,22 @@
 
 s_tag * struct_access (const s_struct *s, const s_sym *key, s_tag *dest)
 {
-  s_tag *tag;
-  tag = struct_get_tag((s_struct *) s, key);
-  if (! tag)
+  const void *data;
+  const s_sym *type;
+  s_tag tmp = {0};
+  void *tmp_data;
+  if (! struct_get_type(s, key, &type))
     return NULL;
-  if (! tag_init_copy(dest, tag))
+  data = struct_get(s, key);
+  if (! data)
     return NULL;
+  if (! sym_to_tag_type(type, &tmp.type))
+    return NULL;
+  if (! tag_to_pointer(&tmp, type, &tmp_data))
+    return NULL;
+  if (! data_init_copy(type, tmp_data, data))
+    return NULL;
+  *dest = tmp;
   return dest;
 }
 
@@ -101,7 +111,7 @@ 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)
+const void * struct_get (const s_struct *s, const s_sym *key)
 {
   uw i = 0;
   assert(s);
@@ -112,17 +122,25 @@ void * struct_get (s_struct *s, const s_sym *key)
   return (u8 *) s->data + s->type->offset[i];
 }
 
-const s_sym ** struct_get_sym (s_struct *s, const s_sym *key)
+const s_sym ** struct_get_sym (const 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)
+const s_tag * struct_get_tag (const 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)
+const s_sym ** struct_get_type (const s_struct *s, const s_sym *key,
+                                const s_sym **dest)
+{
+  s_tag tag_key;
+  tag_init_sym(&tag_key, key);
+  return map_get_type(&s->type->map, &tag_key, dest);
+}
+
+u8 struct_get_u8 (const s_struct *s, const s_sym *key)
 {
   return *(u8 *) struct_get(s, key);
 }
diff --git a/libc3/struct.h b/libc3/struct.h
index bb32c89..1232dcd 100644
--- a/libc3/struct.h
+++ b/libc3/struct.h
@@ -50,9 +50,11 @@ s_tag *        struct_access (const s_struct *s, const s_sym *key,
                               s_tag *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);
+const void *   struct_get (const s_struct *s, const s_sym *key);
+const s_sym ** struct_get_type (const s_struct *s, const s_sym *key,
+                                const s_sym **dest);
+const s_sym ** struct_get_sym (const s_struct *s, const s_sym *key);
+const s_tag *  struct_get_tag (const s_struct *s, const s_sym *key);
+u8             struct_get_u8 (const s_struct *s, const s_sym *key);
 
 #endif /* LIBC3_STRUCT_H */
diff --git a/test/ic3/access.in b/test/ic3/access.in
index f122c3b..462ab9a 100644
--- a/test/ic3/access.in
+++ b/test/ic3/access.in
@@ -24,3 +24,7 @@ quote map.a.b.c + map.a.b.c
 map.a.b.c + map.a.b.c
 quote "0 #{map.a.b.c} 2"
 "0 #{map.a.b.c} 2"
+quote op = %C3.Operator{}
+op = %C3.Operator{}
+quote op.sym
+op.sym
diff --git a/test/ic3/access.out.expected b/test/ic3/access.out.expected
index 8cd99fd..50f61e9 100644
--- a/test/ic3/access.out.expected
+++ b/test/ic3/access.out.expected
@@ -24,3 +24,7 @@ map.a.b.c + map.a.b.c
 2
 "0 #{map.a.b.c} 2"
 "0 1 2"
+op = %C3.Operator{}
+%C3.Operator{sym: :+, symbol_value: ?, operator_precedence: 0, operator_associativity: :left}
+op.sym
+:+