shithub: pprolog

Download patch

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