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