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) ?