ref: ff418c798b580204f6fea5512adc36835f8b7efa
dir: /builtins.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" #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); BuiltinProto(builtincompare); int compareterms(Term *, Term *); Builtin findbuiltin(Term *goal) { int arity; Rune *name; switch(goal->tag){ case AtomTerm: arity = 0; name = goal->text; break; case CompoundTerm: arity = goal->arity; name = goal->text; break; default: return nil; } /* Rewrite this so its not just a long if chain */ if(Match(L"fail", 0)) 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)) 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; if(Match(L"compare", 3)) return builtincompare; return nil; } int builtinfail(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings) { USED(database); USED(goal); USED(goals); USED(choicestack); USED(bindings); return 0; } int builtincall(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings) { USED(database); USED(choicestack); USED(bindings); Goal *g = malloc(sizeof(Goal)); g->goal = goal->children; g->next = *goals; *goals = g; return 1; } int builtincut(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings) { USED(database); USED(goals); USED(bindings); 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 *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); } #define Compare(A, B) ((A < B) ? -1 : ((A > B) ? 1 : 0)) int compareterms(Term *t1, Term *t2) { int result = 0; if(t1->tag != t2->tag) result = Compare(t1->tag, t2->tag); else{ /* Same type term */ switch(t1->tag){ case VariableTerm: if(t1->clausenr == t2->clausenr) result = runestrcmp(t1->text, t2->text); else result = Compare(t1->clausenr, t2->clausenr); break; case NumberTerm: if(t1->numbertype == t2->numbertype){ if(t1->numbertype == NumberInt) result = Compare(t1->ival, t2->ival); else result = Compare(t1->dval, t2->dval); }else result = Compare(t1->numbertype, t2->numbertype); break; case StringTerm: case AtomTerm: result = runestrcmp(t1->text, t2->text); break; case CompoundTerm: result = Compare(t1->arity, t2->arity); if(result != 0) break; result = runestrcmp(t1->text, t2->text); if(result != 0) break; t1 = t1->children; t2 = t2->children; while(t1 != nil && t2 != nil){ result = compareterms(t1, t2); if(result != 0) break; else t1 = t1->next; t2 = t2->next; } break; } } return result; } int builtincompare(Term *database, Term *goal, Goal **goals, Choicepoint **choicestack, Binding **bindings) { USED(database); USED(goals); USED(choicestack); Term *order = goal->children; Term *t1 = order->next; Term *t2 = t1->next; int result = compareterms(t1, t2); Term *resultorder; if(result == -1) resultorder = mkatom(L"<"); else if(result == 0) resultorder = mkatom(L"="); else resultorder = mkatom(L">"); return unify(order, resultorder, bindings); }