diff --git a/ic3/.ic3_history b/ic3/.ic3_history
index 07fec09..c3da4f5 100644
--- a/ic3/.ic3_history
+++ b/ic3/.ic3_history
@@ -1,4 +1,3 @@
-defmodule Plop do def a = 1 end
Plop.a
Plop
defmodule Plop do def a = 1 end
@@ -97,3 +96,4 @@ a
type(a)
def operator_muul = %C3.Operator{sym: :****, symbol_value: cfn Tag "tag_mul" (Tag, Tag, Result), operator_precedence: 11, operator_associativity: :left}
2 **** 4
+1 + 1
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 6052dbd..dd82df2 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -27,6 +27,7 @@
#include "complex.h"
#include "cow.h"
#include "env.h"
+#include "fact.h"
#include "fn.h"
#include "fn_clause.h"
#include "ident.h"
@@ -1019,7 +1020,7 @@ sw buf_parse_cfn (s_buf *buf, s_cfn *dest)
sw result = 0;
const s_sym *result_type;
s_buf_save save;
- s_cfn tmp;
+ s_cfn tmp = {0};
assert(buf);
assert(dest);
buf_save_init(buf, &save);
@@ -1048,8 +1049,11 @@ sw buf_parse_cfn (s_buf *buf, s_cfn *dest)
goto restore;
result += r;
cfn_init(&tmp, name_sym, arg_types, result_type);
+ // FIXME: implement env_eval_cfn
+ /*
cfn_prep_cif(&tmp);
cfn_link(&tmp);
+ */
*dest = tmp;
r = result;
goto clean;
@@ -1481,12 +1485,10 @@ sw buf_parse_f64 (s_buf *buf, f64 *dest) {
sw buf_parse_fact (s_buf *buf, s_fact_w *dest)
{
- s_tag *object = NULL;
- s_tag *predicate = NULL;
sw r;
sw result = 0;
s_buf_save save;
- s_tag *subject = NULL;
+ s_fact_w tmp = {0};
assert(buf);
assert(dest);
buf_save_init(buf, &save);
@@ -1499,7 +1501,7 @@ sw buf_parse_fact (s_buf *buf, s_fact_w *dest)
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
- if ((r = buf_parse_new_tag(buf, &subject)) <= 0)
+ if ((r = buf_parse_tag(buf, &tmp.subject)) <= 0)
goto restore;
result += r;
if ((r = buf_parse_comments(buf)) < 0)
@@ -1517,7 +1519,7 @@ sw buf_parse_fact (s_buf *buf, s_fact_w *dest)
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
- if ((r = buf_parse_new_tag(buf, &predicate)) <= 0)
+ if ((r = buf_parse_tag(buf, &tmp.predicate)) <= 0)
goto restore;
result += r;
if ((r = buf_parse_comments(buf)) < 0)
@@ -1535,7 +1537,7 @@ sw buf_parse_fact (s_buf *buf, s_fact_w *dest)
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
- if ((r = buf_parse_new_tag(buf, &object)) <= 0)
+ if ((r = buf_parse_tag(buf, &tmp.object)) <= 0)
goto restore;
result += r;
if ((r = buf_parse_comments(buf)) < 0)
@@ -1547,19 +1549,12 @@ sw buf_parse_fact (s_buf *buf, s_fact_w *dest)
if ((r = buf_read_1(buf, "}")) < 0)
goto restore;
result += r;
- dest->subject = subject;
- dest->predicate = predicate;
- dest->object = object;
+ *dest = tmp;
r = result;
goto clean;
restore:
+ fact_w_clean(&tmp);
buf_save_restore_rpos(buf, &save);
- if (subject)
- tag_delete(subject);
- if (predicate)
- tag_delete(predicate);
- if (object)
- tag_delete(object);
clean:
buf_save_clean(buf, &save);
return r;
diff --git a/libc3/cfn.c b/libc3/cfn.c
index cd5a8bd..0a7608b 100644
--- a/libc3/cfn.c
+++ b/libc3/cfn.c
@@ -215,7 +215,7 @@ s_cfn * cfn_init_copy (s_cfn *cfn, const s_cfn *src)
return NULL;
tmp.arity = src->arity;
tmp.cif = src->cif;
- if (src->arity) {
+ if (src->arity && src->cif.arg_types) {
tmp.cif.arg_types = alloc((src->cif.nargs + 1) * sizeof(ffi_type *));
if (! tmp.cif.arg_types) {
list_delete_all(tmp.arg_types);
diff --git a/libc3/env.c b/libc3/env.c
index 9ecfb28..94ad8eb 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -578,6 +578,23 @@ bool env_eval_call_resolve (s_env *env, s_call *call)
return true;
}
+bool env_eval_cfn (s_env *env, const s_cfn *cfn, s_tag *dest)
+{
+ s_cfn tmp;
+ assert(cfn);
+ assert(dest);
+ (void) env;
+ if (! cfn_init_copy(&tmp, cfn))
+ return false;
+ if (! cfn_prep_cif(&tmp))
+ return false;
+ if (! cfn_link(&tmp))
+ return false;
+ dest->type = TAG_CFN;
+ dest->data.cfn = tmp;
+ return true;
+}
+
bool env_eval_complex (s_env *env, const s_complex *c, s_tag *dest)
{
s_complex *tmp = NULL;
@@ -1512,6 +1529,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
return env_eval_block(env, &tag->data.block, dest);
case TAG_CALL:
return env_eval_call(env, &tag->data.call, dest);
+ case TAG_CFN:
+ return env_eval_cfn(env, &tag->data.cfn, dest);
case TAG_COMPLEX:
return env_eval_complex(env, tag->data.complex, dest);
case TAG_COW:
@@ -1533,7 +1552,6 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
case TAG_TUPLE:
return env_eval_tuple(env, &tag->data.tuple, dest);
case TAG_BOOL:
- case TAG_CFN:
case TAG_CHARACTER:
case TAG_F32:
case TAG_F64:
@@ -1595,6 +1613,41 @@ bool env_eval_void (s_env *env, const void *_, s_tag *dest)
return true;
}
+s_fact_w * env_fact_w_eval (s_env *env, const s_fact_w *fact,
+ s_fact_w *dest)
+{
+ s_fact_w tmp = {0};
+ assert(env);
+ assert(fact);
+ assert(dest);
+ if (fact->subject.type == TAG_CFN) {
+ if (! env_eval_tag(env, &fact->subject, &tmp.subject))
+ return NULL;
+ }
+ else {
+ if (! tag_init_copy(&tmp.subject, &fact->subject))
+ return NULL;
+ }
+ if (fact->predicate.type == TAG_CFN) {
+ if (! env_eval_tag(env, &fact->predicate, &tmp.predicate))
+ return NULL;
+ }
+ else {
+ if (! tag_init_copy(&tmp.predicate, &fact->predicate))
+ return NULL;
+ }
+ if (fact->object.type == TAG_CFN) {
+ if (! env_eval_tag(env, &fact->object, &tmp.object))
+ return NULL;
+ }
+ else {
+ if (! tag_init_copy(&tmp.object, &fact->object))
+ return NULL;
+ }
+ *dest = tmp;
+ return dest;
+}
+
const s_tag * env_frames_get (const s_env *env, const s_sym *name)
{
const s_tag *tag;
@@ -1944,7 +1997,6 @@ bool env_module_maybe_reload (s_env *env, const s_sym *module,
}
if (! r)
return false;
- //io_inspect_str(&path);
if (! file_mtime(&path, &tag_mtime)) {
str_clean(&path);
return false;
@@ -2292,8 +2344,8 @@ bool * env_struct_type_exists (s_env *env, const s_sym *module,
return NULL;
if (! facts_cursor_next(&cursor, &fact))
return NULL;
- facts_cursor_clean(&cursor);
*dest = fact ? true : false;
+ facts_cursor_clean(&cursor);
return dest;
}
diff --git a/libc3/env.h b/libc3/env.h
index 26abfca..7730ac9 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -66,6 +66,7 @@ bool env_eval_call_fn_args (s_env *env, const s_fn *fn,
const s_list *arguments,
s_tag *dest);
bool env_eval_call_resolve (s_env *env, s_call *call);
+bool env_eval_cfn (s_env *env, const s_cfn *cfn, s_tag *dest);
bool env_eval_complex (s_env *env, const s_complex *c,
s_tag *dest);
bool env_eval_cow (s_env *env, const s_cow *cow, s_tag *dest);
@@ -161,6 +162,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag,
bool env_eval_tuple (s_env *env, const s_tuple *tuple,
s_tag *dest);
bool env_eval_void (s_env *env, const void *_, s_tag *dest);
+s_fact_w * env_fact_w_eval (s_env *env, const s_fact_w *fact,
+ s_fact_w *dest);
bool * env_ident_is_special_operator (s_env *env,
const s_ident *ident,
bool *dest);
diff --git a/libc3/fact.c b/libc3/fact.c
index 11cd450..2737b9f 100644
--- a/libc3/fact.c
+++ b/libc3/fact.c
@@ -91,17 +91,24 @@ s_str * fact_inspect (const s_fact *fact, s_str *dest)
return buf_to_str(&buf, dest);
}
-s_fact * fact_r (const s_fact_w *fact)
+void fact_r (const s_fact_w *fact, s_fact *dest)
{
- return (s_fact *) fact;
+ s_fact tmp = {0};
+ tmp.subject = &fact->subject;
+ tmp.predicate = &fact->predicate;
+ tmp.object = &fact->object;
+ tmp.id = fact->id;
+ *dest = tmp;
}
void fact_w_clean (s_fact_w *fact)
{
- tag_delete(fact->subject);
- fact->subject = NULL;
- tag_delete(fact->predicate);
- fact->predicate = NULL;
- tag_delete(fact->object);
- fact->object = NULL;
+ tag_clean(&fact->subject);
+ tag_clean(&fact->predicate);
+ tag_clean(&fact->object);
+}
+
+s_fact_w * fact_w_eval (const s_fact_w *fact, s_fact_w *dest)
+{
+ return env_fact_w_eval(&g_c3_env, fact, dest);
}
diff --git a/libc3/fact.h b/libc3/fact.h
index 9c1d43c..16563f4 100644
--- a/libc3/fact.h
+++ b/libc3/fact.h
@@ -22,13 +22,14 @@ s_fact * fact_init (s_fact *fact, const s_tag *subject,
s_fact * fact_init_cast (s_fact *fact, const s_sym * const *type,
const s_tag *tag);
s_fact * fact_init_copy (s_fact *fact, const s_fact *src);
+void fact_w_clean (s_fact_w *fact);
/* Observers */
uw * fact_hash_uw (const s_fact *fact, uw *dest);
s_str * fact_inspect (const s_fact *fact, s_str *dest);
-s_fact * fact_r (const s_fact_w *fact);
+void fact_r (const s_fact_w *fact, s_fact *dest);
-/* Modifiers */
-void fact_w_clean (s_fact_w *fact);
+/* Operators */
+s_fact_w * fact_w_eval (const s_fact_w *fact, s_fact_w *dest);
#endif /* LIBC3_FACT_H */
diff --git a/libc3/facts.c b/libc3/facts.c
index 313e92e..a0962ec 100644
--- a/libc3/facts.c
+++ b/libc3/facts.c
@@ -307,7 +307,8 @@ s_facts * facts_init (s_facts *facts)
sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
{
s_fact_w fact;
- s_fact *factp;
+ s_fact_w fact_eval;
+ s_fact fact_eval_r;
u64 line;
sw r;
bool replace;
@@ -316,8 +317,11 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
assert(buf);
if ((r = buf_read_1(buf,
"%{module: C3.Facts.Dump,\n"
- " version: 1}\n")) <= 0)
- goto ko_header;
+ " version: 1}\n")) <= 0) {
+ err_write_1("facts_load: invalid or missing header: ");
+ err_puts(path->ptr.pchar);
+ return -1;
+ }
result += r;
facts_lock_w(facts);
line = 3;
@@ -332,36 +336,62 @@ sw facts_load (s_facts *facts, s_buf *buf, const s_str *path)
break;
}
result += r;
- if ((r = buf_parse_fact(buf, &fact)) <= 0)
- goto ko_fact;
+ if ((r = buf_parse_fact(buf, &fact)) <= 0) {
+ err_write_1("facts_load: invalid fact line ");
+ err_inspect_u64(&line);
+ err_write_1(": ");
+ err_puts(path->ptr.pchar);
+ goto ko;
+ }
result += r;
- factp = fact_r(&fact);
- if (replace)
- facts_replace_fact(facts, factp);
- else
- facts_add_fact(facts, factp);
- fact_w_clean(&fact);
if ((r = buf_read_1(buf, "\n")) <= 0) {
- r = -1;
- goto ko_fact;
+ fact_w_clean(&fact);
+ err_write_1("facts_load: missing newline line ");
+ err_inspect_u64(&line);
+ err_write_1(": ");
+ err_puts(path->ptr.pchar);
+ goto ko;
}
result += r;
+ if (! fact_w_eval(&fact, &fact_eval)) {
+ fact_w_clean(&fact);
+ err_write_1("facts_load: invalid fact line ");
+ err_inspect_u64(&line);
+ err_write_1(": ");
+ err_puts(path->ptr.pchar);
+ goto ko;
+ }
+ fact_r(&fact_eval, &fact_eval_r);
+ if (replace) {
+ if (! facts_replace_fact(facts, &fact_eval_r)) {
+ fact_w_clean(&fact_eval);
+ fact_w_clean(&fact);
+ err_write_1("facts_load: failed to replace fact line ");
+ err_inspect_u64(&line);
+ err_write_1(": ");
+ err_puts(path->ptr.pchar);
+ goto ko;
+ }
+ }
+ else {
+ if (! facts_add_fact(facts, &fact_eval_r)) {
+ fact_w_clean(&fact_eval);
+ fact_w_clean(&fact);
+ err_write_1("facts_load: failed to add fact line ");
+ err_inspect_u64(&line);
+ err_write_1(": ");
+ err_puts(path->ptr.pchar);
+ goto ko;
+ }
+ }
+ fact_w_clean(&fact);
+ fact_w_clean(&fact_eval);
line++;
}
facts_lock_unlock_w(facts);
return result;
- ko_header:
- err_write_1("facts_load: invalid or missing header: ");
- err_puts(path->ptr.pchar);
- return -1;
- ko_fact:
+ ko:
facts_lock_unlock_w(facts);
- err_write_1("facts_load: ");
- err_write_1(r ? "invalid" : "missing");
- err_write_1(" fact line ");
- err_inspect_u64(&line);
- err_write_1(": ");
- err_puts(path->ptr.pchar);
return -1;
}
@@ -591,8 +621,8 @@ sw facts_open_file_create (s_facts *facts, const s_str *path)
sw facts_open_log (s_facts *facts, s_buf *buf)
{
bool b;
- s_fact_w fact;
- s_fact *factp;
+ s_fact_w fact_w;
+ s_fact fact;
sw r;
sw result = 0;
assert(facts);
@@ -602,25 +632,25 @@ sw facts_open_log (s_facts *facts, s_buf *buf)
break;
result += r;
if (r) {
- if ((r = buf_parse_fact(buf, &fact)) <= 0)
+ if ((r = buf_parse_fact(buf, &fact_w)) <= 0)
break;
result += r;
- factp = fact_r(&fact);
- if (! facts_add_fact(facts, factp))
+ fact_r(&fact_w, &fact);
+ if (! facts_add_fact(facts, &fact))
return -1;
goto ok;
}
if ((r = buf_read_1(buf, "remove ")) <= 0)
break;
result += r;
- if ((r = buf_parse_fact(buf, &fact)) <= 0)
+ if ((r = buf_parse_fact(buf, &fact_w)) <= 0)
break;
result += r;
- factp = fact_r(&fact);
- if (! facts_remove_fact(facts, factp, &b))
+ fact_r(&fact_w, &fact);
+ if (! facts_remove_fact(facts, &fact, &b))
return -1;
ok:
- fact_w_clean(&fact);
+ fact_w_clean(&fact_w);
if ((r = buf_read_1(buf, "\n")) <= 0)
break;
result += r;
diff --git a/libc3/module.c b/libc3/module.c
index 6d66c60..b047774 100644
--- a/libc3/module.c
+++ b/libc3/module.c
@@ -161,12 +161,6 @@ s_str * module_path (const s_sym *module, const s_str *prefix,
if ((r = buf_write_1(&out, ext)) < 0)
goto error;
result = buf_to_str(&out, dest);
- /*
- if (result) {
- err_inspect_str(dest);
- err_write_1("\n");
- }
- */
return result;
error:
buf_clean(&out);
diff --git a/libc3/types.h b/libc3/types.h
index 7ab9cfa..86f7579 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -238,13 +238,6 @@ struct fact {
uw id; /* serial id */
};
-struct fact_w {
- s_tag *subject;
- s_tag *predicate;
- s_tag *object;
- uw id; /* serial id */
-};
-
struct facts_transaction {
s_fact_action *log;
s_facts_transaction *next;
@@ -531,6 +524,13 @@ struct error_handler
s_tag tag;
};
+struct fact_w {
+ s_tag subject;
+ s_tag predicate;
+ s_tag object;
+ uw id; /* serial id */
+};
+
struct list {
s_tag tag;
s_tag next;