summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-07-05 16:27:38 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-07-05 16:27:38 +0000
commit44ab8a339c78bcc3460d44b2f435116f21faa60a (patch)
treefa512c143c5df81c0c333a187b9083cbac9636f6 /eval.c
parent3f26a0f2a1f699e628136ec5be6178b5ab40fc44 (diff)
First step on modules. Still very very rough.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c72
1 files changed, 45 insertions, 27 deletions
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;