diff options
author | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-07-27 16:41:12 +0000 |
---|---|---|
committer | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-07-27 16:41:12 +0000 |
commit | 13efe91101a11f41caf6321a8b2fbdd96ef9927a (patch) | |
tree | 4444bb78783fda4d815a4ec91f44052e0de27383 | |
parent | 4fba3e66dce0d167d2031a0d1f1f6f4571cbd981 (diff) |
remove clausenr from terms, and put it into goals instead. Next up is implementing the control constructs in C, since they misbehave right now due to the new changesHEADfront
-rw-r--r-- | builtins.c | 99 | ||||
-rw-r--r-- | dat.h | 2 | ||||
-rw-r--r-- | error.c | 8 | ||||
-rw-r--r-- | eval.c | 75 | ||||
-rw-r--r-- | fns.h | 5 | ||||
-rw-r--r-- | misc.c | 24 | ||||
-rw-r--r-- | parser.c | 6 | ||||
-rw-r--r-- | streams.c | 18 | ||||
-rw-r--r-- | system.pl | 5 | ||||
-rw-r--r-- | types.c | 2 |
10 files changed, 106 insertions, 138 deletions
@@ -20,7 +20,6 @@ BuiltinProto(builtintrue); BuiltinProto(builtinfail); BuiltinProto(builtincall); -BuiltinProto(builtincut); BuiltinProto(builtinvar); BuiltinProto(builtinatom); BuiltinProto(builtininteger); @@ -36,7 +35,6 @@ BuiltinProto(builtinuniv); BuiltinProto(builtincopyterm); BuiltinProto(builtinis); BuiltinProto(builtincatch); -BuiltinProto(builtinthrow); BuiltinProto(builtinsetprologflag); BuiltinProto(builtincurrentprologflags); BuiltinProto(builtinopen); @@ -101,8 +99,6 @@ findbuiltin(Term *goal) return builtinfail; if(Match(L"call", 1)) return builtincall; - if(Match(L"!", 0)) - return builtincut; if(Match(L"var", 1)) return builtinvar; if(Match(L"atom", 1)) @@ -133,8 +129,6 @@ findbuiltin(Term *goal) return builtinis; if(Match(L"catch", 3)) return builtincatch; - if(Match(L"throw", 1)) - return builtinthrow; if(Match(L"$set_prolog_flag", 2)) return builtinsetprologflag; if(Match(L"current_prolog_flags", 1)) @@ -241,21 +235,6 @@ canbecalled(Term *t) return 1; } -void -updateclausenr(Term *t, uvlong nr) -{ - /* Change the clause number on the term and its subterms, unless it is a variable */ - if(t->tag == VariableTerm) - return; - - t->clausenr = nr; - if(t->tag == CompoundTerm){ - Term *child; - for(child = t->children; child != nil; child = child->next) - updateclausenr(child, nr); - } -} - int builtincall(Term *goal, Binding **bindings, Module *module) { @@ -265,27 +244,7 @@ builtincall(Term *goal, Binding **bindings, Module *module) if(!canbecalled(callgoal)) Throw(typeerror(L"callable", callgoal)); - updateclausenr(callgoal, clausenr); - clausenr++; - - goalstack = addgoals(goalstack, callgoal, module); - return 1; -} - -int -builtincut(Term *goal, Binding **bindings, Module *module) -{ - USED(bindings); - USED(module); - - Choicepoint *cp = choicestack; - - /* Cut all choicepoints with an id larger or equal to the goal clause number, since they must have been introduced - after this goal's parent. - */ - while(cp != nil && cp->id >= goal->clausenr) - cp = cp->next; - choicestack = cp; + goalstack = addgoals(goalstack, callgoal, module, clausenr++); return 1; } @@ -563,7 +522,7 @@ builtinuniv(Term *goal, Binding **bindings, Module *module) list = list->children->next; for(i = 1; i < len; i++){ - Term *t = copyterm(list->children, nil); + Term *t = copyterm(list->children); elems = appendterm(elems, t); list = list->children->next; } @@ -575,7 +534,7 @@ builtinuniv(Term *goal, Binding **bindings, Module *module) Term *reallist = mklist(elems); return unify(list, reallist, bindings); }else{ - Term *t = copyterm(term, nil); + Term *t = copyterm(term); t->next = mkatom(L"[]"); Term *reallist = mkcompound(L".", 2, t); return unify(list, reallist, bindings); @@ -588,8 +547,8 @@ builtincopyterm(Term *goal, Binding **bindings, Module *module) USED(module); Term *term1 = goal->children; Term *term2 = term1->next; - Term *t = copyterm(term1, &clausenr); - clausenr++; + Term *t = copyterm(term1); + renametermvars(t); return unify(term2, t, bindings); } @@ -623,44 +582,11 @@ builtincatch(Term *goal, Binding **bindings, Module *module) catchframe->next = goalstack; goalstack = catchframe; - goalstack = addgoals(goalstack, catchgoal, module); + goalstack = addgoals(goalstack, catchgoal, module, clausenr++); return 1; } int -builtinthrow(Term *goal, Binding **bindings, Module *module) -{ - USED(bindings); - USED(module); - - Term *ball = goal->children; - - Goal *g; - for(g = goalstack; g != nil; g = g->next){ - if(g->catcher == nil) - continue; - - if(unify(g->catcher, ball, bindings)){ - goalstack = g->next; - Goal *newgoal = gmalloc(sizeof(Goal)); - newgoal->goal = copyterm(g->goal, nil); - newgoal->module = g->module; - newgoal->catcher = nil; - newgoal->next = goalstack; - goalstack = newgoal; - applybinding(newgoal->goal, *bindings); - - Choicepoint *cp = choicestack; - while(cp != nil && cp->id >= goal->clausenr) - cp = cp->next; - choicestack = cp; - return 1; - } - } - return 0; -} - -int builtincurrentprologflags(Term *goal, Binding **bindings, Module *module) { USED(module); @@ -852,13 +778,13 @@ builtinreadterm(Term *goal, Binding **bindings, Module *module) if(options->tag == CompoundTerm){ VarName *vn; for(vn = varnames; vn != nil; vn = vn->next){ - uniquevars = appendterm(uniquevars, copyterm(vn->var, nil)); + uniquevars = appendterm(uniquevars, copyterm(vn->var)); Term *name = mkatom(vn->name); - name->next = copyterm(vn->var, nil); + name->next = copyterm(vn->var); Term *vnpair = mkcompound(L"=", 2, name); varsnames = appendterm(varsnames, vnpair); if(vn->count == 1) - singlevars = appendterm(singlevars, copyterm(vnpair, nil)); + singlevars = appendterm(singlevars, copyterm(vnpair)); } } @@ -1053,11 +979,10 @@ assertclause(Term *clause, Module *module, int after, int dynamic) else arity = 0; - uvlong id = 0; Clause *cl = gmalloc(sizeof(Clause)); - cl->head = copyterm(head, &id); - cl->body = copyterm(body, &id); - cl->clausenr = id; + cl->head = copyterm(head); + cl->body = copyterm(body); + cl->clausenr = 0; cl->next = nil; Predicate *p; @@ -30,7 +30,6 @@ struct Term { u8int tag; u8int inparens; - uvlong clausenr; Term *next; union { @@ -51,6 +50,7 @@ struct Binding struct Goal { Term *goal; + uvlong goalnr; /* What clause caused this goal to be activated? */ Module *module; /* What module is this goal to be evaluated in? */ Term *catcher; /* When this is non-nil, the goal is a catch frame, goal is the recovery. */ Goal *next; @@ -15,7 +15,7 @@ Term * typeerror(Rune *validtype, Term *culprit) { Term *valid = mkatom(validtype); - valid->next = copyterm(culprit, nil); + valid->next = copyterm(culprit); return mkcompound(L"type_error", 2, valid); } @@ -23,7 +23,7 @@ Term * domainerror(Rune *validdomain, Term *culprit) { Term *valid = mkatom(validdomain); - valid->next = copyterm(culprit, nil); + valid->next = copyterm(culprit); return mkcompound(L"domain_error", 2, valid); } @@ -31,7 +31,7 @@ Term * existenceerror(Rune *objecttype, Term *culprit) { Term *obj = mkatom(objecttype); - obj->next = copyterm(culprit, nil); + obj->next = copyterm(culprit); return mkcompound(L"existence_error", 2, obj); } @@ -40,7 +40,7 @@ permissionerror(Rune *operation, Rune *permissiontype, Term *culprit) { Term *op = mkatom(operation); op->next = mkatom(permissiontype); - op->next->next = copyterm(culprit, nil); + op->next->next = copyterm(culprit); return mkcompound(L"permission_error", 3, op); } @@ -14,19 +14,20 @@ int evalquery(Term *query) { Binding *replbindings = nil; - goalstack = addgoals(goalstack, query, getmodule(L"user")); + goalstack = addgoals(goalstack, query, getmodule(L"user"), 0); while(goalstack->goal != nil){ Term *goal = goalstack->goal; Term *catcher = goalstack->catcher; Module *module = goalstack->module; + uvlong goalnr = goalstack->goalnr; goalstack = goalstack->next; if(catcher) continue; if(flagdebug) - print("Working goal: %S:%S\n", module->name, prettyprint(goal, 0, 0, 0, nil)); + print("Working goal %ulld: %S:%S\n", goalnr, module->name, prettyprint(goal, 0, 1, 0, nil)); if(goal->tag == VariableTerm) goal = instantiationerror(); @@ -35,7 +36,46 @@ evalquery(Term *query) Binding *bindings = nil; Clause *clause = nil; - + + /* handle special cases which need to cut: !/0, throw/1 */ + if(goal->tag == AtomTerm && runestrcmp(goal->text, L"!") == 0){ + Choicepoint *cp = choicestack; + /* Cut all choicepoints with an id larger or equal to the goal clause number, + since they must have been introduced + after this goal's parent. + */ + while(cp != nil && cp->id >= goalnr) + cp = cp->next; + choicestack = cp; + continue; + }else if(goal->tag == CompoundTerm && runestrcmp(goal->text, L"throw") == 0 && goal->arity == 1){ + Term *ball = goal->children; + Goal *g; + int caught = 0; + for(g = goalstack; g != nil && !caught; g = g->next){ + if(g->catcher == nil) + continue; + + if(unify(g->catcher, ball, &bindings)){ + goalstack = g->next; + Goal *newgoal = gmalloc(sizeof(Goal)); + newgoal->goal = copyterm(g->goal); + newgoal->module = g->module; + newgoal->catcher = nil; + newgoal->next = goalstack; + goalstack = newgoal; + applybinding(newgoal->goal, bindings); + + Choicepoint *cp = choicestack; + while(cp != nil && cp->id >= goalnr) + cp = cp->next; + choicestack = cp; + caught = 1; + } + } + continue; + } + /* Try to see if the goal can be solved using a builtin first */ Builtin builtin = findbuiltin(goal); if(builtin != nil){ @@ -79,7 +119,7 @@ evalquery(Term *query) case UnknownFail: replacement = mkatom(L"fail"); } - goalstack = addgoals(goalstack, replacement, module); + goalstack = addgoals(goalstack, replacement, module, goalnr); continue; } @@ -111,9 +151,9 @@ Backtrack: /* Add clause body as goals, with bindings applied */ if(clause != nil && clause->body != nil){ - Term *subgoal = copyterm(clause->body, nil); + Term *subgoal = copyterm(clause->body); applybinding(subgoal, bindings); - goalstack = addgoals(goalstack, subgoal, module); + goalstack = addgoals(goalstack, subgoal, module, clause->clausenr); } } goalstack = goalstack->next; @@ -122,11 +162,11 @@ Backtrack: } Goal * -addgoals(Goal *goals, Term *t, Module *module) +addgoals(Goal *goals, Term *t, Module *module, uvlong goalnr) { if(t->tag == CompoundTerm && runestrcmp(t->text, L",") == 0 && t->arity == 2){ - goals = addgoals(goals, t->children->next, module); - goals = addgoals(goals, t->children, module); + goals = addgoals(goals, t->children->next, module, goalnr); + goals = addgoals(goals, t->children, module, goalnr); }else{ if(t->tag == CompoundTerm && runestrcmp(t->text, L":") == 0 && t->arity == 2){ Term *moduleterm = t->children; @@ -143,6 +183,7 @@ addgoals(Goal *goals, Term *t, Module *module) } Goal *g = gmalloc(sizeof(Goal)); g->goal = t; + g->goalnr = goalnr; g->module = module; g->catcher = nil; g->next = goals; @@ -194,8 +235,8 @@ unify(Term *a, Term *b, Binding **bindings) Term *left; Term *right; - leftstack = copyterm(a, nil); - rightstack = copyterm(b, nil); + leftstack = copyterm(a); + rightstack = copyterm(b); while(leftstack != nil && rightstack != nil){ left = leftstack; @@ -211,7 +252,7 @@ unify(Term *a, Term *b, Binding **bindings) left = right; right = tmp; } - if(left->tag == VariableTerm && right->tag == VariableTerm && right->clausenr > left->clausenr){ + if(left->tag == VariableTerm && right->tag == VariableTerm && right->varnr > left->varnr){ Term *tmp = left; left = right; right = tmp; @@ -235,12 +276,12 @@ unify(Term *a, Term *b, Binding **bindings) Term *leftchild = left->children; Term *rightchild = right->children; while(leftchild != nil && rightchild != nil){ - Term *t1 = copyterm(leftchild, nil); + Term *t1 = copyterm(leftchild); t1->next = leftstack; leftstack = t1; leftchild = leftchild->next; - Term *t2 = copyterm(rightchild, nil); + Term *t2 = copyterm(rightchild); t2->next = rightstack; rightstack = t2; rightchild = rightchild->next; @@ -300,12 +341,13 @@ copygoals(Goal *goals) if(goals != nil){ Goal *g = gmalloc(sizeof(Goal)); g->module = goals->module; + g->goalnr = goals->goalnr; if(goals->goal) - g->goal = copyterm(goals->goal, nil); + g->goal = copyterm(goals->goal); else g->goal = nil; if(goals->catcher) - g->catcher = copyterm(goals->catcher, nil); + g->catcher = copyterm(goals->catcher); else g->catcher = nil; g->next = copygoals(goals->next); @@ -325,6 +367,7 @@ addchoicepoints(Clause *clause, Term *goal, Goal *goals, Module *mod){ Binding *altbindings = nil; clause = findclause(alt, goal, &altbindings); if(clause){ + print("Created choicepoint for %S with id %ulld\n", prettyprint(goal, 0, 1, 0, nil), clause->clausenr); /* Add choicepoint here */ Choicepoint *cp = gmalloc(sizeof(Choicepoint)); cp->goalstack = copygoals(goals); @@ -5,7 +5,8 @@ Term *parse(Biobuf *, Module *, VarName **); Rune *prettyprint(Term *, int, int, int, Module *); /* misc.c */ -Term *copyterm(Term *, uvlong *); +Term *copyterm(Term *); +void renametermvars(Term *); void renameclausevars(Clause *); Term *appendterm(Term *, Term *); int termslength(Term *); @@ -22,7 +23,7 @@ Clause *copyclause(Clause *, uvlong *); int evalquery(Term *); int unify(Term *, Term *, Binding **); void applybinding(Term *, Binding *); -Goal *addgoals(Goal *, Term *, Module *); +Goal *addgoals(Goal *, Term *, Module *, uvlong); Predicate *findpredicate(Predicate *, Term *); Clause *findclause(Clause *, Term *, Binding **); @@ -8,22 +8,17 @@ static uvlong varnr = 0; Term * -copyterm(Term *orig, uvlong *clausenr) +copyterm(Term *orig) { Term *new = gmalloc(sizeof(Term)); memcpy(new, orig, sizeof(Term)); new->next = nil; new->children = nil; - if(clausenr) - new->clausenr = *clausenr; - else - new->clausenr = orig->clausenr; - if(orig->tag == CompoundTerm){ Term *child; for(child = orig->children; child != nil; child = child->next) - new->children = appendterm(new->children, copyterm(child, clausenr)); + new->children = appendterm(new->children, copyterm(child)); } return new; } @@ -68,6 +63,14 @@ addvarnr(Term *t, uvlong offset) } void +renametermvars(Term *t) +{ + uvlong minvar = smallestvar(t); + uvlong offset = varnr - minvar; + addvarnr(t, offset); +} + +void renameclausevars(Clause *c) { uvlong minhead = smallestvar(c->head); @@ -108,7 +111,6 @@ mkterm(int tag) t->next = nil; t->children = nil; t->text = nil; - t->clausenr = 0; t->inparens = 0; t->varnr = 0; return t; @@ -191,7 +193,7 @@ mklist(Term *elems) if(elems == nil) return mkatom(L"[]"); else{ - Term *t = copyterm(elems, nil); + Term *t = copyterm(elems); t->next = mklist(elems->next); return mkcompound(L".", 2, t); } @@ -201,9 +203,9 @@ Clause * copyclause(Clause *orig, uvlong *clausenr) { Clause *new = gmalloc(sizeof(Clause)); - new->head = copyterm(orig->head, clausenr); + new->head = copyterm(orig->head); if(orig->body) - new->body = copyterm(orig->body, clausenr); + new->body = copyterm(orig->body); else new->body = nil; if(clausenr) @@ -66,10 +66,6 @@ parse(Biobuf *bio, Module *mod, VarName **vns) Term *result = parseterm(); *vns = varnames; - if(result){ - result = copyterm(result, &clausenr); - clausenr++; - } return result; } @@ -215,7 +211,7 @@ parsevar(void) for(vn = varnames; vn != nil; vn = vn->next, i++) if(runestrcmp(vn->name, name) == 0 && !runestrcmp(vn->name, L"_") == 0){ vn->count++; - return copyterm(vn->var, nil); + return copyterm(vn->var); } VarName *new = gmalloc(sizeof(VarName)); @@ -365,7 +365,7 @@ Term *streamproperties(Stream *s) /* file_name(F) */ if(s->filename){ arg = mkatom(s->filename); - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"file_name", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -377,13 +377,13 @@ Term *streamproperties(Stream *s) case WriteStream: arg = mkatom(L"write"); break; case AppendStream: arg = mkatom(L"append"); break; } - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"mode", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); /* input or output */ - data = copyterm(stream, nil); + data = copyterm(stream); if(s->mode == ReadStream) data->next = mkatom(L"input"); else @@ -395,7 +395,7 @@ Term *streamproperties(Stream *s) int i; for(i = 0; i < s->nalias; i++){ arg = mkatom(s->aliases[i]); - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"alias", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -404,7 +404,7 @@ Term *streamproperties(Stream *s) /* position(P) */ if(s->reposition){ arg = mkinteger(Boffset(s->bio)); - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"position", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -419,7 +419,7 @@ Term *streamproperties(Stream *s) Bungetrune(s->bio); arg = mkatom(L"not"); } - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"end_of_stream", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -431,7 +431,7 @@ Term *streamproperties(Stream *s) case EofActionEof: arg = mkatom(L"eof_code"); break; case EofActionReset: arg = mkatom(L"reset"); break; } - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"eof_action", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -441,7 +441,7 @@ Term *streamproperties(Stream *s) arg = mkatom(L"true"); else arg = mkatom(L"false"); - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"reposition", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -451,7 +451,7 @@ Term *streamproperties(Stream *s) arg = mkatom(L"text"); else arg = mkatom(L"binary"); - data = copyterm(stream, nil); + data = copyterm(stream); data->next = mkcompound(L"type", 1, arg); prop = mkcompound(L"prop", 2, data); props = appendterm(props, prop); @@ -69,8 +69,6 @@ If ; _ :- _ ; Else :- Else. -A , B :- A , B. - % Term unification A = A. @@ -696,3 +694,6 @@ halt :- consult(File) :- loader:load_module_from_file(File). + +twice(!) :- '$write_term'(4, 'C ', []). +twice(true) :- '$write_term'(4, 'Moss ', []).
\ No newline at end of file @@ -69,4 +69,4 @@ listtail(Term *t) return t->children->next; else return nil; -}
\ No newline at end of file +} |