diff --git a/.ikc3_history b/.ikc3_history
index 676b83b..5b705fa 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,6 +1,3 @@
-128 * 128
-256 * 256 - 1
-type(256 * 256 - 1)
type(-256 * 256 - 1)
type(-256 * 256 + 1)
-256 * 256 + 1
@@ -96,3 +93,7 @@ Struct.offset(%HTTP.Response{}, :code)
Struct.offset(%HTTP.Response{}, :message)
Struct.offset(%HTTP.Response{}, :headers)
Struct.offset(%HTTP.Response{}, :body)
+"a#{a}"
+quote "a#{a}"
+"a#{a}"
+"a#{:a}"
diff --git a/ikc3/.ikc3_history b/ikc3/.ikc3_history
index e107258..43e986f 100644
--- a/ikc3/.ikc3_history
+++ b/ikc3/.ikc3_history
@@ -1,99 +1,99 @@
-Plop.a
-defmodule Plop do def a = 1; def double = fn (x) { x * 2 } end
-Plop.a
-Plop.double
-Plop.double(21)
-def a = 1
-a
-def double = fn (x) { x * 2 }
-double(42)
-defmodule Tiyon do
- def a = 1
- def double = fn (x) { x * 2 }
- def double_tuple = macro (x) do {x, x} end
- def double_list = macro (x) do [x, x] end
+-255 * 256
+-256 * 256 / 2
+-256 * 256 / 2 + 1
+type(-32767)
+type(-256 * 256 / 2 + 1)
+-32767
+type(-32767)
+(S16) -32767
+i = type(-32767)
+-32768 * 65536
+-32768 * 65536 + 1
+-2147483648 * 65536 * 65536 + 1
+q
+%KC3.Operator{}
+%KC3.Operator{sym: :-}
+op = %KC3.Operator{sym: :-}
+op.sym
+op = %{id: 1, sym: :-}
+op.id
+type(op.id)
+type(op.sym)
+(Str) op.sym
+[fd: (S32) -1]
+load("https://git.kmx.io/kc3-lang/kc3/
+)
+load("lib/kc3/0.1/s32.facts")
+(S32) 1
+(S32) -1
+[fd: (S32) -1]
+defmodule Socket do defstruct [fd: (S32) -1]; end
+defmodule Socket do
+dlopen("lib/kc3/0.1/http.so")
+def connect = cfn Socket.Buf "socket_buf_init_connect" (Result, Str, Str)
end
-Tiyon.a
-Tiyon.double(21)
-Tiyon.double_tuple(21)
-Tiyon.double_tuple(21 + 21)
-Tiyon.double_list(21 + 21)
-[42, x] = Tiyon.double_list(21 + 21)
-[42, x] = [42, 42]
-x
-Tiyon.double_list(21 + 21) = [42, y]
-def last = fn (x) do
- [y | _] = List.reverse(x)
- y
-end
-def last = fn (x) do
- [y | _] = List.reverse(x)
- y
-end
-def List.last = fn (x) do
- [y | _] = List.reverse(x)
- y
-end
-List.last([1, 2, 3, 4])
-def List.last = fn (x) do
- [y | z] = List.reverse(x)
- y
-end
-List.last([1, 2, 3, 4])
-[x, y | z] = List.reverse([1, 2, 3])
-x
-y
-z
-[x, y | z] = List.reverse([1, 2, 3, 4])
-x
-y
-z
-if true then true end
-if 42 then true end
-if 0 then true end
-if 0 then true else false end
-List.map
-List.map([1, 2, 3], fn (x) { x * 2 })
-List.reverse
-List.reverse([1, 2, 3])
-List.reverse
-List.reverse([1, 2])
-def a = 1
-a
-module()
-defmodule Plop do
- def m = fn () { module() }
-end
-Plop.m()
-module()
-List.reverse([1, 2, 3])
-List.reverse([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
-(List) {1, 2}
-?
-cow 1
-(Tag) cow 1
-a = cow 1
-a
-a + 1
-cow 1
-type(cow 1)
-cow 1 + cow 1
-cow(1) + cow(1)
-quote [a: 1, b: 2]
-quote [{:a, 1}, {:b, 2}]
-%C3.Operator{}
-%GL.Vertex{}
-123.456
-abc.def
-%{a: 1}
-%{a: 1}.a
-x = %C3.Operator{}
-x.sym
-quote x.sym
-x = %C3.Operator{}
-x.sym
-x = %{
-x = %C3.Operator{sym: :-}
-x = %C3.Operator{sym: 1}
-x = %C3.Operator{sym: (Sym) "1"}
-x = %C3.Operator{sym: :1}
+22
+server = Socket.listen("192.168.1.50
+2
+server = Socket.listen("192.168.2.50", "58000")
+server_client = Socket.Buf.accept(server)
+req = HTTP.Request.buf_parse(server_client.buf_rw.r)
+%HTTP.Response{}
+Struct.offset(%HTTP.Response{}, :message)
+Sym.type_size(Str)
+Struct.offset(%HTTP.Response{}, :message)
+res = %HTTP.Response{}
+res.message
+Sym.type_size(Str)
+Sym.type_size(HTTP.Response)
+Struct.offset(%HTTP.Response{}, :message)
+Sym.type_size(Str)
+Struct.offset(%HTTP.Response{}, :code)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Response{}, :response)
+Struct.offset(%HTTP.Response{}, :protocol)
+Struct.offset(%HTTP.Response{}, :code)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Response{}, :headers)
+Struct.offset(%HTTP.Response{}, :body)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Response{}, :protocol)
+Struct.offset(%HTTP.Response{}, :code)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Response{}, :headers)
+Struct.offset(%HTTP.Response{}, :body)
+Struct.offset(%HTTP.Request{}, :method)
+Struct.offset(%HTTP.Request{}, :url)
+Struct.offset(%HTTP.Request{}, :protocol)
+Struct.offset(%HTTP.Request{}, :headers)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Request{}, :method)
+Struct.offset(%HTTP.Request{}, :url)
+Struct.offset(%HTTP.Request{}, :protocol)
+Struct.offset(%HTTP.Request{}, :headers)
+Struct.offset(%HTTP.Response{}, :protocol)
+Struct.offset(%HTTP.Response{}, :code)
+Struct.offset(%HTTP.Response{}, :message)
+Struct.offset(%HTTP.Response{}, :headers)
+Struct.offset(%HTTP.Response{}, :body)
+"a#{a}"
+quote "a#{a}"
+"a#{a}"
+"a#{:a}"
+quote "a#{a}"
+quote "a#{:a}"
+quote "a"
+quote "a #{:a}"
+"a #{:a}"
+"""a #{:a}"""
+"""a #{":a"}"""
+quote """a #{":a"}"""
+"""a #{":a"}"""
+quote "a#{a}"
+quote "a#{:a}"
+quote """a#{:a}"""
+quote """a#{"a"}"""
+quote """a#{:a}"""
+quote """a #{:a}"""
+quote "a #{:a}"
+quote "a"
diff --git a/lib/kc3/0.1/kc3.facts b/lib/kc3/0.1/kc3.facts
index f728ab9..28a3450 100644
--- a/lib/kc3/0.1/kc3.facts
+++ b/lib/kc3/0.1/kc3.facts
@@ -267,3 +267,6 @@ add {KC3, :symbol, KC3.while}
replace {KC3.while, :arity, 2}
replace {KC3.while, :is_a, :special_operator}
replace {KC3.while, :symbol_value, cfn Tag "kc3_while" (Tag, Tag, Result)}
+add {KC3, :symbol, KC3.str}
+replace {KC3.str, :arity, 1}
+replace {KC3.str, :symbol_value, cfn Str "kc3_str" (Tag, Result)}
diff --git a/libkc3/buf.c b/libkc3/buf.c
index 8e4859d..6b5e131 100644
--- a/libkc3/buf.c
+++ b/libkc3/buf.c
@@ -558,7 +558,7 @@ sw buf_peek_to_str (s_buf *buf, s_str *dest)
str_init_empty(dest);
return 0;
}
- str_init_alloc(dest, size, buf->ptr.pchar + buf->rpos);
+ str_init_alloc_copy(dest, size, buf->ptr.pchar + buf->rpos);
return size;
}
@@ -780,9 +780,9 @@ s_str * buf_read_to_str (s_buf *buf, s_str *dest)
str_init_empty(dest);
return dest;
}
- if (! str_init_alloc(dest, size, buf->ptr.pchar + buf->rpos)) {
- err_puts("buf_read_to_str: str_init_alloc");
- assert(! "buf_read_to_str: str_init_alloc");
+ if (! str_init_alloc_copy(dest, size, buf->ptr.pchar + buf->rpos)) {
+ err_puts("buf_read_to_str: str_init_alloc_copy");
+ assert(! "buf_read_to_str: str_init_alloc_copy");
return NULL;
}
r = buf_ignore(buf, size);
diff --git a/libkc3/buf_inspect.c b/libkc3/buf_inspect.c
index 3079607..3e20af6 100644
--- a/libkc3/buf_inspect.c
+++ b/libkc3/buf_inspect.c
@@ -377,6 +377,12 @@ sw buf_inspect_call (s_buf *buf, const s_call *call)
if (call->ident.module == &g_sym_KC3 &&
call->ident.sym == &g_sym_if_then_else)
return buf_inspect_call_if_then_else(buf, call);
+ if ((! call->ident.module ||
+ call->ident.module == &g_sym_KC3) &&
+ call->ident.sym == &g_sym_str &&
+ call->arguments &&
+ call->arguments->tag.type == TAG_LIST)
+ return buf_inspect_call_str(buf, call);
if (! operator_find(&call->ident, &op))
return -1;
if (op) {
@@ -428,6 +434,25 @@ sw buf_inspect_call_access (s_buf *buf, const s_call *call)
return result;
}
+sw buf_inspect_call_access_size (const s_call *call)
+{
+ s_list *args;
+ sw r;
+ sw result = 0;
+ s_tag *tag_sym;
+ assert(call);
+ args = call->arguments;
+ tag_sym = &args->next.data.list->tag;
+ if ((r = buf_inspect_tag_size(&args->tag)) < 0)
+ return r;
+ result += r;
+ result += strlen(".");
+ if ((r = buf_inspect_ident_sym_size(tag_sym->data.sym)) < 0)
+ return r;
+ result += r;
+ return result;
+}
+
sw buf_inspect_call_args (s_buf *buf, const s_list *args)
{
sw r;
@@ -741,8 +766,17 @@ sw buf_inspect_call_size (const s_call *call)
sw result = 0;
const s_sym *sym;
if (call->ident.module == &g_sym_KC3 &&
+ call->ident.sym == &g_sym_access)
+ return buf_inspect_call_access_size(call);
+ if (call->ident.module == &g_sym_KC3 &&
call->ident.sym == &g_sym_if_then_else)
return buf_inspect_call_if_then_else_size(call);
+ if ((! call->ident.module ||
+ call->ident.module == &g_sym_KC3) &&
+ call->ident.sym == &g_sym_str &&
+ call->arguments &&
+ call->arguments->tag.type == TAG_LIST)
+ return buf_inspect_call_str_size(call);
if (! operator_find(&call->ident, &op))
return -1;
if (op) {
@@ -848,6 +882,34 @@ sw buf_inspect_call_special_operator_size (const s_call *call)
return result;
}
+sw buf_inspect_call_str (s_buf *buf, const s_call *call)
+{
+ if ((call->ident.module &&
+ call->ident.module != &g_sym_KC3) ||
+ call->ident.sym != &g_sym_str ||
+ ! call->arguments ||
+ call->arguments->tag.type != TAG_LIST) {
+ err_puts("buf_inspect_call_str: invalid call");
+ assert(! "buf_inspect_call_str: invalid call");
+ return -1;
+ }
+ return buf_inspect_str_eval(buf, call->arguments->tag.data.list);
+}
+
+sw buf_inspect_call_str_size (const s_call *call)
+{
+ if ((call->ident.module &&
+ call->ident.module != &g_sym_KC3) ||
+ call->ident.sym != &g_sym_str ||
+ ! call->arguments ||
+ call->arguments->tag.type != TAG_LIST) {
+ err_puts("buf_inspect_call_str_size: invalid call");
+ assert(! "buf_inspect_call_str_size: invalid call");
+ return -1;
+ }
+ return buf_inspect_str_eval_size(call->arguments->tag.data.list);
+}
+
sw buf_inspect_cast (s_buf *buf, const s_call *call)
{
s_tag *arg;
@@ -2258,6 +2320,44 @@ sw buf_inspect_str_character_size (const character *c)
return size;
}
+sw buf_inspect_str_eval (s_buf *buf, const s_list *list)
+{
+ const s_list *l;
+ sw r;
+ sw result = 0;
+ const s_tag *tag;
+ if ((r = buf_write_1(buf, "\"")) < 0)
+ return r;
+ l = list;
+ while (l) {
+ if (l->tag.type == TAG_STR) {
+ if ((r = buf_write_str(buf, &l->tag.data.str)) < 0)
+ return r;
+ }
+ else {
+ if ((r = buf_write_1(buf, "#{")) < 0)
+ return r;
+ tag = &l->tag;
+ if (tag_is_cast(tag, &g_sym_Str))
+ tag = &list_next(tag->data.call.arguments)->tag;
+ if ((r = buf_inspect_tag(buf, tag)) < 0)
+ return r;
+ if ((r = buf_write_1(buf, "}")) < 0)
+ return r;
+ }
+ l = list_next(l);
+ }
+ if ((r = buf_write_1(buf, "\"")) < 0)
+ return r;
+ return result;
+}
+
+sw buf_inspect_str_eval_size (const s_list *list)
+{
+ (void) list;
+ return -1;
+}
+
/* keep in sync with buf_inspect_str_reserved_size */
sw buf_inspect_str_reserved (s_buf *buf, const s_str *str)
{
diff --git a/libkc3/buf_inspect.h b/libkc3/buf_inspect.h
index 69a7930..36bf206 100644
--- a/libkc3/buf_inspect.h
+++ b/libkc3/buf_inspect.h
@@ -75,6 +75,7 @@ sw buf_inspect_bool (s_buf *buf, const bool *b);
sw buf_inspect_bool_size (const bool *b);
sw buf_inspect_call (s_buf *buf, const s_call *call);
sw buf_inspect_call_access (s_buf *buf, const s_call *call);
+sw buf_inspect_call_access_size (const s_call *call);
sw buf_inspect_call_args (s_buf *buf, const s_list *args);
sw buf_inspect_call_brackets (s_buf *buf, const s_call *call);
sw buf_inspect_call_if_then_else (s_buf *buf, const s_call *call);
@@ -89,6 +90,8 @@ sw buf_inspect_call_paren_size (const s_call *call);
sw buf_inspect_call_size (const s_call *call);
sw buf_inspect_call_special_operator (s_buf *buf, const s_call *call);
sw buf_inspect_call_special_operator_size (const s_call *call);
+sw buf_inspect_call_str (s_buf *buf, const s_call *call);
+sw buf_inspect_call_str_size (const s_call *call);
sw buf_inspect_cast (s_buf *buf, const s_call *call);
sw buf_inspect_cast_size (const s_call *call);
sw buf_inspect_cfn (s_buf *buf, const s_cfn *cfn);
@@ -155,6 +158,9 @@ sw buf_inspect_str_byte (s_buf *buf, const u8 *byte);
sw buf_inspect_str_byte_size (const u8 *byte);
sw buf_inspect_str_character (s_buf *buf, const character *c);
sw buf_inspect_str_character_size (const character *c);
+sw buf_inspect_str_eval (s_buf *buf, const s_list *list);
+sw buf_inspect_str_eval_size (const s_list *list);
+sw buf_inspect_str (s_buf *buf, const s_str *str);
sw buf_inspect_str_reserved (s_buf *buf, const s_str *str);
sw buf_inspect_str_reserved_size (const s_str *str);
sw buf_inspect_str_size (const s_str *str);
diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index 1960d95..9d116e0 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -30,6 +30,7 @@
#include "fact.h"
#include "fn.h"
#include "fn_clause.h"
+#include "frame.h"
#include "ident.h"
#include "integer.h"
#include "list.h"
@@ -3361,19 +3362,19 @@ sw buf_parse_str_eval (s_buf *buf, s_tag *dest)
buf_save_init(buf, &save);
r = buf_parse_str(buf, &in);
if (r <= 0)
- goto save_clean;
+ goto clean;
result = r;
if (! str_parse_eval(&in, dest)) {
r = -2;
goto restore;
}
r = result;
- goto clean;
+ goto clean_in;
restore:
buf_save_restore_rpos(buf, &save);
- clean:
+ clean_in:
str_clean(&in);
- save_clean:
+ clean:
buf_save_clean(buf, &save);
return r;
}
@@ -3873,10 +3874,44 @@ sw buf_parse_tag_fn (s_buf *buf, s_tag *dest)
sw buf_parse_tag_ident (s_buf *buf, s_tag *dest)
{
sw r;
+ const s_tag *tag;
+ s_tag tmp = {0};
assert(buf);
assert(dest);
- if ((r = buf_parse_ident(buf, &dest->data.ident)) > 0)
- dest->type = TAG_IDENT;
+ tmp.type = TAG_IDENT;
+ r = buf_parse_ident(buf, &tmp.data.ident);
+ if (r <= 0)
+ return r;
+ if (! tmp.data.ident.module ||
+ tmp.data.ident.module == &g_sym_KC3) {
+ if (tmp.data.ident.sym == &g_sym___DIR__ ||
+ tmp.data.ident.sym == &g_sym___FILE__) {
+ if (true) {
+ err_write_1("buf_parse_tag_ident: ");
+ err_inspect_ident(&tmp.data.ident);
+ err_write_1("\n");
+ }
+ tag = frame_get(&g_kc3_env.global_frame, tmp.data.ident.sym);
+ if (! tag) {
+ err_write_1("buf_parse_tag_ident: frame_get: ");
+ err_inspect_sym(&tmp.data.ident.sym);
+ err_puts(" not found in global_frame");
+ assert(! "buf_parse_tag_ident: frame_get");
+ return -1;
+ }
+ if (! tag_init_copy(&tmp, tag)) {
+ err_puts("buf_parse_tag_ident: tag_init_copy");
+ assert(! "buf_parse_tag_ident: tag_init_copy");
+ return -1;
+ }
+ if (true) {
+ err_write_1("buf_parse_tag_ident: ");
+ err_inspect_tag(&tmp);
+ err_write_1("\n");
+ }
+ }
+ }
+ *dest = tmp;
return r;
}
@@ -4079,12 +4114,9 @@ sw buf_parse_tag_special_operator (s_buf *buf, s_tag *dest)
sw buf_parse_tag_str (s_buf *buf, s_tag *dest)
{
- sw r;
assert(buf);
assert(dest);
- if ((r = buf_parse_str(buf, &dest->data.str)) > 0)
- dest->type = TAG_STR;
- return r;
+ return buf_parse_str_eval(buf, dest);
}
sw buf_parse_tag_struct (s_buf *buf, s_tag *dest)
diff --git a/libkc3/env.c b/libkc3/env.c
index 472d9f8..0a76c46 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -1651,24 +1651,6 @@ bool env_eval_quote_unquote (s_env *env, const s_unquote *unquote, s_tag *dest)
return true;
}
-bool env_eval_str (s_env *env, const s_str *str, s_tag *dest)
-{
- bool r = true;
- s_tag tmp = {0};
- if (! str_parse_eval(str, &tmp)) {
- err_puts("env_eval_str: invalid Str");
- assert(! "env_eval_str: invalid Str");
- return false;
- }
- if (tmp.type == TAG_STR) {
- *dest = tmp;
- return true;
- }
- r = env_eval_tag(env, &tmp, dest);
- tag_clean(&tmp);
- return r;
-}
-
bool env_eval_struct (s_env *env, const s_struct *s, s_tag *dest)
{
uw i;
@@ -1775,8 +1757,6 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
return env_eval_map(env, &tag->data.map, dest);
case TAG_QUOTE:
return env_eval_quote(env, &tag->data.quote, dest);
- case TAG_STR:
- return env_eval_str(env, &tag->data.str, dest);
case TAG_STRUCT:
return env_eval_struct(env, &tag->data.struct_, dest);
case TAG_TUPLE:
@@ -1796,8 +1776,9 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
case TAG_S16:
case TAG_S32:
case TAG_S64:
- case TAG_SW:
+ case TAG_STR:
case TAG_STRUCT_TYPE:
+ case TAG_SW:
case TAG_SYM:
case TAG_U8:
case TAG_U16:
@@ -2213,6 +2194,14 @@ bool env_load (s_env *env, const s_str *path)
if (! file_dirname(path, &file_dir->data.str))
goto ko;
tag_init_str(file_path, NULL, path->size, path->ptr.pchar);
+ if (true) {
+ err_write_1("env_load: __DIR__ = ");
+ err_inspect_tag(file_dir);
+ err_write_1("\n");
+ err_write_1("env_load: __FILE__ = ");
+ err_inspect_tag(file_path);
+ err_write_1("\n");
+ }
while (1) {
if ((r = buf_parse_comments(&buf)) < 0)
break;
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index 441f73c..828df48 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -273,6 +273,22 @@ s_list ** kc3_search_modules (s_list **dest)
return env_search_modules(&g_kc3_env, dest);
}
+s_str * kc3_str (const s_tag *tag, s_str *dest)
+{
+ const s_sym *sym;
+ switch (tag->type) {
+ case TAG_LIST:
+ return str_init_concatenate_list(dest,
+ (const s_list **)
+ &tag->data.list);
+ case TAG_STR:
+ return str_init_copy(dest, &tag->data.str);
+ default:
+ sym = &g_sym_Str;
+ return str_init_cast(dest, &sym, tag);
+ }
+}
+
s_tag * kc3_while (const s_tag *cond, const s_tag *body, s_tag *dest)
{
return env_while(&g_kc3_env, cond, body, dest);
diff --git a/libkc3/list.c b/libkc3/list.c
index e9c1af1..51c30cf 100644
--- a/libkc3/list.c
+++ b/libkc3/list.c
@@ -271,11 +271,12 @@ s_list * list_new_list (s_list *x, s_list *next)
s_list * list_new_tag_copy (const s_tag *x, s_list *next)
{
s_list *dest;
- if ((dest = list_new(next))) {
- if (! tag_init_copy(&dest->tag, x)) {
- free(dest);
- return NULL;
- }
+ dest = list_new(next);
+ if (! dest)
+ return NULL;
+ if (! tag_init_copy(&dest->tag, x)) {
+ free(dest);
+ return NULL;
}
return dest;
}
diff --git a/libkc3/list_init.c b/libkc3/list_init.c
index a5f0294..1efdeef 100644
--- a/libkc3/list_init.c
+++ b/libkc3/list_init.c
@@ -377,13 +377,26 @@ s_list * list_init_str_1 (s_list *list, char *p_free, const char *p,
return list;
}
-s_list * list_init_str_cat (s_list *list, const s_str *a,
- const s_str *b, s_list *next)
+s_list * list_init_str_concatenate (s_list *list, const s_str *a,
+ const s_str *b, s_list *next)
{
s_list tmp = {0};
assert(list);
list_init(&tmp, next);
- if (! tag_init_str_cat(&tmp.tag, a, b))
+ if (! tag_init_str_concatenate(&tmp.tag, a, b))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
+s_list * list_init_str_concatenate_list (s_list *list,
+ const s_list **src,
+ s_list *next)
+{
+ s_list tmp = {0};
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_str_concatenate_list(&tmp.tag, src))
return NULL;
*list = tmp;
return list;
@@ -977,13 +990,28 @@ s_list * list_new_str_1 (char *p_free, const char *p, s_list *next)
return list;
}
-s_list * list_new_str_cat (const s_str *a, const s_str *b, s_list *next)
+s_list * list_new_str_concatenate (const s_str *a, const s_str *b,
+ s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_str_concatenate(&list->tag, a, b)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
+s_list * list_new_str_concatenate_list (const s_list **src,
+ s_list *next)
{
s_list *list;
list = list_new(next);
if (! list)
return NULL;
- if (! tag_init_str_cat(&list->tag, a, b)) {
+ if (! tag_init_str_concatenate_list(&list->tag, src)) {
free(list);
return NULL;
}
diff --git a/libkc3/list_init.h b/libkc3/list_init.h
index 0ab1122..f7c9bd3 100644
--- a/libkc3/list_init.h
+++ b/libkc3/list_init.h
@@ -58,8 +58,11 @@ s_list * list_init_str (s_list *list, char *p_free, uw size,
const char *p, s_list *next);
s_list * list_init_str_1 (s_list *list, char *p_free, const char *p,
s_list *next);
-s_list * list_init_str_cat (s_list *list, const s_str *a,
- const s_str *b, s_list *next);
+s_list * list_init_str_concatenate (s_list *list, const s_str *a,
+ const s_str *b, s_list *next);
+s_list * list_init_str_concatenate_list (s_list *list,
+ const s_list **src,
+ s_list *next);
s_list * list_init_str_empty (s_list *list, s_list *next);
s_list * list_init_struct (s_list *list, const s_sym *module,
s_list *next);
@@ -124,8 +127,10 @@ s_list * list_new_s64 (s64 i, s_list *next);
s_list * list_new_str (char *p_free, uw size, const char *p,
s_list *next);
s_list * list_new_str_1 (char *p_free, const char *p, s_list *next);
-s_list * list_new_str_cat (const s_str *a, const s_str *b,
- s_list *next);
+s_list * list_new_str_concatenate (const s_str *a, const s_str *b,
+ s_list *next);
+s_list * list_new_str_concatenate_list (const s_list **src,
+ s_list *next);
s_list * list_new_str_empty (s_list *next);
s_list * list_new_struct (const s_sym *module, s_list *next);
s_list * list_new_struct_with_data (const s_sym *module, void *data,
@@ -184,7 +189,9 @@ s_list * list_s32 (s_list *list, s32 i);
s_list * list_s64 (s_list *list, s64 i);
s_list * list_str (s_list *list, char *p_free, uw size, const char *p);
s_list * list_str_1 (s_list *list, char *p_free, const char *p);
-s_list * list_str_cat (s_list *list, const s_str *a, const s_str *b);
+s_list * list_str_concatenate (s_list *list, const s_str *a,
+ const s_str *b);
+s_list * list_str_concatenate_list (s_list *list, const s_list **src);
s_list * list_str_empty (s_list *list);
s_list * list_struct (s_list *list, const s_sym *module);
s_list * list_struct_with_data (s_list *list, const s_sym *module,
diff --git a/libkc3/str.c b/libkc3/str.c
index 86eb67f..42e2476 100644
--- a/libkc3/str.c
+++ b/libkc3/str.c
@@ -201,8 +201,20 @@ s_str * str_init_1 (s_str *str, char *free, const char *p)
*str = tmp;
return str;
}
+s_str * str_init_alloc (s_str *str, uw size)
+{
+ s_str tmp = {0};
+ assert(str);
+ tmp.free.p = alloc(size + 1);
+ if (! tmp.free.p)
+ return NULL;
+ tmp.size = size;
+ tmp.ptr.p = tmp.free.p;
+ *str = tmp;
+ return str;
+}
-s_str * str_init_alloc (s_str *str, uw size, const char *p)
+s_str * str_init_alloc_copy (s_str *str, uw size, const char *p)
{
s_str tmp = {0};
assert(str);
@@ -279,7 +291,20 @@ s_str * str_init_cast (s_str *str, const s_sym * const *type,
return NULL;
}
-s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b)
+s_str * str_init_character (s_str *str, const character src)
+{
+ char b[4];
+ s_buf buf;
+ buf_init(&buf, false, sizeof(b), b);
+ if (buf_write_character_utf8(&buf, src) < 0)
+ return NULL;
+ if (! buf_read_to_str(&buf, str))
+ return NULL;
+ return str;
+}
+
+s_str * str_init_concatenate (s_str *str, const s_str *a,
+ const s_str *b)
{
s_str tmp = {0};
assert(str);
@@ -298,15 +323,39 @@ s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b)
return str;
}
-s_str * str_init_character (s_str *str, const character src)
+s_str * str_init_concatenate_list (s_str *str,
+ const s_list **list)
{
- char b[4];
- s_buf buf;
- buf_init(&buf, false, sizeof(b), b);
- if (buf_write_character_utf8(&buf, src) < 0)
- return NULL;
- if (! buf_read_to_str(&buf, str))
+ const s_list *l;
+ char *p;
+ s_str tmp = {0};
+ l = *list;
+ while (l) {
+ if (l->tag.type != TAG_STR) {
+ err_write_1("str_init_concatenate_list: not a Str: ");
+ err_inspect_tag(&l->tag);
+ err_write_1("\n");
+ return NULL;
+ }
+ tmp.size += l->tag.data.str.size;
+ l = list_next(l);
+ }
+ if (! str_init_alloc(&tmp, tmp.size))
return NULL;
+ p = tmp.free.pchar;
+ l = *list;
+ while (l) {
+ if (p + l->tag.data.str.size > tmp.free.pchar + tmp.size) {
+ err_puts("str_init_concatenate_list: buffer overflow");
+ assert(! "str_init_concatenate_list: buffer overflow");
+ str_clean(&tmp);
+ return NULL;
+ }
+ memcpy(p, l->tag.data.str.ptr.p, l->tag.data.str.size);
+ p += l->tag.data.str.size;
+ l = list_next(l);
+ }
+ *str = tmp;
return str;
}
@@ -540,38 +589,37 @@ s_str * str_new_vf (const char *fmt, va_list ap)
bool str_parse_eval (const s_str *str, s_tag *dest)
{
+ s_tag *arg;
character c;
s_buf in_buf;
- s_list *list;
- s_list **list_end;
- s_list *list_start = NULL;
- s_ident op;
+ s_list *l;
+ s_list **tail;
+ s_list *list = NULL;
s_buf out_buf = {0};
sw r;
- s_tag *right;
+ s_tag tag;
s_tag tmp = {0};
- s_tag tmp1 = {0};
buf_init_str(&in_buf, false, (s_str *) str);
if (! buf_init_alloc(&out_buf, str->size))
goto restore;
- list_end = &list_start;
+ tail = &list;
while (1) {
r = buf_read_1(&in_buf, "#{");
if (r < 0)
break;
if (r > 0) {
if (out_buf.wpos > 0) {
- *list_end = list_new(NULL);
- (*list_end)->tag.type = TAG_STR;
- buf_read_to_str(&out_buf, &(*list_end)->tag.data.str);
- list_end = &(*list_end)->next.data.list;
+ *tail = list_new(NULL);
+ (*tail)->tag.type = TAG_STR;
+ buf_read_to_str(&out_buf, &(*tail)->tag.data.str);
+ tail = &(*tail)->next.data.list;
out_buf.rpos = out_buf.wpos = 0;
}
- *list_end = list_new(NULL);
- r = buf_parse_tag(&in_buf, &(*list_end)->tag);
+ *tail = list_new(NULL);
+ r = buf_parse_tag(&in_buf, &(*tail)->tag);
if (r <= 0)
goto restore;
- list_end = &(*list_end)->next.data.list;
+ tail = &(*tail)->next.data.list;
r = buf_ignore_spaces(&in_buf);
if (r < 0)
goto restore;
@@ -591,53 +639,44 @@ bool str_parse_eval (const s_str *str, s_tag *dest)
goto restore;
}
if (out_buf.wpos > 0) {
- *list_end = list_new(NULL);
- (*list_end)->tag.type = TAG_STR;
- buf_read_to_str(&out_buf, &(*list_end)->tag.data.str);
+ *tail = list_new(NULL);
+ (*tail)->tag.type = TAG_STR;
+ buf_read_to_str(&out_buf, &(*tail)->tag.data.str);
}
- if (! list_start)
+ if (! list)
tag_init_str_empty(&tmp);
+ else if (list->tag.type == TAG_STR &&
+ ! list_next(list)) {
+ tmp = list->tag;
+ free(list);
+ }
else {
- list = list_start;
- if (list->tag.type == TAG_STR)
- tmp = list->tag;
- else {
- if (! tag_init_call_cast(&tmp, &g_sym_Str))
- goto restore;
- list_next(tmp.data.call.arguments)->tag = list->tag;
- }
- list = list_next(list);
- while (list) {
- tmp1 = (s_tag) {0};
- tmp1.type = TAG_CALL;
- if (! call_init_op(&tmp1.data.call))
- goto restore;
- op.module = &g_sym_KC3;
- op.sym = &g_sym__plus;
- operator_resolve(&op, 2, &tmp1.data.call.ident);
- tmp1.data.call.arguments->tag = tmp;
- right = &tmp1.data.call.arguments->next.data.list->tag;
- if (list->tag.type == TAG_STR)
- *right = list->tag;
- else {
- if (! tag_init_call_cast(right, &g_sym_Str))
- goto restore;
- list_next(right->data.call.arguments)->tag = list->tag;
- }
- tmp = tmp1;
- list = list_next(list);
+ tag_init_call(&tmp);
+ ident_init(&tmp.data.call.ident, &g_sym_KC3, &g_sym_str);
+ tmp.data.call.arguments = list_new(NULL);
+ l = list;
+ while (l) {
+ if (l->tag.type == TAG_STR ||
+ (l->tag.type == TAG_CALL &&
+ l->tag.data.call.ident.module == &g_sym_Str &&
+ l->tag.data.call.ident.sym == &g_sym_cast))
+ goto next;
+ tag_init_call_cast(&tag, &g_sym_Str);
+ arg = &list_next(tag.data.call.arguments)->tag;
+ tag_init_copy(arg, &l->tag);
+ l->tag = tag;
+ next:
+ l = list_next(l);
}
+ arg = &tmp.data.call.arguments->tag;
+ arg->type = TAG_LIST;
+ arg->data.list = list;
}
*dest = tmp;
- while (list_start) {
- list = list_next(list_start);
- free(list_start);
- list_start = list;
- }
buf_clean(&out_buf);
return true;
restore:
- list_delete_all(list_start);
+ list_delete_all(list);
buf_clean(&out_buf);
return false;
}
diff --git a/libkc3/str.h b/libkc3/str.h
index 4909682..a0c0136 100644
--- a/libkc3/str.h
+++ b/libkc3/str.h
@@ -39,10 +39,15 @@
void str_clean (s_str *str);
s_str * str_init (s_str *str, char *free, uw size, const char *p);
s_str * str_init_1 (s_str *str, char *free, const char *p);
-s_str * str_init_alloc (s_str *str, uw size, const char *p);
+s_str * str_init_1_alloc (s_str *str, const char *p);
+s_str * str_init_alloc (s_str *str, uw size);
+s_str * str_init_alloc_copy (s_str *str, uw size, const char *p);
s_str * str_init_cast (s_str *str, const s_sym * const *type,
const s_tag *tag);
-s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b);
+s_str * str_init_concatenate (s_str *str, const s_str *a,
+ const s_str *b);
+s_str * str_init_concatenate_list (s_str *str,
+ const s_list **list);
s_str * str_init_character (s_str *str, const character src);
s_str * str_init_copy (s_str *str, const s_str *src);
s_str * str_init_copy_1 (s_str *str, const char *p);
diff --git a/libkc3/sym.c b/libkc3/sym.c
index 0411c30..6e05ef3 100644
--- a/libkc3/sym.c
+++ b/libkc3/sym.c
@@ -105,6 +105,7 @@ const s_sym g_sym_rwx = {{{NULL}, 3, {"rwx"}}};
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_str = {{{NULL}, 3, {"str"}}};
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"}}};
@@ -397,6 +398,7 @@ void sym_init_g_sym (void)
sym_register(&g_sym_rwx, NULL);
sym_register(&g_sym_rx, NULL);
sym_register(&g_sym_special_operator, NULL);
+ sym_register(&g_sym_str, NULL);
sym_register(&g_sym_struct_type, NULL);
sym_register(&g_sym_sym, NULL);
sym_register(&g_sym_symbol, NULL);
diff --git a/libkc3/sym.h b/libkc3/sym.h
index 8615b72..6260132 100644
--- a/libkc3/sym.h
+++ b/libkc3/sym.h
@@ -106,6 +106,7 @@ extern const s_sym g_sym_rw;
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_str;
extern const s_sym g_sym_struct_type;
extern const s_sym g_sym_sym;
extern const s_sym g_sym_symbol;
diff --git a/libkc3/tag.c b/libkc3/tag.c
index 49ac9c2..00484f8 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -590,6 +590,16 @@ bool tag_is_bound_var (const s_tag *tag)
tag->type != TAG_VAR);
}
+bool tag_is_cast (const s_tag *tag, const s_sym *type)
+{
+ assert(tag);
+ return (tag &&
+ type &&
+ tag->type == TAG_CALL &&
+ tag->data.call.ident.module == type &&
+ tag->data.call.ident.sym == &g_sym_cast);
+}
+
bool tag_is_number (const s_tag *tag)
{
assert(tag);
diff --git a/libkc3/tag.h b/libkc3/tag.h
index d5bee99..6754ad7 100644
--- a/libkc3/tag.h
+++ b/libkc3/tag.h
@@ -47,6 +47,7 @@ uw * tag_hash_uw (const s_tag *tag, uw *dest);
bool tag_ident_is_bound (const s_tag *tag);
bool tag_is_alist (const s_tag *tag);
bool tag_is_bound_var (const s_tag *tag);
+bool tag_is_cast (const s_tag *tag, const s_sym *type);
bool tag_is_number (const s_tag *tag);
bool * tag_is_unbound_var (const s_tag *tag, bool *dest);
bool tag_is_zero(const s_tag *tag);
diff --git a/libkc3/tag_add.c b/libkc3/tag_add.c
index cd9b707..8d1cbcf 100644
--- a/libkc3/tag_add.c
+++ b/libkc3/tag_add.c
@@ -1615,7 +1615,7 @@ s_tag * tag_add (const s_tag *a, const s_tag *b, s_tag *dest)
case TAG_STR:
switch (b->type) {
case TAG_STR:
- return tag_init_str_cat(dest, &a->data.str, &b->data.str);
+ return tag_init_str_concatenate(dest, &a->data.str, &b->data.str);
default:
goto ko;
}
diff --git a/libkc3/tag_init.c b/libkc3/tag_init.c
index 0b4dbd9..30eb29b 100644
--- a/libkc3/tag_init.c
+++ b/libkc3/tag_init.c
@@ -371,12 +371,24 @@ s_tag * tag_init_str_1 (s_tag *tag, char *p_free, const char *p)
return tag;
}
-s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b)
+s_tag * tag_init_str_concatenate (s_tag *tag, const s_str *a,
+ const s_str *b)
{
s_tag tmp = {0};
assert(tag);
tmp.type = TAG_STR;
- if (! str_init_cat(&tmp.data.str, a, b))
+ if (! str_init_concatenate(&tmp.data.str, a, b))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
+s_tag * tag_init_str_concatenate_list (s_tag *tag, const s_list **src)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_concatenate_list(&tmp.data.str, src))
return NULL;
*tag = tmp;
return tag;
@@ -964,14 +976,28 @@ s_tag * tag_new_str_1 (char *p_free, const char *p)
return tag;
}
-s_tag * tag_new_str_cat (const s_str *a, const s_str *b)
+s_tag * tag_new_str_concatenate (const s_str *a, const s_str *b)
{
s_tag *tag;
tag = alloc(sizeof(s_tag));
if (! tag)
return NULL;
tag->type = TAG_STR;
- if (! str_init_cat(&tag->data.str, a, b)) {
+ if (! str_init_concatenate(&tag->data.str, a, b)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
+s_tag * tag_new_str_concatenate_list (const s_list **src)
+{
+ s_tag *tag;
+ tag = alloc(sizeof(s_tag));
+ if (! tag)
+ return NULL;
+ tag->type = TAG_STR;
+ if (! str_init_concatenate_list(&tag->data.str, src)) {
free(tag);
return NULL;
}
@@ -1556,13 +1582,25 @@ s_tag * tag_str_1 (s_tag *tag, char *p_free, const char *p)
return tag;
}
-s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b)
+s_tag * tag_str_concatenate (s_tag *tag, const s_str *a, const s_str *b)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_concatenate(&tmp.data.str, a, b))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
+s_tag * tag_str_concatenate_list (s_tag *tag, const s_list **src)
{
s_tag tmp = {0};
assert(tag);
tag_clean(tag);
tmp.type = TAG_STR;
- if (! str_init_cat(&tmp.data.str, a, b))
+ if (! str_init_concatenate_list(&tmp.data.str, src))
return NULL;
*tag = tmp;
return tag;
diff --git a/libkc3/tag_init.h b/libkc3/tag_init.h
index 6453eab..a42a0c4 100644
--- a/libkc3/tag_init.h
+++ b/libkc3/tag_init.h
@@ -49,7 +49,9 @@ s_tag * tag_init_s32 (s_tag *tag, s32 i);
s_tag * tag_init_s64 (s_tag *tag, s64 i);
s_tag * tag_init_str (s_tag *tag, char *p_free, uw size, const char *p);
s_tag * tag_init_str_1 (s_tag *tag, char *p_free, const char *p);
-s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b);
+s_tag * tag_init_str_concatenate (s_tag *tag, const s_str *a,
+ const s_str *b);
+s_tag * tag_init_str_concatenate_list (s_tag *tag, const s_list **src);
s_tag * tag_init_str_empty (s_tag *tag);
s_tag * tag_init_struct (s_tag *tag, const s_sym *module);
s_tag * tag_init_struct_with_data (s_tag *tag, const s_sym *module,
@@ -107,7 +109,8 @@ s_tag * tag_new_s32 (s32 i);
s_tag * tag_new_s64 (s64 i);
s_tag * tag_new_str (char *p_free, uw size, const char *p);
s_tag * tag_new_str_1 (char *p_free, const char *p);
-s_tag * tag_new_str_cat (const s_str *a, const s_str *b);
+s_tag * tag_new_str_concatenate (const s_str *a, const s_str *b);
+s_tag * tag_new_str_concatenate_list (const s_list **src);
s_tag * tag_new_str_empty (void);
s_tag * tag_new_struct (const s_sym *module);
s_tag * tag_new_struct_with_data (const s_sym *module, void *data,
@@ -163,7 +166,9 @@ s_tag * tag_s32 (s_tag *tag, s32 i);
s_tag * tag_s64 (s_tag *tag, s64 i);
s_tag * tag_str (s_tag *tag, char *p_free, uw size, const char *p);
s_tag * tag_str_1 (s_tag *tag, char *p_free, const char *p);
-s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b);
+s_tag * tag_str_concatenate (s_tag *tag, const s_str *a,
+ const s_str *b);
+s_tag * tag_str_concatenate_list (s_tag *tag, const s_list **src);
s_tag * tag_str_empty (s_tag *tag);
s_tag * tag_struct (s_tag *tag, const s_sym *module);
s_tag * tag_struct_with_data (s_tag *tag, const s_sym *module,
diff --git a/libkc3/tag_init.rb b/libkc3/tag_init.rb
index e233c06..4e16205 100644
--- a/libkc3/tag_init.rb
+++ b/libkc3/tag_init.rb
@@ -368,9 +368,11 @@ class TagInitList
TagInit.new("str", "1", "TAG_STR", :init_mode_init,
[Arg.new("char *", "p_free"),
Arg.new("const char *", "p")]),
- TagInit.new("str", "cat", "TAG_STR", :init_mode_init,
+ TagInit.new("str", "concatenate", "TAG_STR", :init_mode_init,
[Arg.new("const s_str *", "a"),
Arg.new("const s_str *", "b")]),
+ TagInit.new("str", "concatenate_list", "TAG_STR", :init_mode_init,
+ [Arg.new("const s_list **", "src")]),
TagInit.new("str", "empty", "TAG_STR", :init_mode_init, []),
TagInit.new("struct", "TAG_STRUCT", :init_mode_init,
[Arg.new("const s_sym *", "module")]),