Commit fd3b6ed3fabf3ebbd382a9ee0c9c48c15015af72

Thomas de Grivel 2024-04-10T15:20:17

wip defoperator + var_init_cast

diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index f073691..74dd4c6 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -1,6 +1,3 @@
-def fib = fn (x) { if x < 0 1 else fib(x - 2) + fib(x - 1) end }
-fib(-1)
-def fib = fn (x) { if x < 0 0 else fib(x - 2) + fib(x - 1) end }
 def fib = fn (x) { if x < 0 then 0 else fib(x - 2) + fib(x - 1) end }
 def fib = fn { (0) { 1 } (1) { 1 } (x) { if x < 0 then 0 else fib(x - 2) + fib(x - 1) end }}
 do end
@@ -97,3 +94,6 @@ def List.last = fn (x) do
   y
 end
 List.last([1, 2, 3, 4])
+(Tag) ?
+(U8) ?
+type((U8) ?)
diff --git a/libc3/buf_inspect.c b/libc3/buf_inspect.c
index 5b9f80d..64eb88a 100644
--- a/libc3/buf_inspect.c
+++ b/libc3/buf_inspect.c
@@ -2439,7 +2439,7 @@ sw buf_inspect_tag (s_buf *buf, const s_tag *tag)
   case TAG_U64:     return buf_inspect_u64(buf, &tag->data.u64);
   case TAG_UNQUOTE: return buf_inspect_unquote(buf, &tag->data.unquote);
   case TAG_UW:      return buf_inspect_uw(buf, &tag->data.uw);
-  case TAG_VAR:     return buf_inspect_var(buf, NULL);
+  case TAG_VAR:     return buf_inspect_var(buf, tag);
   case TAG_VOID:    return buf_inspect_void(buf, NULL);
   }
   err_puts("buf_inspect_tag: unknown tag_type");
@@ -2494,7 +2494,7 @@ sw buf_inspect_tag_size (const s_tag *tag)
   case TAG_UNQUOTE:
     return buf_inspect_unquote_size(&tag->data.unquote);
   case TAG_UW:       return buf_inspect_uw_size(&tag->data.uw);
-  case TAG_VAR:      return buf_inspect_var_size(NULL);
+  case TAG_VAR:      return buf_inspect_var_size(tag);
   case TAG_VOID:     return buf_inspect_void_size(NULL);
   }
   err_puts("buf_inspect_tag_size: unknown tag type");
@@ -2607,32 +2607,33 @@ sw buf_inspect_unquote_size (const s_unquote *unquote)
   return result;
 }
 
-sw buf_inspect_var (s_buf *buf, const s_tag *var)
+sw buf_inspect_var (s_buf *buf, const s_tag *tag)
 {
   sw r;
   sw result = 0;
-  if ((r = buf_write_1(buf, "var(0x")) < 0)
-    return r;
-  result += r;
-  if ((r = buf_inspect_uw_hexadecimal(buf, (uw *) var)) < 0)
+  assert(buf);
+  assert(tag);
+  assert(tag->type == TAG_VAR);
+  assert(tag->data.var.type);
+  if (tag->data.var.type == &g_sym_Tag)
+    return buf_write_1(buf, "?");
+  if ((r = buf_inspect_paren_sym(buf, tag->data.var.type)) < 0)
     return r;
   result += r;
-  if ((r = buf_write_1(buf, ")")) < 0)
+  if ((r = buf_write_1(buf, " ?")) < 0)
     return r;
   result += r;
   return result;
 }
 
-sw buf_inspect_var_size (const s_tag *var)
+sw buf_inspect_var_size (const s_tag *tag)
 {
   sw r;
   sw result = 0;
-  r = strlen("var(0x");
-  result += r;
-  r = buf_inspect_uw_hexadecimal_size((uw *) var);
-  result += r;
-  r = strlen(")");
+  if ((r = buf_inspect_paren_sym_size(tag->data.var.type)) < 0)
+    return r;
   result += r;
+  result += strlen(" ?");
   return result;
 }
 
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 330b154..47cbb5d 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -3608,7 +3608,7 @@ sw buf_parse_tag_var (s_buf *buf, s_tag *dest)
   sw r;
   assert(buf);
   assert(dest);
-  if ((r = buf_parse_var(buf, NULL)) > 0)
+  if ((r = buf_parse_var(buf, &dest->data.var)) > 0)
     dest->type = TAG_VAR;
   return r;
 }
@@ -3787,21 +3787,32 @@ sw buf_parse_unquote (s_buf *buf, s_unquote *dest)
   return r;
 }
 
-sw buf_parse_var (s_buf *buf, void *dest)
+sw buf_parse_var (s_buf *buf, s_var *dest)
 {
   character c;
   sw r;
+  sw result = 0;
   s_buf_save save;
+  s_var tmp = {0};
   assert(buf);
   (void) dest;
   buf_save_init(buf, &save);
-  if ((r = buf_read_1(buf, "?")) <= 0)
+  if ((r = buf_parse_paren_sym(buf, &tmp.type)) <= 0)
     goto clean;
+  result += r;
+  if ((r = buf_ignore_spaces(buf)) < 0)
+    goto restore;
+  result += r;
+  if ((r = buf_read_1(buf, "?")) <= 0)
+    goto restore;
+  result += r;
   if (buf_peek_character_utf8(buf, &c) > 0 &&
       ! ident_character_is_reserved(c)) {
     r = 0;
     goto restore;
   }
+  *dest = tmp;
+  r = result;
   goto clean;
  restore:
   buf_save_restore_rpos(buf, &save);
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index 299bde8..5899e30 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -135,7 +135,7 @@ sw buf_parse_tag_void (s_buf *buf, s_tag *dest);
 sw buf_parse_tuple (s_buf *buf, s_tuple *dest);
 sw buf_parse_u64_hex (s_buf *buf, u64 *dest);
 sw buf_parse_unquote (s_buf *buf, s_unquote *dest);
-sw buf_parse_var (s_buf *buf, void *dest);
+sw buf_parse_var (s_buf *buf, s_var *dest);
 sw buf_parse_void (s_buf *buf, void *dest);
 sw buf_parse_tag_ratio (s_buf *buf, s_tag *dest);
 sw buf_peek_array_dimensions (s_buf *buf, s_array *dest);
diff --git a/libc3/data.c b/libc3/data.c
index 3bdb75d..34c6d71 100644
--- a/libc3/data.c
+++ b/libc3/data.c
@@ -537,7 +537,7 @@ void * data_init_cast (void *data, const s_sym *type, const s_tag *tag)
   if (type == &g_sym_Uw)
     return uw_init_cast(data, type, tag);
   if (type == &g_sym_Var)
-    return data;
+    return var_init_cast(data, type, tag);
   if (type == &g_sym_Void)
     return data;
   /*
diff --git a/libc3/tag.c b/libc3/tag.c
index 90801b4..65a1f94 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -43,6 +43,7 @@
 #include "time.h"
 #include "tuple.h"
 #include "unquote.h"
+#include "var.h"
 
 s_tag g_tag_first;
 s_tag g_tag_last;
@@ -331,9 +332,6 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
   assert(tag);
   assert(src);
   switch (src->type) {
-  case TAG_VAR:
-    tag_init_var(tag);
-    break;
   case TAG_VOID:
     tag_init_void(tag);
     break;
@@ -384,6 +382,9 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
   case TAG_UNQUOTE:
     unquote_init_copy(&tag->data.unquote, &src->data.unquote);
     break;
+  case TAG_VAR:
+    var_init_copy(tag, src);
+    break;
   case TAG_BOOL:
   case TAG_CHARACTER:
   case TAG_F32:
diff --git a/libc3/types.h b/libc3/types.h
index fc9aac3..116f67d 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -178,6 +178,7 @@ typedef struct tuple                   s_tuple;
 typedef struct type                    s_type;
 typedef struct unquote                 s_unquote;
 typedef struct unwind_protect          s_unwind_protect;
+typedef struct var                     s_var;
 
 /* unions */
 typedef union ptr_     u_ptr;
@@ -315,6 +316,10 @@ struct unwind_protect {
   s_unwind_protect *next;
 };
 
+struct var {
+  const s_sym *type;
+};
+
 /* 2 */
 
 struct buf {
@@ -467,6 +472,7 @@ union tag_data {
   u64           u64;
   s_unquote     unquote;
   uw            uw;
+  s_var         var;
 };
 
 /* 6 */
diff --git a/libc3/var.c b/libc3/var.c
index f10c4a0..0bf28b0 100644
--- a/libc3/var.c
+++ b/libc3/var.c
@@ -11,16 +11,46 @@
  * THIS SOFTWARE.
  */
 #include "assert.h"
+#include "data.h"
+#include "sym.h"
 #include "tag.h"
 #include "var.h"
 
-s_tag * var_init_copy (s_tag *var, const s_tag *src)
+s_tag * var_init_cast (s_tag *tag, const s_sym *type, const s_tag *src)
 {
-  assert(var);
+  void *data;
+  s_tag tmp;
+  assert(tag);
+  assert(tag->type == TAG_VAR);
+  assert(type);
+  assert(src);
+  if (type != tag->data.var.type) {
+    err_write_1("var_init_cast: invalid type, expected ");
+    err_inspect_sym(&tag->data.var.type);
+    err_write_1(" got ");
+    err_inspect_sym(&type);
+    err_write_1("\n");
+    assert(! "var_init_cast: invalid type");
+    return NULL;
+  }
+  if (! sym_to_tag_type(type, &tmp.type))
+    return NULL;
+  if (! tag_to_pointer(&tmp, type, &data))
+    return NULL;
+  if (! data_init_cast(data, type, src))
+    return NULL;
+  *tag = tmp;
+  return tag;
+}
+
+s_tag * var_init_copy (s_tag *tag, const s_tag *src)
+{
+  assert(tag);
   assert(src);
   assert(src->type == TAG_VAR);
   if (src->type != TAG_VAR)
     return NULL;
-  tag_init_var(var);
-  return var;
+  tag->type = TAG_VAR;
+  tag->data.var = src->data.var;
+  return tag;
 }
diff --git a/libc3/var.h b/libc3/var.h
index c91172b..2933f37 100644
--- a/libc3/var.h
+++ b/libc3/var.h
@@ -15,6 +15,7 @@
 
 #include "types.h"
 
-s_tag * var_init_copy (s_tag *var, const s_tag *src);
+s_tag * var_init_cast (s_tag *tag, const s_sym *type, const s_tag *src);
+s_tag * var_init_copy (s_tag *tag, const s_tag *src);
 
 #endif /* LIBC3_VAR_H */
diff --git a/test/ic3/cast.in b/test/ic3/cast.in
index 5623c00..3ddc0fe 100644
--- a/test/ic3/cast.in
+++ b/test/ic3/cast.in
@@ -28,7 +28,3 @@ quote (Sym) "Abc"
 (Sym) "Abc"
 quote (Sym) "abc"
 (Sym) "abc"
-quote (Tag) ?
-(Tag) ?
-quote (U8) ?
-(U8) ?
diff --git a/test/ic3/var.out.expected b/test/ic3/var.out.expected
index 906df4f..7e1596c 100644
--- a/test/ic3/var.out.expected
+++ b/test/ic3/var.out.expected
@@ -1,4 +1,4 @@
-(Tag) ?
+?
 ?
 (U8) ?
 (U8) ?