diff options
Diffstat (limited to 'builtins.c')
-rw-r--r-- | builtins.c | 75 |
1 files changed, 75 insertions, 0 deletions
@@ -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 |