ref: 85adea62d7e8eee9d0e3525d572325db4e58d21a
parent: fa83d3f1aba932e99833244ebb38b7415b142bd7
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Wed Jun 30 19:30:13 EDT 2021
Allow the repl to backtrack to give alternative results
--- a/TODO
+++ b/TODO
@@ -1,4 +1,3 @@
-* 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
--- a/eval.c
+++ b/eval.c
@@ -14,13 +14,12 @@
static uvlong clausenr;
int
-evalquery(Term *database, Term *query, Binding **resultbindings)
+evalquery(Term *database, Term *query, Binding **resultbindings, Choicepoint **resultchoicestack)
{
Goal *goals;
- Choicepoint *choicestack = nil;
+ Choicepoint *choicestack = *resultchoicestack;
- clausenr = 2; /* Start at two since 0 is for the facts in the database, and 1 is for queries */
-
+ if(choicestack == nil){
/*
The goal stack has the original query at the very bottom, protected by a goal there the ->goal field is nil.
This makes it so that we can continue until we hit the protective goal, at which point we have solved everything
@@ -27,17 +26,21 @@
and to get the result we can unify the original query with the one at the bottom of the stack, to get the bindings
applied.
*/
+ goals = malloc(sizeof(Goal));
+ goals->goal = copyterm(query, nil);
+ goals->next = nil;
+ Goal *protector = malloc(sizeof(Goal));
+ protector->goal = nil;
+ protector->next = goals;
+ goals = protector;
- goals = malloc(sizeof(Goal));
- goals->goal = copyterm(query, nil);
- goals->next = nil;
- Goal *protector = malloc(sizeof(Goal));
- protector->goal = nil;
- protector->next = goals;
- goals = protector;
+ /* Now add the actual goals */
+ goals = addgoals(goals, query);
- /* Now add the actual goals */
- goals = addgoals(goals, query);
+ clausenr = 2; /* Start at two since 0 is for the facts in the database, and 1 is for queries */
+ }else{
+ goto Backtrack;
+ }
while(goals->goal != nil){
Term *dbstart;
@@ -76,7 +79,9 @@
Backtrack:
if(choicestack == nil)
return 0;
- print("Backtracking..\n");
+ if(debug)
+ print("Backtracking..\n");
+
Choicepoint *cp = choicestack;
choicestack = cp->next;
/* freegoals(goals) */
@@ -104,6 +109,7 @@
}
goals = goals->next;
unify(query, goals->goal, resultbindings);
+ *resultchoicestack = choicestack;
return 1;
}
--- a/fns.h
+++ b/fns.h
@@ -15,7 +15,7 @@
Term *mkstring(Rune *);
/* eval.c */
-int evalquery(Term *, Term *, Binding **);
+int evalquery(Term *, Term *, Binding **, Choicepoint **);
int unify(Term *, Term *, Binding **);
/* repl.c */
--- a/main.c
+++ b/main.c
@@ -43,7 +43,8 @@
Term *goal;
for(goal = initgoals; goal != nil; goal = goal->next){
Binding *bindings = nil;
- evalquery(database, goal, &bindings);
+ Choicepoint *choicestack = nil;
+ evalquery(database, goal, &bindings, &choicestack);
}
}
--- a/parser.c
+++ b/parser.c
@@ -81,6 +81,7 @@
Term *
parse(int fd, int querymode)
{
+ fd = dup(fd, -1);
parsein = Bfdopen(fd, OREAD);
if(parsein == nil){
print("Could not open file\n");
@@ -95,6 +96,7 @@
uvlong id = 1;
result = copyterm(result, &id);
}
+ Bterm(parsein);
return result;
}
--- a/repl.c
+++ b/repl.c
@@ -1,9 +1,12 @@
#include <u.h>
#include <libc.h>
+#include <bio.h>
#include "dat.h"
#include "fns.h"
+Rune parsefindmore(int);
+
void
repl(Term *database)
{
@@ -12,7 +15,10 @@
print("?- ");
Term *query = parse(fd, 1);
Binding *bindings = nil;
- int success = evalquery(database, query, &bindings);
+ Choicepoint *choicestack = nil;
+ int success;
+FindMore:
+ success = evalquery(database, query, &bindings, &choicestack);
if(success == 0)
print("false.\n");
else{
@@ -20,10 +26,46 @@
print("true.\n");
else{
while(bindings){
- print("%S = %S\n", bindings->name, prettyprint(bindings->value));
+ print(" %S = %S%s",
+ bindings->name,
+ prettyprint(bindings->value),
+ bindings->next ? " ,\n" : "");
bindings = bindings->next;
}
}
+ if(choicestack != nil){
+ print(" ");
+ if(parsefindmore(fd) == L';'){
+ print(";\n");
+ goto FindMore;
+ }else
+ print(".\n");
+ }else{
+ print(".\n");
+ }
}
}
+}
+
+Rune
+parsefindmore(int fd)
+{
+ int consctl = open("/dev/consctl", OWRITE);
+ if(consctl > 0)
+ write(consctl, "rawon", 5);
+ else{
+ print("Could not open /dev/consctl\n");
+ exits("open");
+ }
+
+ fd = dup(fd, -1);
+ Biobuf *input = Bfdopen(fd, OREAD);
+ Rune peek = Bgetrune(input);
+ Bterm(input);
+
+ if(consctl > 0){
+ write(consctl, "rawoff", 6);
+ close(consctl);
+ }
+ return peek;
}
\ No newline at end of file
--- a/stdlib.pl
+++ b/stdlib.pl
@@ -16,10 +16,13 @@
If -> Then ; _ :-
If, !, Then.
+
_ -> _ ; Else :-
!, Else.
+
If ; _ :-
If.
+
_ ; Else :-
Else.