diff options
author | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-06-30 23:30:13 +0000 |
---|---|---|
committer | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-06-30 23:30:13 +0000 |
commit | 85adea62d7e8eee9d0e3525d572325db4e58d21a (patch) | |
tree | e976789abf464f9868f9a12778285329db785d7a | |
parent | fa83d3f1aba932e99833244ebb38b7415b142bd7 (diff) |
Allow the repl to backtrack to give alternative results
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | eval.c | 34 | ||||
-rw-r--r-- | fns.h | 2 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | parser.c | 2 | ||||
-rw-r--r-- | repl.c | 46 | ||||
-rw-r--r-- | stdlib.pl | 3 |
7 files changed, 72 insertions, 19 deletions
@@ -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 @@ -14,30 +14,33 @@ Builtin findbuiltin(Term *); 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; - - clausenr = 2; /* Start at two since 0 is for the facts in the database, and 1 is for queries */ + Choicepoint *choicestack = *resultchoicestack; + 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 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 @@ Retry: 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 @@ Backtrack: } goals = goals->next; unify(query, goals->goal, resultbindings); + *resultchoicestack = choicestack; return 1; } @@ -15,7 +15,7 @@ Term *mknumber(int, vlong, double); Term *mkstring(Rune *); /* eval.c */ -int evalquery(Term *, Term *, Binding **); +int evalquery(Term *, Term *, Binding **, Choicepoint **); int unify(Term *, Term *, Binding **); /* repl.c */ @@ -43,7 +43,8 @@ main(int argc, char *argv[]) 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); } } @@ -81,6 +81,7 @@ Term *prologtext(int); 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 @@ parse(int fd, int querymode) uvlong id = 1; result = copyterm(result, &id); } + Bterm(parsein); return result; } @@ -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 @@ repl(Term *database) 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 @@ repl(Term *database) 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 @@ -16,10 +16,13 @@ If -> Then :- If -> Then ; _ :- If, !, Then. + _ -> _ ; Else :- !, Else. + If ; _ :- If. + _ ; Else :- Else. |