diff --git a/libc3/buf.c b/libc3/buf.c
index bb44e4e..8009e5d 100644
--- a/libc3/buf.c
+++ b/libc3/buf.c
@@ -176,8 +176,6 @@ sw buf_ignore_spaces_but_newline (s_buf *buf)
return r;
result += csize;
}
- if (! result && r < 0)
- return r;
return result;
}
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index c6cc8ee..02c39b4 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -653,6 +653,7 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence)
if (! operator_resolve(&next_op, 2, &next_op))
goto restore;
op = next_op;
+ tmp.ident = op;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
diff --git a/libc3/call.c b/libc3/call.c
index b43046f..829305c 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -17,6 +17,8 @@
#include "buf_parse.h"
#include "call.h"
#include "cfn.h"
+#include "facts.h"
+#include "facts_cursor.h"
#include "facts_with.h"
#include "facts_with_cursor.h"
#include "fn.h"
@@ -47,13 +49,14 @@ s_call * call_copy (const s_call *src, s_call *dest)
bool call_get (s_call *call, s_facts *facts)
{
- s_facts_with_cursor cursor;
+ s_facts_cursor cursor;
s_tag tag_cfn;
s_tag tag_fn;
s_tag tag_ident;
s_tag tag_is_a;
s_tag tag_macro;
s_tag tag_module_name;
+ s_tag tag_operator;
s_tag tag_special_operator;
s_tag tag_sym;
s_tag tag_symbol;
@@ -64,62 +67,54 @@ bool call_get (s_call *call, s_facts *facts)
tag_init_1( &tag_is_a, ":is_a");
tag_init_1( &tag_macro, ":macro");
tag_init_sym( &tag_module_name, call->ident.module);
+ tag_init_1( &tag_operator, ":operator");
tag_init_1( &tag_special_operator, ":special_operator");
tag_init_sym( &tag_sym, call->ident.sym);
tag_init_1( &tag_symbol, ":symbol");
tag_init_var( &tag_var);
- facts_with(facts, &cursor, (t_facts_spec) {
- &tag_module_name,
- &tag_symbol, &tag_ident, /* module exports symbol */
- NULL, NULL });
- if (! facts_with_cursor_next(&cursor)) {
- warnx("symbol %s not found in module %s",
+ if (! facts_find_fact_by_tags(facts, &tag_module_name,
+ &tag_symbol, &tag_ident) &&
+ ! facts_find_fact_by_tags(facts, &tag_module_name,
+ &tag_operator, &tag_ident)) {
+ warnx("call_get: symbol %s not found in module %s",
call->ident.sym->str.ptr.ps8,
call->ident.module->str.ptr.ps8);
- facts_with_cursor_clean(&cursor);
return false;
}
- facts_with_cursor_clean(&cursor);
- facts_with(facts, &cursor, (t_facts_spec) {
- &tag_ident, &tag_fn, &tag_var,
- NULL, NULL });
- if (facts_with_cursor_next(&cursor)) {
- if (tag_var.type != TAG_FN)
- errx(1, "%s.%s is not a function",
- call->ident.module->str.ptr.ps8,
- call->ident.sym->str.ptr.ps8);
- call->fn = fn_new_copy(&tag_var.data.fn);
+ facts_with_tags(facts, &cursor, &tag_ident, &tag_fn, &tag_var);
+ if (facts_cursor_next(&cursor)) {
+ if (tag_var.type == TAG_FN)
+ call->fn = fn_new_copy(&tag_var.data.fn);
+ else
+ warnx("call_get: %s.%s is not a function",
+ call->ident.module->str.ptr.ps8,
+ call->ident.sym->str.ptr.ps8);
}
- facts_with_cursor_clean(&cursor);
- facts_with(facts, &cursor, (t_facts_spec) {
- &tag_ident, &tag_cfn, &tag_var,
- NULL, NULL });
- if (facts_with_cursor_next(&cursor)) {
- if (tag_var.type != TAG_CFN)
+ facts_cursor_clean(&cursor);
+ facts_with_tags(facts, &cursor, &tag_ident, &tag_cfn, &tag_var);
+ if (facts_cursor_next(&cursor)) {
+ if (tag_var.type == TAG_CFN)
+ call->cfn = cfn_new_copy(&tag_var.data.cfn);
+ else
errx(1, "%s.%s is not a C function",
call->ident.module->str.ptr.ps8,
call->ident.sym->str.ptr.ps8);
- call->cfn = cfn_new_copy(&tag_var.data.cfn);
}
- facts_with_cursor_clean(&cursor);
- facts_with(facts, &cursor, (t_facts_spec) {
- &tag_ident, &tag_is_a, &tag_macro, NULL, NULL });
- if (facts_with_cursor_next(&cursor)) {
+ facts_cursor_clean(&cursor);
+ if (facts_find_fact_by_tags(facts, &tag_ident, &tag_is_a,
+ &tag_macro)) {
if (call->fn)
call->fn->macro = true;
if (call->cfn)
call->cfn->macro = true;
}
- facts_with_cursor_clean(&cursor);
- facts_with(facts, &cursor, (t_facts_spec) {
- &tag_ident, &tag_is_a, &tag_special_operator, NULL, NULL});
- if (facts_with_cursor_next(&cursor)) {
+ if (facts_find_fact_by_tags(facts, &tag_ident, &tag_is_a,
+ &tag_special_operator)) {
if (call->fn)
call->fn->special_operator = true;
if (call->cfn)
call->cfn->special_operator = true;
}
- facts_with_cursor_clean(&cursor);
return true;
}
diff --git a/libc3/cfn.c b/libc3/cfn.c
index c629fc2..1ba4e77 100644
--- a/libc3/cfn.c
+++ b/libc3/cfn.c
@@ -58,7 +58,8 @@ s_tag * cfn_apply (s_cfn *cfn, s_list *args, s_tag *dest)
a = args;
while (cfn_arg_types) {
assert(cfn_arg_types->tag.type == TAG_SYM);
- if (cfn_arg_types->tag.data.sym == sym_1("&result"))
+ if (cfn_arg_types->tag.data.sym == sym_1("Result") ||
+ cfn_arg_types->tag.data.sym == sym_1("&result"))
if (cfn->cif.rtype == &ffi_type_pointer) {
arg_pointers[i] = tag_to_ffi_pointer(&tmp2, cfn->result_type);
arg_values[i] = &arg_pointers[i];
@@ -206,7 +207,8 @@ s_cfn * cfn_prep_cif (s_cfn *cfn)
free(arg_ffi_type);
return NULL;
}
- if (a->tag.data.sym == sym_1("&result"))
+ if (a->tag.data.sym == sym_1("Result") ||
+ a->tag.data.sym == sym_1("&result"))
cfn->arg_result = true;
i++;
a = list_next(a);
diff --git a/libc3/env.c b/libc3/env.c
index 3a1d493..7afaf61 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -791,6 +791,17 @@ bool env_operator_find (s_env *env, const s_ident *op)
&tag_operator) ? 1 : 0;
}
+s_ident * env_operator_ident (s_env *env, const s_ident *op,
+ s_ident *dest)
+{
+ assert(env);
+ assert(op);
+ assert(dest);
+ dest->module = op->module;
+ dest->sym = env_operator_symbol(env, op);
+ return dest;
+}
+
bool env_operator_is_right_associative (s_env *env, const s_ident *op)
{
s_tag tag_assoc;
@@ -879,6 +890,32 @@ s_ident * env_operator_resolve (s_env *env, const s_ident *op,
return NULL;
}
+const s_sym * env_operator_symbol (s_env *env, const s_ident *op)
+{
+ s_facts_cursor cursor;
+ const s_sym *r = NULL;
+ s_tag tag_op;
+ s_tag tag_symbol;
+ s_tag tag_var;
+ assert(env);
+ assert(op);
+ tag_init_ident(&tag_op, op);
+ tag_init_1( &tag_symbol, ":symbol");
+ tag_init_var( &tag_var);
+ facts_with_tags(&env->facts, &cursor, &tag_op, &tag_symbol, &tag_var);
+ if (facts_cursor_next(&cursor) &&
+ tag_var.type == TAG_SYM) {
+ r = tag_var.data.sym;
+ }
+ else
+ warnx("env_operator_symbol: "
+ "symbol for operator %s not found in module %s",
+ op->sym->str.ptr.ps8,
+ op->module->str.ptr.ps8);
+ facts_cursor_clean(&cursor);
+ return r;
+}
+
void env_pop_error_handler (s_env *env)
{
if (env->error_handler)
diff --git a/libc3/env.h b/libc3/env.h
index 5f6b753..1d3cab4 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -22,50 +22,53 @@ void env_clean (s_env *env);
s_env * env_init (s_env *env);
/* Modifiers. */
-bool env_eval_array (s_env *env, const s_array *array,
- s_array *dest);
-bool env_eval_array_tag (s_env *env, const s_array *array,
- s_tag *dest);
-bool env_eval_call (s_env *env, const s_call *call,
- s_tag *dest);
-bool env_eval_call_arguments (s_env *env, s_list *args,
- s_list **dest);
-bool env_eval_call_cfn (s_env *env, const s_call *call,
+bool env_eval_array (s_env *env, const s_array *array,
+ s_array *dest);
+bool env_eval_array_tag (s_env *env, const s_array *array,
+ s_tag *dest);
+bool env_eval_call (s_env *env, const s_call *call,
+ s_tag *dest);
+bool env_eval_call_arguments (s_env *env, s_list *args,
+ s_list **dest);
+bool env_eval_call_cfn (s_env *env, const s_call *call,
+ s_tag *dest);
+bool env_eval_call_fn (s_env *env, const s_call *call,
+ s_tag *dest);
+bool env_eval_call_resolve (s_env *env, s_call *call);
+bool env_eval_equal_list (s_env *env, const s_list *a,
+ const s_list *b, s_list **dest);
+bool env_eval_equal_tag (s_env *env, const s_tag *a,
+ const s_tag *b, s_tag *dest);
+bool env_eval_equal_tuple (s_env *env, const s_tuple *a,
+ const s_tuple *b, s_tuple *dest);
+bool env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest);
+bool env_eval_ident (s_env *env, const s_ident *ident,
s_tag *dest);
-bool env_eval_call_fn (s_env *env, const s_call *call,
+bool env_eval_list (s_env *env, const s_list *list,
s_tag *dest);
-bool env_eval_call_resolve (s_env *env, s_call *call);
-bool env_eval_equal_list (s_env *env, const s_list *a,
- const s_list *b, s_list **dest);
-bool env_eval_equal_tag (s_env *env, const s_tag *a,
- const s_tag *b, s_tag *dest);
-bool env_eval_equal_tuple (s_env *env, const s_tuple *a,
- const s_tuple *b, s_tuple *dest);
-bool env_eval_fn (s_env *env, const s_fn *fn, s_tag *dest);
-bool env_eval_ident (s_env *env, const s_ident *ident,
- s_tag *dest);
-bool env_eval_list (s_env *env, const s_list *list,
- s_tag *dest);
-bool env_eval_progn (s_env *env, const s_list *program,
- s_tag *dest);
-bool env_eval_quote (s_env *env, const s_quote *quote,
- s_tag *dest);
-bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest);
-bool env_eval_tuple (s_env *env, const s_tuple *tuple,
- s_tag *dest);
-bool env_module_load (const s_sym *module, s_env *env,
- s_facts *facts);
-bool env_module_maybe_reload (const s_sym *module, s_env *env,
- s_facts *facts);
-s8 env_operator_arity (s_env *env, const s_ident *op);
-bool env_operator_find (s_env *env, const s_ident *op);
-bool env_operator_is_right_associative (s_env *env,
- const s_ident *op);
-s8 env_operator_precedence (s_env *env, const s_ident *op);
-s_ident * env_operator_resolve (s_env *env, const s_ident *op,
- u8 arity, s_ident *dest);
-bool env_tag_ident_is_bound (const s_env *env, const s_tag *tag,
- s_facts *facts);
+bool env_eval_progn (s_env *env, const s_list *program,
+ s_tag *dest);
+bool env_eval_quote (s_env *env, const s_quote *quote,
+ s_tag *dest);
+bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest);
+bool env_eval_tuple (s_env *env, const s_tuple *tuple,
+ s_tag *dest);
+bool env_module_load (const s_sym *module, s_env *env,
+ s_facts *facts);
+bool env_module_maybe_reload (const s_sym *module, s_env *env,
+ s_facts *facts);
+s8 env_operator_arity (s_env *env, const s_ident *op);
+bool env_operator_find (s_env *env, const s_ident *op);
+s_ident * env_operator_ident (s_env *env, const s_ident *op,
+ s_ident *dest);
+bool env_operator_is_right_associative (s_env *env,
+ const s_ident *op);
+s8 env_operator_precedence (s_env *env, const s_ident *op);
+s_ident * env_operator_resolve (s_env *env, const s_ident *op,
+ u8 arity, s_ident *dest);
+const s_sym * env_operator_symbol (s_env *env, const s_ident *op);
+bool env_tag_ident_is_bound (const s_env *env,
+ const s_tag *tag, s_facts *facts);
/* Control structures. */
void env_error_f (s_env *env, const char *fmt, ...);
diff --git a/libc3/operator.c b/libc3/operator.c
index 27a95f7..ca44a7a 100644
--- a/libc3/operator.c
+++ b/libc3/operator.c
@@ -23,6 +23,11 @@ bool operator_find (const s_ident *op)
return env_operator_find(&g_c3_env, op);
}
+s_ident * operator_ident (const s_ident *op, s_ident *dest)
+{
+ return env_operator_ident(&g_c3_env, op, dest);
+}
+
bool operator_is_right_associative (const s_ident *op)
{
return env_operator_is_right_associative(&g_c3_env, op);
@@ -38,3 +43,8 @@ s_ident * operator_resolve (const s_ident *op, u8 arity,
{
return env_operator_resolve(&g_c3_env, op, arity, dest);
}
+
+const s_sym * operator_symbol (const s_ident *op)
+{
+ return env_operator_symbol(&g_c3_env, op);
+}
diff --git a/libc3/operator.h b/libc3/operator.h
index 548ebfe..bb021a3 100644
--- a/libc3/operator.h
+++ b/libc3/operator.h
@@ -16,11 +16,13 @@
#include "types.h"
/* Observers */
-s8 operator_arity (const s_ident *op);
-bool operator_find (const s_ident *op);
-bool operator_is_right_associative (const s_ident *op);
-s8 operator_precedence (const s_ident *op);
-s_ident * operator_resolve (const s_ident *ident, u8 arity,
- s_ident *dest);
+s8 operator_arity (const s_ident *op);
+bool operator_find (const s_ident *op);
+s_ident * operator_ident (const s_ident *op, s_ident *dest);
+bool operator_is_right_associative (const s_ident *op);
+s8 operator_precedence (const s_ident *op);
+s_ident * operator_resolve (const s_ident *ident, u8 arity,
+ s_ident *dest);
+const s_sym * operator_symbol (const s_ident *op);
#endif /* OPERATOR_H */
diff --git a/libc3/tag.c b/libc3/tag.c
index 4294e50..c2f270d 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -8120,125 +8120,157 @@ s_tag * tag_sym_1 (s_tag *tag, const s8 *p)
void * tag_to_ffi_pointer (s_tag *tag, const s_sym *type)
{
- if (type == sym_1("tag"))
+ if (type == sym_1("Tag") ||
+ type == sym_1("tag"))
return tag;
switch (tag->type) {
case TAG_VOID:
- if (type == sym_1("void"))
+ if (type == sym_1("Void") ||
+ type == sym_1("void"))
return NULL;
goto invalid_type;
case TAG_ARRAY:
- if (type == sym_1("array"))
+ if (type == sym_1("Array") ||
+ type == sym_1("array"))
return tag->data.array.data;
goto invalid_type;
case TAG_BOOL:
- if (type == sym_1("bool"))
+ if (type == sym_1("Bool") ||
+ type == sym_1("bool"))
return &tag->data.bool;
goto invalid_type;
case TAG_CALL:
- if (type == sym_1("call"))
+ if (type == sym_1("Call") ||
+ type == sym_1("call"))
return &tag->data.call;
goto invalid_type;
case TAG_CFN:
- if (type == sym_1("cfn"))
+ if (type == sym_1("Cfn") ||
+ type == sym_1("cfn"))
return &tag->data.cfn;
goto invalid_type;
case TAG_CHARACTER:
- if (type == sym_1("character"))
+ if (type == sym_1("Character") ||
+ type == sym_1("character"))
return &tag->data.character;
goto invalid_type;
case TAG_F32:
- if (type == sym_1("f32"))
+ if (type == sym_1("F32") ||
+ type == sym_1("f32"))
return &tag->data.f32;
goto invalid_type;
case TAG_F64:
- if (type == sym_1("f64"))
+ if (type == sym_1("f64") ||
+ type == sym_1("F64"))
return &tag->data.f64;
goto invalid_type;
case TAG_FACT:
- if (type == sym_1("fact"))
+ if (type == sym_1("Fact") ||
+ type == sym_1("fact"))
return &tag->data.fact;
goto invalid_type;
case TAG_FN:
- if (type == sym_1("fn"))
+ if (type == sym_1("Fn") ||
+ type == sym_1("fn"))
return &tag->data.fn;
goto invalid_type;
case TAG_IDENT:
- if (type == sym_1("ident"))
+ if (type == sym_1("Ident") ||
+ type == sym_1("ident"))
return &tag->data.ident;
goto invalid_type;
case TAG_INTEGER:
- if (type == sym_1("integer"))
+ if (type == sym_1("Integer") ||
+ type == sym_1("integer"))
return &tag->data.integer;
goto invalid_type;
case TAG_SW:
- if (type == sym_1("sw"))
+ if (type == sym_1("Sw") ||
+ type == sym_1("sw"))
return &tag->data.sw;
goto invalid_type;
case TAG_S64:
- if (type == sym_1("s64"))
+ if (type == sym_1("S64") ||
+ type == sym_1("s64"))
return &tag->data.s64;
goto invalid_type;
case TAG_S32:
- if (type == sym_1("s32"))
+ if (type == sym_1("S32") ||
+ type == sym_1("s32"))
return &tag->data.s32;
goto invalid_type;
case TAG_S16:
- if (type == sym_1("s16"))
+ if (type == sym_1("S16") ||
+ type == sym_1("s16"))
return &tag->data.s16;
goto invalid_type;
case TAG_S8:
- if (type == sym_1("s8"))
+ if (type == sym_1("S8") ||
+ type == sym_1("s8"))
return &tag->data.s8;
goto invalid_type;
case TAG_U8:
- if (type == sym_1("u8"))
+ if (type == sym_1("U8") ||
+ type == sym_1("u8"))
return &tag->data.u8;
goto invalid_type;
case TAG_U16:
- if (type == sym_1("u16"))
+ if (type == sym_1("U16") ||
+ type == sym_1("u16"))
return &tag->data.u16;
goto invalid_type;
case TAG_U32:
- if (type == sym_1("u32"))
+ if (type == sym_1("U32") ||
+ type == sym_1("u32"))
return &tag->data.u32;
goto invalid_type;
case TAG_U64:
- if (type == sym_1("u64"))
+ if (type == sym_1("U64") ||
+ type == sym_1("u64"))
return &tag->data.u64;
goto invalid_type;
case TAG_UW:
- if (type == sym_1("uw"))
+ if (type == sym_1("Uw") ||
+ type == sym_1("uw"))
return &tag->data.uw;
goto invalid_type;
case TAG_LIST:
- if (type == sym_1("list"))
+ if (type == sym_1("List") ||
+ type == sym_1("list"))
return &tag->data.list;
goto invalid_type;
case TAG_PTAG:
- if (type == sym_1("ptag"))
+ if (type == sym_1("Ptag") ||
+ type == sym_1("ptag"))
return (void *) tag->data.ptag;
goto invalid_type;
case TAG_QUOTE:
- if (type == sym_1("quote"))
+ if (type == sym_1("Quote") ||
+ type == sym_1("quote"))
return &tag->data.quote;
goto invalid_type;
case TAG_STR:
- if (type == sym_1("str"))
+ if (type == sym_1("Str") ||
+ type == sym_1("str"))
return &tag->data.str;
- if (type == sym_1("char*"))
+ if (type == sym_1("Char*") ||
+ type == sym_1("char*"))
return (void *) tag->data.str.ptr.ps8;
goto invalid_type;
case TAG_SYM:
- if (type == sym_1("sym"))
+ if (type == sym_1("Sym") ||
+ type == sym_1("sym"))
return (void *) tag->data.sym;
- if (type == sym_1("str"))
+ if (type == sym_1("Str") ||
+ type == sym_1("str"))
return (void *) &tag->data.sym->str;
- if (type == sym_1("char*"))
+ if (type == sym_1("Char*") ||
+ type == sym_1("char*"))
return (void *) tag->data.sym->str.ptr.ps8;
goto invalid_type;
case TAG_TUPLE:
- if (type == sym_1("tuple"))
+ if (type == sym_1("Tuple") ||
+ type == sym_1("tuple"))
return &tag->data.tuple;
goto invalid_type;
case TAG_VAR:
diff --git a/test/env_test.c b/test/env_test.c
index de7dd2e..aabe2f8 100644
--- a/test/env_test.c
+++ b/test/env_test.c
@@ -10,23 +10,52 @@
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
+#include "../libc3/call.h"
#include "../libc3/compare.h"
#include "../libc3/env.h"
#include "../libc3/frame.h"
+#include "../libc3/list.h"
#include "../libc3/sym.h"
#include "../libc3/tag.h"
#include "test.h"
void env_test ();
+TEST_CASE_PROTOTYPE(env_eval_call);
TEST_CASE_PROTOTYPE(env_eval_equal_tag);
+TEST_CASE_PROTOTYPE(env_eval_tag);
TEST_CASE_PROTOTYPE(env_init_clean);
void env_test ()
{
TEST_CASE_RUN(env_init_clean);
TEST_CASE_RUN(env_eval_equal_tag);
+ TEST_CASE_RUN(env_eval_call);
+ TEST_CASE_RUN(env_eval_tag);
}
+TEST_CASE(env_eval_call)
+{
+ s_env env;
+ s_call call;
+ s_tag result;
+ s_tag expected;
+ env_init(&env);
+ test_context("env_eval_call(1 + 2) -> 3");
+ call_init_op(&call);
+ call.ident.module = sym_1("C3");
+ call.ident.sym = sym_1("operator08");
+ call.arguments = list_1("(1, 2)");
+ tag_init_u8(&expected, 3);
+ TEST_ASSERT(env_eval_call(&env, &call, &result));
+ TEST_EQ(compare_tag(&result, &expected), 0);
+ call_clean(&call);
+ tag_clean(&result);
+ tag_clean(&expected);
+ env_clean(&env);
+ test_context(NULL);
+}
+TEST_CASE_END(env_eval_call)
+
TEST_CASE(env_eval_equal_tag)
{
s_env env;
@@ -91,6 +120,26 @@ TEST_CASE(env_eval_equal_tag)
}
TEST_CASE_END(env_eval_equal_tag)
+TEST_CASE(env_eval_tag)
+{
+ s_env env;
+ s_tag x;
+ s_tag y;
+ s_tag expected;
+ env_init(&env);
+ test_context("env_eval_tag(1 + 2) -> 3");
+ TEST_EQ(tag_init_1(&x, "1 + 2"), &x);
+ TEST_EQ(tag_init_1(&expected, "3"), &expected);
+ TEST_ASSERT(env_eval_tag(&env, &x, &y));
+ TEST_EQ(compare_tag(&y, &expected), 0);
+ tag_clean(&x);
+ tag_clean(&y);
+ tag_clean(&expected);
+ env_clean(&env);
+ test_context(NULL);
+}
+TEST_CASE_END(env_eval_tag)
+
TEST_CASE(env_init_clean)
{
s_env env;