shithub: pprolog

Download patch

ref: 0f958749e189e4dacd7a1f70cfc33460e1228d3b
parent: 73b9bad83e6405809e80809c10c8917f4bd4e341
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Wed Jul 7 12:32:02 EDT 2021

Make '=..'/2 work according to spec. Introduce types.c for functions which tells us something about term types. Should be used a lot more instead of explicitly looking into terms->tag everywhere

--- a/builtins.c
+++ b/builtins.c
@@ -409,6 +409,23 @@
 	Term *term = goal->children;
 	Term *list = term->next;
 
+	if(term->tag == VariableTerm && ispartiallist(list))
+		Throw(instantiationerror());
+	if(!(ispartiallist(list) || islist(list)))
+		Throw(typeerror(L"list", list));
+
+	Term *head = listhead(list);
+	Term *tail = listtail(list);
+
+	if(term->tag == VariableTerm && head->tag == VariableTerm)
+		Throw(instantiationerror());
+	if(islist(list) && !(head->tag == AtomTerm || head->tag == VariableTerm) && !isemptylist(tail))
+		Throw(typeerror(L"atom", head));
+	if(islist(list) && head->tag == CompoundTerm && isemptylist(tail))
+		Throw(typeerror(L"atomic", head));
+	if(term->tag == VariableTerm && isemptylist(list))
+		Throw(domainerror(L"non_empty_list", list));
+
 	int len;
 	if(term->tag == VariableTerm){
 		Rune *name;
--- a/fns.h
+++ b/fns.h
@@ -63,4 +63,12 @@
 /* module.c */
 void initmodules(void);
 Module *parsemodule(char *);
-Module *getmodule(Rune *);
\ No newline at end of file
+Module *getmodule(Rune *);
+
+/* types.c */
+int islist(Term *);
+int ispartiallist(Term *t);
+int isemptylist(Term *);
+int isnonemptylist(Term *);
+Term *listhead(Term *);
+Term *listtail(Term *);
--- a/mkfile
+++ b/mkfile
@@ -13,7 +13,8 @@
 	flags.$O\
 	error.$O\
 	streams.$O\
-	module.$O
+	module.$O\
+	types.$O\
 
 HFILES=dat.h fns.h
 
--- /dev/null
+++ b/types.c
@@ -1,0 +1,58 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "dat.h"
+#include "fns.h"
+
+/* Type tests */
+int
+islist(Term *t)
+{
+	return (isemptylist(t) || isnonemptylist(t));
+}
+
+int
+ispartiallist(Term *t)
+{
+	if(t->tag == VariableTerm)
+		return 1;
+	else if(t->tag == CompoundTerm && runestrcmp(t->text, L".") == 0 && t->arity == 2)
+		return ispartiallist(listtail(t));
+	else
+		return 0;
+}
+
+int
+isemptylist(Term *t)
+{
+	return (t->tag == AtomTerm && runestrcmp(t->text, L"[]") == 0);
+}
+
+int
+isnonemptylist(Term *t)
+{
+	if(t->tag == CompoundTerm && runestrcmp(t->text, L".") == 0 && t->arity == 2)
+		return islist(listtail(t));
+	else
+		return 0;	
+}
+
+/* Other functions */
+Term *
+listhead(Term *t)
+{
+	if(t->tag == CompoundTerm && runestrcmp(t->text, L".") == 0 && t->arity == 2)
+		return t->children;
+	else
+		return nil;
+}
+
+Term *
+listtail(Term *t)
+{
+	if(t->tag == CompoundTerm && runestrcmp(t->text, L".") == 0 && t->arity == 2)
+		return t->children->next;
+	else
+		return nil;
+}
\ No newline at end of file