diff --git a/.ikc3_history b/.ikc3_history
index 1db7ffa..ca49c99 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,17 +1,3 @@
-a = ? <- 1 ; 2
-a
-a = ? <- 1 ; 2
-a
-(a = ? <- 1) ; 2
-a
-a = ? <- 1 ; 2
-quote a = ? <- 1 ; 2
-to_lisp(quote a = ? <- 1 ; 2)
-operator(:";")
-KC3.Operator.find(:";")
-a = ?
-a
-a <- 1
a
a = 1
a
@@ -97,3 +83,17 @@ Str.ftime(Time.now(), "%a, %b %d %G %T %Z")
cow 1
cow(1)
cow 1
+cow 1 + 1
+quote cow 1 + 1
+a = cow 1 + 1
+a
+a + 1
+a <- 3
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
diff --git a/ikc3/.ikc3_history b/ikc3/.ikc3_history
index f76e1d9..ca49c99 100644
--- a/ikc3/.ikc3_history
+++ b/ikc3/.ikc3_history
@@ -1,100 +1,99 @@
-op = ?
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, ^ op], [^ op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-op = ?
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, ^ op], [^ op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-op = ?
-op <- 1
-op
-op <- ?
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, ^ op], [^ op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op], [^ op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op], [op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, unquote(op)], [unquote(op), :symbol_value, value]], fn (fact) { puts(op); 1 })
-op = ?
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, unquote(op)], [unquote(op), :symbol_value, value]], fn (fact) { puts(op); 1 })
-op
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op = ?], [op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op], [^ op, :symbol_value, value]], fn (fact) { puts(op); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op]], fn (fact) { puts(op); 1 })
-Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
-?
-a = ?
-?
-a
-a = ?
-a
-a = ?
-a
-a <- 1
-a
-(U8) (Ptr) a
-(Tag) (Ptr) a
-(Ptr) a
-(Tag) (Ptr) a
-a = ?
-a
-(Ptr) a
-a = ?
a
-a <- 1
+a = 1
a
-(Ptr) 0x1801350e830
-(Tag) (Ptr) 0x1801350e830
-Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
-Facts.with(Facts.env_facts(), [[KC3, :operator, ?]], fn (fact) { puts(fact.object); 1 })
-(Ptr) 0xf24fc9ce000
-(Tag) (Ptr) 0xf24fc9ce000
-?
-Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
-Facts.with(Facts.env_facts(), [[KC3, :operator, ?]], fn (fact) { puts(fact.object); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op]], fn (fact) { puts(fact.object); 1 })
-op
-op = ?
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op]], fn (fact) { puts(fact.object); 1 })
-op
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op]], fn (fact) { puts(fact.object); 1 })
-Facts.with(Facts.env_facts(), quote [[KC3, :operator, op = (Ident) ?]], fn (fact) { puts(fact.object); 1 })
+to_lisp(quote a = ? <- 1 ; 2)
a = ?
-a <- void
-a
-%KC3.Operator{symbol_value: void}
-%KC3.Operator{symbol_value: 1}
-%KC3.Operator{symbol_value: void}
-1; 2; 3
-1; 2
-1 ; 2
-a = 1; 2
-a = ?; 2
-a
-a = ?; 2
-a
-a = 1; 2
-a
-a = ?
-b = (Var) 0x9ee46e3ef10
-? <- 1
-a = ? <- 1
-a
-a = ? <- 1 ; b = a
-b
-a
-a = ? <- 1 ; 2
-a
-a = ? <- 1 ; 2
-a
-(a = ? <- 1) ; 2
-a
-a = ? <- 1 ; 2
-a
-a = ? <- 1 ; 2
-a
-a = ? <- 1 ; 2
-a
-(a = ? <- 1) ; 2
-a
-a = ? <- 1 ; 2
+Facts.with_tags(Facts.env_facts(), KC3, :operator, a, fn (fact) { puts(a); 1 })
+to_lisp(quote a = ? <- 1 ; 2)
+to_lisp(quote a = 1 ; 2)
+to_lisp(quote a = ? <- 1 ; 2)
+q
+exit
+to_lisp(quote a = ? <- 1 ; 2)
+quote if true do if true do %KC3.Operator{} end end
+quote if true do if true do unquote(%KC3.Operator{}) end end
+quote if true do if true do %KC3.Operator{sym: :a} end end
+to_lisp(quote a = ? <- 1 ; 2)
+quote if true do if true do %KC3.Operator{symbol_value: void} end end
+quote if true do if true do %KC3.Operator{sym: :-, symbol_value: void} end end
+to_lisp(quote a = ? <- 1 ; 2)
quote a = ? <- 1 ; 2
-KC3.Operator.find(:xxx)
-KC3.Operator.find(:+)
quote 1 + 20 / 3 * 4 - 5
+quote 1 + 20 / 3 * 4
+quote 1 + 20 / 3 * 4 - 5
+1 + 1
+1 + 1000000000000000000000000000000000000000000000000000000
+(1 + 1000000000000000000000000000000000000000000000000000000) * 2
+sqrt(1 + 1000000000000000000000000000000000000000000000000000000)
+List.reverse([1, 2, 3, 4])
+List.reverse
+List.reverse([1, 2, 3, 4])
+List.map([1, 2, 3, 4], fn (x) { x * 2 })
+List.has?([1, 2, 3, 4], 1)
+List.has?([1, 2, 3, 4], 0)
+quote if true do if true do %KC3.Operator{} end end
+quote if true do if true do %KC3.Operator{sym: :-} end end
+quote if true do if true do %KC3.Operator{sym: :-, symbol_value: void} end end
+quote if true do if true do %KC3.Operator{sym: :-, symbol_value: void} else 0 end else 1 end
+a = ?
+b = ?
+a = ? ; void
+Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
+EKC3.html_escape("plop <1>")
+Facts.first_with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { fact.object })
+first_operator = Facts.first_with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { fact.object })
+first_operator
+List.append([1, 2, 3], 4)
+HTTPd.routes
+a = :dir
+file = %{type: :dir}
+file.type
+file.type == :dir
+file = %{type: :dir, items = [%{type: file, items: []}]}
+file = %{type: :dir, items: [%{type: file, items: []}]}
+file = %{type: :dir, items: [%{type: :file, items: []}]}
+file = "plop.md"
+Str.starts_with?(file, ".") ||
+(Sw) 4 > 0
+q
+List.sort([1, 2, 3, 4])
+List.sort([4, 3, 2, 1])
+List.sort(["1. a", "2. bc", "3. cde", "4. fghi"])
+List.sort(["1. abcd", "2. efg", "3. hi", "4. j"])
+1/3
+1/3 * 2
+2/6 * 2
+double = fn (x) { x * 2 }
+double(4)
+double(21)
+List.map([1, 2, 3, 4], double)
+List.reverse([1, 2, 3, 4])
+Time.now
+Time.now()
+Str.ftime(Time.now(), "%a")
+Str.ftim
+Str.ftime
+Str.ftime(Time.now(), "%a")
+Str.ftime(Time.now(), "%a, %d")
+Str.ftime(Time.now(), "%a, %G")
+Str.ftime(Time.now(), "%a, %m %d %G")
+Str.ftime(Time.now(), "%a, %b %d %G")
+Str.ftime(Time.now(), "%a, %b %d %G %T %Z")
+cow 1
+cow(1)
+cow 1
+cow 1 + 1
+quote cow 1 + 1
+a = cow 1 + 1
+a
+a + 1
+a <- 3
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
+a = cow 1 + 1
+a
diff --git a/lib/kc3/0.1/kc3.facts b/lib/kc3/0.1/kc3.facts
index e5046ee..2afba6f 100644
--- a/lib/kc3/0.1/kc3.facts
+++ b/lib/kc3/0.1/kc3.facts
@@ -194,14 +194,14 @@ add {KC3, :operator, KC3.operator_assign}
replace {KC3.operator_assign, :is_a, :operator}
replace {KC3.operator_assign, :sym, :<-}
replace {KC3.operator_assign, :arity, 2}
-replace {KC3.operator_assign, :symbol_value, cfn Tag "var_assign" (Var, Tag, Result)}
+replace {KC3.operator_assign, :symbol_value, cfn Tag "tag_assign" (Tag, Tag, Result)}
replace {KC3.operator_assign, :operator_precedence, 3}
replace {KC3.operator_assign, :operator_associativity, :left}
add {KC3, :operator, KC3.operator_assign_2}
replace {KC3.operator_assign_2, :is_a, :operator}
replace {KC3.operator_assign_2, :sym, :←}
replace {KC3.operator_assign_2, :arity, 2}
-replace {KC3.operator_assign_2, :symbol_value, cfn Tag "var_assign" (Var, Tag, Result)}
+replace {KC3.operator_assign_2, :symbol_value, cfn Tag "tag_assign" (Tag, Tag, Result)}
replace {KC3.operator_assign_2, :operator_precedence, 3}
replace {KC3.operator_assign_2, :operator_associativity, :left}
add {KC3, :operator, KC3.operator_equal}
diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index b708373..67fb444 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -1364,10 +1364,10 @@ sw buf_parse_cow (s_buf *buf, s_cow *cow)
goto restore;
result += r;
}
- if ((r = buf_read_1(buf, "cow ")) <= 0)
+ if ((r = buf_read_1(buf, "cow")) <= 0)
goto restore;
result += r;
- if ((r = buf_ignore_spaces(buf)) < 0)
+ if ((r = buf_ignore_spaces(buf)) <= 0)
goto restore;
result += r;
if (! cow_init(&tmp, type))
@@ -4112,6 +4112,7 @@ sw buf_parse_tag_primary_4 (s_buf *buf, s_tag *dest)
switch (c) {
case '(':
if ((r = buf_parse_tag_var(buf, dest)) ||
+ (r = buf_parse_tag_cow(buf, dest)) ||
(r = buf_parse_tag_number(buf, dest)) ||
(r = buf_parse_tag_array(buf, dest)) ||
(r = buf_parse_tag_cast(buf, dest)) ||
diff --git a/libkc3/cow.c b/libkc3/cow.c
index d8b8272..5e581a3 100644
--- a/libkc3/cow.c
+++ b/libkc3/cow.c
@@ -22,6 +22,17 @@
#include "sym.h"
#include "tag.h"
+s_tag * cow_assign (s_cow *cow, const s_tag *value, s_tag *dest)
+{
+ if (! tag_init_copy(cow_read_write(cow), value))
+ return NULL;
+ if (! cow_freeze(cow))
+ return NULL;
+ dest->type = TAG_COW;
+ dest->data.cow = cow;
+ return dest;
+}
+
void cow_clean (s_cow *cow)
{
assert(cow);
diff --git a/libkc3/cow.h b/libkc3/cow.h
index b0baad6..914d3a4 100644
--- a/libkc3/cow.h
+++ b/libkc3/cow.h
@@ -31,7 +31,7 @@
/* Stack-allocation compatible functions. Call cow_clean after use. */
void cow_clean (s_cow *cow);
s_cow * cow_init (s_cow *cow, const s_sym *type);
-s_cow * cow_init_1 (s_cow *cow, const char *utf8);
+/* s_cow * cow_init_1 (s_cow *cow, const char *utf8); */
s_cow * cow_init_cast (s_cow *cow, const s_sym * const *type,
const s_tag *tag);
s_cow * cow_init_copy (s_cow *cow, const s_cow *src);
@@ -41,7 +41,7 @@ s_cow * cow_init_tag_copy (s_cow *cow, const s_sym *type,
/* Heap-allocation functions. Call cow_delete after use. */
void cow_delete (s_cow *cow);
s_cow * cow_new (const s_sym *type);
-s_cow * cow_new_1 (const char *utf8);
+/* s_cow * cow_new_1 (const char *utf8); */
s_cow * cow_new_cast (const s_sym * const *type, const s_tag *tag);
s_cow * cow_new_copy (const s_cow *src);
s_cow * cow_new_tag_copy (const s_sym *type, const s_tag *src);
@@ -53,6 +53,7 @@ s_tag * cow_read_write (s_cow *cow);
const s_tag * cow_resolve (const s_cow *cow);
/* Operators. */
+s_tag * cow_assign (s_cow *cow, const s_tag *value, s_tag *dest);
s_cow * cow_freeze (s_cow *cow);
s_cow * cow_freeze_copy (s_cow *cow, const s_tag *src);
s_cow * cow_thaw (s_cow *cow);
diff --git a/libkc3/tag.c b/libkc3/tag.c
index e0059a7..d13300a 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -78,6 +78,49 @@ s8 tag_arity (const s_tag *tag)
return -1;
}
+s_tag * tag_assign (const s_tag *tag, const s_tag *value, s_tag *dest)
+{
+ assert(tag);
+ assert(value);
+ assert(dest);
+ switch (tag->type) {
+ case TAG_VAR:
+ return var_assign(&tag->data.var, value, dest);
+ case TAG_COW:
+ return cow_assign(tag->data.cow, value, dest);
+ default:
+ break;
+ }
+ err_write_1("tag_assign: cannot assign to ");
+ err_write_1(tag_type_to_string(tag->type));
+ err_write_1("\n");
+ assert(! "tag_assign: cannot assign to this tag type");
+ return NULL;
+}
+
+s_tag * tag_brackets (const s_tag *tag, const s_tag *address,
+ s_tag *dest)
+{
+ assert(tag);
+ assert(address);
+ assert(dest);
+ switch (tag->type) {
+ case TAG_ARRAY:
+ switch (address->type) {
+ case TAG_ARRAY:
+ return array_data_tag(&tag->data.array, &address->data.array,
+ dest);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ err_puts("tag_brackets: invalid arguments");
+ assert(! "tag_brackets: invalid arguments");
+ return NULL;
+}
+
s_tag * tag_cast_integer_to_s8 (s_tag *tag)
{
s8 i;
@@ -200,29 +243,6 @@ void tag_clean (s_tag *tag)
}
}
-s_tag * tag_brackets (const s_tag *tag, const s_tag *address,
- s_tag *dest)
-{
- assert(tag);
- assert(address);
- assert(dest);
- switch (tag->type) {
- case TAG_ARRAY:
- switch (address->type) {
- case TAG_ARRAY:
- return array_data_tag(&tag->data.array, &address->data.array,
- dest);
- default:
- break;
- }
- default:
- break;
- }
- err_puts("tag_brackets: invalid arguments");
- assert(! "tag_brackets: invalid arguments");
- return NULL;
-}
-
void tag_delete (s_tag *tag)
{
tag_clean(tag);
diff --git a/libkc3/tag.h b/libkc3/tag.h
index c18fcd7..aaaa71a 100644
--- a/libkc3/tag.h
+++ b/libkc3/tag.h
@@ -81,12 +81,14 @@ bool tag_to_pointer (s_tag *tag, const s_sym *type, void **dest);
/* KC3 operators. */
s_tag * tag_add (const s_tag *a, const s_tag *b, s_tag *dest);
bool * tag_and (const s_tag *a, const s_tag *b, bool *dest);
+s_tag * tag_assign (const s_tag *tag, const s_tag *value, s_tag *dest);
s_tag * tag_band (const s_tag *a, const s_tag *b, s_tag *dest);
s_tag * tag_bnot (const s_tag *tag, s_tag *dest);
s_tag * tag_bor (const s_tag *a, const s_tag *b, s_tag *dest);
s_tag * tag_brackets (const s_tag *tag, const s_tag *address,
s_tag *dest);
s_tag * tag_bxor (const s_tag *a, const s_tag *b, s_tag *dest);
+s_tag * tag_cow (const s_tag *value, s_tag *dest);
s_tag * tag_div (const s_tag *a, const s_tag *b, s_tag *dest);
bool * tag_lt (const s_tag *a, const s_tag *b, bool *dest);
bool * tag_lte (const s_tag *a, const s_tag *b, bool *dest);
diff --git a/libkc3/var.c b/libkc3/var.c
index d742c96..d4ee907 100644
--- a/libkc3/var.c
+++ b/libkc3/var.c
@@ -19,7 +19,7 @@
#include "tag.h"
#include "var.h"
-s_tag * var_assign (s_var *var, const s_tag *value, s_tag *dest)
+s_tag * var_assign (const s_var *var, const s_tag *value, s_tag *dest)
{
assert(var);
assert(value);
@@ -119,7 +119,7 @@ s_var * var_init_copy (s_var *var, const s_var *src)
return var;
}
-bool * var_is_unbound (s_var *var, bool *dest)
+bool * var_is_unbound (const s_var *var, bool *dest)
{
assert(var);
assert(dest);
@@ -127,7 +127,7 @@ bool * var_is_unbound (s_var *var, bool *dest)
return dest;
}
-s_var * var_reset (s_var *var)
+const s_var * var_reset (const s_var *var)
{
s_tag tmp = {0};
assert(var);
@@ -139,7 +139,7 @@ s_var * var_reset (s_var *var)
return var;
}
-s_var * var_set (s_var *var, const s_tag *value)
+const s_var * var_set (const s_var *var, const s_tag *value)
{
const s_sym *value_type;
assert(var);
diff --git a/libkc3/var.h b/libkc3/var.h
index 95ff67e..2124582 100644
--- a/libkc3/var.h
+++ b/libkc3/var.h
@@ -23,10 +23,12 @@ s_var * var_init_cast (s_var *tag, const s_sym * const *type,
s_var * var_init_copy (s_var *tag, const s_var *src);
/* Observers. */
-bool * var_is_unbound (s_var *var, bool *dest);
+bool * var_is_unbound (const s_var *var, bool *dest);
/* Operators. */
-s_var * var_reset (s_var *var);
-s_var * var_set (s_var *var, const s_tag *value);
+s_tag * var_assign (const s_var *var, const s_tag *value,
+ s_tag *dest);
+const s_var * var_reset (const s_var *var);
+const s_var * var_set (const s_var *var, const s_tag *value);
#endif /* LIBKC3_VAR_H */