summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-07-27 16:41:12 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-07-27 16:41:12 +0000
commit13efe91101a11f41caf6321a8b2fbdd96ef9927a (patch)
tree4444bb78783fda4d815a4ec91f44052e0de27383 /eval.c
parent4fba3e66dce0d167d2031a0d1f1f6f4571cbd981 (diff)
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 changesHEADfront
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);