/****************************************************************************** UNSW Prolog (version 4) Written by Claude Sammut Department of Computer Science University of New South Wales (and St. Joseph's U., Philadelphia) Copyright (c) 1983 - Claude Sammut ******************************************************************************/ /* Meta-logical predicates */ #include "pred.h" extern pval termb, intern(), new(), mkclause(); extern compterm *record(); extern clause *create(); extern int argn, bind(), unbind(), isbound(); extern atom *_comma, *_neck, *same_proc; extern binding *frameb; extern integer *stack_int; extern var **varcell; static assert PREDICATE { register pval rval; var **old_vc, *vc[MAXVAR]; if (iscompound(arg[0])) { argn = 0; old_vc = varcell; varcell = vc; rval = mkclause(arg[0], frame[0]); rval -> g.nvars = argn; add_clause(rval); varcell = old_vc; argn = 0; return(TRUE); } else fail("Assert - argument must be compound") } static asserta PREDICATE { register pval rval; register atom *x; register clause *y; var **old_vc, *vc[MAXVAR]; if (iscompound(arg[0])) { argn = 0; varcell = vc; rval = mkclause(arg[0], frame[0]); rval -> g.nvars = argn; x = (atom *) rval -> g.goal[0] -> c.term[0]; y = VAL(x); VAL(x) = (clause *) rval; VAL(x) -> rest = y; same_proc = 0; varcell = old_vc; argn = 0; return(TRUE); } else fail("Asserta - argument must be compound") } static pterm PREDICATE { register int i; if (TYPE(arg[0]) != INT || TYPE(arg[1]) == VAR) fail("Arg - bad argument") i = INT_VAL(0); if (isatom(arg[1]) && i == 0) return(unify(arg[2], frame[2], arg[1], 0)); else if (iscompound(arg[1]) && i <= SIZE(arg[1])) return(unify(arg[2], frame[2], arg[1] -> c.term[i], frame[1])); else return(FALSE); } #define MAX_VAR 20 static int _nvars = 0; static var *_var[MAX_VAR]; static pval mkfn(functor, arity) atom *functor; int arity; { register compterm *rval; register int i; register var *v; char buf[6]; if (arity > MAX_VAR) fail("Functor - Too many variables") rval = record(arity); rval -> term[0] = (pval) functor; for (i = 0; i < arity; i++) { if (i < _nvars) rval -> term[i + 1] = (pval) _var[i]; else { sprintf(buf, "_%d", i + 1); v = (var *) new(VAR); v -> offset = i; v -> pname = (atom *) intern(ATOM, buf, strlen(buf)+1, FALSE); _var[_nvars++] = v; rval -> term[i + 1] = (pval) v; } } return((pval) rval); } static functor PREDICATE { extern binding *stack; extern short sp; register pval rval; register int arity; if (isvariable(arg[0]) && isatom(arg[1]) && isinteger(arg[2])) { if ((arity = INT_VAL(2)) == 0) { bind(arg[0], frame[0], arg[1], 0); return(TRUE); } if ((int)(rval = mkfn(arg[1], arity)) == FALSE) return(FALSE); bind(arg[0], frame[0], rval, &stack[sp]); clear_frame(arity); return(TRUE); } if (TYPE(arg[1]) != VAR || TYPE(arg[2]) != VAR) fail("Functor - 2nd and 3rd arguments must be variables") else if (isatom(arg[0])) { bind(arg[1], frame[1], arg[0], 0); bind_num(2, 0); return(TRUE); } else if (TYPE(arg[0]) == FN) { bind(arg[1], frame[1], arg[0] -> c.term[0], 0); bind_num(2, SIZE(arg[0])); return(TRUE); } else fail("Functor - first argument must be functor") } static concat PREDICATE { extern atom *nil; extern char token_buff[]; register i = 0; pval tl_term, rval; binding *tl_frame; if (arg[0] == (pval) nil) return(FALSE); if (TYPE(arg[0]) == LIST) { termb = arg[0]; frameb = frame[0]; while (TYPE(termb) != VAR && termb != (pval) nil) { tl_term = termb; tl_frame = frameb; unbind(termb -> c.term[0], frameb); if (isatom(termb)) { sprintf(&token_buff[i], "%s", NAME(termb)); i = strlen(token_buff); } else if (isinteger(termb)) if (termb == (pval) stack_int) { sprintf(&token_buff[i], "%d", (int) frameb); i = strlen(token_buff); } else { sprintf(&token_buff[i], "%d", termb -> i.int_val); i = strlen(token_buff); } else fail("Concat - list members must be atomic") unbind(tl_term -> c.term[1], tl_frame); } token_buff[i++] = 0; rval = intern(atype(token_buff), token_buff, i, FALSE); if (isatom(arg[1])) return(arg[1] == rval); else if (isvariable(arg[1])) { bind(arg[1], frame[1], rval, 0); return(TRUE); } else fail("Concat - bad second argument") } else fail("Concat - first argument must be a list") } typedef enum { WORDCH , STRINGCH , SYMBOLCH , PUNCTCH , QUOTECH , DIGIT , WHITESP , ILLEGALCH } chartype; static p_char PREDICATE { extern chartype chtype[]; char buf[2]; register i; register pval rval; if (isinteger(arg[0]) && isatom(arg[1])) { i = INT_VAL(0); if (i < 1 || i > strlen(NAME(arg[1]))) return(FALSE); buf[0] = NAME(arg[1])[i - 1]; buf[1] = 0; rval = intern(ATOM, buf, 2, chtype[buf[0]] != WORDCH); if (isatom(arg[2])) return(rval == arg[2]); else if (isvariable(arg[2])) { bind(arg[2], frame[2], rval, 0); return(TRUE); } } fail("Char - bad argument") } #define BOTTOM -1 extern var _1, _2; static struct {itemtype type; var *_1, *_2;} _list = {LIST, &_1, &_2}; static ancestors PREDICATE { extern environment *env_stack; extern short parent, sp; extern binding *stack; extern atom *nil; /* 9/9/86 - WEN - needed for VAX C */ register pval t; register short i; register environment *p; binding *f, *s; t = arg[0]; f = frame[0]; for (i = env_stack[parent].parent; i != BOTTOM; i = env_stack[i].parent) { p = &env_stack[i]; s = &stack[sp]; clear_frame(2); if (! unify(t, f, &_list, s)) fail("Ancestors - incorrect argument") s -> termv = (pval)(*(p -> cl)); if (p -> parent == -1) s -> framev = stack; else s -> framev = &stack[env_stack[p -> parent].sp]; t = (pval)(&_2); f = s; } bind(t, f, nil, 0); return(TRUE); } static int next_no = 0; static numv(x, f) pval x; binding *f; { int i, limit; pval a; char buf[16]; switch (TYPE(x)) { case LIST: case FN: limit = SIZE(x); break; case VAR: if (isbound(x, f)) numv(termb, frameb); else { sprintf(buf, "_%d", next_no++); i = strlen(buf); a = intern(ATOM, buf, i + 1, FALSE); bind(x, f, a, 0); } default: return; } for (i = 0; i <= limit; i++) numv(x -> c.term[i], f); } static number_vars PREDICATE { if (TYPE(arg[1]) != INT) fail("Numbervars - second argument must be an integer") if (TYPE(arg[2]) != INT && TYPE(arg[2]) != VAR) fail("Numbervars - third arg must be integer or variable") next_no = INT_VAL(1); numv(arg[0], frame[0]); return(unify(arg[2], frame[2], stack_int, next_no)); } atom_table p_meta = { SET_PRED(NONOP, 0, 3, "term", pterm), SET_PRED(NONOP, 0, 3, "arg", pterm), SET_PRED(NONOP, 0, 3, "functor", functor), SET_PRED(NONOP, 0, 1, "assert", assert), SET_PRED(NONOP, 0, 1, "asserta", asserta), SET_PRED(NONOP, 0, 1, "assertz", assert), SET_PRED(NONOP, 0, 2, "concat", concat), SET_PRED(NONOP, 0, 3, "char", p_char), SET_PRED(NONOP, 0, 1, "ancestors", ancestors), SET_PRED(NONOP, 0, 3, "numbervars", number_vars), END_MARK };