/****************************************************************************** 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 ******************************************************************************/ /* 'bag' and data base predicates */ #include "pred.h" #define MAXBAG 50 extern atom *nil; extern pval new(), make(); static int cur_bag = -1; static struct {pval start, tail;} bag[MAXBAG]; static open_bag PREDICATE { if (++cur_bag == MAXBAG) fatal("Too many open bags"); bag[cur_bag].start = (pval) nil; bag[cur_bag].tail = (pval) nil; return(TRUE); } static write_bag PREDICATE { extern var **varcell; var ** old_vc; pval result; if (isvariable(arg[0]) || cur_bag == -1) fail("Argument to `write_bag' must not be an variable") result = new(LIST); old_vc = varcell; varcell = 0; result -> c.term[0] = make(arg[0], frame[0]); varcell = old_vc; result -> c.term[1] = (pval) nil; if (bag[cur_bag].start == (pval) nil) bag[cur_bag].start = result; else bag[cur_bag].tail -> c.term[1] = result; bag[cur_bag].tail = result; return(FALSE); } static close_bag PREDICATE { return unify(arg[0], frame[0], bag[cur_bag].start, 0); } static free_bag PREDICATE { free_term(bag[cur_bag--].start); return(TRUE); } static conc PREDICATE { extern var **varcell; var **old_vc; register pval p, result; if (isvariable(arg[1])) fail("2nd argument to `conc' must not be a variable") p = arg[0]; repeat { if (TYPE(p) != LIST) fail("1st argument to `conc' must be a list") if (isvariable(p -> c.term[0])) fail("Variables not allowed in `conc' list") if (p -> c.term[1] == (pval) nil) break; p = p -> c.term[1]; } result = new(LIST); p -> c.term[1] = result; old_vc = varcell; varcell = 0; result -> c.term[0] = make(arg[1], frame[1]); varcell = old_vc; result -> c.term[1] = (pval) nil; return(TRUE); } atom_table p_bag = { SET_PRED(NONOP, 0, 0, "open_bag", open_bag), SET_PRED(NONOP, 0, 1, "write_bag", write_bag), SET_PRED(NONOP, 0, 1, "close_bag", close_bag), SET_PRED(NONOP, 0, 0, "free_bag", free_bag), SET_PRED(NONOP, 0, 2, "conc", conc), END_MARK };