diff --git a/.ic3_history b/.ic3_history
index 612f5b4..5eb1a86 100644
--- a/.ic3_history
+++ b/.ic3_history
@@ -1,5 +1,3 @@
-123.123
-(3)
type(3)
type(2)
type(1 + 2)
@@ -97,3 +95,5 @@ hello("Baptiste")
hello = fn (name) { "Hello, #{name} !" }
hello("Thomas")
hello = fn (name) { "Hello, #{name} !" }
+name("Thomas")
+hello("Thomas")
diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index 7443865..d5456cd 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -35,3 +35,5 @@ type(0x193a838c800)
"a"
"abc"
"abc#{1}"
+hello = fn (name) { "Hello, #{name} !" }
+hello("Thomas")
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index e3003af..b459a17 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -2562,129 +2562,24 @@ sw buf_parse_str_character_unicode (s_buf *buf, character *dest)
sw buf_parse_str_eval (s_buf *buf, s_tag *dest)
{
- character c;
s_str in;
- s_buf in_buf;
- s_list *list;
- s_list **list_end;
- s_list *list_start = NULL;
- s_ident op;
- s_buf out_buf = {0};
sw r;
sw result;
- s_tag *right;
s_buf_save save;
- s_tag tmp = {0};
- s_tag tmp1 = {0};
buf_save_init(buf, &save);
r = buf_parse_str(buf, &in);
if (r <= 0)
goto save_clean;
result = r;
- buf_init_str(&in_buf, false, &in);
- if (! buf_init_alloc(&out_buf, in.size)) {
+ if (! str_parse_eval(&in, dest)) {
r = -2;
goto restore;
}
- list_end = &list_start;
- 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;
- out_buf.rpos = out_buf.wpos = 0;
- }
- *list_end = list_new(NULL);
- r = buf_parse_tag(&in_buf, &(*list_end)->tag);
- if (r <= 0)
- goto restore;
- list_end = &(*list_end)->next.data.list;
- r = buf_ignore_spaces(&in_buf);
- if (r < 0)
- goto restore;
- r = buf_parse_comments(&in_buf);
- if (r < 0)
- goto restore;
- r = buf_read_1(&in_buf, "}");
- if (r <= 0)
- goto restore;
- continue;
- }
- r = buf_peek_character_utf8(&in_buf, &c);
- if (r <= 0)
- break;
- r = buf_xfer(&out_buf, &in_buf, r);
- if (r <= 0) {
- r = -2;
- 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);
- }
- if (! list_start)
- tag_init_str_empty(&tmp);
- else {
- list = list_start;
- if (list->tag.type == TAG_STR)
- tmp = list->tag;
- else {
- if (! tag_init_call_cast(&tmp, &g_sym_Str)) {
- r = -2;
- goto restore;
- }
- 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)) {
- r = -2;
- goto restore;
- }
- op.module = &g_sym_C3;
- 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)) {
- r = -2;
- goto restore;
- }
- right->data.call.arguments->tag = list->tag;
- }
- tmp = tmp1;
- list = list_next(list);
- }
- }
- *dest = tmp;
r = result;
goto clean;
restore:
- list = list_start;
- while (list) {
- tag_clean(&list->tag);
- list = list_next(list);
- }
- buf_clean(&out_buf);
buf_save_restore_rpos(buf, &save);
clean:
- while (list_start) {
- list = list_next(list_start);
- free(list_start);
- list_start = list;
- }
str_clean(&in);
save_clean:
buf_save_clean(buf, &save);
@@ -3234,7 +3129,7 @@ sw buf_parse_tag_primary (s_buf *buf, s_tag *dest)
(r = buf_parse_tag_bool(buf, dest)) != 0 ||
(r = buf_parse_tag_character(buf, dest)) != 0 ||
(r = buf_parse_tag_map(buf, dest)) != 0 ||
- (r = buf_parse_str_eval(buf, dest)) != 0 ||
+ (r = buf_parse_tag_str(buf, dest)) != 0 ||
(r = buf_parse_tag_tuple(buf, dest)) != 0 ||
(r = buf_parse_tag_quote(buf, dest)) != 0 ||
(r = buf_parse_tag_cfn(buf, dest)) != 0 ||
diff --git a/libc3/env.c b/libc3/env.c
index 6ef829d..d8cfd0f 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -668,6 +668,24 @@ bool env_eval_quote (s_env *env, const s_quote *quote, 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;
+ if (str_parse_eval(str, &tmp) < 0) {
+ 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;
@@ -744,6 +762,8 @@ 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:
@@ -765,7 +785,6 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
case TAG_S32:
case TAG_S64:
case TAG_SW:
- case TAG_STR:
case TAG_STRUCT_TYPE:
case TAG_SYM:
case TAG_U8:
diff --git a/libc3/str.c b/libc3/str.c
index f8e77b3..ff4f2ab 100644
--- a/libc3/str.c
+++ b/libc3/str.c
@@ -18,12 +18,31 @@
#include <string.h>
#include "buf.h"
#include "buf_inspect.h"
+#include "buf_parse.h"
+#include "call.h"
#include "character.h"
#include "ident.h"
+#include "list.h"
+#include "operator.h"
#include "str.h"
#include "sym.h"
+#include "tag.h"
#include "tag_type.h"
+#define DEF_STR_INIT(type) \
+ s_str * str_init_ ## type (s_str *str, type x) \
+ { \
+ s_buf buf; \
+ sw size; \
+ size = buf_inspect_ ## type ## _size(&x); \
+ if (size <= 0) \
+ return NULL; \
+ buf_init_alloc(&buf, size); \
+ buf_inspect_ ## type(&buf, &x); \
+ assert(buf.wpos == (uw) size); \
+ return buf_to_str(&buf, str); \
+ }
+
sw str_character (const s_str *str, uw position, character *dest)
{
character c;
@@ -139,10 +158,30 @@ s_str * str_init_cast (s_str *str, const s_tag *tag)
assert(str);
assert(tag);
switch (tag->type) {
+ case TAG_S8:
+ return str_init_s8(str, tag->data.s8);
+ case TAG_S16:
+ return str_init_s16(str, tag->data.s16);
+ case TAG_S32:
+ return str_init_s32(str, tag->data.s32);
+ case TAG_S64:
+ return str_init_s64(str, tag->data.s64);
case TAG_STR:
return str_init_copy(str, &tag->data.str);
case TAG_SYM:
return str_init_copy(str, &tag->data.sym->str);
+ case TAG_SW:
+ return str_init_sw(str, tag->data.sw);
+ case TAG_U8:
+ return str_init_u8(str, tag->data.u8);
+ case TAG_U16:
+ return str_init_u16(str, tag->data.u16);
+ case TAG_U32:
+ return str_init_u32(str, tag->data.u32);
+ case TAG_U64:
+ return str_init_u64(str, tag->data.u64);
+ case TAG_UW:
+ return str_init_uw(str, tag->data.uw);
default:
break;
}
@@ -235,6 +274,12 @@ s_str * str_init_f (s_str *str, const char *fmt, ...)
return str;
}
+DEF_STR_INIT(s8)
+DEF_STR_INIT(s16)
+DEF_STR_INIT(s32)
+DEF_STR_INIT(s64)
+DEF_STR_INIT(sw)
+
s_str * str_init_slice (s_str *str, const s_str *src, sw start, sw end)
{
s_buf buf;
@@ -257,30 +302,11 @@ s_str * str_init_slice (s_str *str, const s_str *src, sw start, sw end)
return str;
}
-uw * str_sw_pos_to_uw (sw pos, uw max_pos, uw *dest)
-{
- assert(dest);
- if (pos >= 0) {
- if ((uw) pos > max_pos) {
- warnx("str_sw_pos_to_uw: index out of bounds: %ld > %lu",
- pos, max_pos);
- assert(! "str_sw_pos_to_uw: index too large");
- return NULL;
- }
- *dest = (uw) pos;
- }
- else {
- if (max_pos > SW_MAX || pos >= (sw) -max_pos)
- *dest = max_pos - pos;
- else {
- warnx("str_sw_pos_to_uw: index out of bounds: %ld < -%lu",
- pos, max_pos);
- assert(! "str_sw_pos_to_uw: index too low");
- return NULL;
- }
- }
- return dest;
-}
+DEF_STR_INIT(u8)
+DEF_STR_INIT(u16)
+DEF_STR_INIT(u32)
+DEF_STR_INIT(u64)
+DEF_STR_INIT(uw)
s_str * str_init_vf (s_str *str, const char *fmt, va_list ap)
{
@@ -392,6 +418,104 @@ s_str * str_new_vf (const char *fmt, va_list ap)
return dest;
}
+bool str_parse_eval (const s_str *str, s_tag *dest)
+{
+ character c;
+ s_buf in_buf;
+ s_list *list;
+ s_list **list_end;
+ s_list *list_start = NULL;
+ s_ident op;
+ s_buf out_buf = {0};
+ sw r;
+ s_tag *right;
+ 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;
+ 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;
+ out_buf.rpos = out_buf.wpos = 0;
+ }
+ *list_end = list_new(NULL);
+ r = buf_parse_tag(&in_buf, &(*list_end)->tag);
+ if (r <= 0)
+ goto restore;
+ list_end = &(*list_end)->next.data.list;
+ r = buf_ignore_spaces(&in_buf);
+ if (r < 0)
+ goto restore;
+ r = buf_parse_comments(&in_buf);
+ if (r < 0)
+ goto restore;
+ r = buf_read_1(&in_buf, "}");
+ if (r <= 0)
+ goto restore;
+ continue;
+ }
+ r = buf_peek_character_utf8(&in_buf, &c);
+ if (r <= 0)
+ break;
+ r = buf_xfer(&out_buf, &in_buf, r);
+ if (r <= 0)
+ 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);
+ }
+ if (! list_start)
+ tag_init_str_empty(&tmp);
+ 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;
+ 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_C3;
+ 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;
+ right->data.call.arguments->tag = list->tag;
+ }
+ tmp = tmp1;
+ list = list_next(list);
+ }
+ }
+ *dest = tmp;
+ return true;
+ restore:
+ list_delete_all(list_start);
+ buf_clean(&out_buf);
+ return false;
+}
+
sw str_peek_character_utf8 (const s_str *str, character *c)
{
assert(str);
@@ -498,6 +622,31 @@ uw * str_rindex_character (const s_str *str, character c, uw *dest)
return NULL;
}
+uw * str_sw_pos_to_uw (sw pos, uw max_pos, uw *dest)
+{
+ assert(dest);
+ if (pos >= 0) {
+ if ((uw) pos > max_pos) {
+ warnx("str_sw_pos_to_uw: index out of bounds: %ld > %lu",
+ pos, max_pos);
+ assert(! "str_sw_pos_to_uw: index too large");
+ return NULL;
+ }
+ *dest = (uw) pos;
+ }
+ else {
+ if (max_pos > SW_MAX || pos >= (sw) -max_pos)
+ *dest = max_pos - pos;
+ else {
+ warnx("str_sw_pos_to_uw: index out of bounds: %ld < -%lu",
+ pos, max_pos);
+ assert(! "str_sw_pos_to_uw: index too low");
+ return NULL;
+ }
+ }
+ return dest;
+}
+
s_str * str_to_hex (const s_str *src, s_str *dest)
{
s_buf buf;
diff --git a/libc3/str.h b/libc3/str.h
index 924319a..226284b 100644
--- a/libc3/str.h
+++ b/libc3/str.h
@@ -26,6 +26,9 @@
#define STR_MAX (16 * 1024 * 1024)
+#define PROTOTYPE_STR_INIT(type) \
+ s_str * str_init_ ## type (s_str *str, type x)
+
/* Stack allocation compatible functions */
void str_clean (s_str *str);
s_str * str_init (s_str *str, char *free, uw size, const char *p);
@@ -37,9 +40,19 @@ s_str * str_init_copy (s_str *str, const s_str *src);
s_str * str_init_copy_1 (s_str *str, const char *p);
s_str * str_init_empty (s_str *str);
s_str * str_init_f (s_str *str, const char *fmt, ...);
+PROTOTYPE_STR_INIT(s8);
+PROTOTYPE_STR_INIT(s16);
+PROTOTYPE_STR_INIT(s32);
+PROTOTYPE_STR_INIT(s64);
s_str * str_init_slice (s_str *str, const s_str *src, sw start, sw end);
s_str * str_init_slice_utf8 (s_str *str, const s_str *src, sw start,
sw end);
+PROTOTYPE_STR_INIT(sw);
+PROTOTYPE_STR_INIT(u8);
+PROTOTYPE_STR_INIT(u16);
+PROTOTYPE_STR_INIT(u32);
+PROTOTYPE_STR_INIT(u64);
+PROTOTYPE_STR_INIT(uw);
s_str * str_init_vf (s_str *str, const char *fmt, va_list ap);
/* Constructors, call str_delete after use */
@@ -61,31 +74,32 @@ character str_character_escape (character c);
bool str_character_is_reserved (character c);
sw str_character_position (const s_str *str, character c);
bool str_has_reserved_characters (const s_str *str);
-s_str * str_inspect (const s_str *x, s_str *dest);
+s_str * str_inspect (const s_str *str, s_str *dest);
sw str_length_utf8 (const s_str *str);
-sw str_peek_bool (const s_str *src, bool *p);
-sw str_peek_character_utf8 (const s_str *src, character *p);
-sw str_peek_f32 (const s_str *src, f32 *p);
-sw str_peek_f64 (const s_str *src, f64 *p);
-sw str_peek_s8 (const s_str *src, s8 *p);
-sw str_peek_s16 (const s_str *src, s16 *p);
-sw str_peek_s32 (const s_str *src, s32 *p);
-sw str_peek_s64 (const s_str *src, s64 *p);
-sw str_peek_str (const s_str *src, s_str *p);
-sw str_peek_sym (const s_str *src, s_sym *p);
-sw str_peek_u8 (const s_str *src, u8 *p);
-sw str_peek_u16 (const s_str *src, u16 *p);
-sw str_peek_u32 (const s_str *src, u32 *p);
-sw str_peek_u64 (const s_str *src, u64 *p);
+bool str_parse_eval (const s_str *str, s_tag *dest);
+sw str_peek_bool (const s_str *str, bool *dest);
+sw str_peek_character_utf8 (const s_str *str, character *dest);
+sw str_peek_f32 (const s_str *str, f32 *dest);
+sw str_peek_f64 (const s_str *str, f64 *dest);
+sw str_peek_s8 (const s_str *str, s8 *dest);
+sw str_peek_s16 (const s_str *str, s16 *dest);
+sw str_peek_s32 (const s_str *str, s32 *dest);
+sw str_peek_s64 (const s_str *str, s64 *dest);
+sw str_peek_str (const s_str *str, s_str *dest);
+sw str_peek_sym (const s_str *str, s_sym *dest);
+sw str_peek_u8 (const s_str *str, u8 *dest);
+sw str_peek_u16 (const s_str *str, u16 *dest);
+sw str_peek_u32 (const s_str *str, u32 *dest);
+sw str_peek_u64 (const s_str *str, u64 *dest);
uw * str_rindex_character (const s_str *str, character c,
uw *dest);
uw * str_sw_pos_to_uw (sw pos, uw max_pos, uw *dest);
-s_str * str_to_hex (const s_str *src, s_str *dest);
-s_ident * str_to_ident (const s_str *src, s_ident *dest);
-const s_sym * str_to_sym (const s_str *src);
+s_str * str_to_hex (const s_str *str, s_str *dest);
+s_ident * str_to_ident (const s_str *str, s_ident *dest);
+const s_sym * str_to_sym (const s_str *str);
/* Modifiers */
-sw str_read_u8 (s_str *str, u8 *p);
+sw str_read_u8 (s_str *str, u8 *dest);
sw str_read_character_utf8 (s_str *str, character *c);
#endif /* LIBC3_STR_H */
diff --git a/test/ic3/str.in b/test/ic3/str.in
index 37cb6db..ab8a962 100644
--- a/test/ic3/str.in
+++ b/test/ic3/str.in
@@ -46,3 +46,5 @@ def"""
abc
def
"""
+quote "1 + 2 = #{1 + 2}"
+"1 + 2 = #{1 + 2}"
diff --git a/test/ic3/str.out.expected b/test/ic3/str.out.expected
index 769ed5e..4611598 100644
--- a/test/ic3/str.out.expected
+++ b/test/ic3/str.out.expected
@@ -31,3 +31,5 @@
"abc\ndef\n"
"abc\ndef"
"abc\ndef"
+"1 + 2 = #{1 + 2}"
+"1 + 2 = 3"