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