diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 63 |
1 files changed, 33 insertions, 30 deletions
@@ -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 |