summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-06-30 17:03:25 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-06-30 17:03:25 +0000
commit50f83a91220940042962fdb55d07bb03991f52be (patch)
treec2d1046393d7c3f75becd7b2150afab46156baf0 /eval.c
parent347e5bc533070a5e988d82e7588a4e905c7096f3 (diff)
Add support for builtins, and implement true/0, fail/0, call/1, and !/0 builtins
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c95
1 files changed, 46 insertions, 49 deletions
diff --git a/eval.c b/eval.c
index 8a372a3..cf26fdf 100644
--- a/eval.c
+++ b/eval.c
@@ -4,28 +4,13 @@
#include "dat.h"
#include "fns.h"
-typedef struct Goal Goal;
-typedef struct Choicepoint Choicepoint;
-
-struct Goal
-{
- Term *goal;
- Goal *next;
-};
-
-struct Choicepoint
-{
- Goal *goalstack;
- Term *retryclause;
- Choicepoint *next;
-};
-
Goal *addgoals(Goal *, Term *);
Term *findclause(Term *, Term *, Binding **);
int unify(Term *, Term *, Binding **);
int equalterms(Term *, Term *);
void applybinding(Term *, Binding *);
Goal *copygoals(Goal *);
+Builtin findbuiltin(Term *);
static uvlong clausenr;
@@ -63,43 +48,55 @@ evalquery(Term *database, Term *query, Binding **resultbindings)
Retry:
goal = goals->goal;
- /* Find a clause where the head unifies with the goal */
Binding *bindings = nil;
- Term *clause = findclause(dbstart, 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. */
- Choicepoint *cp = malloc(sizeof(Choicepoint));
- cp->goalstack = copygoals(goals);
- cp->next = choicestack;
- cp->retryclause = clause->next;
- choicestack = cp;
- }
- goals = goals->next;
+ Term *clause = nil;
- /* Apply bindings to all goals on the stack. */
- Goal *g;
- for(g = goals; g != nil; g = g->next){
- if(g->goal != nil)
- applybinding(g->goal, bindings);
- }
-
- /* Add clause body as goals, with bindings applied */
- if(clause->tag == CompoundTerm && clause->arity == 2 && runestrcmp(clause->text, L":-") == 0){
- Term *subgoal = copyterm(clause->children->next, nil);
- applybinding(subgoal, bindings);
- goals = addgoals(goals, subgoal);
- }
+ /* 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, &goals->next, &choicestack, &bindings);
+ if(!success)
+ goto Backtrack;
}else{
- if(choicestack == nil)
- return 0;
- Choicepoint *cp = choicestack;
- choicestack = cp->next;
- /* freegoals(goals) */
- goals = cp->goalstack;
- dbstart = cp->retryclause;
+ /* Find a clause where the head unifies with the goal */
+ clause = findclause(dbstart, 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. */
+ Choicepoint *cp = malloc(sizeof(Choicepoint));
+ cp->goalstack = copygoals(goals);
+ cp->next = choicestack;
+ cp->retryclause = clause->next;
+ cp->id = clause->clausenr;
+ choicestack = cp;
+ }
+ }else{
+Backtrack:
+ if(choicestack == nil)
+ return 0;
+ Choicepoint *cp = choicestack;
+ choicestack = cp->next;
+ /* freegoals(goals) */
+ goals = cp->goalstack;
+ dbstart = cp->retryclause;
+ goto Retry;
+ }
+ }
+
+ goals = goals->next;
+
+ /* Apply bindings to all goals on the stack. */
+ Goal *g;
+ for(g = goals; g != nil; g = g->next){
+ if(g->goal != nil)
+ applybinding(g->goal, bindings);
+ }
- goto Retry;
+ /* 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);
+ applybinding(subgoal, bindings);
+ goals = addgoals(goals, subgoal);
}
}
goals = goals->next;