shithub: pprolog

ref: a8b1fadd149126e9c8d3081a56d206812211f1e6
dir: /builtins.c/

View raw version
#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);

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;

	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);
}