diff --git a/.ikc3_history b/.ikc3_history
index ea7b717..75b2914 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,15 +1,3 @@
-Struct.offset(%HTTP.Response{}, :message)
-Sym.type_size(Str)
-Struct.offset(%HTTP.Response{}, :code)
-Struct.offset(%HTTP.Response{}, :message)
-Struct.offset(%HTTP.Response{}, :response)
-Struct.offset(%HTTP.Response{}, :protocol)
-Struct.offset(%HTTP.Response{}, :code)
-Struct.offset(%HTTP.Response{}, :message)
-Struct.offset(%HTTP.Response{}, :headers)
-Struct.offset(%HTTP.Response{}, :body)
-Struct.offset(%HTTP.Response{}, :message)
-Struct.offset(%HTTP.Response{}, :protocol)
Struct.offset(%HTTP.Response{}, :code)
Struct.offset(%HTTP.Response{}, :message)
Struct.offset(%HTTP.Response{}, :headers)
@@ -97,3 +85,15 @@ Facts.with(Facts.env_facts(), [[?, :symbol_value, ?]], fn (fact) { puts("#{fact.
Facts.with(Facts.env_facts(), [[?, :symbol_value, ?]], fn (fact) { puts(fact.subject); puts(fact.object); void })
Facts.with(Facts.env_facts(), [[?, :symbol_value, object = ?], [object, ], fn (fact) { puts(fact.subject); puts(fact.object); void })
Facts.with(Facts.env_facts(), [[KC3, :operator, ?]], fn (fact) { puts(fact.object); void })
+quote if true do if false do %KC3.Operator{} end end
+if true do if true do %KC3.Operator{} end end
+1 + 100000000000000000000000000000
+1 +i 1
+1 / 2
+1/2
+1.0 / 2
+1.0 / 2 + 1/2
+1.0 / 2 + 0.5
+Facts.with(Facts.env_facts(), [[KC3, :operator, ?]], fn (fact) { puts(fact.object); void })
+Facts.with(Facts.env_facts(), [[?, :operator, ?]], fn (fact) { puts(fact.subject); puts(fact.object); void })
+Facts.with(Facts.env_facts(), [[plop, :operator, op], [op, :symbol_value, value]], fn (fact) { puts(value); void })
diff --git a/libkc3/data.c b/libkc3/data.c
index 9b18b2b..a21391c 100644
--- a/libkc3/data.c
+++ b/libkc3/data.c
@@ -664,7 +664,7 @@ void * data_init_copy (const s_sym *type, void *data, const void *src)
if (type == &g_sym_Uw)
return uw_init_copy(data, src);
if (type == &g_sym_Var)
- return var_init_copy(data, src);
+ return tag_init_copy(data, src);
if (type == &g_sym_Void)
return data;
if (! struct_type_find(type, &st))
diff --git a/libkc3/env.c b/libkc3/env.c
index 4fe5dfd..7de4417 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -35,6 +35,7 @@
#include "fact.h"
#include "facts.h"
#include "facts_cursor.h"
+#include "facts_spec.h"
#include "facts_transaction.h"
#include "facts_with.h"
#include "facts_with_cursor.h"
@@ -2027,7 +2028,7 @@ s_tag * env_facts_with (s_env *env, s_facts *facts, s_list **spec,
if (! struct_allocate(&arguments->tag.data.struct_))
return NULL;
fact_w = arguments->tag.data.struct_.data;
- if (! facts_with_list(facts, &cursor, *spec))
+ if (! env_facts_with_list(env, facts, &cursor, *spec))
return NULL;
while (1) {
if (! facts_with_cursor_next(&cursor, &fact))
@@ -2055,6 +2056,64 @@ s_tag * env_facts_with (s_env *env, s_facts *facts, s_list **spec,
return NULL;
}
+s_facts_with_cursor * env_facts_with_list (s_env *env, s_facts *facts,
+ s_facts_with_cursor *cursor,
+ s_list *spec)
+{
+ s_ident *ident;
+ s_list *spec_i;
+ s_list *spec_j;
+ s_list *tmp;
+ s_list **tmp_tail;
+ s_list **tmp_tail_j;
+ p_facts_spec facts_spec;
+ s_tag *var;
+ assert(facts);
+ assert(cursor);
+ assert(spec);
+ spec_i = spec;
+ tmp = NULL;
+ tmp_tail = &tmp;
+ while (spec_i) {
+ if (spec_i->tag.type != TAG_LIST)
+ goto ko;
+ *tmp_tail = list_new(NULL);
+ tmp_tail_j = &(*tmp_tail)->tag.data.list;
+ spec_j = spec_i->tag.data.list;
+ while (spec_j) {
+ *tmp_tail_j = list_new(NULL);
+ if (spec_j->tag.type == TAG_IDENT) {
+ ident = &spec_j->tag.data.ident;
+ if (! (var = binding_get_w(env->frame->bindings, ident->sym))) {
+ if (! (var = frame_binding_new(env->frame, ident->sym)))
+ goto ko;
+ tag_init_var(var, &g_sym_Tag);
+ }
+ tag_init_copy(&(*tmp_tail_j)->tag, var);
+ }
+ else
+ if (! env_eval_tag(env, &spec_j->tag, &(*tmp_tail_j)->tag))
+ goto ko;
+ tmp_tail_j = &(*tmp_tail_j)->next.data.list;
+ spec_j = list_next(spec_j);
+ }
+ tmp_tail = &(*tmp_tail)->next.data.list;
+ spec_i = list_next(spec_i);
+ }
+ if (! (facts_spec = facts_spec_new_list(tmp))) {
+ err_puts("env_facts_with_list: facts_spec_new_list");
+ assert(! "env_facts_with_list: facts_spec_new_list");
+ goto ko;
+ }
+ if (! facts_with(facts, cursor, facts_spec))
+ goto ko;
+ list_delete_all(tmp);
+ return cursor;
+ ko:
+ list_delete_all(tmp);
+ return NULL;
+}
+
s_tag * env_facts_with_tags (s_env *env, s_facts *facts, s_tag *subject,
s_tag *predicate, s_tag *object,
s_fn *callback, s_tag *dest)
diff --git a/libkc3/env.h b/libkc3/env.h
index b683f0f..29b63f8 100644
--- a/libkc3/env.h
+++ b/libkc3/env.h
@@ -181,6 +181,10 @@ s_fact_w * env_fact_w_eval (s_env *env, const s_fact_w *fact,
s_fact_w *dest);
s_tag * env_facts_with (s_env *env, s_facts *facts, s_list **spec,
s_fn *callback, s_tag *dest);
+s_facts_with_cursor *
+ env_facts_with_list (s_env *env, s_facts *facts,
+ s_facts_with_cursor *cursor,
+ s_list *spec);
s_tag * env_facts_with_tags (s_env *env, s_facts *facts,
s_tag *subject, s_tag *predicate,
s_tag *object, s_fn *callback,
diff --git a/libkc3/facts.c b/libkc3/facts.c
index 9473358..b5fddb7 100644
--- a/libkc3/facts.c
+++ b/libkc3/facts.c
@@ -193,7 +193,8 @@ sw facts_dump (s_facts *facts, s_buf *buf)
return r;
result += r;
facts_lock_r(facts);
- facts_with_0(facts, &cursor, &subject, &predicate, &object);
+ facts_with_0(facts, &cursor, &subject.data.var, &predicate.data.var,
+ &object.data.var);
if (! facts_cursor_next(&cursor, &fact))
goto clean;
while (fact) {
diff --git a/libkc3/facts_cursor.c b/libkc3/facts_cursor.c
index 41b819c..d683ed1 100644
--- a/libkc3/facts_cursor.c
+++ b/libkc3/facts_cursor.c
@@ -23,12 +23,12 @@
void facts_cursor_clean (s_facts_cursor *cursor)
{
assert(cursor);
- if (cursor->var_subject)
- tag_var(cursor->var_subject, cursor->var_subject_type);
- if (cursor->var_predicate)
- tag_var(cursor->var_predicate, cursor->var_predicate_type);
- if (cursor->var_object)
- tag_var(cursor->var_object, cursor->var_object_type);
+ if (cursor->var_subject.ptr)
+ var_reset(&cursor->var_subject);
+ if (cursor->var_predicate.ptr)
+ var_reset(&cursor->var_predicate);
+ if (cursor->var_object.ptr)
+ var_reset(&cursor->var_object);
facts_cursor_lock_clean(cursor);
}
@@ -39,39 +39,35 @@ s_facts_cursor * facts_cursor_init (s_facts *facts,
s_fact *end)
{
s_skiplist_node__fact *pred;
+ s_facts_cursor tmp = {0};
assert(cursor);
assert(index);
pred = skiplist_pred__fact(index, start);
if (! pred)
return NULL;
- cursor->index = index;
- cursor->node = SKIPLIST_NODE_NEXT__fact(pred, 0);
+ tmp.index = index;
+ tmp.node = SKIPLIST_NODE_NEXT__fact(pred, 0);
skiplist_node_delete__fact(pred);
if (start)
- cursor->start = *start;
+ tmp.start = *start;
else {
- cursor->start.subject = TAG_FIRST;
- cursor->start.predicate = TAG_FIRST;
- cursor->start.object = TAG_FIRST;
+ tmp.start.subject = TAG_FIRST;
+ tmp.start.predicate = TAG_FIRST;
+ tmp.start.object = TAG_FIRST;
}
if (end)
- cursor->end = *end;
+ tmp.end = *end;
else {
- cursor->end.subject = TAG_LAST;
- cursor->end.predicate = TAG_LAST;
- cursor->end.object = TAG_LAST;
+ tmp.end.subject = TAG_LAST;
+ tmp.end.predicate = TAG_LAST;
+ tmp.end.object = TAG_LAST;
}
- cursor->var_subject = NULL;
- cursor->var_subject_type = NULL;
- cursor->var_predicate = NULL;
- cursor->var_predicate_type = NULL;
- cursor->var_object = NULL;
- cursor->var_object_type = NULL;
- cursor->facts = facts;
- if (! facts_cursor_lock_init(cursor)) {
- facts_cursor_clean(cursor);
+ tmp.facts = facts;
+ if (! facts_cursor_lock_init(&tmp)) {
+ facts_cursor_clean(&tmp);
return NULL;
}
+ *cursor = tmp;
return cursor;
}
@@ -139,57 +135,57 @@ const s_fact ** facts_cursor_next (s_facts_cursor *cursor,
cursor->node = NULL;
}
if (! cursor->node) {
- if (cursor->var_subject)
- tag_var(cursor->var_subject, cursor->var_subject_type);
- if (cursor->var_predicate)
- tag_var(cursor->var_predicate, cursor->var_predicate_type);
- if (cursor->var_object)
- tag_var(cursor->var_object, cursor->var_object_type);
+ if (cursor->var_subject.ptr)
+ var_reset(&cursor->var_subject);
+ if (cursor->var_predicate.ptr)
+ var_reset(&cursor->var_predicate);
+ if (cursor->var_object.ptr)
+ var_reset(&cursor->var_object);
facts_cursor_lock_unlock(cursor);
*dest = NULL;
return dest;
}
fact = cursor->node->fact;
- if (cursor->var_subject) {
- tag_var(cursor->var_subject, cursor->var_subject_type);
+ if (cursor->var_subject.ptr) {
+ var_reset(&cursor->var_subject);
if (! tag_type(fact->subject, &type))
goto ko;
- if (cursor->var_subject_type != &g_sym_Tag &&
- cursor->var_subject_type != type)
+ if (cursor->var_subject.type != &g_sym_Tag &&
+ cursor->var_subject.type != type)
goto next;
- if (! var_set(cursor->var_subject, fact->subject))
+ if (! var_set(&cursor->var_subject, fact->subject))
goto ko;
}
- if (cursor->var_predicate) {
- tag_var(cursor->var_predicate, cursor->var_predicate_type);
+ if (cursor->var_predicate.ptr) {
+ var_reset(&cursor->var_predicate);
if (! tag_type(fact->predicate, &type))
goto ko;
- if (cursor->var_predicate_type != &g_sym_Tag &&
- cursor->var_predicate_type != type)
+ if (cursor->var_predicate.type != &g_sym_Tag &&
+ cursor->var_predicate.type != type)
goto next;
- if (! var_set(cursor->var_predicate, fact->predicate))
+ if (! var_set(&cursor->var_predicate, fact->predicate))
goto ko;
}
- if (cursor->var_object) {
- tag_var(cursor->var_object, cursor->var_object_type);
+ if (cursor->var_object.ptr) {
+ var_reset(&cursor->var_object);
if (! tag_type(fact->object, &type))
goto ko;
- if (cursor->var_object_type != &g_sym_Tag &&
- cursor->var_object_type != type)
+ if (cursor->var_object.type != &g_sym_Tag &&
+ cursor->var_object.type != type)
goto next;
- if (! var_set(cursor->var_object, fact->object))
+ if (! var_set(&cursor->var_object, fact->object))
goto ko;
}
facts_cursor_lock_unlock(cursor);
*dest = fact;
return dest;
ko:
- if (cursor->var_subject)
- tag_var(cursor->var_subject, cursor->var_subject_type);
- if (cursor->var_predicate)
- tag_var(cursor->var_predicate, cursor->var_predicate_type);
- if (cursor->var_object)
- tag_var(cursor->var_object, cursor->var_object_type);
+ if (cursor->var_subject.ptr)
+ var_reset(&cursor->var_subject);
+ if (cursor->var_predicate.ptr)
+ var_reset(&cursor->var_predicate);
+ if (cursor->var_object.ptr)
+ var_reset(&cursor->var_object);
facts_cursor_lock_unlock(cursor);
return NULL;
}
diff --git a/libkc3/facts_with.c b/libkc3/facts_with.c
index c34e1d3..2b54df8 100644
--- a/libkc3/facts_with.c
+++ b/libkc3/facts_with.c
@@ -20,6 +20,7 @@
#include "facts_with.h"
#include "sym.h"
#include "tag.h"
+#include "var.h"
s_facts_with_cursor * facts_with (s_facts *facts,
s_facts_with_cursor *cursor,
@@ -62,22 +63,16 @@ s_facts_with_cursor * facts_with (s_facts *facts,
s_facts_cursor * facts_with_0 (s_facts *facts,
s_facts_cursor *cursor,
- s_tag *var_subject,
- s_tag *var_predicate,
- s_tag *var_object)
+ s_var *var_subject,
+ s_var *var_predicate,
+ s_var *var_object)
{
assert(facts);
assert(cursor);
facts_cursor_init(facts, cursor, facts->index_spo, NULL, NULL);
- cursor->var_subject = var_subject;
- cursor->var_subject_type =
- var_subject ? var_subject->data.var.type : &g_sym_Void;
- cursor->var_predicate = var_predicate;
- cursor->var_predicate_type =
- var_predicate ? var_predicate->data.var.type : &g_sym_Void;
- cursor->var_object = var_object;
- cursor->var_object_type =
- var_object ? var_object->data.var.type : &g_sym_Void;
+ var_init_copy(&cursor->var_subject, var_subject);
+ var_init_copy(&cursor->var_predicate, var_predicate);
+ var_init_copy(&cursor->var_object, var_object);
return cursor;
}
@@ -86,9 +81,9 @@ s_facts_cursor * facts_with_1_2 (s_facts *facts,
const s_tag *subject,
const s_tag *predicate,
const s_tag *object,
- s_tag *var_subject,
- s_tag *var_predicate,
- s_tag *var_object)
+ s_var *var_subject,
+ s_var *var_predicate,
+ s_var *var_object)
{
s_fact start;
s_fact end;
@@ -112,15 +107,12 @@ s_facts_cursor * facts_with_1_2 (s_facts *facts,
else
tree = facts->index_osp;
facts_cursor_init(facts, cursor, tree, &start, &end);
- cursor->var_subject = var_subject;
- cursor->var_subject_type =
- var_subject ? var_subject->data.var.type : &g_sym_Void;
- cursor->var_predicate = var_predicate;
- cursor->var_predicate_type =
- var_predicate ? var_predicate->data.var.type : &g_sym_Void;
- cursor->var_object = var_object;
- cursor->var_object_type =
- var_object ? var_object->data.var.type : &g_sym_Void;
+ if (var_subject)
+ var_init_copy(&cursor->var_subject, var_subject);
+ if (var_predicate)
+ var_init_copy(&cursor->var_predicate, var_predicate);
+ if (var_object)
+ var_init_copy(&cursor->var_object, var_object);
return cursor;
}
@@ -142,22 +134,6 @@ s_facts_cursor * facts_with_3 (s_facts *facts,
return facts_cursor_init(facts, cursor, facts->index_spo, &fact, &fact);
}
-s_facts_with_cursor * facts_with_list (s_facts *facts,
- s_facts_with_cursor *cursor,
- s_list *spec)
-{
- p_facts_spec s;
- assert(facts);
- assert(cursor);
- assert(spec);
- if (! (s = facts_spec_new_list(spec))) {
- err_puts("facts_with_list: facts_spec_new_list");
- assert(! "facts_with_list: facts_spec_new_list");
- return NULL;
- }
- return facts_with(facts, cursor, s);
-}
-
s_facts_cursor * facts_with_tags (s_facts *facts,
s_facts_cursor *cursor,
s_tag *subject,
@@ -165,9 +141,9 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
s_tag *object)
{
bool unbound;
- s_tag *var_subject = NULL;
- s_tag *var_predicate = NULL;
- s_tag *var_object = NULL;
+ s_var *var_subject = NULL;
+ s_var *var_predicate = NULL;
+ s_var *var_object = NULL;
assert(facts);
assert(cursor);
assert(subject);
@@ -176,15 +152,15 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
if (! tag_is_unbound_var(subject, &unbound))
return NULL;
if (unbound)
- var_subject = subject;
+ var_subject = &subject->data.var;
if (! tag_is_unbound_var(predicate, &unbound))
return NULL;
if (unbound)
- var_predicate = predicate;
+ var_predicate = &predicate->data.var;
if (! tag_is_unbound_var(object, &unbound))
return NULL;
if (unbound)
- var_object = object;
+ var_object = &object->data.var;
if (var_subject && var_predicate && var_object)
return facts_with_0(facts, cursor, var_subject, var_predicate,
var_object);
diff --git a/libkc3/facts_with.h b/libkc3/facts_with.h
index 793198a..904b3a4 100644
--- a/libkc3/facts_with.h
+++ b/libkc3/facts_with.h
@@ -21,18 +21,18 @@ s_facts_with_cursor * facts_with (s_facts *facts,
s_facts_cursor * facts_with_0 (s_facts *facts,
s_facts_cursor *cursor,
- s_tag *var_subject,
- s_tag *var_predicate,
- s_tag *var_object);
+ s_var *var_subject,
+ s_var *var_predicate,
+ s_var *var_object);
s_facts_cursor * facts_with_1_2 (s_facts *facts,
s_facts_cursor *cursor,
const s_tag *subject,
const s_tag *predicate,
const s_tag *object,
- s_tag *var_subject,
- s_tag *var_predicate,
- s_tag *var_object);
+ s_var *var_subject,
+ s_var *var_predicate,
+ s_var *var_object);
s_facts_cursor * facts_with_3 (s_facts *facts,
s_facts_cursor *cursor,
@@ -40,10 +40,6 @@ s_facts_cursor * facts_with_3 (s_facts *facts,
const s_tag *predicate,
const s_tag *object);
-s_facts_with_cursor * facts_with_list (s_facts *facts,
- s_facts_with_cursor *cursor,
- s_list *spec);
-
s_facts_cursor * facts_with_tags (s_facts *facts,
s_facts_cursor *cursor,
s_tag *subject,
diff --git a/libkc3/list_init.c b/libkc3/list_init.c
index 403ea6a..fe3379a 100644
--- a/libkc3/list_init.c
+++ b/libkc3/list_init.c
@@ -647,17 +647,6 @@ s_list * list_init_uw (s_list *list, uw i, s_list *next)
return list;
}
-s_list * list_init_var (s_list *list, const s_sym *type, s_list *next)
-{
- s_list tmp = {0};
- assert(list);
- list_init(&tmp, next);
- if (! tag_init_var(&tmp.tag, type))
- return NULL;
- *list = tmp;
- return list;
-}
-
s_list * list_init_void (s_list *list, s_list *next)
{
s_list tmp = {0};
@@ -1369,19 +1358,6 @@ s_list * list_new_uw (uw i, s_list *next)
return list;
}
-s_list * list_new_var (const s_sym *type, s_list *next)
-{
- s_list *list;
- list = list_new(next);
- if (! list)
- return NULL;
- if (! tag_init_var(&list->tag, type)) {
- free(list);
- return NULL;
- }
- return list;
-}
-
s_list * list_new_void (s_list *next)
{
s_list *list;
diff --git a/libkc3/tag.c b/libkc3/tag.c
index 21e1534..3ce7908 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -527,8 +527,7 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
return tag;
case TAG_VAR:
tag->type = src->type;
- if (! var_init_copy(tag, src))
- return NULL;
+ var_init_copy(&tag->data.var, &src->data.var);
return tag;
case TAG_VOID:
tag_init_void(tag);
@@ -588,6 +587,16 @@ s_tag * tag_init_cast_struct (s_tag *tag, const s_sym * const *type,
return NULL;
}
+s_tag * tag_init_var (s_tag *tag, const s_sym *type)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_VAR;
+ var_init(&tmp.data.var, tag, type);
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_integer_reduce (s_tag *tag)
{
s_integer *i;
@@ -976,12 +985,8 @@ uw * tag_size (const s_tag *tag, uw *dest)
const s_sym *type;
uw tmp = 0;
assert(tag);
- if (tag->type == TAG_VAR) {
- if (! sym_type_size(&tag->data.var.type, &tmp))
- return NULL;
- }
- else if (! tag_type(tag, &type) ||
- ! sym_type_size(&type, &tmp))
+ if (! tag_type(tag, &type) ||
+ ! sym_type_size(&type, &tmp))
return NULL;
*dest = tmp;
return dest;
diff --git a/libkc3/tag_init.c b/libkc3/tag_init.c
index 5ebc612..f6812b7 100644
--- a/libkc3/tag_init.c
+++ b/libkc3/tag_init.c
@@ -624,17 +624,6 @@ s_tag * tag_init_uw (s_tag *tag, uw i)
return tag;
}
-s_tag * tag_init_var (s_tag *tag, const s_sym *type)
-{
- s_tag tmp = {0};
- assert(tag);
- tmp.type = TAG_VAR;
- if (! var_init(&tmp.data.var, type))
- return NULL;
- *tag = tmp;
- return tag;
-}
-
s_tag * tag_init_void (s_tag *tag)
{
s_tag tmp = {0};
@@ -1349,20 +1338,6 @@ s_tag * tag_new_uw (uw i)
return tag;
}
-s_tag * tag_new_var (const s_sym *type)
-{
- s_tag *tag;
- tag = alloc(sizeof(s_tag));
- if (! tag)
- return NULL;
- tag->type = TAG_VAR;
- if (! var_init(&tag->data.var, type)) {
- free(tag);
- return NULL;
- }
- return tag;
-}
-
s_tag * tag_new_void (void)
{
s_tag *tag;
@@ -2009,18 +1984,6 @@ s_tag * tag_uw (s_tag *tag, uw i)
return tag;
}
-s_tag * tag_var (s_tag *tag, const s_sym *type)
-{
- s_tag tmp = {0};
- assert(tag);
- tag_clean(tag);
- tmp.type = TAG_VAR;
- if (! var_init(&tmp.data.var, type))
- return NULL;
- *tag = tmp;
- return tag;
-}
-
s_tag * tag_void (s_tag *tag)
{
s_tag tmp = {0};
diff --git a/libkc3/tag_init.rb b/libkc3/tag_init.rb
index 4f88f33..63e6f58 100644
--- a/libkc3/tag_init.rb
+++ b/libkc3/tag_init.rb
@@ -422,7 +422,7 @@ class TagInitList
[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_init,
+ TagInitProto.new("var", "TAG_VAR", :init_mode_none,
[Arg.new("const s_sym *", "type")]),
TagInit.new("void", "TAG_VOID", :init_mode_none, [])])
end
diff --git a/libkc3/types.h b/libkc3/types.h
index 09172c5..c7df6ac 100644
--- a/libkc3/types.h
+++ b/libkc3/types.h
@@ -355,6 +355,7 @@ struct unwind_protect {
};
struct var {
+ s_tag *ptr;
const s_sym *type;
};
@@ -681,12 +682,9 @@ struct facts_cursor {
s_skiplist_node__fact *node;
s_fact start;
s_fact end;
- s_tag *var_subject;
- const s_sym *var_subject_type;
- s_tag *var_predicate;
- const s_sym *var_predicate_type;
- s_tag *var_object;
- const s_sym *var_object_type;
+ s_var var_subject;
+ s_var var_predicate;
+ s_var var_object;
pthread_mutex_t mutex;
};
diff --git a/libkc3/var.c b/libkc3/var.c
index 6de5913..24ad8e1 100644
--- a/libkc3/var.c
+++ b/libkc3/var.c
@@ -16,9 +16,11 @@
#include "tag.h"
#include "var.h"
-s_var * var_init (s_var *var, const s_sym *type)
+s_var * var_init (s_var *var, s_tag *ptr, const s_sym *type)
{
+ s_var tmp = {0};
assert(var);
+ assert(ptr);
assert(type);
if (! sym_is_module(type)) {
err_write_1("var_init: invalid type: ");
@@ -27,7 +29,9 @@ s_var * var_init (s_var *var, const s_sym *type)
assert(! "var_init: invalid type");
return NULL;
}
- var->type = type;
+ tmp.ptr = ptr;
+ tmp.type = type;
+ *var = tmp;
return var;
}
@@ -54,36 +58,45 @@ s_tag * var_init_cast (s_tag *tag, const s_sym * const *type,
return tag;
}
-s_tag * var_init_copy (s_tag *tag, const s_tag *src)
+s_var * var_init_copy (s_var *var, const s_var *src)
{
- assert(tag);
+ assert(var);
assert(src);
- assert(src->type == TAG_VAR);
- if (src->type != TAG_VAR)
- return NULL;
- tag->type = TAG_VAR;
- tag->data.var = src->data.var;
- return tag;
+ *var = *src;
+ return var;
}
-s_tag * var_set (s_tag *var, const s_tag *value)
+bool * var_is_unbound (s_var *var, bool *dest)
+{
+ assert(var);
+ assert(dest);
+ *dest = var->ptr->type == TAG_VAR;
+ return dest;
+}
+
+s_var * var_reset (s_var *var)
+{
+ s_tag tmp = {0};
+ assert(var);
+ assert(var->ptr);
+ tmp.type = TAG_VAR;
+ var_init(&tmp.data.var, var->ptr, var->type);
+ tag_clean(var->ptr);
+ *var->ptr = tmp;
+ return var;
+}
+
+s_var * var_set (s_var *var, const s_tag *value)
{
const s_sym *value_type;
- const s_sym *var_type;
assert(var);
assert(value);
- if (var->type != TAG_VAR) {
- err_puts("var_set: not a TAG_VAR");
- assert(! "var_set: not a TAG_VAR");
- return NULL;
- }
- var_type = var->data.var.type;
- if (var_type != &g_sym_Tag) {
+ if (var->type != &g_sym_Tag) {
if (! tag_type(value, &value_type))
return NULL;
- if (var_type != value_type) {
+ if (var->type != value_type) {
err_write_1("var_set: type mismatch: ");
- err_inspect_sym(&var_type);
+ err_inspect_sym(&var->type);
err_write_1(" != ");
err_inspect_sym(&value_type);
err_write_1("\n");
@@ -91,5 +104,7 @@ s_tag * var_set (s_tag *var, const s_tag *value)
return NULL;
}
}
- return tag_init_copy(var, value);
+ if (! tag_init_copy(var->ptr, value))
+ return NULL;
+ return var;
}
diff --git a/libkc3/var.h b/libkc3/var.h
index 0e4f97a..e906835 100644
--- a/libkc3/var.h
+++ b/libkc3/var.h
@@ -16,12 +16,16 @@
#include "types.h"
/* Stack-allocation compatible functions. */
-s_var * var_init (s_var *var, const s_sym *type);
+s_var * var_init (s_var *var, s_tag *ptr, const s_sym *type);
s_tag * var_init_cast (s_tag *tag, const s_sym * const *type,
const s_tag *src);
-s_tag * var_init_copy (s_tag *tag, const s_tag *src);
+s_var * var_init_copy (s_var *tag, const s_var *src);
+
+/* Observers. */
+bool * var_is_unbound (s_var *var, bool *dest);
/* Operators. */
-s_tag * var_set (s_tag *var, const s_tag *value);
+s_var * var_reset (s_var *var);
+s_var * var_set (s_var *var, const s_tag *value);
#endif /* LIBKC3_VAR_H */