diff --git a/libc3/buf_inspect.c b/libc3/buf_inspect.c
index 64eb88a..f5ad38a 100644
--- a/libc3/buf_inspect.c
+++ b/libc3/buf_inspect.c
@@ -1387,7 +1387,7 @@ sw buf_inspect_ident (s_buf *buf, const s_ident *ident)
assert(buf);
assert(ident);
result = 0;
- if (ident->module) {
+ if (ident->module && ident->module != g_c3_env.current_module) {
if ((r = buf_inspect_sym(buf, &ident->module)) < 0)
return r;
result += r;
diff --git a/libc3/env.c b/libc3/env.c
index 5f561d0..401cf33 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -876,6 +876,7 @@ bool env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest)
goto ko;
i++;
}
+ (*tmp_clause)->algo.short_form = src_clause->algo.short_form;
tmp_clause = &(*tmp_clause)->next_clause;
src_clause = src_clause->next_clause;
}
@@ -889,6 +890,335 @@ bool env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest)
return false;
}
+// Like tag_init_copy excepted that the idents get resolved.
+bool env_eval_fn_tag (s_env *env, const s_tag *tag, s_tag *dest)
+{
+ assert(env);
+ assert(tag);
+ assert(dest);
+ switch (tag->type) {
+ case TAG_ARRAY:
+ return env_eval_fn_tag_array(env, &tag->data.array, dest);
+ case TAG_BLOCK:
+ return env_eval_fn_tag_block(env, &tag->data.block, dest);
+ case TAG_CALL:
+ return env_eval_fn_tag_call(env, &tag->data.call, dest);
+ case TAG_COMPLEX:
+ return env_eval_fn_tag_complex(env, tag->data.complex, dest);
+ case TAG_IDENT:
+ return env_eval_fn_tag_ident(env, &tag->data.ident, dest);
+ case TAG_LIST:
+ return env_eval_fn_tag_list(env, tag->data.list, dest);
+ case TAG_MAP:
+ return env_eval_fn_tag_map(env, &tag->data.map, dest);
+ case TAG_QUOTE:
+ return env_eval_fn_tag_quote(env, &tag->data.quote, dest);
+ case TAG_STRUCT:
+ return env_eval_fn_tag_struct(env, &tag->data.struct_, dest);
+ case TAG_TUPLE:
+ return env_eval_fn_tag_tuple(env, &tag->data.tuple, dest);
+ case TAG_UNQUOTE:
+ return env_eval_fn_tag_unquote(env, &tag->data.unquote, dest);
+ case TAG_VOID:
+ case TAG_BOOL:
+ case TAG_CFN:
+ case TAG_CHARACTER:
+ case TAG_F32:
+ case TAG_F64:
+ case TAG_F128:
+ case TAG_FACT:
+ case TAG_FN:
+ case TAG_INTEGER:
+ case TAG_PTAG:
+ case TAG_PTR:
+ case TAG_PTR_FREE:
+ case TAG_RATIO:
+ case TAG_S8:
+ case TAG_S16:
+ case TAG_S32:
+ case TAG_S64:
+ case TAG_STR:
+ case TAG_STRUCT_TYPE:
+ case TAG_SW:
+ case TAG_SYM:
+ case TAG_U8:
+ case TAG_U16:
+ case TAG_U32:
+ case TAG_U64:
+ case TAG_UW:
+ case TAG_VAR:
+ if (! tag_init_copy(dest, tag))
+ return false;
+ return true;
+ }
+ err_puts("env_eval_fn_tag: invalid tag type");
+ assert(! "env_eval_fn_tag: invalid tag type");
+ return false;
+}
+
+bool env_eval_fn_tag_array (s_env *env, const s_array *array,
+ s_tag *dest)
+{
+ uw i;
+ s_tag *tag;
+ s_array tmp = {0};
+ s_tag *tmp_tag;
+ assert(env);
+ assert(array);
+ assert(dest);
+ if (! array->dimension || array->data || ! array->tags) {
+ if (! tag_init_array_copy(dest, array))
+ return false;
+ return true;
+ }
+ if (! array_init_copy_shallow(&tmp, array))
+ return false;
+ tag = array->tags;
+ tmp.tags = alloc(tmp.count * sizeof(s_tag));
+ if (! tmp.tags)
+ goto ko;
+ tmp_tag = tmp.tags;
+ i = 0;
+ while (i < array->count) {
+ if (! env_eval_fn_tag(env, tag, tmp_tag))
+ goto ko;
+ tag++;
+ tmp_tag++;
+ i++;
+ }
+ dest->type = TAG_ARRAY;
+ dest->data.array = tmp;
+ return true;
+ ko:
+ array_clean(&tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_block (s_env *env, const s_block *block,
+ s_tag *dest)
+{
+ uw i = 0;
+ s_block tmp;
+ assert(env);
+ assert(block);
+ assert(dest);
+ block_init(&tmp, block->count);
+ while (i < block->count) {
+ if (! env_eval_fn_tag(env, block->tag + i, tmp.tag + i))
+ goto ko;
+ i++;
+ }
+ dest->type = TAG_BLOCK;
+ dest->data.block = tmp;
+ return true;
+ ko:
+ block_clean(&tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_call (s_env *env, const s_call *call, s_tag *dest)
+{
+ const s_list *arg;
+ s_call tmp = {0};
+ s_list **tmp_arg_last;
+ assert(call);
+ assert(dest);
+ if (! env_ident_resolve_module(env, &call->ident, &tmp.ident))
+ return false;
+ tmp_arg_last = &tmp.arguments;
+ arg = call->arguments;
+ while (arg) {
+ *tmp_arg_last = list_new(NULL);
+ if (! env_eval_fn_tag(env, &arg->tag, &(*tmp_arg_last)->tag))
+ goto ko;
+ tmp_arg_last = &(*tmp_arg_last)->next.data.list;
+ arg = list_next(arg);
+ }
+ if (call->cfn) {
+ tmp.cfn = cfn_new_copy(call->cfn);
+ if (! tmp.cfn)
+ goto ko;
+ }
+ if (call->fn) {
+ tmp.fn = fn_new_copy(call->fn);
+ if (! tmp.fn)
+ goto ko;
+ }
+ dest->type = TAG_CALL;
+ dest->data.call = tmp;
+ return true;
+ ko:
+ call_clean(&tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_complex (s_env *env, const s_complex *c,
+ s_tag *dest)
+{
+ s_tag tmp = {0};
+ assert(env);
+ assert(c);
+ assert(dest);
+ tmp.type = TAG_COMPLEX;
+ tmp.data.complex = complex_new();
+ if (! env_eval_fn_tag(env, &c->x, &tmp.data.complex->x) ||
+ ! env_eval_fn_tag(env, &c->y, &tmp.data.complex->y)) {
+ complex_delete(tmp.data.complex);
+ return false;
+ }
+ *dest = tmp;
+ return true;
+}
+
+bool env_eval_fn_tag_ident (s_env *env, const s_ident *ident,
+ s_tag *dest)
+{
+ s_ident tmp = {0};
+ assert(env);
+ assert(ident);
+ assert(dest);
+ if (! env_ident_resolve_module(env, ident, &tmp))
+ return false;
+ dest->type = TAG_IDENT;
+ dest->data.ident = tmp;
+ return true;
+}
+
+bool env_eval_fn_tag_list (s_env *env, const s_list *list, s_tag *dest)
+{
+ s_list *next;
+ s_list *tmp = NULL;
+ s_list **tail = &tmp;
+ assert(env);
+ assert(dest);
+ while (list) {
+ *tail = list_new(NULL);
+ if (! *tail)
+ goto ko;
+ if (! env_eval_fn_tag(env, &list->tag, &(*tail)->tag))
+ goto ko;
+ next = list_next(list);
+ if (! next)
+ if (! env_eval_fn_tag(env, &list->next, &(*tail)->next))
+ goto ko;
+ tail = &(*tail)->next.data.list;
+ list = next;
+ }
+ dest->type = TAG_LIST;
+ dest->data.list = tmp;
+ return true;
+ ko:
+ list_delete_all(tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_map (s_env *env, const s_map *map, s_tag *dest)
+{
+ s_map tmp;
+ uw i = 0;
+ assert(env);
+ assert(map);
+ assert(dest);
+ if (! map_init(&tmp, map->count))
+ return false;
+ while (i < tmp.count) {
+ if (! env_eval_fn_tag(env, map->key + i, tmp.key + i) ||
+ ! env_eval_fn_tag(env, map->value + i, tmp.value + i))
+ goto ko;
+ i++;
+ }
+ dest->type = TAG_MAP;
+ dest->data.map = tmp;
+ return true;
+ ko:
+ map_clean(&tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_quote (s_env *env, const s_quote *quote,
+ s_tag *dest)
+{
+ s_tag tmp = {0};
+ assert(env);
+ assert(quote);
+ assert(dest);
+ tmp.type = TAG_QUOTE;
+ tmp.data.quote.tag = tag_new();
+ if (! env_eval_fn_tag(env, quote->tag, tmp.data.quote.tag))
+ return false;
+ *dest = tmp;
+ return true;
+}
+
+bool env_eval_fn_tag_struct (s_env *env, const s_struct *s, s_tag *dest)
+{
+ uw i;
+ s_struct *t;
+ s_tag tmp = {0};
+ assert(env);
+ assert(s);
+ assert(dest);
+ tmp.type = TAG_STRUCT;
+ t = &tmp.data.struct_;
+ if (s->data || ! s->tag) {
+ if (! struct_init_copy(t, s))
+ return false;
+ *dest = tmp;
+ return true;
+ }
+ t->type = s->type;
+ t->tag = alloc(t->type->map.count * sizeof(s_tag));
+ if (! t->tag)
+ return false;
+ i = 0;
+ while (i < t->type->map.count) {
+ if (! env_eval_fn_tag(env, s->tag + i, t->tag + i))
+ goto ko;
+ i++;
+ }
+ *dest = tmp;
+ return true;
+ ko:
+ struct_clean(t);
+ return false;
+}
+
+bool env_eval_fn_tag_tuple (s_env *env, const s_tuple *tuple, s_tag *dest)
+{
+ uw i = 0;
+ s_tuple tmp;
+ assert(env);
+ assert(tuple);
+ assert(dest);
+ tuple_init(&tmp, tuple->count);
+ while (i < tuple->count) {
+ if (! env_eval_fn_tag(env, tuple->tag + i, tmp.tag + i))
+ goto ko;
+ i++;
+ }
+ dest->type = TAG_TUPLE;
+ dest->data.tuple = tmp;
+ return true;
+ ko:
+ tuple_clean(&tmp);
+ return false;
+}
+
+bool env_eval_fn_tag_unquote (s_env *env, const s_unquote *unquote,
+ s_tag *dest)
+{
+ s_tag tmp = {0};
+ assert(env);
+ assert(unquote);
+ assert(dest);
+ tmp.type = TAG_UNQUOTE;
+ tmp.data.unquote.tag = tag_new();
+ if (! env_eval_fn_tag(env, unquote->tag, tmp.data.unquote.tag))
+ return false;
+ *dest = tmp;
+ return true;
+}
+
bool env_eval_ident (s_env *env, const s_ident *ident, s_tag *dest)
{
const s_tag *tag;
@@ -1064,9 +1394,16 @@ bool env_eval_quote_call (s_env *env, const s_call *call, s_tag *dest)
tmp_arg_last = &(*tmp_arg_last)->next.data.list;
arg = list_next(arg);
}
- // TODO: copy cfn and fn ?
- tmp.cfn = call->cfn;
- tmp.fn = call->fn;
+ if (call->cfn) {
+ tmp.cfn = cfn_new_copy(call->cfn);
+ if (! tmp.cfn)
+ goto ko;
+ }
+ if (call->fn) {
+ tmp.fn = fn_new_copy(call->fn);
+ if (! tmp.fn)
+ goto ko;
+ }
dest->type = TAG_CALL;
dest->data.call = tmp;
return true;
diff --git a/test/ic3/call.out.expected b/test/ic3/call.out.expected
index b63c7c8..3629d81 100644
--- a/test/ic3/call.out.expected
+++ b/test/ic3/call.out.expected
@@ -7,7 +7,7 @@ Test.test(1)
Test.test(1, 2)
Test.test(1, 2, 3)
first([1, 2])
-C3.first([1, 2])
+first([1, 2])
1
2
3
diff --git a/test/ic3/def.out.expected b/test/ic3/def.out.expected
index 2afe3bc..494bdec 100644
--- a/test/ic3/def.out.expected
+++ b/test/ic3/def.out.expected
@@ -1,13 +1,13 @@
def zero = 0
-C3.zero
+zero
zero
0
def one_two_three = [1, 2, 3]
-C3.one_two_three
+one_two_three
one_two_three
[1, 2, 3]
def double = fn (x) { x * 2 }
-C3.double
+double
double
fn (x) { x * 2 }
double(200)
@@ -20,7 +20,7 @@ def double_tuple = macro (x) do
{x, x}
end
end
-C3.double_tuple
+double_tuple
double_tuple
macro (x) do
quote do
@@ -35,20 +35,20 @@ double_tuple(zero)
double_tuple(one_two_three)
{[1, 2, 3], [1, 2, 3]}
def reverse = fn (x) { List.reverse(x) }
-C3.reverse
-C3.reverse
+reverse
+reverse
fn (x) { List.reverse(x) }
reverse([1, 2, 3])
[3, 2, 1]
def reverse = fn (x) { [:reversed | List.reverse(x)] }
-C3.reverse
-C3.reverse
+reverse
+reverse
fn (x) { [:reversed | List.reverse(x)] }
reverse([1, 2, 3])
[:reversed, 3, 2, 1]
def reverse = fn (x) { List.reverse(x) }
-C3.reverse
-C3.reverse
+reverse
+reverse
fn (x) { List.reverse(x) }
reverse([1, 2, 3])
[3, 2, 1]
diff --git a/test/ic3/defmodule.out.expected b/test/ic3/defmodule.out.expected
index 14ce49e..a240053 100644
--- a/test/ic3/defmodule.out.expected
+++ b/test/ic3/defmodule.out.expected
@@ -23,6 +23,6 @@ Plop
Plop.a
1
Plop.b
-fn () { a }
+fn () { Plop.a }
Plop.b()
1
diff --git a/test/ic3/defoperator.out.expected b/test/ic3/defoperator.out.expected
index eb89716..22c0cde 100644
--- a/test/ic3/defoperator.out.expected
+++ b/test/ic3/defoperator.out.expected
@@ -1,5 +1,5 @@
def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
-C3.operator_muul
+operator_muul
4 **** 4
16
4 **** 4 **** 4