summaryrefslogtreecommitdiff
path: root/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtins.c')
-rw-r--r--builtins.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/builtins.c b/builtins.c
index 4a2161f..cbb01e6 100644
--- a/builtins.c
+++ b/builtins.c
@@ -24,6 +24,8 @@ BuiltinProto(builtinfunctor);
BuiltinProto(builtinarg);
BuiltinProto(builtinuniv);
BuiltinProto(builtinis);
+BuiltinProto(builtincatch);
+BuiltinProto(builtinthrow);
int compareterms(Term *, Term *);
@@ -81,6 +83,10 @@ findbuiltin(Term *goal)
return builtinuniv;
if(Match(L"is", 2))
return builtinis;
+ if(Match(L"catch", 3))
+ return builtincatch;
+ if(Match(L"throw", 1))
+ return builtinthrow;
return nil;
}
@@ -105,6 +111,7 @@ builtincall(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack,
Goal *g = malloc(sizeof(Goal));
g->goal = goal->children;
+ g->catcher = nil;
g->next = *goals;
*goals = g;
@@ -484,4 +491,72 @@ builtinis(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, B
return unify(result, realresult, bindings);
else
return 0;
+}
+
+int
+builtincatch(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(choicestack);
+ USED(bindings);
+
+ Term *catchgoal = goal->children;
+ Term *catcher = catchgoal->next;
+ Term *recover = catcher->next;
+
+ Goal *catchframe = malloc(sizeof(Goal));
+ catchframe->goal = recover;
+ catchframe->catcher = catcher;
+ catchframe->next = *goals;
+ *goals = catchframe;
+
+ Goal *g = malloc(sizeof(Goal));
+ g->goal = catchgoal;
+ g->catcher = nil;
+ g->next = *goals;
+ *goals = g;
+
+ return 1;
+}
+
+int
+builtinthrow(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(choicestack);
+ USED(bindings);
+ USED(goals);
+
+ Term *ball = goal->children;
+
+ print("Throwing: %S\n", prettyprint(ball));
+ Goal *g;
+ for(g = *goals; g != nil; g = g->next){
+ if(g->catcher == nil)
+ continue;
+
+ if(unify(g->catcher, ball, bindings)){
+ if(g->goal == nil){
+ /* As soon as we have print facilities as builtins, we can avoid this by having the protector frame have a unhandled exception handler*/
+ print("Unhandled exception: %S\n", prettyprint(ball));
+ exits("exception");
+ return 0;
+ }else{
+ *goals = g->next;
+ Goal *newgoal = malloc(sizeof(Goal));
+ newgoal->goal = copyterm(g->goal, nil);
+ newgoal->catcher = nil;
+ newgoal->next = *goals;
+ *goals = newgoal;
+ applybinding(newgoal->goal, *bindings);
+
+ Choicepoint *cp = *choicestack;
+ while(cp != nil && cp->id >= goal->clausenr)
+ cp = cp->next;
+ *choicestack = cp;
+ return 1;
+ }
+ }
+ }
+ return 0;
} \ No newline at end of file