shithub: pprolog

Download patch

ref: a8b1fadd149126e9c8d3081a56d206812211f1e6
parent: baea4aa939861fd4efbc71b96f93ba890f01ac40
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Wed Jun 30 15:33:55 EDT 2021

Add builtins for typetests

--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
-1) Add a repl
-2) Figure out how to print the final bindings after running a query
-3) Stop comparing strings all the time
-4) Stop copying the entire goal stack into every choicepoint
-5) Stop creating choicepoints when it is not needed
-6) How to implement builtins nicely?
-7) Right now we copy and allocate a lot, but almost never free stuff.
\ No newline at end of file
+* Add a repl
+* Stop comparing strings all the time
+* Stop copying the entire goal stack into every choicepoint
+* Stop creating choicepoints when it is not needed
+* How to implement builtins nicely?
+* Right now we copy and allocate a lot, but almost never free stuff.
\ No newline at end of file
--- a/builtins.c
+++ b/builtins.c
@@ -4,10 +4,22 @@
 #include "dat.h"
 #include "fns.h"
 
-int builtinfail(Term *, Term *, Goal **, Choicepoint **, Binding **);
-int builtincall(Term *, Term *, Goal **, Choicepoint **, Binding **);
-int builtincut(Term *, Term *, Goal **, Choicepoint **, Binding **);
+#define BuiltinProto(name) int name(Term *, Term *, Goal **, Choicepoint **, Binding **)
+#define Match(X, Y) (runestrcmp(name, X) == 0 && arity == Y)
 
+BuiltinProto(builtinfail);
+BuiltinProto(builtincall);
+BuiltinProto(builtincut);
+BuiltinProto(builtinvar);
+BuiltinProto(builtinatom);
+BuiltinProto(builtininteger);
+BuiltinProto(builtinfloat);
+BuiltinProto(builtinatomic);
+BuiltinProto(builtincompound);
+BuiltinProto(builtinnonvar);
+BuiltinProto(builtinnumber);
+BuiltinProto(builtinstring);
+
 Builtin
 findbuiltin(Term *goal)
 {
@@ -27,12 +39,31 @@
 		return nil;
 	}
 
-	if(!runestrcmp(name, L"fail") && arity == 0)
+	/* Rewrite this so its not just a long if chain */
+	if(Match(L"fail", 0))
 		return builtinfail;
-	if(!runestrcmp(name, L"call") && arity == 1)
+	if(Match(L"call", 1))
 		return builtincall;
-	if(!runestrcmp(name, L"!") && arity == 0)
+	if(Match(L"!", 0))
 		return builtincut;
+	if(Match(L"var", 1))
+		return builtinvar;
+	if(Match(L"atom", 1))
+		return builtinatom;
+	if(Match(L"integer", 1))
+		return builtininteger;
+	if(Match(L"float", 1))
+		return builtinfloat;
+	if(Match(L"atomic", 1))
+		return builtinatomic;
+	if(Match(L"compound", 1))
+		return builtincompound;
+	if(Match(L"nonvar", 1))
+		return builtinnonvar;
+	if(Match(L"number", 1))
+		return builtinnumber;
+	if(Match(L"string", 1))
+		return builtinstring;
 
 	return nil;
 }
@@ -79,4 +110,103 @@
 		cp = cp->next;
 	*choicestack = cp;
 	return 1;
+}
+
+int
+builtinvar(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == VariableTerm);
+}
+
+int
+builtinatom(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == AtomTerm);
+}
+
+int
+builtininteger(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == NumberTerm && arg->numbertype == NumberInt);
+}
+
+int
+builtinfloat(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == NumberTerm && arg->numbertype == NumberFloat);
+}
+
+int
+builtinatomic(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == AtomTerm || arg->tag == NumberTerm);
+}
+
+int
+builtincompound(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == CompoundTerm);
+}
+
+int
+builtinnonvar(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag != VariableTerm);
+}
+
+int
+builtinnumber(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == NumberTerm);
+}
+
+int
+builtinstring(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+	USED(database);
+	USED(goals);
+	USED(choicestack);
+	USED(bindings);
+	Term *arg = goal->children;
+	return (arg->tag == StringTerm);
 }
\ No newline at end of file
--- a/fns.h
+++ b/fns.h
@@ -12,6 +12,7 @@
 Term *mkvariable(Rune *);
 Term *mkcompound(Rune *, int, Term *);
 Term *mknumber(int, vlong, double);
+Term *mkstring(Rune *);
 
 /* eval.c */
 int evalquery(Term *, Term *, Binding **);
--- a/misc.c
+++ b/misc.c
@@ -90,3 +90,11 @@
 	t->dval = dval;
 	return t;
 }
+
+Term *
+mkstring(Rune *text)
+{
+	Term *t = mkterm(StringTerm);
+	t->text = text;
+	return t;
+}
\ No newline at end of file
--- a/parser.c
+++ b/parser.c
@@ -186,8 +186,12 @@
 		result = fullterm(ParenRightTok, nil, nil);
 		match(ParenRightTok);
 		break;
+	case StringTok:
+		result = mkstring(lookahead.text);
+		match(StringTok);
+		break;
 	default:
-		print("Cant parse term of token type %d\n", lookahead.tag);
+		print("Can't parse term of token type %d\n", lookahead.tag);
 		syntaxerror("term");
 		result = nil;
 	}
@@ -513,6 +517,7 @@
 				numD += (peek - L'0') / (10 * place);
 				peek = Bgetrune(parsein);
 			}
+			Bungetrune(parsein);
 			/* Should also lex 123.45E10 */
 			lookahead.tag = FloatTok;
 			lookahead.dval = negative ? -numD : numD;
--- a/prettyprint.c
+++ b/prettyprint.c
@@ -30,6 +30,9 @@
 		else
 			result = runesmprint("%f", t->dval);
 		break;
+	case StringTerm:
+		result = runesmprint("\"%S\"", t->text);
+		break;
 	default:
 		result = runesmprint("cant print term with tag %d", t->tag);
 		break;