ref: fa83d3f1aba932e99833244ebb38b7415b142bd7
parent: a106f8db4ec30b159c0fcef120c3e8b55b3ffdb8
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Wed Jun 30 18:43:00 EDT 2021
Add =../2
--- a/builtins.c
+++ b/builtins.c
@@ -22,6 +22,7 @@
BuiltinProto(builtincompare);
BuiltinProto(builtinfunctor);
BuiltinProto(builtinarg);
+BuiltinProto(builtinuniv);
int compareterms(Term *, Term *);
@@ -75,6 +76,8 @@
return builtinfunctor;
if(Match(L"arg", 3))
return builtinarg;
+ if(Match(L"=..", 2))
+ return builtinuniv;
return nil;
}
@@ -362,4 +365,72 @@
Term *t;
for(i = 0, t = term->children; i < n->ival; i++, t = t->next);
return unify(arg, t, bindings);
+}
+
+Term *
+mklist(Term *elems)
+{
+ if(elems == nil)
+ return mkatom(L"[]");
+ else{
+ Term *t = copyterm(elems, nil);
+ t->next = mklist(elems->next);
+ return mkcompound(L".", 2, t);
+ }
+}
+
+int
+listlength(Term *term)
+{
+ if(term->tag == AtomTerm && runestrcmp(term->text, L"[]") == 0)
+ return 0;
+ else if(term->tag == CompoundTerm && term->arity == 2 && runestrcmp(term->text, L".") == 0){
+ int taillength = listlength(term->children->next);
+ return (taillength == -1) ? -1 : 1 + taillength;
+ }else
+ return -1;
+}
+
+int
+builtinuniv(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ Term *term = goal->children;
+ Term *list = term->next;
+
+ int len;
+ if(term->tag == VariableTerm){
+ Rune *name;
+ Term *elems = nil;
+ Term *realterm;
+ int i;
+
+ len = listlength(list);
+ if(len < 1)
+ return 0;
+ if(list->children->tag != AtomTerm)
+ return 0;
+ name = list->children->text;
+
+ list = list->children->next;
+ for(i = 1; i < len; i++){
+ Term *t = copyterm(list->children, nil);
+ elems = appendterm(elems, t);
+ list = list->children->next;
+ }
+ realterm = mkcompound(name, len-1, elems);
+ return unify(term, realterm, bindings);
+ }else if(term->tag == CompoundTerm){
+ Term *elems = mkatom(term->text);
+ elems->next = term->children;
+ Term *reallist = mklist(elems);
+ return unify(list, reallist, bindings);
+ }else{
+ Term *t = copyterm(term, nil);
+ t->next = mkatom(L"[]");
+ Term *reallist = mkcompound(L".", 2, t);
+ return unify(list, reallist, bindings);
+ }
}
\ No newline at end of file