ref: a8b1fadd149126e9c8d3081a56d206812211f1e6
parent: baea4aa939861fd4efbc71b96f93ba890f01ac40
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Wed Jun 30 15:33:55 EDT 2021
Add builtins for typetests
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
-1) Add a repl
-2) Figure out how to print the final bindings after running a query
-3) Stop comparing strings all the time
-4) Stop copying the entire goal stack into every choicepoint
-5) Stop creating choicepoints when it is not needed
-6) How to implement builtins nicely?
-7) Right now we copy and allocate a lot, but almost never free stuff.
\ No newline at end of file
+* Add a repl
+* Stop comparing strings all the time
+* Stop copying the entire goal stack into every choicepoint
+* Stop creating choicepoints when it is not needed
+* How to implement builtins nicely?
+* Right now we copy and allocate a lot, but almost never free stuff.
\ No newline at end of file
--- a/builtins.c
+++ b/builtins.c
@@ -4,10 +4,22 @@
#include "dat.h"
#include "fns.h"
-int builtinfail(Term *, Term *, Goal **, Choicepoint **, Binding **);
-int builtincall(Term *, Term *, Goal **, Choicepoint **, Binding **);
-int builtincut(Term *, Term *, Goal **, Choicepoint **, Binding **);
+#define BuiltinProto(name) int name(Term *, Term *, Goal **, Choicepoint **, Binding **)
+#define Match(X, Y) (runestrcmp(name, X) == 0 && arity == Y)
+BuiltinProto(builtinfail);
+BuiltinProto(builtincall);
+BuiltinProto(builtincut);
+BuiltinProto(builtinvar);
+BuiltinProto(builtinatom);
+BuiltinProto(builtininteger);
+BuiltinProto(builtinfloat);
+BuiltinProto(builtinatomic);
+BuiltinProto(builtincompound);
+BuiltinProto(builtinnonvar);
+BuiltinProto(builtinnumber);
+BuiltinProto(builtinstring);
+
Builtin
findbuiltin(Term *goal)
{
@@ -27,12 +39,31 @@
return nil;
}
- if(!runestrcmp(name, L"fail") && arity == 0)
+ /* Rewrite this so its not just a long if chain */
+ if(Match(L"fail", 0))
return builtinfail;
- if(!runestrcmp(name, L"call") && arity == 1)
+ if(Match(L"call", 1))
return builtincall;
- if(!runestrcmp(name, L"!") && arity == 0)
+ if(Match(L"!", 0))
return builtincut;
+ if(Match(L"var", 1))
+ return builtinvar;
+ if(Match(L"atom", 1))
+ return builtinatom;
+ if(Match(L"integer", 1))
+ return builtininteger;
+ if(Match(L"float", 1))
+ return builtinfloat;
+ if(Match(L"atomic", 1))
+ return builtinatomic;
+ if(Match(L"compound", 1))
+ return builtincompound;
+ if(Match(L"nonvar", 1))
+ return builtinnonvar;
+ if(Match(L"number", 1))
+ return builtinnumber;
+ if(Match(L"string", 1))
+ return builtinstring;
return nil;
}
@@ -79,4 +110,103 @@
cp = cp->next;
*choicestack = cp;
return 1;
+}
+
+int
+builtinvar(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == VariableTerm);
+}
+
+int
+builtinatom(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == AtomTerm);
+}
+
+int
+builtininteger(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == NumberTerm && arg->numbertype == NumberInt);
+}
+
+int
+builtinfloat(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == NumberTerm && arg->numbertype == NumberFloat);
+}
+
+int
+builtinatomic(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == AtomTerm || arg->tag == NumberTerm);
+}
+
+int
+builtincompound(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == CompoundTerm);
+}
+
+int
+builtinnonvar(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag != VariableTerm);
+}
+
+int
+builtinnumber(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == NumberTerm);
+}
+
+int
+builtinstring(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings)
+{
+ USED(database);
+ USED(goals);
+ USED(choicestack);
+ USED(bindings);
+ Term *arg = goal->children;
+ return (arg->tag == StringTerm);
}
\ No newline at end of file
--- a/fns.h
+++ b/fns.h
@@ -12,6 +12,7 @@
Term *mkvariable(Rune *);
Term *mkcompound(Rune *, int, Term *);
Term *mknumber(int, vlong, double);
+Term *mkstring(Rune *);
/* eval.c */
int evalquery(Term *, Term *, Binding **);
--- a/misc.c
+++ b/misc.c
@@ -90,3 +90,11 @@
t->dval = dval;
return t;
}
+
+Term *
+mkstring(Rune *text)
+{
+ Term *t = mkterm(StringTerm);
+ t->text = text;
+ return t;
+}
\ No newline at end of file
--- a/parser.c
+++ b/parser.c
@@ -186,8 +186,12 @@
result = fullterm(ParenRightTok, nil, nil);
match(ParenRightTok);
break;
+ case StringTok:
+ result = mkstring(lookahead.text);
+ match(StringTok);
+ break;
default:
- print("Cant parse term of token type %d\n", lookahead.tag);
+ print("Can't parse term of token type %d\n", lookahead.tag);
syntaxerror("term");
result = nil;
}
@@ -513,6 +517,7 @@
numD += (peek - L'0') / (10 * place);
peek = Bgetrune(parsein);
}
+ Bungetrune(parsein);
/* Should also lex 123.45E10 */
lookahead.tag = FloatTok;
lookahead.dval = negative ? -numD : numD;
--- a/prettyprint.c
+++ b/prettyprint.c
@@ -30,6 +30,9 @@
else
result = runesmprint("%f", t->dval);
break;
+ case StringTerm:
+ result = runesmprint("\"%S\"", t->text);
+ break;
default:
result = runesmprint("cant print term with tag %d", t->tag);
break;