/****************************************************************************** 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 ******************************************************************************/ /* predicates for manipulating clauses */ #include "pred.h" extern binding *stack; extern short sp; extern integer *stack_int; static definition PREDICATE { register clause *rval; register binding *rframe; extern run; if (TYPE(arg[0]) != ATOM) fail("Definition - first argument must be an atom") if (TYPE(arg[1]) != VAR) fail("Definition - second argument must be unbound") if ((rval = VAL(arg[0])) == 0) return(FALSE); rframe = &stack[sp]; clear_frame(rval -> nvars); bind(arg[1], frame[1], rval, rframe); return(TRUE); } static next_clause PREDICATE { register clause *rval; register binding *rframe; if (TYPE(arg[0]) != CLAUSE) fail("Next_clause - first argument must be a clause") if (TYPE(arg[1]) != VAR) fail("Next_clause - second argument must be unbound") if ((rval = arg[0] -> g.rest) == 0) return(FALSE); rframe = &stack[sp]; clear_frame(rval -> nvars); bind(arg[1], frame[1], rval, rframe); return(TRUE); } static head PREDICATE { if (TYPE(arg[0]) != CLAUSE) fail("Head - first argument must be a clause") return(unify(arg[0] -> g.goal[0], frame[0], arg[1], frame[1])); } extern atom *_true, *_comma; extern var _1, _2; static struct { itemtype type; card size; atom *fun; var *left, *right; } _conjunction = { FN, 2, 0, &_1, &_2 }; static body PREDICATE { extern binding *stack; extern short sp; register pval *b; register binding *s, *s1, *s2; if (TYPE(arg[0]) != CLAUSE) fail("Body - first argument must be a clause") _conjunction.fun = _comma; b = &(arg[0] -> g.goal[1]); if (*b == 0) return(unify(arg[1], frame[1], _true, 0)); if (*(b + 1) == 0) return(unify(arg[1], frame[1], *b, frame[0])); s = &stack[sp]; clear_frame(2); s1 = s; s1[0].termv = *b++; s1[0].framev = frame[0]; while (*(b + 1)) { s2 = &stack[sp]; clear_frame(2); s1[1].termv = (pval) (&_conjunction); s1[1].framev = s2; s2[0].termv = *b++; s2[0].framev = frame[0]; s1 = s2; } s1[1].termv = *b; s1[1].framev = frame[0]; return(unify(arg[1], frame[1], &_conjunction, s)); } static unl_clause PREDICATE { pval head, p_name; register clause **p; if (TYPE(arg[0]) != CLAUSE) fail("$unlink - argument must be clause") head = arg[0] -> g.goal[0]; if (isatom(head)) p_name = head; else p_name = head -> c.term[0]; p = &VAL(p_name); while (*p) { if (*p == (clause *) arg[0]) { *p = (*p) -> rest; return(TRUE); } else p = &((*p) -> rest); } fail("$unlink - clause not found") } static p_free PREDICATE { if (isvariable(arg[0])) fail("Cannot free unbound term") free_term(arg[0]); return(TRUE); } static p_free_proc PREDICATE { if (isatom(arg[0])) { free_proc(VAL(arg[0])); VAL(arg[0]) = 0; return(TRUE); } fail("Free proc - argument must be an atom") } static remob PREDICATE { extern atom *hashtable[]; atom **p; if (isatom(arg[0])) { p = &hashtable[hash(NAME(arg[0]))]; while (*p) { if (*p == (atom *) arg[0]) { *p = (*p) -> link; return(TRUE); } else p = &((*p) -> link); } fail("Remob - atom not found") } else fail("Remob - argument must be an atom") } atom_table p_clause = { SET_PRED(NONOP, 0, 1, "unlink_clause", unl_clause), SET_PRED(NONOP, 0, 1, "free", p_free), SET_PRED(NONOP, 0, 1, "free_proc", p_free_proc), SET_PRED(NONOP, 0, 1, "remob", remob), SET_PRED(NONOP, 0, 2, "head", head), SET_PRED(NONOP, 0, 2, "body", body), SET_PRED(NONOP, 0, 2, "definition", definition), SET_PRED(NONOP, 0, 2, "next_clause", next_clause), END_MARK };