summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-07-06 21:23:41 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-07-06 21:23:41 +0000
commit03738c67684b83692d9112858f07c745f355a157 (patch)
tree61ea389bcadab7211212646ea0c532b7d7635325 /eval.c
parenta0eb2bb268774a85411f037983d931f35bc7830f (diff)
Store the calling module in each goal, and fix a bug where unification could leave behind some bindings even though the unification failed.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/eval.c b/eval.c
index e42439f..6c20a7e 100644
--- a/eval.c
+++ b/eval.c
@@ -5,7 +5,6 @@
#include "dat.h"
#include "fns.h"
-Goal *addgoals(Goal *, Term *);
Predicate *findpredicate(Predicate *, Term *);
Clause *findclause(Clause *, Term *, Binding **);
int equalterms(Term *, Term *);
@@ -18,7 +17,6 @@ static uvlong clausenr;
int
evalquery(Term *query, Binding **resultbindings)
{
- static Module *currentmodule = nil;
if(choicestack == nil){
/*
The goal stack has the original query at the very bottom, protected by a catch frame where the ->goal field is nil.
@@ -28,20 +26,21 @@ evalquery(Term *query, Binding **resultbindings)
*/
goalstack = malloc(sizeof(Goal));
goalstack->goal = copyterm(query, nil);
+ goalstack->module = usermodule;
goalstack->catcher = nil;
goalstack->next = nil;
Goal *protector = malloc(sizeof(Goal));
protector->goal = nil;
+ protector->module = usermodule;
protector->catcher = mkvariable(L"catch-var");
protector->next = goalstack;
goalstack = protector;
/* Now add the actual goals */
- goalstack = addgoals(goalstack, query);
+ goalstack = addgoals(goalstack, query, usermodule);
clausenr = 2; /* Start at two since 0 is for the facts in the database, and 1 is for queries */
- currentmodule = usermodule;
}else{
goto Backtrack;
}
@@ -49,27 +48,14 @@ evalquery(Term *query, Binding **resultbindings)
while(goalstack->goal != nil){
Term *goal = goalstack->goal;
Term *catcher = goalstack->catcher;
+ Module *module = goalstack->module;
goalstack = goalstack->next;
if(catcher)
continue;
if(debug)
- print("Working goal: %S\n", prettyprint(goal, 0, 0, 0));
-
- if(goal->tag == CompoundTerm && goal->arity == 2 && runestrcmp(goal->text, L":") == 0){
- Term *module = goal->children;
- if(module->tag == AtomTerm){
- Module *m = getmodule(module->text);
- if(m == nil)
- goal = existenceerror(L"module", module);
- else{
- goal = module->next;
- currentmodule = m;
- }
- }else
- goal = typeerror(L"module", module);
- }
+ print("Working goal: %S:%S\n", module->name, prettyprint(goal, 0, 0, 0));
Binding *bindings = nil;
Clause *clause = nil;
@@ -77,20 +63,20 @@ evalquery(Term *query, Binding **resultbindings)
/* Try to see if the goal can be solved using a builtin first */
Builtin builtin = findbuiltin(goal);
if(builtin != nil){
- int success = builtin(goal, &bindings);
+ int success = builtin(goal, &bindings, module);
if(!success)
goto Backtrack;
}else{
- Predicate *pred = findpredicate(currentmodule->predicates, goal);
+ Predicate *pred = findpredicate(module->predicates, goal);
if(pred == nil){
- print("No predicate matches: %S\n", prettyprint(goal, 0, 0, 0));
+ print("No predicate matches: %S:%S\n", module->name, prettyprint(goal, 0, 0, 0));
goto Backtrack;
}
/* Find a clause where the head unifies with the goal */
clause = findclause(pred->clauses, goal, &bindings);
if(clause != nil)
- addchoicepoints(clause, goal, goalstack, currentmodule);
+ addchoicepoints(clause, goal, goalstack, module);
else{
Backtrack:
if(choicestack == nil)
@@ -100,7 +86,7 @@ Backtrack:
Choicepoint *cp = choicestack;
choicestack = cp->next;
goalstack = cp->goalstack;
- currentmodule = cp->currentmodule;
+ module = cp->currentmodule;
clause = cp->alternative;
bindings = cp->altbindings;
}
@@ -117,7 +103,7 @@ Backtrack:
if(clause != nil && clause->body != nil){
Term *subgoal = copyterm(clause->body, nil);
applybinding(subgoal, bindings);
- goalstack = addgoals(goalstack, subgoal);
+ goalstack = addgoals(goalstack, subgoal, module);
}
}
goalstack = goalstack->next;
@@ -126,14 +112,28 @@ Backtrack:
}
Goal *
-addgoals(Goal *goals, Term *t)
+addgoals(Goal *goals, Term *t, Module *module)
{
if(t->tag == CompoundTerm && runestrcmp(t->text, L",") == 0 && t->arity == 2){
- goals = addgoals(goals, t->children->next);
- goals = addgoals(goals, t->children);
+ goals = addgoals(goals, t->children->next, module);
+ goals = addgoals(goals, t->children, module);
}else{
+ if(t->tag == CompoundTerm && runestrcmp(t->text, L":") == 0 && t->arity == 2){
+ Term *moduleterm = t->children;
+ if(moduleterm->tag == AtomTerm){
+ Module *m = getmodule(moduleterm->text);
+ if(m == nil)
+ t = existenceerror(L"module", moduleterm);
+ else{
+ t = moduleterm->next;
+ module = m;
+ }
+ }else
+ t = typeerror(L"module", moduleterm);
+ }
Goal *g = malloc(sizeof(Goal));
g->goal = t;
+ g->module = module;
g->catcher = nil;
g->next = goals;
goals = g;
@@ -198,7 +198,7 @@ unify(Term *a, Term *b, Binding **bindings)
if(equalterms(left, right))
continue;
else if(left->tag == VariableTerm || right->tag == VariableTerm){
- if(right->tag == VariableTerm){
+ if(left->tag != VariableTerm && right->tag == VariableTerm){
Term *tmp = left;
left = right;
right = tmp;
@@ -235,8 +235,10 @@ unify(Term *a, Term *b, Binding **bindings)
rightstack = t2;
rightchild = rightchild->next;
}
- }else
+ }else{
+ *bindings = nil;
return 0; /* failure */
+ }
}
return 1;
}
@@ -287,6 +289,7 @@ copygoals(Goal *goals)
{
if(goals != nil){
Goal *g = malloc(sizeof(Goal));
+ g->module = goals->module;
if(goals->goal)
g->goal = copyterm(goals->goal, nil);
else