diff --git a/lib/kc3/0.1/kc3.facts b/lib/kc3/0.1/kc3.facts
index 20d2518..021d2f8 100644
--- a/lib/kc3/0.1/kc3.facts
+++ b/lib/kc3/0.1/kc3.facts
@@ -12,7 +12,7 @@ add {KC3, :operator, KC3.operator_brackets}
replace {KC3.operator_brackets, :is_a, :operator}
replace {KC3.operator_brackets, :sym, :"[]"}
replace {KC3.operator_brackets, :arity, 2}
-replace {KC3.operator_brackets, :symbol_value, cfn Tag "tag_brackets" (Tag, Tag, Result)}
+replace {KC3.operator_brackets, :symbol_value, cfn Tag "kc3_access" (Tag, List, Result)}
replace {KC3.operator_brackets, :operator_precedence, 13}
replace {KC3.operator_brackets, :operator_associativity, :left}
add {KC3, :operator, KC3.operator_bnot}
@@ -252,7 +252,7 @@ replace {KC3.module, :symbol_value, cfn Sym "kc3_module" (Result)}
add {KC3, :symbol, KC3.search_modules}
replace {KC3.search_modules, :symbol_value, cfn List "kc3_search_modules" (Result)}
add {KC3, :symbol, KC3.access}
-replace {KC3.access, :symbol_value, cfn Tag "kc3_access" (Tag, Sym, Result)}
+replace {KC3.access, :symbol_value, cfn Tag "kc3_access" (Tag, List, Result)}
add {KC3, :symbol, KC3.let}
replace {KC3.let, :arity, 2}
replace {KC3.let, :is_a, :special_operator}
diff --git a/libkc3/array.c b/libkc3/array.c
index 7cd29dc..24d210e 100644
--- a/libkc3/array.c
+++ b/libkc3/array.c
@@ -19,9 +19,25 @@
#include "buf_parse.h"
#include "data.h"
#include "io.h"
+#include "list.h"
#include "sym.h"
#include "tag.h"
+s_tag * array_access (const s_array *a, const s_list * const *key,
+ s_tag *dest)
+{
+ s_array address;
+ s_tag *r;
+ if (! list_to_array(*key, &g_sym_Uw_brackets, &address)) {
+ err_puts("array_access: list_to_array");
+ assert(! "array_access: list_to_array");
+ return NULL;
+ }
+ r = array_data_tag(a, &address, dest);
+ array_clean(&address);
+ return r;
+}
+
s_array * array_allocate (s_array *a)
{
assert(a);
@@ -107,43 +123,33 @@ s_array * array_data_set (s_array *a, const uw *address,
return NULL;
}
-s_tag * array_data_tag (const s_tag *a, const s_tag *address,
+s_tag * array_data_tag (const s_array *a, const s_array *address,
s_tag *dest)
{
void *a_data;
void *tmp_data;
s_tag tmp = {0};
- if (a->type != TAG_ARRAY) {
- err_puts("array_data_tag: not an array");
- assert(! "array_data_tag: not an array");
- return NULL;
- }
- if (address->type != TAG_ARRAY) {
- err_puts("array_data_tag: address: not an array");
- assert(! "array_data_tag: address: not an array");
- return NULL;
- }
- if (address->data.array.dimension != 1) {
+ if (address->dimension != 1) {
err_puts("array_data_tag: address dimension != 1");
assert(! "array_data_tag: address dimension != 1");
return NULL;
}
- if (address->data.array.dimensions[0].count !=
- a->data.array.dimension) {
+ if (address->dimensions[0].count !=
+ a->dimension) {
err_write_1("array_data_tag: address dimension mismatch: ");
- err_inspect_uw(&address->data.array.dimensions[0].count);
+ err_inspect_uw(&address->dimensions[0].count);
err_write_1(" != ");
- err_inspect_uw(&a->data.array.dimension);
+ err_inspect_uw(&a->dimension);
err_write_1("\n");
assert(! "array_data_tag: address dimension mismatch");
return NULL;
}
- a_data = array_data(&a->data.array, address->data.array.data);
+ a_data = array_data(a, address->data);
if (! a_data)
return NULL;
- if (! sym_to_tag_type(a->data.array.element_type, &tmp.type) ||
- ! tag_to_pointer(&tmp, a->data.array.element_type, &tmp_data) ||
- ! data_init_copy(a->data.array.element_type, tmp_data, a_data))
+ if (! sym_to_tag_type(a->element_type, &tmp.type) ||
+ ! tag_to_pointer(&tmp, a->element_type, &tmp_data) ||
+ ! data_init_copy(a->element_type, tmp_data, a_data))
return NULL;
*dest = tmp;
return dest;
diff --git a/libkc3/array.h b/libkc3/array.h
index 2645649..84bd87f 100644
--- a/libkc3/array.h
+++ b/libkc3/array.h
@@ -28,10 +28,13 @@ s_array * array_init_void (s_array *array);
/* Observers */
void * array_data (const s_array *a, const uw *address);
-s_tag * array_data_tag (const s_tag *a, const s_tag *address,
+s_tag * array_data_tag (const s_array *a,
+ const s_array *address,
s_tag *dest);
/* Operators */
+s_tag * array_access (const s_array *a, const s_list * const *key,
+ s_tag *dest);
s_array * array_allocate (s_array *a);
s_array * array_data_set (s_array *a, const uw *address,
const void *data);
diff --git a/libkc3/buf_inspect.c b/libkc3/buf_inspect.c
index fd7cc20..2de9462 100644
--- a/libkc3/buf_inspect.c
+++ b/libkc3/buf_inspect.c
@@ -523,21 +523,35 @@ sw buf_inspect_call_access (s_buf *buf, const s_call *call)
s_list *args;
sw r;
sw result = 0;
- s_tag *tag_sym;
+ s_list *key;
assert(buf);
assert(call);
args = call->arguments;
- tag_sym = &args->next.data.list->tag;
if ((r = buf_inspect_tag(buf, &args->tag)) < 0)
return r;
result += r;
- if ((r = buf_write_1(buf, ".")) < 0)
- return r;
- result += r;
- if ((r = buf_inspect_ident_sym(buf, tag_sym->data.sym)) < 0)
- return r;
- result += r;
+ key = list_next(args);
+ if (key->tag.type != TAG_LIST)
+ goto invalid_key;
+ key = key->tag.data.list;
+ while (key) {
+ if (key->tag.type != TAG_SYM)
+ goto invalid_key;
+ if ((r = buf_write_1(buf, ".")) < 0)
+ return r;
+ result += r;
+ if ((r = buf_inspect_ident_sym(buf, key->tag.data.sym)) < 0)
+ return r;
+ result += r;
+ key = list_next(key);
+ }
return result;
+ invalid_key:
+ err_write_1("buf_inspect_call_access: invalid key: ");
+ err_inspect_tag(&list_next(args)->tag);
+ err_write_1("\n");
+ assert(! "buf_inspect_call_access: invalid key");
+ return -1;
}
sw buf_inspect_call_access_size (s_pretty *pretty, const s_call *call)
@@ -609,41 +623,34 @@ sw buf_inspect_call_args_size (s_pretty *pretty, const s_list *args)
sw buf_inspect_call_brackets (s_buf *buf, const s_call *call)
{
- s_array *address;
- s_tag *array;
- const s_sym *buf_inspect_type;
- uw i = 0;
+ s_list *key;
s_list *next;
sw r;
sw result = 0;
+ s_tag *tag;
assert(buf);
assert(call);
assert(call->arguments);
next = list_next(call->arguments);
assert(next);
assert(! list_next(next));
- assert(next->tag.type == TAG_ARRAY);
- address = &next->tag.data.array;
- assert(address->dimension == 1);
- array = &call->arguments->tag;
- if ((r = buf_inspect_tag(buf, array)) < 0)
+ assert(next->tag.type == TAG_LIST);
+ key = next->tag.data.list;
+ tag = &call->arguments->tag;
+ if ((r = buf_inspect_tag(buf, tag)) < 0)
return r;
result += r;
- while (i < address->dimensions[0].count) {
+ while (key) {
if ((r = buf_write_1(buf, "[")) < 0)
return r;
result += r;
- buf_inspect_type = g_buf_inspect_type;
- g_buf_inspect_type = &g_sym_Uw;
- if ((r = buf_inspect_uw(buf, ((uw *) address->data)
- + i)) < 0)
+ if ((r = buf_inspect_tag(buf, &key->tag)) < 0)
return r;
result += r;
- g_buf_inspect_type = buf_inspect_type;
if ((r = buf_write_1(buf, "]")) < 0)
return r;
result += r;
- i++;
+ key = list_next(key);
}
return result;
}
diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index 50c71a4..b1bdc04 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -628,7 +628,6 @@ sw buf_parse_bool (s_buf *buf, bool *p)
sw buf_parse_brackets (s_buf *buf, s_call *dest)
{
s_tag *arg_addr;
- uw d;
uw address = 0;
s_list *addr = NULL;
s_list **addr_last = &addr;
@@ -641,7 +640,7 @@ sw buf_parse_brackets (s_buf *buf, s_call *dest)
buf_save_init(buf, &save);
tmp.arguments = list_new(list_new(NULL));
arg_addr = &(list_next(tmp.arguments)->tag);
- if ((r = buf_parse_tag_primary(buf, &tmp.arguments->tag)) <= 0)
+ if ((r = buf_parse_tag_primary_2(buf, &tmp.arguments->tag)) <= 0)
goto restore;
result += r;
while (1) {
@@ -653,31 +652,29 @@ sw buf_parse_brackets (s_buf *buf, s_call *dest)
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
- if ((r = buf_parse_uw(buf, &d)) <= 0)
+ *addr_last = list_new(NULL);
+ if ((r = buf_parse_tag(buf, &(*addr_last)->tag)) <= 0)
goto restore;
result += r;
+ addr_last = &(*addr_last)->next.data.list;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
if ((r = buf_read_1(buf, "]")) <= 0)
goto restore;
result += r;
- *addr_last = list_new(NULL);
- tag_init_uw(&(*addr_last)->tag, d);
- addr_last = &(*addr_last)->next.data.list;
address++;
}
if (! address) {
goto restore;
}
- arg_addr->type = TAG_ARRAY;
- if (! list_to_array(addr, &g_sym_Uw_brackets, &arg_addr->data.array))
- goto restore;
ident_init(&tmp.ident, NULL, &g_sym__brackets);
if (! operator_resolve(&tmp.ident, 2, &tmp.ident)) {
err_puts("buf_parse_brackets: could not resolve operator []");
goto restore;
}
+ arg_addr->type = TAG_LIST;
+ arg_addr->data.list = addr;
*dest = tmp;
r = result;
goto clean;
@@ -685,8 +682,8 @@ sw buf_parse_brackets (s_buf *buf, s_call *dest)
r = 0;
buf_save_restore_rpos(buf, &save);
call_clean(&tmp);
- clean:
list_delete_all(addr);
+ clean:
buf_save_clean(buf, &save);
return r;
}
@@ -718,6 +715,56 @@ sw buf_parse_call (s_buf *buf, s_call *dest)
return r;
}
+sw buf_parse_call_access (s_buf *buf, s_call *dest)
+{
+ s_list **k;
+ s_list *key = NULL;
+ sw r;
+ sw result = 0;
+ s_buf_save save;
+ s_call tmp = {0};
+ assert(buf);
+ assert(dest);
+ buf_save_init(buf, &save);
+ if (! call_init_op(&tmp))
+ return -1;
+ tmp.ident.module = &g_sym_KC3;
+ tmp.ident.sym = &g_sym_access;
+ r = buf_parse_tag_primary_3(buf, &tmp.arguments->tag);
+ if (r <= 0)
+ goto restore;
+ result += r;
+ k = &key;
+ while (1) {
+ if ((r = buf_read_1(buf, ".")) <= 0)
+ goto restore;
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ *k = list_new(NULL);
+ r = buf_parse_tag_ident_sym(buf, &(*k)->tag);
+ k = &(*k)->next.data.list;
+ if (r <= 0)
+ goto restore;
+ result += r;
+ if ((r = buf_peek_1(buf, ".")) < 0)
+ goto restore;
+ if (r == 0)
+ break;
+ }
+ tag_init_list(&list_next(tmp.arguments)->tag, key);
+ *dest = tmp;
+ r = result;
+ goto clean;
+ restore:
+ call_clean(&tmp);
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
+}
+
sw buf_parse_call_args_paren (s_buf *buf, s_call *dest)
{
s_list **args;
@@ -812,66 +859,6 @@ sw buf_parse_call_args_paren (s_buf *buf, s_call *dest)
return r;
}
-sw buf_parse_call_access (s_buf *buf, s_call *dest)
-{
- sw r;
- sw result = 0;
- s_buf_save save;
- s_tag *tag_left;
- s_tag *tag_sym;
- s_call tmp = {0};
- s_call tmp2 = {0};
- assert(buf);
- assert(dest);
- if (! call_init_op(&tmp))
- return -1;
- buf_save_init(buf, &save);
- tag_left = &tmp.arguments->tag;
- tmp.ident.module = &g_sym_KC3;
- tmp.ident.sym = &g_sym_access;
- r = buf_parse_tag_primary_2(buf, &tmp.arguments->tag);
- if (r <= 0)
- goto restore;
- result += r;
- while (1) {
- if ((r = buf_read_1(buf, ".")) <= 0)
- goto restore;
- result += r;
- if ((r = buf_ignore_spaces(buf)) < 0)
- goto restore;
- result += r;
- tag_sym = &tmp.arguments->next.data.list->tag;
- tag_sym->type = TAG_SYM;
- r = buf_parse_ident_sym(buf, &tag_sym->data.sym);
- if (r <= 0)
- goto restore;
- result += r;
- if ((r = buf_peek_1(buf, ".")) < 0)
- goto restore;
- if (r == 0)
- break;
- if (! call_init_op(&tmp2)) {
- r = -1;
- goto restore;
- }
- tmp2.ident.module = &g_sym_KC3;
- tmp2.ident.sym = &g_sym_access;
- tag_left = &tmp2.arguments->tag;
- tag_left->type = TAG_CALL;
- tag_left->data.call = tmp;
- tmp = tmp2;
- }
- *dest = tmp;
- r = result;
- goto clean;
- restore:
- call_clean(&tmp);
- buf_save_restore_rpos(buf, &save);
- clean:
- buf_save_clean(buf, &save);
- return r;
-}
-
sw buf_parse_call_op (s_buf *buf, s_call *dest)
{
s_ident next_op;
@@ -3678,7 +3665,6 @@ sw buf_parse_tag (s_buf *buf, s_tag *dest)
result += r;
}
if ((r = buf_parse_tag_special_operator(buf, dest)) != 0 ||
- (r = buf_parse_tag_brackets(buf, dest)) != 0 ||
(r = buf_parse_tag_call_op(buf, dest)) != 0 ||
(r = buf_parse_tag_tuple(buf, dest)) != 0 ||
(r = buf_parse_tag_block(buf, dest)) != 0 ||
@@ -3889,6 +3875,16 @@ sw buf_parse_tag_ident (s_buf *buf, s_tag *dest)
return r;
}
+sw buf_parse_tag_ident_sym (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ assert(buf);
+ assert(dest);
+ if ((r = buf_parse_ident_sym(buf, &dest->data.sym)) > 0)
+ dest->type = TAG_SYM;
+ return r;
+}
+
sw buf_parse_tag_if (s_buf *buf, s_tag *dest)
{
sw r;
@@ -3977,8 +3973,7 @@ sw buf_parse_tag_primary (s_buf *buf, s_tag *dest)
goto restore;
result += r;
}
- if ((r = buf_parse_tag_call_access(buf, dest)) != 0 ||
- (r = buf_parse_tag_call_op_unary(buf, dest)) != 0 ||
+ if ((r = buf_parse_tag_brackets(buf, dest)) != 0 ||
(r = buf_parse_tag_primary_2(buf, dest)) != 0)
goto end;
goto restore;
@@ -4015,6 +4010,80 @@ sw buf_parse_tag_primary_2 (s_buf *buf, s_tag *dest)
goto restore;
result += r;
}
+ if ((r = buf_parse_tag_call_access(buf, dest)) != 0 ||
+ (r = buf_parse_tag_primary_3(buf, dest)) != 0)
+ goto end;
+ goto restore;
+ end:
+ if (r < 0)
+ goto restore;
+ if (r > 0) {
+ result += r;
+ if ((r = buf_parse_comments(buf)) > 0)
+ result += r;
+ }
+ r = result;
+ goto clean;
+ restore:
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
+}
+
+sw buf_parse_tag_primary_3 (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ sw result = 0;
+ s_buf_save save;
+ assert(buf);
+ assert(dest);
+ buf_save_init(buf, &save);
+ if ((r = buf_parse_comments(buf)) < 0)
+ goto clean;
+ if (r > 0) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) <= 0)
+ goto restore;
+ result += r;
+ }
+ if ((r = buf_parse_tag_call_op_unary(buf, dest)) != 0 ||
+ (r = buf_parse_tag_primary_4(buf, dest)) != 0)
+ goto end;
+ goto restore;
+ end:
+ if (r < 0)
+ goto restore;
+ if (r > 0) {
+ result += r;
+ if ((r = buf_parse_comments(buf)) > 0)
+ result += r;
+ }
+ r = result;
+ goto clean;
+ restore:
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
+}
+
+sw buf_parse_tag_primary_4 (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ sw result = 0;
+ s_buf_save save;
+ assert(buf);
+ assert(dest);
+ buf_save_init(buf, &save);
+ if ((r = buf_parse_comments(buf)) < 0)
+ goto clean;
+ if (r > 0) {
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) <= 0)
+ goto restore;
+ result += r;
+ }
if ((r = buf_parse_tag_var(buf, dest)) != 0 ||
(r = buf_parse_tag_void(buf, dest)) != 0 ||
(r = buf_parse_tag_number(buf, dest)) != 0 ||
diff --git a/libkc3/buf_parse.h b/libkc3/buf_parse.h
index a380eb5..e61f77a 100644
--- a/libkc3/buf_parse.h
+++ b/libkc3/buf_parse.h
@@ -120,6 +120,7 @@ sw buf_parse_tag_f32 (s_buf *buf, s_tag *dest);
sw buf_parse_tag_f64 (s_buf *buf, s_tag *dest);
sw buf_parse_tag_fn (s_buf *buf, s_tag *dest);
sw buf_parse_tag_ident (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_ident_sym (s_buf *buf, s_tag *dest);
sw buf_parse_tag_if (s_buf *buf, s_tag *dest);
sw buf_parse_tag_integer (s_buf *buf, s_tag *dest);
sw buf_parse_tag_list (s_buf *buf, s_tag *dest);
@@ -128,6 +129,8 @@ sw buf_parse_tag_module_name (s_buf *buf, s_tag *module_name);
sw buf_parse_tag_number (s_buf *buf, s_tag *dest);
sw buf_parse_tag_primary (s_buf *buf, s_tag *dest);
sw buf_parse_tag_primary_2 (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_primary_3 (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_primary_4 (s_buf *buf, s_tag *dest);
sw buf_parse_tag_quote (s_buf *buf, s_tag *dest);
sw buf_parse_tag_special_operator (s_buf *buf, s_tag *dest);
sw buf_parse_tag_str (s_buf *buf, s_tag *dest);
diff --git a/libkc3/io.c b/libkc3/io.c
index 9640ee7..af67315 100644
--- a/libkc3/io.c
+++ b/libkc3/io.c
@@ -72,18 +72,6 @@ sw err_inspect_buf (const s_buf *buf)
return err_write(buf->ptr.pchar + pos, buf->rpos - pos);
}
-sw err_inspect_struct (const s_struct *s) {
- sw r;
- if (! s) {
- err_puts("err_inspect_struct: NULL input");
- return -1;
- }
- if ((r = buf_inspect_struct(&g_kc3_env.err, s)) < 0)
- return r;
- buf_flush(&g_kc3_env.err);
- return r;
-}
-
sw err_inspect_tag_type (e_tag_type type)
{
return err_write_1(tag_type_to_string(type));
@@ -221,6 +209,7 @@ DEF_ERR_IO_INSPECT(s64, const s64 *)
DEF_ERR_IO_INSPECT(s64_decimal, const s64 *)
DEF_ERR_IO_INSPECT(s64_hexadecimal, const s64 *)
DEF_ERR_IO_INSPECT(str, const s_str *)
+DEF_ERR_IO_INSPECT(struct, const s_struct *)
DEF_ERR_IO_INSPECT(sw, const sw *)
DEF_ERR_IO_INSPECT(sw_decimal, const sw *)
DEF_ERR_IO_INSPECT(sw_hexadecimal, const sw *)
diff --git a/libkc3/io.h b/libkc3/io.h
index c58c860..9e084c7 100644
--- a/libkc3/io.h
+++ b/libkc3/io.h
@@ -72,6 +72,7 @@ PROTOTYPES_ERR_IO_INSPECT(s64, const s64 *);
PROTOTYPES_ERR_IO_INSPECT(s64_decimal, const s64 *);
PROTOTYPES_ERR_IO_INSPECT(s64_hexadecimal, const s64 *);
PROTOTYPES_ERR_IO_INSPECT(str, const s_str *);
+PROTOTYPES_ERR_IO_INSPECT(struct, const s_struct *);
PROTOTYPES_ERR_IO_INSPECT(sw, const sw *);
PROTOTYPES_ERR_IO_INSPECT(sw_decimal, const sw *);
PROTOTYPES_ERR_IO_INSPECT(sw_hexadecimal, const sw *);
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index e08c1e4..6b85a7a 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "array.h"
#include "assert.h"
#include "bool.h"
#include "buf.h"
@@ -40,24 +41,26 @@ const s_str g_kc3_bases_hexadecimal[2] = {{{NULL}, 16,
{"0123456789ABCDEF"}}};
sw g_kc3_exit_code = 1;
-s_tag * kc3_access (const s_tag *tag, const s_sym * const *sym,
- s_tag *dest)
+s_tag * kc3_access (const s_tag *tag, const s_list * const *key,
+ s_tag *dest)
{
assert(tag);
- assert(sym);
+ assert(key);
assert(dest);
switch (tag->type) {
+ case TAG_ARRAY:
+ return array_access(&tag->data.array, key, dest);
case TAG_MAP:
- return map_access(&tag->data.map, *sym, dest);
+ return map_access(&tag->data.map, key, dest);
case TAG_STRUCT:
- return struct_access(&tag->data.struct_, *sym, dest);
+ return struct_access(&tag->data.struct_, key, dest);
default:
break;
}
err_write_1("kc3_access: cannot access tag type ");
err_write_1(tag_type_to_string(tag->type));
err_write_1(" for key ");
- err_inspect_sym(sym);
+ err_inspect_list(key);
err_write_1("\n");
return NULL;
}
diff --git a/libkc3/kc3_main.h b/libkc3/kc3_main.h
index 2e29c8a..51c8fa0 100644
--- a/libkc3/kc3_main.h
+++ b/libkc3/kc3_main.h
@@ -43,7 +43,7 @@ const s_sym ** kc3_module (const s_sym **dest);
sw kc3_puts (const s_tag *tag);
/* Operators. */
-s_tag * kc3_access (const s_tag *tag, const s_sym * const *sym,
+s_tag * kc3_access (const s_tag *tag, const s_list * const *addr,
s_tag *dest);
s_tag * kc3_buf_parse_tag (s_buf *buf, s_tag *dest);
s_tag * kc3_def (const s_call *call, s_tag *dest);
diff --git a/libkc3/list.c b/libkc3/list.c
index 79a581d..d2840e8 100644
--- a/libkc3/list.c
+++ b/libkc3/list.c
@@ -286,7 +286,6 @@ s_array * list_to_array (const s_list *list, const s_sym *array_type,
s_array *dest)
{
s8 *data;
- const void *data_list;
const s_list *l;
uw len;
bool must_clean;
@@ -322,12 +321,8 @@ s_array * list_to_array (const s_list *list, const s_sym *array_type,
data = tmp.data = tmp.free_data;
l = list;
while (l) {
- if (! tag_to_const_pointer(&l->tag, tmp.element_type, &data_list))
+ if (! data_init_cast(data, &tmp.element_type, &l->tag))
goto ko;
- if (data_list) {
- if (! data_init_copy(tmp.element_type, data, data_list))
- goto ko;
- }
data += size;
l = list_next(l);
}
diff --git a/libkc3/map.c b/libkc3/map.c
index 68c8022..475d1c8 100644
--- a/libkc3/map.c
+++ b/libkc3/map.c
@@ -17,19 +17,37 @@
#include "buf_parse.h"
#include "compare.h"
#include "eval.h"
+#include "kc3_main.h"
#include "list.h"
#include "map.h"
#include "tag.h"
-s_tag * map_access (const s_map *map, const s_sym *key, s_tag *value)
+s_tag * map_access (const s_map *map, const s_list * const *key,
+ s_tag *dest)
{
- s_tag tag_key;
+ const s_tag *first;
+ const s_list *next;
+ s_tag *r;
+ s_tag tag;
assert(map);
assert(key);
- assert(value);
- tag_key.type = TAG_SYM;
- tag_key.data.sym = key;
- return map_get(map, &tag_key, value);
+ assert(dest);
+ first = &(*key)->tag;
+ next = list_next(*key);
+ if (! next)
+ return map_get(map, first, dest);
+ if (! map_get(map, first, &tag)) {
+ err_write_1("map_access: map_get(");
+ err_inspect_map(map);
+ err_write_1(", ");
+ err_inspect_tag(first);
+ err_write_1(")\n");
+ assert(! "map_access: map_get");
+ return NULL;
+ }
+ r = kc3_access(&tag, &next, dest);
+ tag_clean(&tag);
+ return r;
}
s_map * map_init_cast (s_map *map, const s_tag *tag)
diff --git a/libkc3/map.h b/libkc3/map.h
index b46a115..2b77b7f 100644
--- a/libkc3/map.h
+++ b/libkc3/map.h
@@ -35,7 +35,7 @@ s_map * map_set (s_map *map, const s_tag *key, const s_tag *value);
s_map * map_sort (s_map *map);
/* Observers. */
-s_tag * map_access (const s_map *map, const s_sym *key,
+s_tag * map_access (const s_map *map, const s_list * const *key,
s_tag *value);
s_map * map_cast (const s_tag *tag, s_map *map);
s_tag * map_get (const s_map *map, const s_tag *key, s_tag *dest);
diff --git a/libkc3/struct.c b/libkc3/struct.c
index 7e70a99..55006f6 100644
--- a/libkc3/struct.c
+++ b/libkc3/struct.c
@@ -17,6 +17,7 @@
#include "buf_parse.h"
#include "data.h"
#include "env.h"
+#include "kc3_main.h"
#include "list.h"
#include "map.h"
#include "struct.h"
@@ -25,7 +26,44 @@
#include "tag.h"
#include "tag_type.h"
-s_tag * struct_access (const s_struct *s, const s_sym *key, s_tag *dest)
+s_tag * struct_access (const s_struct *s, const s_list * const *key,
+ s_tag *dest)
+{
+ const s_tag *first;
+ const s_list *next;
+ s_tag *r;
+ s_tag tag;
+ assert(s);
+ assert(key);
+ assert(dest);
+ first = &(*key)->tag;
+ next = list_next(*key);
+ if (first->type != TAG_SYM) {
+ err_write_1("struct_access: key is not a Sym: (");
+ err_inspect_struct(s);
+ err_write_1(", ");
+ err_inspect_tag(first);
+ err_write_1(")\n");
+ assert(! "struct_access: key is not a Sym");
+ return NULL;
+ }
+ if (! next)
+ return struct_access_sym(s, first->data.sym, dest);
+ if (! struct_access_sym(s, first->data.sym, &tag)) {
+ err_write_1("struct_access: map_get(");
+ err_inspect_struct(s);
+ err_write_1(", ");
+ err_inspect_tag(first);
+ err_write_1(")\n");
+ assert(! "struct_access: map_get");
+ return NULL;
+ }
+ r = kc3_access(&tag, &next, dest);
+ tag_clean(&tag);
+ return r;
+}
+
+s_tag * struct_access_sym (const s_struct *s, const s_sym *key, s_tag *dest)
{
const void *data;
const s_struct_type *st;
diff --git a/libkc3/struct.h b/libkc3/struct.h
index 7991b79..f61ffb3 100644
--- a/libkc3/struct.h
+++ b/libkc3/struct.h
@@ -46,10 +46,13 @@ s_struct * struct_set (s_struct *s, const s_sym *key,
const s_tag *value);
/* Observers. */
-s_tag * struct_access (const s_struct *s, const s_sym *key,
+s_tag * struct_access (const s_struct *s,
+ const s_list * const *key,
s_tag *dest);
-bool struct_find_key_index (const s_struct *s, const s_sym *key,
- uw *dest);
+s_tag * struct_access_sym (const s_struct *s, const s_sym *key,
+ s_tag *dest);
+bool struct_find_key_index (const s_struct *s,
+ const s_sym *key, uw *dest);
const void * struct_get (const s_struct *s, const s_sym *key);
const s_sym ** struct_get_type (const s_struct *s, const s_sym *key,
const s_sym **dest);
diff --git a/libkc3/tag.c b/libkc3/tag.c
index 6f6f108..b07a303 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -210,7 +210,8 @@ s_tag * tag_brackets (const s_tag *tag, const s_tag *address,
case TAG_ARRAY:
switch (address->type) {
case TAG_ARRAY:
- return array_data_tag(tag, address, dest);
+ return array_data_tag(&tag->data.array, &address->data.array,
+ dest);
default:
break;
}
diff --git a/test/ikc3/access.kc3 b/test/ikc3/access.kc3
index 31f4601..931fa06 100644
--- a/test/ikc3/access.kc3
+++ b/test/ikc3/access.kc3
@@ -1,15 +1,39 @@
quote %{a: 1, b: 2, c: 3}.a
%{a: 1, b: 2, c: 3}.a
+quote %{"a" => 1, "b" => 2, "c" => 3}["a"]
+%{"a" => 1, "b" => 2, "c" => 3}["a"]
+quote %{a: 1, b: 2, c: 3}[:a]
+%{a: 1, b: 2, c: 3}[:a]
quote %{a: 1, b: 2, c: 3}.b
%{a: 1, b: 2, c: 3}.b
+quote %{a: 1, b: 2, c: 3}[:b]
+%{a: 1, b: 2, c: 3}[:b]
+quote %{"a" => 1, "b" => 2, "c" => 3}["b"]
+%{"a" => 1, "b" => 2, "c" => 3}["b"]
quote %{a: 1, b: 2, c: 3}.c
%{a: 1, b: 2, c: 3}.c
+quote %{a: 1, b: 2, c: 3}[:c]
+%{a: 1, b: 2, c: 3}[:c]
+quote %{"a" => 1, "b" => 2, "c" => 3}["c"]
+%{"a" => 1, "b" => 2, "c" => 3}["c"]
quote %{a: %{b: %{c: 1}}}.a
%{a: %{b: %{c: 1}}}.a
+quote %{a: %{b: %{c: 1}}}[:a]
+%{a: %{b: %{c: 1}}}[:a]
+quote %{"a" => %{"b" => %{"c" => 3}}}["a"]
+%{"a" => %{"b" => %{"c" => 3}}}["a"]
quote %{a: %{b: %{c: 1}}}.a.b
%{a: %{b: %{c: 1}}}.a.b
+quote %{a: %{b: %{c: 1}}}[:a][:b]
+%{a: %{b: %{c: 1}}}[:a][:b]
+quote %{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]
+%{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]
quote %{a: %{b: %{c: 1}}}.a.b.c
%{a: %{b: %{c: 1}}}.a.b.c
+quote %{a: %{b: %{c: 1}}}[:a][:b][:c]
+%{a: %{b: %{c: 1}}}[:a][:b][:c]
+quote %{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]["c"]
+%{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]["c"]
quote map = %{a: %{b: %{c: 1}}}
map = %{a: %{b: %{c: 1}}}
quote map
@@ -24,6 +48,20 @@ quote map.a.b.c + map.a.b.c
map.a.b.c + map.a.b.c
quote "0 #{map.a.b.c} 2"
"0 #{map.a.b.c} 2"
+quote map = %{"a" => %{"b" => %{"c" => 1}}}
+map = %{"a" => %{"b" => %{"c" => 1}}}
+quote map
+map
+quote map["a"]
+map["a"]
+quote map["a"]["b"]
+map["a"]["b"]
+quote map["a"]["b"]["c"]
+map["a"]["b"]["c"]
+quote map["a"]["b"]["c"] + map["a"]["b"]["c"]
+map["a"]["b"]["c"] + map["a"]["b"]["c"]
+quote """0 #{map["a"]["b"]["c"]} 2"""
+"""0 #{map["a"]["b"]["c"]} 2"""
quote op = %KC3.Operator{}
op = %KC3.Operator{}
quote op.sym
diff --git a/test/ikc3/access.out.expected b/test/ikc3/access.out.expected
index 37be3c5..c2970eb 100644
--- a/test/ikc3/access.out.expected
+++ b/test/ikc3/access.out.expected
@@ -2,20 +2,56 @@
b: 2,
c: 3}.a
1
+%{"a" => 1,
+ "b" => 2,
+ "c" => 3}["a"]
+1
+%{a: 1,
+ b: 2,
+ c: 3}[:a]
+1
%{a: 1,
b: 2,
c: 3}.b
2
%{a: 1,
b: 2,
+ c: 3}[:b]
+2
+%{"a" => 1,
+ "b" => 2,
+ "c" => 3}["b"]
+2
+%{a: 1,
+ b: 2,
c: 3}.c
3
+%{a: 1,
+ b: 2,
+ c: 3}[:c]
+3
+%{"a" => 1,
+ "b" => 2,
+ "c" => 3}["c"]
+3
%{a: %{b: %{c: 1}}}.a
%{b: %{c: 1}}
+%{a: %{b: %{c: 1}}}[:a]
+%{b: %{c: 1}}
+%{"a" => %{"b" => %{"c" => 3}}}["a"]
+%{"b" => %{"c" => 3}}
%{a: %{b: %{c: 1}}}.a.b
%{c: 1}
+%{a: %{b: %{c: 1}}}[:a][:b]
+%{c: 1}
+%{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]
+%{"c" => 3}
%{a: %{b: %{c: 1}}}.a.b.c
1
+%{a: %{b: %{c: 1}}}[:a][:b][:c]
+1
+%{"a" => %{"b" => %{"c" => 3}}}["a"]["b"]["c"]
+3
map = %{a: %{b: %{c: 1}}}
%{a: %{b: %{c: 1}}}
map
@@ -30,6 +66,20 @@ map.a.b.c + map.a.b.c
2
"0 #{map.a.b.c} 2"
"0 1 2"
+map = %{"a" => %{"b" => %{"c" => 1}}}
+%{"a" => %{"b" => %{"c" => 1}}}
+map
+%{"a" => %{"b" => %{"c" => 1}}}
+map["a"]
+%{"b" => %{"c" => 1}}
+map["a"]["b"]
+%{"c" => 1}
+map["a"]["b"]["c"]
+1
+map["a"]["b"]["c"] + map["a"]["b"]["c"]
+2
+"0 #{map["a"]["b"]["c"]} 2"
+"0 1 2"
op = %KC3.Operator{}
%KC3.Operator{sym: :+,
symbol_value: ?,
diff --git a/test/ikc3/str.out.expected b/test/ikc3/str.out.expected
index a72e855..bf20e08 100644
--- a/test/ikc3/str.out.expected
+++ b/test/ikc3/str.out.expected
@@ -68,4 +68,4 @@
{0, 0}}}"
"(U8[]) {{0, 0},\n {0, 0},\n {0, 0}}"
"#{%Socket.Buf{}}"
-"%Socket.Buf{addr: (Ptr) 0x0,\n addr_len: (U32) 0,\n sockfd: (S32) -1,\n buf_rw: %BufRW{r: (Ptr) 0x0,\n w: (Ptr) 0x0}}"
+"%Socket.Buf{addr: (Ptr) 0x0,\n addr_len: (U32) 0,\n addr_str: \"\",\n sockfd: (S32) -1,\n buf_rw: %BufRW{r: (Ptr) 0x0,\n w: (Ptr) 0x0}}"