/****************************************************************************** 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 ******************************************************************************/ /* MEMORY ALLOCATION ROUTINES */ #include #include "g.h" extern compterm *record(); extern integer *stack_int; extern char *malloc(); char *alloc(size) unsigned size; { register char *ptr; if((ptr = malloc((unsigned) size)) == NULL) { warning("malloc: out of core"); exit(); } return ptr; } pval new(t) register itemtype t; { register pval rval; switch(t) { case STRING : case ATOM : rval = (pval) alloc(sizeof(atom)); rval -> a.type = t; rval -> a.traced = 0; rval -> a.val = 0; rval -> a.pred = 0; rval -> a.op_t = NONOP; rval -> a.link = 0; break; case VAR : rval = (pval) alloc(sizeof(var)); rval -> v.type = t; rval -> v.offset = 0; break; case INT : rval = (pval) alloc(sizeof(integer)); rval -> i.type = INT; rval -> i.int_val = 0; break; case LIST : rval = (pval) record(1); rval -> c.type = LIST; break; } return(rval); } compterm *record(n) char n; { register compterm *r; r = (compterm *) alloc(sizeof(compterm) + n * WORD_LENGTH); r -> type = FN; r -> size = n; return(r); } clause *create(ngoals, nvars) int ngoals; int nvars; { register clause *r; r = (clause *) alloc(sizeof(clause) + (1 + ngoals) * WORD_LENGTH); r -> type = CLAUSE; r -> nvars = nvars; r -> rest = 0; r -> goal[0] = r -> goal[ngoals + 1] = 0; return(r); } /* Hash table use to uniquely store atoms */ atom *hashtable[HASHSIZE]; hash(string) register char *string; { register h = 0; while (*string) h += *string++; return(h & 0177); } pval intern(type, string, size) itemtype type; register char *string,size; { register h; register atom *p; h = hash(string); for (p = hashtable[h]; p != 0; p = p -> link) { if (strcmp(string, p->name) != 0) continue; if (type == STRING) { if (TYPE(p) != STRING) continue; } else if (TYPE(p) == STRING) continue; return((pval) p); } p = (atom *) new(type); p -> name = alloc(size); strcpy(p -> name, string); p -> link = hashtable[h]; p -> lib = FALSE; p -> op_t = NONOP; p -> pred = 0; hashtable[h] = p; return((pval) p); } /* Data structures to compute the offset for each variable */ extern pval error(); var **varcell; var *variable(id) register atom *id; { extern atom *anon; extern int argn; register i; register var *rval; if (id != anon) for (i = 0; i < argn; i++) if (id == varcell[i] -> pname) return(varcell[i]); if (++argn > MAXVAR) error("TOO MANY VARIABLES IN CLAUSE", FALSE); varcell[argn-1] = rval = (var *) new(VAR); rval -> offset = argn - 1; rval -> pname = id; return(rval); } pval in_uniop(oper,opand) pval oper,opand; { pval rval; rval = (pval) record(1); rval -> c.term[0] = oper; rval -> c.term[1] = opand; return(rval); } pval in_biop(oper, opand1, opand2) pval oper, opand1, opand2; { pval rval; rval = (pval) record(2); rval -> c.term[0] = oper; rval -> c.term[1] = opand1; rval -> c.term[2] = opand2; return(rval); } clause *Q; atom *same_proc = 0; atom *add_clause(cl) register clause *cl; { register atom *a; register clause *p; extern int library, read_err; if (read_err) return(0); if (isatom(cl -> goal[0])) a = (atom *) cl -> goal[0]; else if (iscompound(cl->goal[0]) && isatom(cl->goal[0]->c.term[0])) a = (atom *) (cl -> goal[0] -> c.term[0]); else error("Bad principal functor in clause head", FALSE); if (TYPE(a) == PREDEF || (a -> lib && ! library)) error("can't redefine a predefined function", FALSE); if (a == same_proc) { Q -> rest = cl; Q = Q -> rest; } else { same_proc = a; if (a -> val == 0) Q = a -> val = cl; else { p = a -> val; while (p -> rest != 0) p = p -> rest; Q = p -> rest = cl; } a -> lib = library; } return(a); } /* Garbage disposal */ free_term(t) pval t; { register i, limit; if (t == 0) return; switch(TYPE(t)) { case FREE : case ATOM : case PREDEF : case STRING : return; case INT : if (t == (pval) stack_int) return; free(t); return; case VAR : TYPE(t) = FREE; free(t); return; case FN : #ifndef PRINC_VAR i = 1; break; #endif case LIST : i = 0; break; case CLAUSE : for (i = 0; t -> g.goal[i]; i++) free_term(t -> g.goal[i]); free(t); same_proc = (atom *) 0; return; default : fprintf(stderr, "\nProlog error: FREE - Unknown type %d\n", TYPE(t)); exit(); } limit = SIZE(t); while (i <= limit) free_term(t -> c.term[i++]); free(t); } free_proc(p) clause *p; { register clause *q; register i; while (p) { q = p; p = p -> rest; for (i = 0; q -> goal[i]; i++) free_term(q -> goal[i]); free(q); } same_proc = (atom *) 0; }