shithub: pprolog

ref: 13efe91101a11f41caf6321a8b2fbdd96ef9927a
dir: pprolog/misc.c

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>

#include "dat.h"
#include "fns.h"

static uvlong varnr = 0;

Term *
copyterm(Term *orig)
{
	Term *new = gmalloc(sizeof(Term));
	memcpy(new, orig, sizeof(Term));
	new->next = nil;
	new->children = nil;

	if(orig->tag == CompoundTerm){
		Term *child;
		for(child = orig->children; child != nil; child = child->next)
			new->children = appendterm(new->children, copyterm(child));
	}
	return new;
}

uvlong
smallestvar(Term *t)
{
	if(t == nil)
		return varnr;

	if(t->tag == VariableTerm)
		return t->varnr;
	if(t->tag == CompoundTerm){
		Term *child;
		uvlong min = varnr;
		for(child = t->children; child != nil; child = child->next){
			uvlong v = smallestvar(child);
			if(v < min)
				min = v;
		}
		return min;
	}else
		return varnr;
}

void
addvarnr(Term *t, uvlong offset)
{
	if(t == nil)
		return;

	if(t->tag == VariableTerm){
		t->varnr += offset;
		if(t->varnr >= varnr)
			varnr = t->varnr+1;
	}
	if(t->tag == CompoundTerm){
		Term *child;
		for(child = t->children; child != nil; child = child->next)
			addvarnr(child, offset);
	}
}

void
renametermvars(Term *t)
{
	uvlong minvar = smallestvar(t);
	uvlong offset = varnr - minvar;
	addvarnr(t, offset);
}

void
renameclausevars(Clause *c)
{
	uvlong minhead = smallestvar(c->head);
	uvlong minbody = smallestvar(c->body);
	uvlong minvar = minhead < minbody ? minhead : minbody;
	uvlong offset = varnr - minvar;
	addvarnr(c->head, offset);
	addvarnr(c->body, offset);
}

Term *
appendterm(Term *a, Term *b)
{
	if(a == nil)
		return b;
	if(b == nil)
		return a;

	Term *tmp;
	for(tmp = a; tmp->next != nil; tmp = tmp->next);
	tmp->next = b;
	return a;
}

int
termslength(Term *list)
{
	int len;
	for(len = 0; list != nil; len++, list = list->next);
	return len;
}

Term *
mkterm(int tag)
{
	Term *t = gmalloc(sizeof(Term));
	t->tag = tag;
	t->next = nil;
	t->children = nil;
	t->text = nil;
	t->inparens = 0;
	t->varnr = 0;
	return t;
}

Term *
mkatom(Rune *name)
{
	Term *t = mkterm(AtomTerm);
	t->text = name;
	return t;
}

Term *
mkvariable(void)
{
	Term *t = mkterm(VariableTerm);
	t->varnr = varnr++;
	return t;
}

Term *
mkcompound(Rune *name, int arity, Term *args)
{
	Term *t = mkterm(CompoundTerm);
	t->text = name;
	t->arity = arity;
	t->children = args;
	return t;
}

Term *
mkfloat(double dval)
{
	Term *t = mkterm(FloatTerm);
	t->dval = dval;
	return t;
}

Term *
mkinteger(vlong ival)
{
	Term *t = mkterm(IntegerTerm);
	t->ival = ival;
	return t;
}

Term *
mkstring(Rune *text)
{
	Term *t = nil;
	Rune *r;

	switch(flagdoublequotes){
	case DoubleQuotesChars:
		for(r = text; *r != '\0'; r++){
			Rune *chtext = runesmprint("%C", *r);
			Term *ch = mkatom(chtext);
			t = appendterm(t, ch);
		}
		t = mklist(t);
		break;
	case DoubleQuotesCodes:
		for(r = text; *r != '\0'; r++){
			Term *code = mkinteger(*r);
			t = appendterm(t, code);
		}
		t = mklist(t);
		break;
		break;
	case DoubleQuotesAtom:
		t = mkatom(text);
	}
	return t;
}

Term *
mklist(Term *elems)
{
	if(elems == nil)
		return mkatom(L"[]");
	else{
		Term *t = copyterm(elems);
		t->next = mklist(elems->next);
		return mkcompound(L".", 2, t);
	}
}

Clause *
copyclause(Clause *orig, uvlong *clausenr)
{
	Clause *new = gmalloc(sizeof(Clause));
	new->head = copyterm(orig->head);
	if(orig->body)
		new->body = copyterm(orig->body);
	else
		new->body = nil;
	if(clausenr)
		new->clausenr = *clausenr;
	else
		new->clausenr = orig->clausenr;
	new->next = nil;
	return new;
}