ref: d2a0828140c31514c514b8e4fb9a4d52c389d8fe
parent: e9f5f2ffcc62eee564d37d5776e701bab548a496
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Thu Jul 8 17:54:27 EDT 2021
Add current_predicate/1 builtin
--- a/builtins.c
+++ b/builtins.c
@@ -48,6 +48,7 @@
BuiltinProto(builtinwriteterm);
BuiltinProto(builtingeq);
BuiltinProto(builtinclause);
+BuiltinProto(builtincurrentpredicate);
int compareterms(Term *, Term *);
@@ -133,6 +134,8 @@
return builtingeq;
if(Match(L"clause", 3))
return builtinclause;
+ if(Match(L"current_predicate", 2))
+ return builtincurrentpredicate;
return nil;
}
@@ -860,4 +863,43 @@
}
Term *realclauselist = mklist(realclauses);
return unify(clauselist, realclauselist, bindings);
+}
+
+int
+builtincurrentpredicate(Term *goal, Binding **bindings, Module *module)
+{
+ Term *pi = goal->children;
+ Term *list = pi->next;
+
+ if(pi->tag != VariableTerm && !ispredicateindicator(pi, 1))
+ Throw(typeerror(L"predicate_indicator", pi));
+
+ Rune *predname = nil;
+ int arity = -1;
+ if(ispredicateindicator(pi, 1)){
+ Term *functor = pi->children;
+ Term *arityterm = functor->next;
+ if(functor->tag == AtomTerm)
+ predname = functor->text;
+ if(arityterm->tag == IntegerTerm)
+ arity = arityterm->ival;
+ }
+
+ Term *pilist = nil;
+ Predicate *pred;
+ for(pred = module->predicates; pred != nil; pred = pred->next){
+ if(pred->builtin)
+ continue;
+ if(predname && runestrcmp(pred->name, predname) != 0)
+ continue;
+ if(arity != -1 && pred->arity != arity)
+ continue;
+
+ Term *functor = mkatom(pred->name);
+ functor->next = mkinteger(pred->arity);
+ Term *t = mkcompound(L"/", 2, functor);
+ pilist = appendterm(t, pilist);
+ }
+ Term *reallist = mklist(pilist);
+ return unify(list, reallist, bindings);
}
\ No newline at end of file
--- a/dat.h
+++ b/dat.h
@@ -59,6 +59,7 @@
Rune *name;
int arity;
int public;
+ int builtin; /* All the predicates from the system module are builtin */
Clause *clauses;
Predicate *next;
};
--- a/fns.h
+++ b/fns.h
@@ -72,6 +72,7 @@
int ispartiallist(Term *t);
int isemptylist(Term *);
int isnonemptylist(Term *);
+int ispredicateindicator(Term *, int);
Term *listhead(Term *);
Term *listtail(Term *);
--- a/module.c
+++ b/module.c
@@ -18,6 +18,11 @@
exits(nil);
}
+ Predicate *p;
+ for(p = systemmodule->predicates; p != nil; p = p->next){
+ p->builtin = 1;
+ }
+
usermodule = addemptymodule(L"user");
}
@@ -83,6 +88,7 @@
currentpred->arity = arity;
currentpred->clauses = cl;
currentpred->public = 1; /* everything is public for now */
+ currentpred->builtin = 0;
currentpred->next = nil;
}else
currentpred->clauses = appendclause(currentpred->clauses, cl);
--- a/stdlib.pl
+++ b/stdlib.pl
@@ -156,6 +156,10 @@
clause(Head, Body, Clauses),
member(clause(Head, Body), Clauses).
+current_predicate(PI) :-
+ current_predicate(PI, Predicates),
+ member(PI, Predicates).
+
% Basic list predicates
member(X, [X|_]).
member(X, [_|Tail]) :-
--- a/types.c
+++ b/types.c
@@ -38,6 +38,20 @@
return 0;
}
+int
+ispredicateindicator(Term *t, int allowvars)
+{
+ if(t->tag == CompoundTerm && runestrcmp(t->text, L"/") == 0 && t->arity == 2){
+ Term *f = t->children;
+ Term *a = f->next;
+ if(allowvars)
+ return (f->tag == VariableTerm || f->tag == AtomTerm) && (a->tag == VariableTerm || a->tag == IntegerTerm);
+ else
+ return (f->tag == AtomTerm) && (a->tag == IntegerTerm);
+ }else
+ return 0;
+}
+
/* Other functions */
Term *
listhead(Term *t)