From 44ab8a339c78bcc3460d44b2f435116f21faa60a Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Mon, 5 Jul 2021 16:27:38 +0000 Subject: First step on modules. Still very very rough. --- eval.c | 72 +++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 27 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index dea8b2b..a7f2c43 100644 --- a/eval.c +++ b/eval.c @@ -6,7 +6,7 @@ #include "fns.h" Goal *addgoals(Goal *, Term *); -Term *findclause(Term *, Term *, Binding **); +Clause *findclause(Clause *, Term *, Binding **); int equalterms(Term *, Term *); Goal *copygoals(Goal *); Builtin findbuiltin(Term *); @@ -14,8 +14,9 @@ Builtin findbuiltin(Term *); static uvlong clausenr; int -evalquery(Term *database, Term *query, Binding **resultbindings) +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. @@ -37,42 +38,60 @@ evalquery(Term *database, Term *query, Binding **resultbindings) goalstack = addgoals(goalstack, query); clausenr = 2; /* Start at two since 0 is for the facts in the database, and 1 is for queries */ + + currentmodule = usermodule; }else{ goto Backtrack; } while(goalstack->goal != nil){ - Term *dbstart; + Clause *startclause; Term *goal; Goal *oldgoalstack; - dbstart = database; + startclause = nil; /* Where to start looking for a matching clause. Used by backtracking */ Retry: - print("Loop run\n"); goal = goalstack->goal; oldgoalstack = goalstack; goalstack = goalstack->next; - if(oldgoalstack->catcher){ - print("Was catchframe\n"); + if(oldgoalstack->catcher) continue; - } if(debug) print("Working goal: %S\n", prettyprint(goal, 0, 0, 0)); + if(startclause == nil && 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; + startclause = m->clauses; + oldgoalstack->goal = goal; + } + }else + goal = typeerror(L"module", module); + } + + if(startclause == nil) + startclause = currentmodule->clauses; + Binding *bindings = nil; - Term *clause = nil; + Clause *clause = nil; /* Try to see if the goal can be solved using a builtin first */ Builtin builtin = findbuiltin(goal); if(builtin != nil){ - int success = builtin(database, goal, &bindings); + int success = builtin(goal, &bindings); if(!success) goto Backtrack; }else{ /* Find a clause where the head unifies with the goal */ - clause = findclause(dbstart, goal, &bindings); + clause = findclause(startclause, goal, &bindings); if(clause != nil){ if(clause->next != nil){ /* Add a choicepoint. Note we create a choicepoint every time, so there is room for improvement. */ @@ -81,6 +100,7 @@ Retry: cp->next = choicestack; cp->retryclause = clause->next; cp->id = clause->clausenr; + cp->currentmodule = currentmodule; choicestack = cp; } }else{ @@ -93,7 +113,8 @@ Backtrack: choicestack = cp->next; /* freegoals(goals) */ goalstack = cp->goalstack; - dbstart = cp->retryclause; + currentmodule = cp->currentmodule; + startclause = cp->retryclause; goto Retry; } } @@ -106,8 +127,8 @@ Backtrack: } /* Add clause body as goals, with bindings applied */ - if(clause != nil && clause->tag == CompoundTerm && clause->arity == 2 && runestrcmp(clause->text, L":-") == 0){ - Term *subgoal = copyterm(clause->children->next, nil); + if(clause != nil && clause->body != nil){ + Term *subgoal = copyterm(clause->body, nil); applybinding(subgoal, bindings); goalstack = addgoals(goalstack, subgoal); } @@ -133,21 +154,18 @@ addgoals(Goal *goals, Term *t) return goals; } -Term * -findclause(Term *database, Term *goal, Binding **bindings) +Clause * +findclause(Clause *clauses, Term *goal, Binding **bindings) { - Term *clause; - Term *head; - for(; database != nil; database = database->next){ - clause = copyterm(database, &clausenr); - clausenr++; - clause->next = database->next; - if(clause->tag == CompoundTerm && runestrcmp(clause->text, L":-") == 0 && clause->arity == 2) - head = clause->children; - else - head = clause; + Clause *clause; + for(; clauses != nil; clauses = clauses->next){ + if(!clauses->public) + continue; - if(unify(head, goal, bindings)) + clause = copyclause(clauses, &clausenr); + clausenr++; + clause->next = clauses->next; + if(unify(clause->head, goal, bindings)) return clause; } return nil; -- cgit v1.2.3