diff --git a/libc3/env.c b/libc3/env.c
index ebc53f8..c51c97d 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -690,14 +690,8 @@ bool env_eval_quote_array (s_env *env, const s_array *array,
tmp_tag = tmp.tags = calloc(tmp.count, sizeof(s_tag));
i = 0;
while (i < array->count) {
- if (tag->type == TAG_UNQUOTE) {
- if (! env_eval_tag(env, tag->data.unquote.tag, tmp_tag))
- goto ko;
- }
- else {
- if (! tag_init_copy(tmp_tag, tag))
- goto ko;
- }
+ if (! env_eval_quote_tag(env, tag, tmp_tag))
+ goto ko;
tag++;
tmp_tag++;
i++;
@@ -941,7 +935,14 @@ bool env_eval_quote_unquote (s_env *env, const s_unquote *unquote, s_tag *dest)
return false;
}
env->unquote_level++;
- r = env_eval_tag(env, unquote->tag, &tmp);
+ if (env->unquote_level == 1) {
+ if (env->quote_level == 1)
+ r = env_eval_tag(env, unquote->tag, &tmp);
+ else
+ r = tag_init_copy(&tmp, unquote->tag) ? true : false;
+ }
+ else
+ r = tag_init_unquote_copy(&tmp, unquote) ? true : false;
env->unquote_level--;
if (! r)
return false;
diff --git a/libc3/list_init.c b/libc3/list_init.c
index 8f98f03..2d0cf1f 100644
--- a/libc3/list_init.c
+++ b/libc3/list_init.c
@@ -230,6 +230,18 @@ s_list * list_init_ptr_free (s_list *list, void *p, s_list *next)
return list;
}
+s_list * list_init_quote_copy (s_list *list, const s_quote *quote,
+ s_list *next)
+{
+ s_list tmp;
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_quote_copy(&tmp.tag, quote))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
s_list * list_init_s8 (s_list *list, s8 i, s_list *next)
{
s_list tmp;
@@ -435,6 +447,18 @@ s_list * list_init_u64 (s_list *list, u64 i, s_list *next)
return list;
}
+s_list * list_init_unquote_copy (s_list *list,
+ const s_unquote *unquote, s_list *next)
+{
+ s_list tmp;
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_unquote_copy(&tmp.tag, unquote))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
s_list * list_init_uw (s_list *list, uw i, s_list *next)
{
s_list tmp;
@@ -690,6 +714,19 @@ s_list * list_new_ptr_free (void *p, s_list *next)
return list;
}
+s_list * list_new_quote_copy (const s_quote *quote, s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_quote_copy(&list->tag, quote)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
s_list * list_new_s8 (s8 i, s_list *next)
{
s_list *list;
@@ -928,6 +965,19 @@ s_list * list_new_u64 (u64 i, s_list *next)
return list;
}
+s_list * list_new_unquote_copy (const s_unquote *unquote, s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_unquote_copy(&list->tag, unquote)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
s_list * list_new_uw (uw i, s_list *next)
{
s_list *list;
diff --git a/libc3/list_init.h b/libc3/list_init.h
index cacebe3..b553564 100644
--- a/libc3/list_init.h
+++ b/libc3/list_init.h
@@ -41,6 +41,8 @@ s_list * list_init_map (s_list *list, uw count, s_list *next);
s_list * list_init_map_1 (s_list *list, const char *p, s_list *next);
s_list * list_init_ptr (s_list *list, void *p, s_list *next);
s_list * list_init_ptr_free (s_list *list, void *p, s_list *next);
+s_list * list_init_quote_copy (s_list *list, const s_quote *quote,
+ s_list *next);
s_list * list_init_s8 (s_list *list, s8 i, s_list *next);
s_list * list_init_s16 (s_list *list, s16 i, s_list *next);
s_list * list_init_s32 (s_list *list, s32 i, s_list *next);
@@ -67,6 +69,9 @@ s_list * list_init_u8 (s_list *list, u8 i, s_list *next);
s_list * list_init_u16 (s_list *list, u16 i, s_list *next);
s_list * list_init_u32 (s_list *list, u32 i, s_list *next);
s_list * list_init_u64 (s_list *list, u64 i, s_list *next);
+s_list * list_init_unquote_copy (s_list *list,
+ const s_unquote *unquote,
+ s_list *next);
s_list * list_init_uw (s_list *list, uw i, s_list *next);
s_list * list_init_var (s_list *list, s_list *next);
s_list * list_init_void (s_list *list, s_list *next);
@@ -92,6 +97,7 @@ s_list * list_new_map (uw count, s_list *next);
s_list * list_new_map_1 (const char *p, s_list *next);
s_list * list_new_ptr (void *p, s_list *next);
s_list * list_new_ptr_free (void *p, s_list *next);
+s_list * list_new_quote_copy (const s_quote *quote, s_list *next);
s_list * list_new_s8 (s8 i, s_list *next);
s_list * list_new_s16 (s16 i, s_list *next);
s_list * list_new_s32 (s32 i, s_list *next);
@@ -116,6 +122,7 @@ s_list * list_new_u8 (u8 i, s_list *next);
s_list * list_new_u16 (u16 i, s_list *next);
s_list * list_new_u32 (u32 i, s_list *next);
s_list * list_new_u64 (u64 i, s_list *next);
+s_list * list_new_unquote_copy (const s_unquote *unquote, s_list *next);
s_list * list_new_uw (uw i, s_list *next);
s_list * list_new_var (s_list *next);
s_list * list_new_void (s_list *next);
@@ -141,6 +148,7 @@ s_list * list_map (s_list *list, uw count);
s_list * list_map_1 (s_list *list, const char *p);
s_list * list_ptr (s_list *list, void *p);
s_list * list_ptr_free (s_list *list, void *p);
+s_list * list_quote_copy (s_list *list, const s_quote *quote);
s_list * list_s8 (s_list *list, s8 i);
s_list * list_s16 (s_list *list, s16 i);
s_list * list_s32 (s_list *list, s32 i);
@@ -161,6 +169,7 @@ s_list * list_u8 (s_list *list, u8 i);
s_list * list_u16 (s_list *list, u16 i);
s_list * list_u32 (s_list *list, u32 i);
s_list * list_u64 (s_list *list, u64 i);
+s_list * list_unquote_copy (s_list *list, const s_unquote *unquote);
s_list * list_uw (s_list *list, uw i);
s_list * list_var (s_list *list);
s_list * list_void (s_list *list);
diff --git a/libc3/tag_init.c b/libc3/tag_init.c
index 1b0afeb..1f6e9c8 100644
--- a/libc3/tag_init.c
+++ b/libc3/tag_init.c
@@ -37,6 +37,7 @@
#include "tag_init.h"
#include "time.h"
#include "tuple.h"
+#include "unquote.h"
s_tag * tag_init_array (s_tag *tag, const s_sym *type, uw dimension,
const uw *dimensions)
@@ -230,6 +231,17 @@ s_tag * tag_init_ptr_free (s_tag *tag, void *p)
return tag;
}
+s_tag * tag_init_quote_copy (s_tag *tag, const s_quote *quote)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_QUOTE;
+ if (! quote_init_copy(&tmp.data.quote, quote))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_init_s8 (s_tag *tag, s8 i)
{
s_tag tmp = {0};
@@ -420,6 +432,17 @@ s_tag * tag_init_u64 (s_tag *tag, u64 i)
return tag;
}
+s_tag * tag_init_unquote_copy (s_tag *tag, const s_unquote *unquote)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_UNQUOTE;
+ if (! unquote_init_copy(&tmp.data.unquote, unquote))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_init_uw (s_tag *tag, uw i)
{
s_tag tmp = {0};
@@ -698,6 +721,21 @@ s_tag * tag_new_ptr_free (void *p)
return tag;
}
+s_tag * tag_new_quote_copy (const s_quote *quote)
+{
+ s_tag *tag;
+ if (! (tag = calloc(1, sizeof(s_tag)))) {
+ warn("tag_new_quote_copy: calloc");
+ return NULL;
+ }
+ tag->type = TAG_QUOTE;
+ if (! quote_init_copy(&tag->data.quote, quote)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
s_tag * tag_new_s8 (s8 i)
{
s_tag *tag;
@@ -940,6 +978,21 @@ s_tag * tag_new_u64 (u64 i)
return tag;
}
+s_tag * tag_new_unquote_copy (const s_unquote *unquote)
+{
+ s_tag *tag;
+ if (! (tag = calloc(1, sizeof(s_tag)))) {
+ warn("tag_new_unquote_copy: calloc");
+ return NULL;
+ }
+ tag->type = TAG_UNQUOTE;
+ if (! unquote_init_copy(&tag->data.unquote, unquote)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
s_tag * tag_new_uw (uw i)
{
s_tag *tag;
@@ -1184,6 +1237,18 @@ s_tag * tag_ptr_free (s_tag *tag, void *p)
return tag;
}
+s_tag * tag_quote_copy (s_tag *tag, const s_quote *quote)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_QUOTE;
+ if (! quote_init_copy(&tmp.data.quote, quote))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_s8 (s_tag *tag, s8 i)
{
s_tag tmp = {0};
@@ -1392,6 +1457,18 @@ s_tag * tag_u64 (s_tag *tag, u64 i)
return tag;
}
+s_tag * tag_unquote_copy (s_tag *tag, const s_unquote *unquote)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_UNQUOTE;
+ if (! unquote_init_copy(&tmp.data.unquote, unquote))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_uw (s_tag *tag, uw i)
{
s_tag tmp = {0};
diff --git a/libc3/tag_init.h b/libc3/tag_init.h
index 5f1547c..fc39760 100644
--- a/libc3/tag_init.h
+++ b/libc3/tag_init.h
@@ -36,6 +36,7 @@ s_tag * tag_init_map (s_tag *tag, uw count);
s_tag * tag_init_map_1 (s_tag *tag, const char *p);
s_tag * tag_init_ptr (s_tag *tag, void *p);
s_tag * tag_init_ptr_free (s_tag *tag, void *p);
+s_tag * tag_init_quote_copy (s_tag *tag, const s_quote *quote);
s_tag * tag_init_s8 (s_tag *tag, s8 i);
s_tag * tag_init_s16 (s_tag *tag, s16 i);
s_tag * tag_init_s32 (s_tag *tag, s32 i);
@@ -56,6 +57,7 @@ s_tag * tag_init_u8 (s_tag *tag, u8 i);
s_tag * tag_init_u16 (s_tag *tag, u16 i);
s_tag * tag_init_u32 (s_tag *tag, u32 i);
s_tag * tag_init_u64 (s_tag *tag, u64 i);
+s_tag * tag_init_unquote_copy (s_tag *tag, const s_unquote *unquote);
s_tag * tag_init_uw (s_tag *tag, uw i);
s_tag * tag_init_var (s_tag *tag);
s_tag * tag_init_void (s_tag *tag);
@@ -81,6 +83,7 @@ s_tag * tag_new_map (uw count);
s_tag * tag_new_map_1 (const char *p);
s_tag * tag_new_ptr (void *p);
s_tag * tag_new_ptr_free (void *p);
+s_tag * tag_new_quote_copy (const s_quote *quote);
s_tag * tag_new_s8 (s8 i);
s_tag * tag_new_s16 (s16 i);
s_tag * tag_new_s32 (s32 i);
@@ -101,6 +104,7 @@ s_tag * tag_new_u8 (u8 i);
s_tag * tag_new_u16 (u16 i);
s_tag * tag_new_u32 (u32 i);
s_tag * tag_new_u64 (u64 i);
+s_tag * tag_new_unquote_copy (const s_unquote *unquote);
s_tag * tag_new_uw (uw i);
s_tag * tag_new_var (void);
s_tag * tag_new_void (void);
@@ -126,6 +130,7 @@ s_tag * tag_map (s_tag *tag, uw count);
s_tag * tag_map_1 (s_tag *tag, const char *p);
s_tag * tag_ptr (s_tag *tag, void *p);
s_tag * tag_ptr_free (s_tag *tag, void *p);
+s_tag * tag_quote_copy (s_tag *tag, const s_quote *quote);
s_tag * tag_s8 (s_tag *tag, s8 i);
s_tag * tag_s16 (s_tag *tag, s16 i);
s_tag * tag_s32 (s_tag *tag, s32 i);
@@ -146,6 +151,7 @@ s_tag * tag_u8 (s_tag *tag, u8 i);
s_tag * tag_u16 (s_tag *tag, u16 i);
s_tag * tag_u32 (s_tag *tag, u32 i);
s_tag * tag_u64 (s_tag *tag, u64 i);
+s_tag * tag_unquote_copy (s_tag *tag, const s_unquote *unquote);
s_tag * tag_uw (s_tag *tag, uw i);
s_tag * tag_var (s_tag *tag);
s_tag * tag_void (s_tag *tag);
diff --git a/libc3/tag_init.rb b/libc3/tag_init.rb
index 2922eef..745aaf2 100644
--- a/libc3/tag_init.rb
+++ b/libc3/tag_init.rb
@@ -340,6 +340,8 @@ class TagInitList
[Arg.new("void *", "p")]),
TagInit.new("ptr_free", "TAG_PTR_FREE", :init_mode_init,
[Arg.new("void *", "p")]),
+ TagInit.new("quote", "copy", "TAG_QUOTE", :init_mode_init,
+ [Arg.new("const s_quote *", "quote")]),
TagInit.new("s8", "TAG_S8", :init_mode_direct,
[Arg.new("s8", "i")]),
TagInit.new("s16", "TAG_S16", :init_mode_direct,
@@ -383,6 +385,8 @@ class TagInitList
[Arg.new("u32", "i")]),
TagInit.new("u64", "TAG_U64", :init_mode_direct,
[Arg.new("u64", "i")]),
+ TagInit.new("unquote", "copy", "TAG_UNQUOTE", :init_mode_init,
+ [Arg.new("const s_unquote *", "unquote")]),
TagInit.new("uw", "TAG_UW", :init_mode_direct,
[Arg.new("uw", "i")]),
TagInit.new("var", "TAG_VAR", :init_mode_none, []),
@@ -520,6 +524,7 @@ tag_init_c.content = <<EOF
#include "tag_init.h"
#include "time.h"
#include "tuple.h"
+#include "unquote.h"
#{inits.def_tag_init.c_word_wrap}
#{inits.def_tag_new.c_word_wrap}
#{inits.def_tag.c_word_wrap}
diff --git a/test/ic3/quote.in b/test/ic3/quote.in
new file mode 100644
index 0000000..4af054b
--- /dev/null
+++ b/test/ic3/quote.in
@@ -0,0 +1,35 @@
+quote 1
+quote a = 1 + 1
+quote a + a
+quote %{a: 1}
+quote %{"a" => 1}
+quote %{1 => 1}
+quote %{1 + 1 => 1}
+quote %{1 => 1 + 1}
+quote quote 1
+quote quote a = 1 + 1
+quote quote a + a
+quote quote %{a: 1}
+quote quote %{"a" => 1}
+quote quote %{1 => 1}
+quote quote %{1 + 1 => 1}
+quote quote %{1 => 1 + 1}
+quote quote 1
+quote quote unquote a = 1 + 1
+quote quote unquote a + a
+quote quote %{a: unquote 1}
+quote quote %{unquote "a" => unquote 1}
+quote quote %{unquote 1 => unquote 1}
+quote quote %{unquote 1 => 1}
+quote quote %{unquote 1 + 1 => 1}
+quote quote %{1 => unquote 1 + 1}
+quote quote %{unquote unquote 1 + 1 => 1}
+quote quote %{1 => unquote unquote 1 + 1}
+quote unquote 1
+quote unquote a = 1 + 1
+quote unquote a + a
+quote unquote %{a: 1}
+quote unquote %{"a" => 1}
+quote unquote %{1 => 1}
+quote unquote %{1 + 1 => 1}
+quote unquote %{1 => 1 + 1}
diff --git a/test/ic3/quote.out.expected b/test/ic3/quote.out.expected
new file mode 100644
index 0000000..db57b2b
--- /dev/null
+++ b/test/ic3/quote.out.expected
@@ -0,0 +1,35 @@
+1
+a = 1 + 1
+a + a
+%{a: 1}
+%{"a" => 1}
+%{1 => 1}
+%{1 + 1 => 1}
+%{1 => 1 + 1}
+quote 1
+quote a = 1 + 1
+quote a + a
+quote %{a: 1}
+quote %{"a" => 1}
+quote %{1 => 1}
+quote %{1 + 1 => 1}
+quote %{1 => 1 + 1}
+quote 1
+quote a = 1 + 1
+quote a + a
+quote %{a: 1}
+quote %{"a" => 1}
+quote %{1 => 1}
+quote %{1 => 1}
+quote %{1 + 1 => 1}
+quote %{1 => 1 + 1}
+quote %{unquote 1 + 1 => 1}
+quote %{1 => unquote 1 + 1}
+1
+2
+4
+%{a: 1}
+%{"a" => 1}
+%{1 => 1}
+%{2 => 1}
+%{1 => 2}
diff --git a/test/ic3/quote.ret.expected b/test/ic3/quote.ret.expected
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/ic3/quote.ret.expected
@@ -0,0 +1 @@
+0