summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c75
1 files changed, 59 insertions, 16 deletions
diff --git a/eval.c b/eval.c
index c8388e6..b5f78bc 100644
--- a/eval.c
+++ b/eval.c
@@ -14,19 +14,20 @@ int
evalquery(Term *query)
{
Binding *replbindings = nil;
- goalstack = addgoals(goalstack, query, getmodule(L"user"));
+ goalstack = addgoals(goalstack, query, getmodule(L"user"), 0);
while(goalstack->goal != nil){
Term *goal = goalstack->goal;
Term *catcher = goalstack->catcher;
Module *module = goalstack->module;
+ uvlong goalnr = goalstack->goalnr;
goalstack = goalstack->next;
if(catcher)
continue;
if(flagdebug)
- print("Working goal: %S:%S\n", module->name, prettyprint(goal, 0, 0, 0, nil));
+ print("Working goal %ulld: %S:%S\n", goalnr, module->name, prettyprint(goal, 0, 1, 0, nil));
if(goal->tag == VariableTerm)
goal = instantiationerror();
@@ -35,7 +36,46 @@ evalquery(Term *query)
Binding *bindings = nil;
Clause *clause = nil;
-
+
+ /* handle special cases which need to cut: !/0, throw/1 */
+ if(goal->tag == AtomTerm && runestrcmp(goal->text, L"!") == 0){
+ Choicepoint *cp = choicestack;
+ /* Cut all choicepoints with an id larger or equal to the goal clause number,
+ since they must have been introduced
+ after this goal's parent.
+ */
+ while(cp != nil && cp->id >= goalnr)
+ cp = cp->next;
+ choicestack = cp;
+ continue;
+ }else if(goal->tag == CompoundTerm && runestrcmp(goal->text, L"throw") == 0 && goal->arity == 1){
+ Term *ball = goal->children;
+ Goal *g;
+ int caught = 0;
+ for(g = goalstack; g != nil && !caught; g = g->next){
+ if(g->catcher == nil)
+ continue;
+
+ if(unify(g->catcher, ball, &bindings)){
+ goalstack = g->next;
+ Goal *newgoal = gmalloc(sizeof(Goal));
+ newgoal->goal = copyterm(g->goal);
+ newgoal->module = g->module;
+ newgoal->catcher = nil;
+ newgoal->next = goalstack;
+ goalstack = newgoal;
+ applybinding(newgoal->goal, bindings);
+
+ Choicepoint *cp = choicestack;
+ while(cp != nil && cp->id >= goalnr)
+ cp = cp->next;
+ choicestack = cp;
+ caught = 1;
+ }
+ }
+ continue;
+ }
+
/* Try to see if the goal can be solved using a builtin first */
Builtin builtin = findbuiltin(goal);
if(builtin != nil){
@@ -79,7 +119,7 @@ evalquery(Term *query)
case UnknownFail:
replacement = mkatom(L"fail");
}
- goalstack = addgoals(goalstack, replacement, module);
+ goalstack = addgoals(goalstack, replacement, module, goalnr);
continue;
}
@@ -111,9 +151,9 @@ Backtrack:
/* Add clause body as goals, with bindings applied */
if(clause != nil && clause->body != nil){
- Term *subgoal = copyterm(clause->body, nil);
+ Term *subgoal = copyterm(clause->body);
applybinding(subgoal, bindings);
- goalstack = addgoals(goalstack, subgoal, module);
+ goalstack = addgoals(goalstack, subgoal, module, clause->clausenr);
}
}
goalstack = goalstack->next;
@@ -122,11 +162,11 @@ Backtrack:
}
Goal *
-addgoals(Goal *goals, Term *t, Module *module)
+addgoals(Goal *goals, Term *t, Module *module, uvlong goalnr)
{
if(t->tag == CompoundTerm && runestrcmp(t->text, L",") == 0 && t->arity == 2){
- goals = addgoals(goals, t->children->next, module);
- goals = addgoals(goals, t->children, module);
+ goals = addgoals(goals, t->children->next, module, goalnr);
+ goals = addgoals(goals, t->children, module, goalnr);
}else{
if(t->tag == CompoundTerm && runestrcmp(t->text, L":") == 0 && t->arity == 2){
Term *moduleterm = t->children;
@@ -143,6 +183,7 @@ addgoals(Goal *goals, Term *t, Module *module)
}
Goal *g = gmalloc(sizeof(Goal));
g->goal = t;
+ g->goalnr = goalnr;
g->module = module;
g->catcher = nil;
g->next = goals;
@@ -194,8 +235,8 @@ unify(Term *a, Term *b, Binding **bindings)
Term *left;
Term *right;
- leftstack = copyterm(a, nil);
- rightstack = copyterm(b, nil);
+ leftstack = copyterm(a);
+ rightstack = copyterm(b);
while(leftstack != nil && rightstack != nil){
left = leftstack;
@@ -211,7 +252,7 @@ unify(Term *a, Term *b, Binding **bindings)
left = right;
right = tmp;
}
- if(left->tag == VariableTerm && right->tag == VariableTerm && right->clausenr > left->clausenr){
+ if(left->tag == VariableTerm && right->tag == VariableTerm && right->varnr > left->varnr){
Term *tmp = left;
left = right;
right = tmp;
@@ -235,12 +276,12 @@ unify(Term *a, Term *b, Binding **bindings)
Term *leftchild = left->children;
Term *rightchild = right->children;
while(leftchild != nil && rightchild != nil){
- Term *t1 = copyterm(leftchild, nil);
+ Term *t1 = copyterm(leftchild);
t1->next = leftstack;
leftstack = t1;
leftchild = leftchild->next;
- Term *t2 = copyterm(rightchild, nil);
+ Term *t2 = copyterm(rightchild);
t2->next = rightstack;
rightstack = t2;
rightchild = rightchild->next;
@@ -300,12 +341,13 @@ copygoals(Goal *goals)
if(goals != nil){
Goal *g = gmalloc(sizeof(Goal));
g->module = goals->module;
+ g->goalnr = goals->goalnr;
if(goals->goal)
- g->goal = copyterm(goals->goal, nil);
+ g->goal = copyterm(goals->goal);
else
g->goal = nil;
if(goals->catcher)
- g->catcher = copyterm(goals->catcher, nil);
+ g->catcher = copyterm(goals->catcher);
else
g->catcher = nil;
g->next = copygoals(goals->next);
@@ -325,6 +367,7 @@ addchoicepoints(Clause *clause, Term *goal, Goal *goals, Module *mod){
Binding *altbindings = nil;
clause = findclause(alt, goal, &altbindings);
if(clause){
+ print("Created choicepoint for %S with id %ulld\n", prettyprint(goal, 0, 1, 0, nil), clause->clausenr);
/* Add choicepoint here */
Choicepoint *cp = gmalloc(sizeof(Choicepoint));
cp->goalstack = copygoals(goals);