diff --git a/.ikc3_history b/.ikc3_history
index 79c11c6..18f3486 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,5 +1,3 @@
-s = Serialize.new()
-Serialize.tag(s, 123)
Serialize.to_str(s)
s = Serialize.new()
s = Serialize.tag_to_str(12)
@@ -97,3 +95,5 @@ x = fn (a, b) { a + b }
inspect(x)
x = fn (a, b) { a + b }
inspect(x)
++(1, 1)
+1 + 1
diff --git a/lib/kc3/0.1/init.kc3 b/lib/kc3/0.1/init.kc3
index b0f3a17..be34c66 100644
--- a/lib/kc3/0.1/init.kc3
+++ b/lib/kc3/0.1/init.kc3
@@ -5,63 +5,236 @@ defoperator %KC3.Op{sym: :"()",
associativity: 1,
callable: cfn Tag "tag_paren" (Tag, Result)}
-def human_size = fn (size) {
- size = integer_reduce(size)
- if (size >= 1024 * 1024 * 1024 * 1024) do
- s = size * 10 / 1024 / 1024 / 1024 / 1024
- "#{s / 10}.#{s mod 10}Tb"
- else
- if (size >= 1024 * 1024 * 1024) do
- s = size * 10 / 1024 / 1024 / 1024
- "#{s / 10}.#{s mod 10}Gb"
- else
- if (size >= 1024 * 1024) do
- s = size * 10 / 1024 / 1024
- "#{s / 10}.#{s mod 10}Mb"
- else
- if (size >= 1024) do
- s = size * 10 / 1024
- "#{s / 10}.#{s mod 10}Kb"
- else
- "#{size}b"
- end
- end
- end
- end
-}
-
-def load_directory = fn (dir) {
- if File.exists?(dir) && File.is_directory?(dir) do
- files = List.sort(File.list(dir))
- List.each(files, fn (file) {
- if (! Str.starts_with?(file, ".")) do
- path = dir + file
- if File.is_directory?(path) do
- load_directory(path + "/")
- else
- if Str.ends_with?(path, ".kc3") do
- load(path)
- end
- end
- end
- })
- end
-}
-
-def maybe_reload_directory = fn (dir) {
- if File.exists?(dir) && File.is_directory?(dir) do
- files = List.sort(File.list(dir))
- List.each(files, fn (file) {
- if (! Str.starts_with?(file, ".")) do
- path = dir + file
- if File.is_directory?(path) do
- maybe_reload_directory(path + "/")
- else
- if Str.ends_with?(path, ".kc3") do
- maybe_reload(path)
- end
- end
- end
- })
- end
-}
+defoperator %KC3.Op{sym: :"[]",
+ arity: 2,
+ precedence: 15,
+ associativity: 1,
+ callable: cfn Tag "kc3_access" (Tag, List, Result)}
+
+defoperator %KC3.Op{sym: :~,
+ arity: 1,
+ precedence: 14,
+ associativity: 2,
+ callable: cfn Tag "tag_bnot" (Tag, Result)}
+
+defoperator %KC3.Op{sym: :-,
+ arity: 1,
+ precedence: 14,
+ associativity: 2,
+ callable: cfn Tag "tag_neg" (Tag, Result)}
+
+defoperator %KC3.Op{sym: :!,
+ arity: 1,
+ precedence: 14,
+ associativity: 2,
+ callable: cfn Tag "tag_not" (Tag, Result)}
+
+defoperator %KC3.Op{sym: :^,
+ arity: 1,
+ precedence: 14,
+ associativity: 2,
+ callable: cfn Tag "kc3_identity" (Tag, Result)}
+
+defoperator %KC3.Op{sym: :/,
+ arity: 2,
+ precedence: 13,
+ associativity: 1,
+ callable: cfn Tag "tag_div" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :mod,
+ arity: 2,
+ precedence: 13,
+ associativity: 1,
+ callable: cfn Tag "tag_mod" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :*,
+ arity: 2,
+ precedence: 13,
+ associativity: 1,
+ callable: cfn Tag "tag_mul" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :+,
+ arity: 2,
+ precedence: 12,
+ associativity: 1,
+ callable: cfn Tag "tag_add" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :+i,
+ arity: 2,
+ precedence: 12,
+ associativity: 1,
+ callable: cfn Tag "tag_addi" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :-,
+ arity: 2,
+ precedence: 12,
+ associativity: 1,
+ callable: cfn Tag "tag_sub" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :<<,
+ arity: 2,
+ precedence: 11,
+ associativity: 1,
+ callable: cfn Tag "tag_shift_left" (Tag, Tag,
+ Result)}
+
+defoperator %KC3.Op{sym: :>>,
+ arity: 2,
+ precedence: 11,
+ associativity: 1,
+ callable: cfn Tag "tag_shift_right" (Tag, Tag,
+ Result)}
+
+defoperator %KC3.Op{sym: :<,
+ arity: 2,
+ precedence: 10,
+ associativity: 1,
+ callable: cfn Bool "tag_lt" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :<=,
+ arity: 2,
+ precedence: 10,
+ associativity: 1,
+ callable: cfn Bool "tag_lte" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :>,
+ arity: 2,
+ precedence: 10,
+ associativity: 1,
+ callable: cfn Bool "tag_gt" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :>=,
+ arity: 2,
+ precedence: 10,
+ associativity: 1,
+ callable: cfn Bool "tag_gte" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :==,
+ arity: 2,
+ precedence: 9,
+ associativity: 1,
+ callable: cfn Bool "tag_eq" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :!=,
+ arity: 2,
+ precedence: 9,
+ associativity: 1,
+ callable: cfn Bool "tag_not_eq" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :&,
+ arity: 2,
+ precedence: 8,
+ associativity: 1,
+ callable: cfn Tag "tag_band" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :^,
+ arity: 2,
+ precedence: 7,
+ associativity: 1,
+ callable: cfn Tag "tag_bxor" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :bor,
+ arity: 2,
+ precedence: 6,
+ associativity: 1,
+ callable: cfn Tag "tag_bor" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :&&,
+ arity: 2,
+ precedence: 5,
+ associativity: 1,
+ callable: cfn Tag "kc3_and" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :||,
+ arity: 2,
+ precedence: 4,
+ associativity: 1,
+ callable: cfn Tag "kc3_or" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :<-,
+ arity: 2,
+ precedence: 3,
+ associativity: 1,
+ callable: cfn Tag "tag_assign" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :←,
+ arity: 2,
+ precedence: 3,
+ associativity: 1,
+ callable: cfn Tag "tag_assign" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :=,
+ arity: 2,
+ precedence: 2,
+ associativity: 2,
+ callable: cfn Tag "tag_equal" (Tag, Tag, Result)}
+
+defoperator %KC3.Op{sym: :";",
+ arity: 2,
+ precedence: 1,
+ associativity: 1,
+ callable: cfn Tag "tag_semicolon" (Tag, Tag, Result)}
+
+puts("init.kc3: done with operators")
+
+#def human_size = fn (size) {
+# size = integer_reduce(size)
+# if (size >= 1024 * 1024 * 1024 * 1024) do
+# s = size * 10 / 1024 / 1024 / 1024 / 1024
+# "#{s / 10}.#{s mod 10}Tb"
+# else
+# if (size >= 1024 * 1024 * 1024) do
+# s = size * 10 / 1024 / 1024 / 1024
+# "#{s / 10}.#{s mod 10}Gb"
+# else
+# if (size >= 1024 * 1024) do
+# s = size * 10 / 1024 / 1024
+# "#{s / 10}.#{s mod 10}Mb"
+# else
+# if (size >= 1024) do
+# s = size * 10 / 1024
+# "#{s / 10}.#{s mod 10}Kb"
+# else
+# "#{size}b"
+# end
+# end
+# end
+# end
+#}
+#
+#def load_directory = fn (dir) {
+# if File.exists?(dir) && File.is_directory?(dir) do
+# files = List.sort(File.list(dir))
+# List.each(files, fn (file) {
+# if (! Str.starts_with?(file, ".")) do
+# path = dir + file
+# if File.is_directory?(path) do
+# load_directory(path + "/")
+# else
+# if Str.ends_with?(path, ".kc3") do
+# load(path)
+# end
+# end
+# end
+# })
+# end
+#}
+#
+#def maybe_reload_directory = fn (dir) {
+# if File.exists?(dir) && File.is_directory?(dir) do
+# files = List.sort(File.list(dir))
+# List.each(files, fn (file) {
+# if (! Str.starts_with?(file, ".")) do
+# path = dir + file
+# if File.is_directory?(path) do
+# maybe_reload_directory(path + "/")
+# else
+# if Str.ends_with?(path, ".kc3") do
+# maybe_reload(path)
+# end
+# end
+# end
+# })
+# end
+#}
+#
diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index d675c6a..ffa9a10 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -27,6 +27,7 @@
#include "character.h"
#include "complex.h"
#include "cow.h"
+#include "data.h"
#include "env.h"
#include "fact.h"
#include "fn.h"
@@ -1082,11 +1083,7 @@ sw buf_parse_call_paren (s_buf *buf, s_call *dest)
goto restore;
result += r;
call_init_op_unary(&tmp);
- if (! ops_get(env_global()->ops, &g_sym__paren, 1)) {
- assert(! "buf_parse_call_paren: could not resolve operator ()");
- r = -1;
- goto restore;
- }
+ tmp.ident.sym = &g_sym__paren;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
@@ -4094,7 +4091,12 @@ sw buf_parse_tag_module_name (s_buf *buf, s_tag *dest)
sw buf_parse_tag_number (s_buf *buf, s_tag *dest)
{
+ void *data = NULL;
+ s_tag i = {0};
sw r;
+ sw result = 0;
+ s_buf_save save = {0};
+ const s_sym *type = NULL;
assert(buf);
assert(dest);
r = buf_parse_tag_f128(buf, dest);
@@ -4109,12 +4111,42 @@ sw buf_parse_tag_number (s_buf *buf, s_tag *dest)
r = buf_parse_tag_ratio(buf, dest);
if (r > 0)
return r;
- r = buf_parse_tag_integer(buf, dest);
- if (r > 0) {
+ buf_save_init(buf, &save);
+ if ((r = buf_parse_paren_sym(buf, &type)) > 0) {
+ if (! sym_type_is_integer(&type)) {
+ r = 0;
+ goto restore;
+ }
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
+ if ((r = buf_parse_tag_integer(buf, &i)) <= 0)
+ goto restore;
+ result += r;
+ if (type) {
+ sym_to_tag_type(type, &dest->type);
+ if (! tag_to_pointer(dest, type, &data)) {
+ r = -1;
+ goto clean;
+ }
+ if (! data_init_cast(data, &type, &i)) {
+ r = -1;
+ goto clean;
+ }
+ }
+ else {
+ *dest = i;
tag_integer_reduce(dest);
- return r;
}
- return 0;
+ r = result;
+ goto clean;
+ restore:
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
}
sw buf_parse_tag_primary (s_buf *buf, s_tag *dest)
diff --git a/libkc3/buf_parse_s.c.in b/libkc3/buf_parse_s.c.in
index 1262b6f..c59ba09 100644
--- a/libkc3/buf_parse_s.c.in
+++ b/libkc3/buf_parse_s.c.in
@@ -32,8 +32,16 @@ sw buf_parse_s_bits$ (s_buf *buf, s_bits$ *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(S_bits$)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/buf_parse_s16.c b/libkc3/buf_parse_s16.c
index 8c1e7d2..90aa4a1 100644
--- a/libkc3/buf_parse_s16.c
+++ b/libkc3/buf_parse_s16.c
@@ -32,8 +32,16 @@ sw buf_parse_s16 (s_buf *buf, s16 *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(S16)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/buf_parse_s32.c b/libkc3/buf_parse_s32.c
index 7fe84f0..7760505 100644
--- a/libkc3/buf_parse_s32.c
+++ b/libkc3/buf_parse_s32.c
@@ -32,8 +32,16 @@ sw buf_parse_s32 (s_buf *buf, s32 *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(S32)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/buf_parse_s64.c b/libkc3/buf_parse_s64.c
index 86b42c1..fb828cc 100644
--- a/libkc3/buf_parse_s64.c
+++ b/libkc3/buf_parse_s64.c
@@ -32,8 +32,16 @@ sw buf_parse_s64 (s_buf *buf, s64 *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(S64)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/buf_parse_s8.c b/libkc3/buf_parse_s8.c
index 183124a..0790989 100644
--- a/libkc3/buf_parse_s8.c
+++ b/libkc3/buf_parse_s8.c
@@ -32,8 +32,16 @@ sw buf_parse_s8 (s_buf *buf, s8 *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(S8)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/buf_parse_sw.c b/libkc3/buf_parse_sw.c
index ed409ba..d0c982e 100644
--- a/libkc3/buf_parse_sw.c
+++ b/libkc3/buf_parse_sw.c
@@ -32,8 +32,16 @@ sw buf_parse_sw (s_buf *buf, sw *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "(Sw)")) < 0)
+ goto restore;
+ if (r) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_read_1(buf, "-")) < 0)
- goto clean;
+ goto restore;
if (r > 0) {
result += r;
negative = true;
diff --git a/libkc3/ht.c b/libkc3/ht.c
index 4135af3..a80c6f2 100644
--- a/libkc3/ht.c
+++ b/libkc3/ht.c
@@ -20,8 +20,7 @@
bool ht_add (s_ht *ht, void *data)
{
uw hash = ht->hash(data);
- void *ref = ht->new_ref(data);
- return ht_add_hash(ht, ref, hash);
+ return ht_add_hash(ht, data, hash);
}
/* Returns true if data was added or is already present. */
@@ -29,19 +28,23 @@ bool ht_add_hash (s_ht *ht, void *data, uw hash)
{
s8 c;
uw index;
- s_ht_item *item;
+ s_ht_item **item;
+ s_ht_item *item_new;
assert(ht);
+ assert(ht->size);
assert(data);
/* FIXME: lock / unlock */
- index = hash % ht->count;
- item = ht->items[index];
- while (item && (c = ht->compare(item, data)) < 0)
- item = item->next;
- if (c == 0)
- return true;
- if (! (item = ht_item_new(data, ht->items[index])))
+ index = hash % ht->size;
+ item = &ht->items[index];
+ while (*item && (c = ht->compare(*item, data)) < 0)
+ item = &(*item)->next;
+ if (*item && ! c) {
+ *item = ht_item_delete(ht, *item);
+ ht->count--;
+ }
+ if (! (item_new = ht_item_new(ht, data, *item)))
return false;
- ht->items[index] = item;
+ *item = item_new;
ht->count++;
return true;
}
diff --git a/libkc3/ht_item.c b/libkc3/ht_item.c
index 792ab39..9c03b65 100644
--- a/libkc3/ht_item.c
+++ b/libkc3/ht_item.c
@@ -33,25 +33,24 @@ s_ht_item * ht_item_delete (s_ht *ht, s_ht_item *ht_item)
return next;
}
-s_ht_item * ht_item_init (s_ht_item *ht_item, void *data,
+s_ht_item * ht_item_init (s_ht *ht, s_ht_item *ht_item, void *data,
s_ht_item *next)
{
s_ht_item tmp = {0};
assert(ht_item);
assert(data);
- assert(next);
- tmp.data = data;
+ tmp.data = ht->new_ref(data);
tmp.next = next;
*ht_item = tmp;
return ht_item;
}
-s_ht_item * ht_item_new (void *data, s_ht_item *next)
+s_ht_item * ht_item_new (s_ht *ht, void *data, s_ht_item *next)
{
s_ht_item *item;
if (! (item = alloc(sizeof(s_ht_item))))
return NULL;
- if (! ht_item_init(item, data, next)) {
+ if (! ht_item_init(ht, item, data, next)) {
free(item);
return NULL;
}
diff --git a/libkc3/ht_item.h b/libkc3/ht_item.h
index 9cce4e5..41ca399 100644
--- a/libkc3/ht_item.h
+++ b/libkc3/ht_item.h
@@ -20,11 +20,12 @@
/* Stack-allocation compatible functions, call ht_item_clean
after use. */
void ht_item_clean (s_ht *ht, s_ht_item *item);
-s_ht_item * ht_item_init (s_ht_item *item, void *data, s_ht_item *next);
+s_ht_item * ht_item_init (s_ht *ht, s_ht_item *item, void *data,
+ s_ht_item *next);
/* Heap allocation compatible functions, call ht_item_delete
after use. */
s_ht_item * ht_item_delete (s_ht *ht, s_ht_item *item);
-s_ht_item * ht_item_new (void *data, s_ht_item *next);
+s_ht_item * ht_item_new (s_ht *ht, void *data, s_ht_item *next);
#endif /* LIBKC3_HT_ITEM_H */
diff --git a/libkc3/io.c b/libkc3/io.c
index f53d6ee..7a91cbf 100644
--- a/libkc3/io.c
+++ b/libkc3/io.c
@@ -87,6 +87,11 @@ sw err_inspect_tag_type (e_tag_type type)
return err_write_1(tag_type_to_string(type));
}
+sw err_stacktrace (void)
+{
+ return err_inspect_stacktrace(env_global()->stacktrace);
+}
+
sw err_puts (const char *x)
{
sw r;
@@ -165,6 +170,11 @@ sw io_inspect_tag_type (e_tag_type type)
return io_write_1(tag_type_to_string(type));
}
+sw io_stacktrace (void)
+{
+ return io_inspect_stacktrace(env_global()->stacktrace);
+}
+
sw io_puts (const char *x)
{
sw r;
diff --git a/libkc3/io.h b/libkc3/io.h
index 212b8b4..4782d57 100644
--- a/libkc3/io.h
+++ b/libkc3/io.h
@@ -29,6 +29,7 @@
sw err_flush (void);
sw err_inspect (const s_tag *x);
sw err_puts (const char *x);
+sw err_stacktrace (void);
sw err_write (const void *x, uw len);
sw err_write_1 (const char *x);
sw err_write_str (const s_str *x);
@@ -38,6 +39,7 @@ sw err_write_u8 (u8 x);
sw io_flush (void);
sw io_inspect (const s_tag *x);
sw io_puts (const char *x);
+sw io_stacktrace (void);
sw io_write (const void *x, uw len);
sw io_write_1 (const char *x);
sw io_write_str (const s_str *x);
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index 05df185..8c859f8 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -178,28 +178,20 @@ s_tag * kc3_defoperator (s_tag *op_tag, s_tag *dest)
return NULL;
}
env = env_global();
- if (! op_tag->data.struct_.data) {
- tag.type = TAG_STRUCT;
- if (! env_eval_struct(env, &op_tag->data.struct_,
- &tag.data.struct_)) {
- err_puts("kc3_defoperator: env_eval_struct");
- assert(! "kc3_defoperator: env_eval_struct");
- return NULL;
- }
- if (! env_defoperator(env, tag.data.struct_.data, dest)) {
- err_puts("kc3_defoperator: env_defoperator 1");
- assert(! "kc3_defoperator: env_defoperator 1");
- tag_clean(&tag);
- return NULL;
- }
- return dest;
+ tag.type = TAG_STRUCT;
+ if (! env_eval_struct(env, &op_tag->data.struct_,
+ &tag.data.struct_)) {
+ err_puts("kc3_defoperator: env_eval_struct");
+ assert(! "kc3_defoperator: env_eval_struct");
+ return NULL;
}
- if (! env_defoperator(env, op_tag->data.struct_.data, dest)) {
- err_puts("kc3_defoperator: env_defoperator 2");
- assert(! "kc3_defoperator: env_defoperator 2");
+ if (! env_defoperator(env, tag.data.struct_.data, dest)) {
+ err_puts("kc3_defoperator: env_defoperator 1");
+ assert(! "kc3_defoperator: env_defoperator 1");
tag_clean(&tag);
return NULL;
}
+ tag_clean(&tag);
return dest;
}
diff --git a/libkc3/sym.c b/libkc3/sym.c
index 964529b..ee4b0b3 100644
--- a/libkc3/sym.c
+++ b/libkc3/sym.c
@@ -1086,6 +1086,22 @@ bool sym_to_tag_type (const s_sym *sym, e_tag_type *dest)
return false;
}
+bool sym_type_is_integer (const s_sym * const *type)
+{
+ const s_sym *t = *type;
+ return (t == &g_sym_Integer ||
+ t == &g_sym_S8 ||
+ t == &g_sym_S16 ||
+ t == &g_sym_S32 ||
+ t == &g_sym_S64 ||
+ t == &g_sym_Sw ||
+ t == &g_sym_U8 ||
+ t == &g_sym_U16 ||
+ t == &g_sym_U32 ||
+ t == &g_sym_U64 ||
+ t == &g_sym_Uw);
+}
+
uw * sym_type_size (const s_sym * const *type, uw *dest)
{
s_struct_type *st;
diff --git a/libkc3/sym.h b/libkc3/sym.h
index 4f2968f..c614ba1 100644
--- a/libkc3/sym.h
+++ b/libkc3/sym.h
@@ -159,6 +159,7 @@ bool sym_search_modules (const s_sym *sym, const s_sym **dest);
bool sym_to_ffi_type (const s_sym *sym, ffi_type *result_type,
ffi_type **dest);
bool sym_to_tag_type (const s_sym *sym, e_tag_type *dest);
+bool sym_type_is_integer (const s_sym * const *type);
uw * sym_type_size (const s_sym * const *type, uw *size);
#endif /* LIBKC3_SYM_H */
diff --git a/libkc3/tag.c b/libkc3/tag.c
index 0d44027..a6ac77c 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -1158,7 +1158,7 @@ s_tag * tag_resolve_cow (s_tag *tag)
return tag;
}
-s_tag * tag_semicolumn (const s_tag *a, s_tag *b, s_tag *dest)
+s_tag * tag_semicolon (const s_tag *a, s_tag *b, s_tag *dest)
{
(void) a;
return tag_init_copy(dest, b);
diff --git a/libkc3/tag.h b/libkc3/tag.h
index 32bb184..eef49d3 100644
--- a/libkc3/tag.h
+++ b/libkc3/tag.h
@@ -104,6 +104,7 @@ bool * tag_not (s_tag *tag, bool *dest);
bool * tag_not_eq (s_tag *a, s_tag *b, bool *dest);
s_tag * tag_or (s_tag *a, s_tag *b, s_tag *dest);
s_tag * tag_paren (s_tag *tag, s_tag *dest);
+s_tag * tag_semicolon (const s_tag *a, s_tag *b, s_tag *dest);
s_tag * tag_shift_left (s_tag *a, s_tag *b, s_tag *dest);
s_tag * tag_shift_right (s_tag *a, s_tag *b, s_tag *dest);
s_tag * tag_sqrt (s_tag *tag, s_tag *dest);
diff --git a/test/libkc3_test.c b/test/libkc3_test.c
index 9c3a696..7707dd2 100644
--- a/test/libkc3_test.c
+++ b/test/libkc3_test.c
@@ -31,6 +31,7 @@ void fn_test (void);
void ident_test (void);
void inspect_test (void);
void list_test (void);
+void ops_test (void);
void ratio_test (void);
void set__fact_test (void);
void set__tag_test (void);
@@ -56,13 +57,14 @@ int main (int argc, char **argv)
return 1;
test_init(env_global()->argv[0], &argc, &argv);
TEST_TARGET(types);
- TEST_TARGET(array);
+ TEST_TARGET(ops);
TEST_TARGET(bool);
TEST_TARGET(character);
TEST_TARGET(buf);
TEST_TARGET(buf_parse);
TEST_TARGET(buf_inspect);
TEST_TARGET(buf_file);
+ TEST_TARGET(array);
TEST_TARGET(str);
TEST_TARGET(sym);
TEST_TARGET(ident);
diff --git a/test/ops_test.c b/test/ops_test.c
new file mode 100644
index 0000000..42af790
--- /dev/null
+++ b/test/ops_test.c
@@ -0,0 +1,95 @@
+/* kc3
+ * Copyright 2022,2023,2024 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <assert.h>
+#include <string.h>
+#include "../libkc3/callable.h"
+#include "../libkc3/op.h"
+#include "../libkc3/ops.h"
+#include "../libkc3/sym.h"
+#include "test.h"
+
+TEST_CASE_PROTOTYPE(ops_init_clean);
+TEST_CASE_PROTOTYPE(ops_new_delete);
+TEST_CASE_PROTOTYPE(ops_add);
+TEST_CASE_PROTOTYPE(ops_get);
+
+void ops_test (void)
+{
+ TEST_CASE_RUN(ops_init_clean);
+ TEST_CASE_RUN(ops_new_delete);
+ TEST_CASE_RUN(ops_add);
+ TEST_CASE_RUN(ops_get);
+}
+
+TEST_CASE(ops_init_clean)
+{
+ s_ops ops;
+ test_context("ops_init_clean");
+ TEST_EQ(ops_init(&ops), &ops);
+ ops_clean(&ops);
+ test_context(NULL);
+}
+TEST_CASE_END(ops_init_clean)
+
+TEST_CASE(ops_new_delete)
+{
+ s_ops *ops;
+ test_context("ops_new_delete");
+ TEST_ASSERT((ops = ops_new()));
+ ops_delete(ops);
+ test_context(NULL);
+}
+TEST_CASE_END(ops_init_clean)
+
+TEST_CASE(ops_add)
+{
+ s_ops *ops;
+ s_op *op;
+ test_context("ops_add");
+ TEST_ASSERT((ops = ops_new()));
+ TEST_ASSERT((op = op_new()));
+ op->sym = sym_1("+");
+ op->arity = 2;
+ op->precedence = 1;
+ op->associativity = 1;
+ op->callable = callable_new();
+ TEST_ASSERT(ops_add(ops, op));
+ op_delete(op);
+ ops_delete(ops);
+ test_context(NULL);
+}
+TEST_CASE_END(ops_add)
+
+TEST_CASE(ops_get)
+{
+ s_ops *ops;
+ s_op *op;
+ test_context("ops_get");
+ TEST_ASSERT((ops = ops_new()));
+ TEST_ASSERT((op = op_new()));
+ op->sym = sym_1("+");
+ op->arity = 2;
+ op->precedence = 3;
+ op->associativity = 1;
+ op->callable = callable_new();
+ TEST_ASSERT(ops_add(ops, op));
+ op_delete(op);
+ TEST_ASSERT((op = ops_get(ops, sym_1("+"), 2)));
+ TEST_EQ(op->sym, sym_1("+"));
+ TEST_EQ(op->arity, 2);
+ TEST_EQ(op->precedence, 3);
+ TEST_EQ(op->associativity, 1);
+ ops_delete(ops);
+ test_context(NULL);
+}
+TEST_CASE_END(ops_get)
diff --git a/test/sources.mk b/test/sources.mk
index 37bed6a..f0068fb 100644
--- a/test/sources.mk
+++ b/test/sources.mk
@@ -27,16 +27,17 @@ SOURCES = \
"character_test.c" \
"compare_test.c" \
"env_test.c" \
- "fact_test.c" \
"facts_cursor_test.c" \
"facts_test.c" \
"facts_with_test.c" \
+ "fact_test.c" \
"fn_test.c" \
"hash_test.c" \
"ident_test.c" \
"inspect_test.c" \
"libkc3_test.c" \
"list_test.c" \
+ "ops_test.c" \
"ratio_test.c" \
"set__fact_test.c" \
"set__tag_test.c" \
diff --git a/test/sources.sh b/test/sources.sh
index 8632c43..f838b72 100644
--- a/test/sources.sh
+++ b/test/sources.sh
@@ -1,3 +1,3 @@
# sources.sh generated by update_sources
HEADERS='buf_parse_test.h buf_parse_test_su.h compare_test.h fact_test.h tag_test.h test.h '
-SOURCES='array_test.c bool_test.c buf_file_test.c buf_inspect_test.c buf_parse_test.c buf_parse_test_s16.c buf_parse_test_s32.c buf_parse_test_s64.c buf_parse_test_s8.c buf_parse_test_u16.c buf_parse_test_u32.c buf_parse_test_u64.c buf_parse_test_u8.c buf_test.c call_test.c cfn_test.c character_test.c compare_test.c env_test.c fact_test.c facts_cursor_test.c facts_test.c facts_with_test.c fn_test.c hash_test.c ident_test.c inspect_test.c libkc3_test.c list_test.c ratio_test.c set__fact_test.c set__tag_test.c skiplist__fact_test.c str_test.c struct_test.c sym_test.c tag_test.c test.c tuple_test.c types_test.c '
+SOURCES='array_test.c bool_test.c buf_file_test.c buf_inspect_test.c buf_parse_test.c buf_parse_test_s16.c buf_parse_test_s32.c buf_parse_test_s64.c buf_parse_test_s8.c buf_parse_test_u16.c buf_parse_test_u32.c buf_parse_test_u64.c buf_parse_test_u8.c buf_test.c call_test.c cfn_test.c character_test.c compare_test.c env_test.c facts_cursor_test.c facts_test.c facts_with_test.c fact_test.c fn_test.c hash_test.c ident_test.c inspect_test.c libkc3_test.c list_test.c ops_test.c ratio_test.c set__fact_test.c set__tag_test.c skiplist__fact_test.c str_test.c struct_test.c sym_test.c tag_test.c test.c tuple_test.c types_test.c '