From 13efe91101a11f41caf6321a8b2fbdd96ef9927a Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Tue, 27 Jul 2021 16:41:12 +0000 Subject: remove clausenr from terms, and put it into goals instead. Next up is implementing the control constructs in C, since they misbehave right now due to the new changes --- eval.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 16 deletions(-) (limited to 'eval.c') 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); -- cgit v1.2.3