summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-06-30 14:04:15 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-06-30 14:04:15 +0000
commitee4298a2cfbbd9e015cfc775d9d714a9f5035846 (patch)
tree8d6f4b139abf1a645e9e4fe0fba811f64b03839f /eval.c
parent79d1fe1cf2eb6748e2c12ffe9c36a678655302b1 (diff)
Add a basic repl
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c67
1 files changed, 33 insertions, 34 deletions
diff --git a/eval.c b/eval.c
index c755cf5..f3a1e15 100644
--- a/eval.c
+++ b/eval.c
@@ -4,18 +4,9 @@
#include "dat.h"
#include "fns.h"
-typedef struct Binding Binding;
typedef struct Goal Goal;
typedef struct Choicepoint Choicepoint;
-struct Binding
-{
- Rune *name;
- uvlong nr; /* Unique number for each clause. Every time a clause is used, it gets a new number. */
- Term *value;
- Binding *next;
-};
-
struct Goal
{
Term *goal;
@@ -38,15 +29,33 @@ Goal *copygoals(Goal *);
static uvlong clausenr;
-void
-evalquery(Term *database, Term *query)
+int
+evalquery(Term *database, Term *query, Binding **resultbindings)
{
- Goal *goals = addgoals(nil, query);
+ Goal *goals;
Choicepoint *choicestack = nil;
clausenr = 0;
- while(goals != 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;
+
+ /* Now add the actual goals */
+ goals = addgoals(goals, query);
+
+ while(goals->goal != nil){
Term *dbstart;
Term *goal;
@@ -54,13 +63,6 @@ evalquery(Term *database, Term *query)
Retry:
goal = goals->goal;
- if(goal == nil){
- goals = goals->next;
- continue;
- }
-
- print("Solving goal %S\n", prettyprint(goal));
-
/* Find a clause where the head unifies with the goal */
Binding *bindings = nil;
Term *clause = findclause(dbstart, goal, &bindings);
@@ -74,28 +76,23 @@ Retry:
choicestack = cp;
}
goals = goals->next;
- /* Apply bindings to all goals on the top of the stack, down to the "bodystart" goal */
+
+ /* Apply bindings to all goals on the stack. */
Goal *g;
- for(g = goals; g != nil && g->goal != nil; g = g->next)
- applybinding(g->goal, bindings);
+ for(g = goals; g != nil; g = g->next){
+ if(g->goal != nil)
+ applybinding(g->goal, bindings);
+ }
/* Add clause body as goals, with bindings applied */
if(clause->tag == CompoundTerm && clause->arity == 2 && runestrcmp(clause->text, L":-") == 0){
- Goal *bodystart = malloc(sizeof(Goal));
- bodystart->goal = nil;
- bodystart->next = goals;
- goals = bodystart;
-
Term *subgoal = copyterm(clause->children->next, nil);
applybinding(subgoal, bindings);
goals = addgoals(goals, subgoal);
}
}else{
- if(choicestack == nil){
- print("Fail\n");
- return;
- }
- print("Backtracking...\n");
+ if(choicestack == nil)
+ return 0;
Choicepoint *cp = choicestack;
choicestack = cp->next;
/* freegoals(goals) */
@@ -105,7 +102,9 @@ Retry:
goto Retry;
}
}
- print("Success.\n");
+ goals = goals->next;
+ unify(query, goals->goal, resultbindings);
+ return 1;
}
Goal *