shithub: pprolog

Download patch

ref: 13efe91101a11f41caf6321a8b2fbdd96ef9927a
parent: 4fba3e66dce0d167d2031a0d1f1f6f4571cbd981
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Tue Jul 27 12:41:12 EDT 2021

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 changes

--- a/builtins.c
+++ b/builtins.c
@@ -20,7 +20,6 @@
 BuiltinProto(builtintrue);
 BuiltinProto(builtinfail);
 BuiltinProto(builtincall);
-BuiltinProto(builtincut);
 BuiltinProto(builtinvar);
 BuiltinProto(builtinatom);
 BuiltinProto(builtininteger);
@@ -36,7 +35,6 @@
 BuiltinProto(builtincopyterm);
 BuiltinProto(builtinis);
 BuiltinProto(builtincatch);
-BuiltinProto(builtinthrow);
 BuiltinProto(builtinsetprologflag);
 BuiltinProto(builtincurrentprologflags);
 BuiltinProto(builtinopen);
@@ -101,8 +99,6 @@
 		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 @@
 		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 @@
 		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,31 +244,11 @@
 	if(!canbecalled(callgoal))
 		Throw(typeerror(L"callable", callgoal));
 
-	updateclausenr(callgoal, clausenr);
-	clausenr++;
-
-	goalstack = addgoals(goalstack, callgoal, module);
+	goalstack = addgoals(goalstack, callgoal, module, clausenr++);
 	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;
-	return 1;
-}
-
-int
 builtinvar(Term *goal, Binding **bindings, Module *module)
 {
 	USED(bindings);
@@ -563,7 +522,7 @@
 
 		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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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;
--- a/dat.h
+++ b/dat.h
@@ -30,7 +30,6 @@
 {
 	u8int tag;
 	u8int inparens;
-	uvlong clausenr;
 	Term *next;
 
 	union {
@@ -51,6 +50,7 @@
 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;
--- a/error.c
+++ b/error.c
@@ -15,7 +15,7 @@
 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 @@
 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 @@
 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 @@
 {
 	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);
 }
 
--- a/eval.c
+++ b/eval.c
@@ -14,12 +14,13 @@
 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)
@@ -26,7 +27,7 @@
 			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 @@
 
 		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 @@
 				case UnknownFail:
 					replacement = mkatom(L"fail");
 				}
-				goalstack = addgoals(goalstack, replacement, module);
+				goalstack = addgoals(goalstack, replacement, module, goalnr);
 				continue;
 			}
 
@@ -111,9 +151,9 @@
 
 		/* 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 @@
 }
 
 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 @@
 		}
 		Goal *g = gmalloc(sizeof(Goal));
 		g->goal = t;
+		g->goalnr = goalnr;
 		g->module = module;
 		g->catcher = nil;
 		g->next = goals;
@@ -194,8 +235,8 @@
 	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 @@
 				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 @@
 			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 @@
 	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 @@
 		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);
--- a/fns.h
+++ b/fns.h
@@ -5,7 +5,8 @@
 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 @@
 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 **);
 
--- a/misc.c
+++ b/misc.c
@@ -8,7 +8,7 @@
 static uvlong varnr = 0;
 
 Term *
-copyterm(Term *orig, uvlong *clausenr)
+copyterm(Term *orig)
 {
 	Term *new = gmalloc(sizeof(Term));
 	memcpy(new, orig, sizeof(Term));
@@ -15,15 +15,10 @@
 	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 @@
 }
 
 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 @@
 	t->next = nil;
 	t->children = nil;
 	t->text = nil;
-	t->clausenr = 0;
 	t->inparens = 0;
 	t->varnr = 0;
 	return t;
@@ -191,7 +193,7 @@
 	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 @@
 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)
--- a/parser.c
+++ b/parser.c
@@ -66,10 +66,6 @@
 
 	Term *result = parseterm();
 	*vns = varnames;
-	if(result){
-		result = copyterm(result, &clausenr);
-		clausenr++;
-	}
 	return result;
 }
 
@@ -215,7 +211,7 @@
 	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));
--- a/streams.c
+++ b/streams.c
@@ -365,7 +365,7 @@
 	/* 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 @@
 	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 @@
 	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 @@
 	/* 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 @@
 			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 @@
 	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 @@
 		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 @@
 		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);
--- a/system.pl
+++ b/system.pl
@@ -69,8 +69,6 @@
 _ ; Else :-
 	Else.
 
-A , B :- A , B.
-
 % Term unification
 A = A.
 
@@ -696,3 +694,6 @@
 
 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
--- a/types.c
+++ b/types.c
@@ -69,4 +69,4 @@
 		return t->children->next;
 	else
 		return nil;
-}
\ No newline at end of file
+}