From ca8f949e7bf65b3ed0ab0e738226b5029984467d Mon Sep 17 00:00:00 2001 From: mathfichen <95310750+mathfichen@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:17:44 +0000 Subject: [PATCH] Curated outputs for PR #8 --- metadata/checksums.csv | 1 + metadata/journal.md | 5 + source_code/README.md | 3 - source_code/c-prolog-1982/._copyrigh.t | Bin 0 -> 176 bytes source_code/c-prolog-1982/arith.c | 530 +++ source_code/c-prolog-1982/arith.o | Bin 0 -> 19108 bytes source_code/c-prolog-1982/arithop.h | 60 + source_code/c-prolog-1982/auxfn.c | 210 + source_code/c-prolog-1982/auxfn.o | Bin 0 -> 12624 bytes source_code/c-prolog-1982/bootcmd | 2 + source_code/c-prolog-1982/compare.c | 68 + source_code/c-prolog-1982/compare.o | Bin 0 -> 7516 bytes source_code/c-prolog-1982/copyrigh.t | 15 + source_code/c-prolog-1982/dbase.c | 519 +++ source_code/c-prolog-1982/dbase.o | Bin 0 -> 22068 bytes source_code/c-prolog-1982/evalp.h | 154 + source_code/c-prolog-1982/hw1 | 105 + source_code/c-prolog-1982/hw4.pl | 159 + source_code/c-prolog-1982/main.c | 1788 +++++++++ source_code/c-prolog-1982/main.o | Bin 0 -> 70268 bytes source_code/c-prolog-1982/makefile | 51 + source_code/c-prolog-1982/makefile.save | 50 + source_code/c-prolog-1982/makesys.com | 23 + source_code/c-prolog-1982/man/app.me | 107 + source_code/c-prolog-1982/man/app.out | 131 + source_code/c-prolog-1982/man/cprolog.me | 2891 ++++++++++++++ source_code/c-prolog-1982/man/cprolog.out | 3959 +++++++++++++++++++ source_code/c-prolog-1982/man/makefile | 5 + source_code/c-prolog-1982/man/makefile.save | 5 + source_code/c-prolog-1982/parms.c | 84 + source_code/c-prolog-1982/parms.o | Bin 0 -> 6800 bytes source_code/c-prolog-1982/pl.h | 581 +++ source_code/c-prolog-1982/pl/all | 17 + source_code/c-prolog-1982/pl/arith | 106 + source_code/c-prolog-1982/pl/grammar | 51 + source_code/c-prolog-1982/pl/init | 541 +++ source_code/c-prolog-1982/pl/listing | 64 + source_code/c-prolog-1982/pl/protect | 64 + source_code/c-prolog-1982/pl/setof | 166 + source_code/c-prolog-1982/pl/tracing | 147 + source_code/c-prolog-1982/pl/vmsall | 17 + source_code/c-prolog-1982/prolog | Bin 0 -> 230240 bytes source_code/c-prolog-1982/pstartup1.5 | Bin 0 -> 59624 bytes source_code/c-prolog-1982/read.me | 258 ++ source_code/c-prolog-1982/rewrite.c | 818 ++++ source_code/c-prolog-1982/rewrite.o | Bin 0 -> 27340 bytes source_code/c-prolog-1982/space.c | 405 ++ source_code/c-prolog-1982/space.o | Bin 0 -> 14776 bytes source_code/c-prolog-1982/startup | Bin 0 -> 59624 bytes source_code/c-prolog-1982/sysbits.c | 650 +++ source_code/c-prolog-1982/sysbits.o | Bin 0 -> 28192 bytes source_code/c-prolog-1982/trace.c | 275 ++ source_code/c-prolog-1982/trace.h | 26 + source_code/c-prolog-1982/trace.o | Bin 0 -> 15612 bytes source_code/c-prolog-1982/unify.c | 341 ++ source_code/c-prolog-1982/unify.o | Bin 0 -> 18644 bytes 56 files changed, 15449 insertions(+), 3 deletions(-) delete mode 100644 source_code/README.md create mode 100755 source_code/c-prolog-1982/._copyrigh.t create mode 100755 source_code/c-prolog-1982/arith.c create mode 100755 source_code/c-prolog-1982/arith.o create mode 100755 source_code/c-prolog-1982/arithop.h create mode 100755 source_code/c-prolog-1982/auxfn.c create mode 100755 source_code/c-prolog-1982/auxfn.o create mode 100755 source_code/c-prolog-1982/bootcmd create mode 100755 source_code/c-prolog-1982/compare.c create mode 100755 source_code/c-prolog-1982/compare.o create mode 100755 source_code/c-prolog-1982/copyrigh.t create mode 100755 source_code/c-prolog-1982/dbase.c create mode 100755 source_code/c-prolog-1982/dbase.o create mode 100755 source_code/c-prolog-1982/evalp.h create mode 100755 source_code/c-prolog-1982/hw1 create mode 100755 source_code/c-prolog-1982/hw4.pl create mode 100755 source_code/c-prolog-1982/main.c create mode 100755 source_code/c-prolog-1982/main.o create mode 100755 source_code/c-prolog-1982/makefile create mode 100755 source_code/c-prolog-1982/makefile.save create mode 100755 source_code/c-prolog-1982/makesys.com create mode 100755 source_code/c-prolog-1982/man/app.me create mode 100755 source_code/c-prolog-1982/man/app.out create mode 100755 source_code/c-prolog-1982/man/cprolog.me create mode 100755 source_code/c-prolog-1982/man/cprolog.out create mode 100755 source_code/c-prolog-1982/man/makefile create mode 100755 source_code/c-prolog-1982/man/makefile.save create mode 100755 source_code/c-prolog-1982/parms.c create mode 100755 source_code/c-prolog-1982/parms.o create mode 100755 source_code/c-prolog-1982/pl.h create mode 100755 source_code/c-prolog-1982/pl/all create mode 100755 source_code/c-prolog-1982/pl/arith create mode 100755 source_code/c-prolog-1982/pl/grammar create mode 100755 source_code/c-prolog-1982/pl/init create mode 100755 source_code/c-prolog-1982/pl/listing create mode 100755 source_code/c-prolog-1982/pl/protect create mode 100755 source_code/c-prolog-1982/pl/setof create mode 100755 source_code/c-prolog-1982/pl/tracing create mode 100755 source_code/c-prolog-1982/pl/vmsall create mode 100755 source_code/c-prolog-1982/prolog create mode 100755 source_code/c-prolog-1982/pstartup1.5 create mode 100755 source_code/c-prolog-1982/read.me create mode 100755 source_code/c-prolog-1982/rewrite.c create mode 100755 source_code/c-prolog-1982/rewrite.o create mode 100755 source_code/c-prolog-1982/space.c create mode 100755 source_code/c-prolog-1982/space.o create mode 100755 source_code/c-prolog-1982/startup create mode 100755 source_code/c-prolog-1982/sysbits.c create mode 100755 source_code/c-prolog-1982/sysbits.o create mode 100755 source_code/c-prolog-1982/trace.c create mode 100755 source_code/c-prolog-1982/trace.h create mode 100755 source_code/c-prolog-1982/trace.o create mode 100755 source_code/c-prolog-1982/unify.c create mode 100755 source_code/c-prolog-1982/unify.o diff --git a/metadata/checksums.csv b/metadata/checksums.csv index f9620cc..45b040e 100644 --- a/metadata/checksums.csv +++ b/metadata/checksums.csv @@ -1 +1,2 @@ path,size,sha256 +/home/runner/work/C-Prolog-Workbench/C-Prolog-Workbench/raw_materials/c-prolog-1.5/c-prolog.tar.gz,360515,6db9e4db921ba3758b4d7c0dbd40e5d5325fcb4b07e0f97265bd065bf534fdf5 diff --git a/metadata/journal.md b/metadata/journal.md index 7a00d2f..79bac11 100644 --- a/metadata/journal.md +++ b/metadata/journal.md @@ -1 +1,6 @@ # Curation journal + +## 2026-07-03 + +Recorded checksums for: +- /home/runner/work/C-Prolog-Workbench/C-Prolog-Workbench/raw_materials/c-prolog-1.5/c-prolog.tar.gz (360515 bytes) sha256=6db9e4db921ba3758b4d7c0dbd40e5d5325fcb4b07e0f97265bd065bf534fdf5 diff --git a/source_code/README.md b/source_code/README.md deleted file mode 100644 index 132b864..0000000 --- a/source_code/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This folder is for the curated revision of the source code, which should be organized putting in a separated folder each major version of the code, in view of the recontruction of the development history as a new git repository. - -Please refer to the [SWHAPPE](https://github.com/Unipisa/SWHAPPE) guidelines for greater details. diff --git a/source_code/c-prolog-1982/._copyrigh.t b/source_code/c-prolog-1982/._copyrigh.t new file mode 100755 index 0000000000000000000000000000000000000000..4dd48d7ea9c6ad2b258c9d7341add6727b22e083 GIT binary patch literal 176 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aUBqY_#1$j2;dkJ5(HHS(y;)D1)zKw z#Rz090AirHRC0c +#include + +#define NEVER 0 +#define SOMETIMES 1 +#define ALWAYS 2 + +double +ffail() +{ + ArithError("internal error - undefined operator"); +} + +extern double sin(), asin(), exp(), sqrt(); +extern double cos(), acos(), log(), floor(); +extern double tan(), atan(), log10(); + +extern int brklev; + +static double (*UFloat[])() = { + ffail, + ffail, + ffail, + ffail, + exp, + log, + log10, + sqrt, + sin, + cos, + tan, + asin, + acos, + atan, + floor, + ffail +}; + +static char floatable[] = { /* code arity function */ + NEVER, /* 0 - UNUSABLE */ + NEVER, /* 1 1 ID */ + SOMETIMES, /* 2 1 - */ + NEVER, /* 3 1 \ */ + ALWAYS, /* 4 1 exp */ + ALWAYS, /* 5 1 log */ + ALWAYS, /* 6 1 log10 */ + ALWAYS, /* 7 1 sqrt */ + ALWAYS, /* 8 1 sin */ + ALWAYS, /* 9 1 cos */ + ALWAYS, /* 10 1 tan */ + ALWAYS, /* 11 1 asin */ + ALWAYS, /* 12 1 acos */ + ALWAYS, /* 13 1 atan */ + SOMETIMES, /* 14 1 floor */ + SOMETIMES, /* 15 1 SPARE */ + ALWAYS, /* 16 - UNUSABLE */ + SOMETIMES, /* 1 2 + */ + SOMETIMES, /* 2 2 - */ + SOMETIMES, /* 3 2 * */ + ALWAYS, /* 4 2 / */ + NEVER, /* 5 2 mod */ + NEVER, /* 6 2 /\ */ + NEVER, /* 7 2 \/ */ + NEVER, /* 8 2 << */ + NEVER, /* 9 2 >> */ + NEVER, /* 10 2 // */ + ALWAYS, /* 11 2 ^ */ + NEVER, /* 12 2 SPARE */ + NEVER, /* 13 2 SPARE */ + NEVER, /* 14 2 SPARE */ + NEVER /* 15 2 SPARE */ +}; + + +typedef struct { + char Float; + union { + int asInt; + double asFloat; + } val; +} Value; + +#define AsInt val.asInt +#define AsFloat val.asFloat + +int AllFloat = TRUE; + +static Value unary(), binary(); + +static Value +eval(t,g) +PTR t, g; +/* traverses a term producing its val and type. + t is the term (derefed and unwrapped), + g is the associated global frame (if t is a skel) +*/ +{ + int b, n, i, typ, fl; PTR f1, f2, arg1, arg2; Value v1, v2; + FUNCTOR *fn; + + if (IsRef(t) && Undef(*t)) /* undefined cell */ + NotNumber(); + if (IsPrim(t)) { /* primitive type */ + if (IsInt(t)) { /* integer */ + v1.Float = FALSE; + v1.AsInt = XtrInt(t); + return v1; + } + if (IsFloat(t)) { /* float */ + v1.Float = TRUE; + v1.AsFloat = XtrFloat(t); + return v1; + } + NotNumber(); /* non-number */ + } + /* atom or skel */ + /* grab expression info field */ + fn = FunctorP(SkelP(t)->Fn); + b = (fn->flgsoffe)&0x1f; + if (!b) NotOp(fn); + if (IsAtomic(t)) { /* atom */ + switch (b) { + case TIME: + v1.Float = TRUE; + v1.AsFloat = CPUTime(); + return v1; + case HEAP: + v1.Float = FALSE; + v1.AsInt = HeapUsed(); + return v1; + case BREAKLEV: + v1.Float = FALSE; + v1.AsInt = brklev; + return v1; + default: + NotOp(fn); + } + } + /* skel (first check for [_]) */ + if (fn == FunctorP(listfunc)) { + if (argv(Addr(SkelP(t)->Arg2),g,&f1) != atomnil) + ArithError("not a string"); + arg1 = argv(Addr(SkelP(t)->Arg1),g,&f1); + return eval(arg1,f1); + } + /* skel (general case) */ + n = fn->arityoffe; /* grab arity */ + if (n > 2) NotOp(fn); + switch (n) { + case 1: /* unary */ + arg1 = argv(++t,g,&f1); + return unary(b,arg1,f1); + case 2: /* binary */ + arg1 = argv(++t,g,&f1); + arg2 = argv(++t,g,&f2); + return binary(b, arg1, arg2, f1, f2); + default: + ffail(); + } +} + +static Value +unary(op,arg,env) +int op; PTR arg, env; +{ + int fl = floatable[op], typ; + Value v; + + typ = fl-(1-AllFloat) > 0; + errno = 0; /* no errors */ + v = eval(arg,env); + if (fl == NEVER) { + if (!ForceInt(&v)) NotInt(); + } else + if (v.Float) + typ = TRUE; + else if (typ) { + v.AsFloat = (double)(v.AsInt); + v.Float = TRUE; + } + switch (op) { + case ID: + break; + case UMINUS: + if (typ) v.AsFloat = -v.AsFloat; + else v.AsInt = -v.AsInt; + break; + case NOT: + v.AsInt = ~v.AsInt; + break; + default: /* ALWAYS functions */ + v.AsFloat = (*UFloat[op])(v.AsFloat); + } + if (errno != 0) ArithError(SysError()); + return v; +} + +static Value +binary(op,arg1,arg2,env1, env2) +int op; PTR arg1, arg2, env1, env2; +{ + Value v1, v2; + int fl = floatable[op+16], typ; + + v1 = eval(arg1,env1); + v2 = eval(arg2,env2); + typ = fl-(1-AllFloat) > 0; + errno = 0; /* no errors */ + if (fl == NEVER) { + if (!ForceInt(&v1)) NotInt(); + if (!ForceInt(&v2)) NotInt(); + } else { + typ |= v1.Float | v2.Float; + if (typ) { /* coerce both args. to float */ + if (!v1.Float) v1.AsFloat = (double)(v1.AsInt); + if (!v2.Float) v2.AsFloat = (double)(v2.AsInt); + } + v2.Float = typ; + } + switch (op) { + case PLUS: + if (typ) + v2.AsFloat = v1.AsFloat+v2.AsFloat; + else + v2.AsInt = v1.AsInt+v2.AsInt; + break; + case MINUS: + if (typ) + v2.AsFloat = v1.AsFloat-v2.AsFloat; + else + v2.AsInt = v1.AsInt-v2.AsInt; + break; + case TIMES: + if (typ) + v2.AsFloat = v1.AsFloat*v2.AsFloat; + else + v2.AsInt = v1.AsInt*v2.AsInt; + break; + case DIVIDE: + if (typ) + v2.AsFloat = v1.AsFloat/v2.AsFloat; + else + v2.AsInt = v1.AsInt/v2.AsInt; + break; + case MOD: + v2.AsInt = v1.AsInt%v2.AsInt; + return v2; + case AND: + v2.AsInt = v1.AsInt&v2.AsInt; + return v2; + case OR: + v2.AsInt = v1.AsInt|v2.AsInt; + return v2; + case LSHIFT: + v2.AsInt = v1.AsInt<>v2.AsInt; + return v2; + case IDIV: + v2.AsInt = v1.AsInt/v2.AsInt; + return v2; + case POW: + v2.AsFloat = pow(v1.AsFloat,v2.AsFloat); + return v2; + default: + ffail(); + } + if (errno) ArithError(SysError()); + return v2; +} + +int +intval(p) +PTR p; +/* Evaluates an expression as an integer, causes an event if + the value is not an integer */ +{ + PTR f, v; Value r; + + v = vvalue(p,&f); + r = eval(v,f); + if (r.Float) { + r.Float = !Narrow(r.AsFloat, &(r.AsInt)); + if (r.Float) ArithError("Integer expected"); + } + return r.AsInt; +} + +PTR +numeval(p) +PTR p; +/* Evaluates expression p and returns a number representation */ +{ + PTR f, v; + Value r; + + v = vvalue(p,&f); + r = eval(v,f); + if (r.Float) + r.Float = !Narrow(r.AsFloat, &(r.AsInt)); + if (r.Float) + return ConsFloat(r.AsFloat); + else + return ConsInt(r.AsInt); +} + +PTR +Unary(op,v) +int op; PTR v; +/* Applies op to x and returns a number representation */ +{ + Value r; PTR f; + + v = vvalue(v,&f); + r = unary(op,v,f); + if (r.Float) + r.Float = !Narrow(r.AsFloat, &(r.AsInt)); + if (r.Float) + return ConsFloat(r.AsFloat); + else + return ConsInt(r.AsInt); +} + +PTR +Binary(op,v1,v2) +int op; PTR v1, v2; +/* Applies op to v1 and v2 and returns a number representation */ +{ + Value r; PTR f1, f2; + + v1 = vvalue(v1,&f1); + v2 = vvalue(v2,&f2); + r = binary(op,v1,v2,f1,f2); + if (r.Float) + r.Float = !Narrow(r.AsFloat, &(r.AsInt)); + if (r.Float) + return ConsFloat(r.AsFloat); + else + return ConsInt(r.AsInt); +} + +int +numcompare(op,t1,t2) +int op; +PTR t1, t2; +/* Applies comparison operation op to expressions t1 and t2 */ +{ + PTR f, t; + Value v1, v2; + + t = vvalue(t1,&f); + v1 = eval(t,f); + t = vvalue(t2,&f); + v2 = eval(t,f); + if (v1.Float || v2.Float) { + if (!v1.Float) v1.AsFloat = (double)(v1.AsInt); + if (!v2.Float) v2.AsFloat = (double)(v2.AsInt); + switch (op) { + case EQ: return v1.AsFloat == v2.AsFloat; + case NE: return v1.AsFloat != v2.AsFloat; + case LT: return v1.AsFloat < v2.AsFloat; + case GT: return v1.AsFloat > v2.AsFloat; + case LE: return v1.AsFloat <= v2.AsFloat; + case GE: return v1.AsFloat >= v2.AsFloat; + default: return NEVER; + } + } + switch (op) { + case EQ: return v1.AsInt == v2.AsInt; + case NE: return v1.AsInt != v2.AsInt; + case LT: return v1.AsInt < v2.AsInt; + case GT: return v1.AsInt > v2.AsInt; + case LE: return v1.AsInt <= v2.AsInt; + case GE: return v1.AsInt >= v2.AsInt; + default: return NEVER; + } +} + +int +intsign(n1,n2) +PTR n1, n2; +/* returns the sign of the difference between numbers t1 and t2 */ +{ + double v1, v2; + + v1 = IsInt(n1) ? (double)XtrInt(n1) : XtrFloat(n1); + v2 = IsInt(n2) ? (double)XtrInt(n2) : XtrFloat(n2); + return (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0); +} + +/* ====================================================================== + +These two functions are totally dependant on the float representation +of the machine. The type tag for a constructed float is binary 110 +in the most significant bits of a 32 bit word. To fit a machine +float into a constructed float, the 3 least significant bits of the +mantissa are dropped. In the VAX F_floating format, the lowest +significance bits are on the right in the second 16 bit word +of the value. + +The code given here for the Perq appears to work. + +In the IEEE single precision floating point, the lowest significant bits +are on the right. + +*/ + +typedef union { +#ifdef vax + struct { + short loword; + short hiword; + } aswords; +#endif +#ifdef IEEE + unsigned asunsigned; +#endif + float asfloat; + PTR asPTR; + } Mixed; + +PTR +ConsFloat(f) + float f; + { + Mixed m; + + m.asfloat = f; +#ifdef vax + m.aswords.hiword = ((m.aswords.hiword>>3)&0x1fff)|(FLOAT_TAG>>16); +#endif +#ifdef IEEE + m.asunsigned = (m.asunsigned>>3)|FLOAT_TAG; +#endif + return m.asPTR; + } + +float +XtrFloat(p) + PTR p; + { + Mixed m; + + m.asPTR = p; +#ifdef Perq + m.aslong <<= 3; +#endif +#ifdef vax + m.aswords.hiword <<= 3; +#endif +#ifdef IEEE + m.asunsigned <<= 3; +#endif + return m.asfloat; + } + +/* ====================================================================== */ + +int +Narrow(f,i) + double f; int *i; + { + register int k; + + if (f < MinInt || f > MaxInt) return FALSE; + if ((double)(k = (int)f) != f) return FALSE; + *i = k; + return TRUE; + } + +static int +ForceInt(v) + register Value *v; + { + if (v->Float) v->Float = !Narrow(v->AsFloat, &(v->AsInt)); + return !v->Float; + } + +ArithError(s) + char *s; + { + ErrorMess = s; + Event(ARITH_ERROR); + } + +NotNumber() + { + ArithError("not a number"); + } + +static +NotInt() + { + ArithError("arithmetic operation requires integers"); + } + +static +NotOp(fn) + FUNCTOR *fn; + { + sprintf(OutBuf, + fn->arityoffe + ? "%s is not an arithmetic operator" + : "%s is not a number", + AtomP(fn->atoffe)->stofae); + ArithError(OutBuf); + } + diff --git a/source_code/c-prolog-1982/arith.o b/source_code/c-prolog-1982/arith.o new file mode 100755 index 0000000000000000000000000000000000000000..bdb56a9936f017713cb468a96c434b6e6aa0f405 GIT binary patch literal 19108 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 */ +#define LE 4 /* =< */ +#define GE 5 /* >= */ + +/* nullary */ + +#define TIME 1 +#define HEAP 2 +#define BREAKLEV 3 + +/* unary */ + +#define ID 1 +#define UMINUS 2 +#define NOT 3 +#define EXP 4 +#define LOG 5 +#define LOG10 6 +#define SQRT 7 +#define SIN 8 +#define COS 9 +#define TAN 10 +#define ASIN 11 +#define ACOS 12 +#define ATAN 13 +#define FLOOR 14 + +/* binary */ + +#define PLUS 1 +#define MINUS 2 +#define TIMES 3 +#define DIVIDE 4 +#define MOD 5 +#define AND 6 +#define OR 7 +#define LSHIFT 8 +#define RSHIFT 9 +#define IDIV 10 +#define POW 11 diff --git a/source_code/c-prolog-1982/auxfn.c b/source_code/c-prolog-1982/auxfn.c new file mode 100755 index 0000000..c1824e5 --- /dev/null +++ b/source_code/c-prolog-1982/auxfn.c @@ -0,0 +1,210 @@ +/********************************************************************** +* * +* C Prolog auxfn.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +#include "pl.h" + +PTR +fentry(atom,arity) +PTR atom; int arity; +{ + register PTR fe, ne, p; int i; + + for (fe = atom;; fe = FunctorP(fe)->nxtoffe) + if (FunctorP(fe)->arityoffe == arity) + return fe; + else if (Undef(FunctorP(fe)->nxtoffe)) + break; + ne = getsp(szoffe+arity); + Unsafe(); + FunctorP(ne)->atoffe = atom; FunctorP(ne)->infoffe = 0; + FunctorP(ne)->arityoffe = arity; + FunctorP(ne)->FClauses.First = FunctorP(ne)->FClauses.Last = NULL; + FunctorP(ne)->FRecords.First = FunctorP(ne)->FRecords.Last = NULL; + FunctorP(ne)->nxtoffe = NULL; + FunctorP(fe)->nxtoffe = ne; + p = Addr(FunctorP(ne)->gtoffe); + for (i = 0; i < arity; i++) + *++p = SkelGlobal(i); + FunctorP(ne)->gtoffe = ne; + Safe(); + return ne; +} + +PTR +apply(at,n,args) +PTR at; register PTR args; register int n; +{ + PTR sk, s; register PTR r; + sk = Addr(FunctorP(fentry(at,n))->gtoffe); + s = r = v1; GrowGlobal(n); + while (n-- > 0) + *r++ = *args++; + ConsMol(sk,s,r); + return r; +} + +PTR +makelist(n,elms) +int n; PTR elms; +{ + register PTR p; PTR f; register int i; register PTR r; + p = elms+n-1; + for (; n > 10; n -= 9) { + f = r = v1; GrowGlobal(10); + for (i = 0; i < 10; i++) + *r++ = *p--; + ConsMol(List10,f,*++p); + } + f = r = v1; GrowGlobal(n); + for (i = 0; i < n; i++) + *r++ = *p--; + ConsMol(List10+(10-n)*3,f,r); + return r; +} + +int +list_to_string(t,s,n) +PTR t; +char *s; +int n; +{ + int c; + PTR e, a; + + if (t == atomnil) { + *s = '\0'; + return TRUE; + } + if (IsInp(t) || Undef(*t)) return FALSE; + e = MolP(t)->Env; t = MolP(t)->Sk; + while (t != atomnil) { + if (IsAtomic(t) || IsVar(t) || SkelP(t)->Fn != listfunc) return FALSE; + if (n-- <= 0) return FALSE; + a = arg(Addr(SkelP(t)->Arg1),e); + t = argv(Addr(SkelP(t)->Arg2),e,&e); + if (!IsInt(a)) return FALSE; + c = XtrInt(a); + if (c < 0 || c > 255) return FALSE; + *s++ = c; + } + *s = 0; + return TRUE; +} + +/* Print execution statistics */ + +Statistics() +{ + int i; PTR p; + + + for (i = 0; i < NAreas; i++) + printf("%s: %dK (in use: %d, max. used: %d)\n", + AreaName[i], Size[i]/K, used(i), tide(i)); + printf("Runtime: %8.2f sec.\n", CPUTime()); +} + +static int +used(a) +int a; +{ + int u; + + switch (a) { + case AtomId: u = sizeof(PTR)*(atomfp-atom0); break; + case AuxId: u = sizeof(PTR)*(vrz-auxstk0); break; + case TrailId: u = sizeof(PTR)*(tr-trbase); break; + case HeapId: u = HeapUsed(); break; + case GlobalId: u = sizeof(PTR)*(v1-glb0); break; + case LocalId: u = sizeof(PTR)*(v-lcl0); break; + default: u = 0; + } + return u; +} + +static int +tide(a) +int a; +{ + int u; + + switch (a) { + case HeapId: u = HeapTide(); break; + case AtomId: u = sizeof(PTR)*(atomfp-atom0); break; + case AuxId: + case TrailId: + case GlobalId: + case LocalId: u = sizeof(PTR)*(Tide[a]-Origin[a]); break; + default: u = 0; + } + return u; +} + +/* Atom hash function */ + +static PTR +string_to_atom(name,app) +char *name; PTR **app; +{ + register unsigned int h; register ATOM **ap; register char *s = name; + + h = strlen(s); + while (*s) h += *s++; + for (ap = (ATOM **)(hasha+h%HASHSIZE); *ap; + ap = (ATOM **)Addr((*ap)->nxtofae)) + if (strcmp((*ap)->stofae,name) == 0) break; + *app = (PTR*)ap; + return *ap; +} + +/* Intern a string to get a prolog atom */ + +PTR +lookup(id) +char *id; +{ + PTR old, ptr, new; + + if (old = string_to_atom(id,&ptr)) return old; + new = atomfp; + GrowAtom(Words(szofae+strlen(id))); + Unsafe(); + *ptr = new; ptr = new; + AtomP(ptr)->atofae = ptr; + AtomP(ptr)->infofae = 0; + AtomP(ptr)->infxofae = + AtomP(ptr)->prfxofae = AtomP(ptr)->psfxofae = -1; + AtomP(ptr)->AClauses.First = AtomP(ptr)->AClauses.Last = NULL; + AtomP(ptr)->ARecords.First = AtomP(ptr)->ARecords.Last = NULL; + AtomP(ptr)->fcofae = NULL; + AtomP(ptr)->nxtofae = NULL; + strcpy(AtomP(ptr)->stofae,id); + Safe(); + return ptr; +} + +int +hide_atom(a) +ATOM *a; +{ + PTR *aa; PTR *lostatoms = CellP(hasha+HASHSIZE); + + if (!string_to_atom(a->stofae,&aa)) return FALSE; + *aa = a->nxtofae; + a->nxtofae = *lostatoms; + *lostatoms = (PTR)a; + return TRUE; +} diff --git a/source_code/c-prolog-1982/auxfn.o b/source_code/c-prolog-1982/auxfn.o new file mode 100755 index 0000000000000000000000000000000000000000..54a103f23ab6fcc3f54b3c198833aeee63c28ed6 GIT binary patch literal 12624 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 b|Jz0X!bShuMfFn->arityoffe)) + +compare(T1,T2) +PTR T1, T2; +/* Returns the comparison value between T1 and T2 */ +{ + PTR E1, E2; + + E1 = E2 = NULL; + T1 = vvalue(T1,&E1); + T2 = vvalue(T2,&E2); + return comp(T1,E1,T2,E2); +} + +static comp(T1,E1,T2,E2) +PTR T1, E1, T2, E2; +{ + PTR t1, e1, t2, e2; int d1, d; + + if (T1 == T2 && E1 == E2) return 0; + d1 = code(T1); + d = d1 - code(T2); + if (d) return d; /* If codes different return difference */ + if (d1 < 0) { /* Both vars. or primitives */ + if (IsNumber(T1)) /* Both numbers */ + return intsign(T1,T2); + else + return T1-T2; /* Both variables or pointers */ + } + /* both atoms or molecules */ + if (SkelP(T1)->Fn == SkelP(T2)->Fn) { + /* same functors (can't be atoms) */ + while (d1-- > 0) { + t1 = argv(++T1,E1,&e1); + t2 = argv(++T2,E2,&e2); + if (d = comp(t1,e1,t2,e2)) + break; + } + return d; + } + /* compare names */ + return strcmp(SkelP(T1)->Fn->atoffe->stofae, + SkelP(T2)->Fn->atoffe->stofae); +} + diff --git a/source_code/c-prolog-1982/compare.o b/source_code/c-prolog-1982/compare.o new file mode 100755 index 0000000000000000000000000000000000000000..17c765bd724e7608e547cd3422df46d8f8ebea94 GIT binary patch literal 7516 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 MAX_VAR) { + toomany = TRUE; + return MAX_VAR; + } + vid[nvars] = vi; vn[nvars] = 0; + return nvars++; +} + +PTR +heapify(t,g) +PTR t, g; +{ + int n; PTR p1, p3, f; unsigned p2; + if (IsPrim(t) && IsDBRef(t)) /* if database reference */ + XtrDBRef(t)->refcofcl++; /* increment ref count of refed term */ + if (IsAtomic(t)) + return t; /* nothing to store for atomic terms */ + if (Undef(*t)) { /* if variable */ + n = LookVar(t); /* look it up in variable table */ + p2 = vn[n]; /* get variable properties */ + if (p2) /* if previously used */ + p2 |= Twice; /* mark as multiple occurrence */ + if (onhead) /* if processing clause head */ + p2 |= OnHead; /* mark as such */ + else + p2 |= OnBody; /* else mark as body variable */ + if (lev > 1) /* if not at outer level */ + p2 |= Global; /* mark as global */ + vn[n] = p2; /* store updated properties */ + p2 = SkelGlobal(n); /* make variable prototype (global n) */ + if ((!lev) && !onhead) { /* handle variable goal */ + p1 = getsp(SkelSz(1)); /* by converting into call(X) */ + SkelP(p1)->Fn = calltag; SkelP(p1)->Arg1 = p2; + return p1; + } + return p2; /* return variable prototype */ + } + if(IsRef(t)) /* compound term */ + g = MolP(t)->Env, t = MolP(t)->Sk; /* extract skel and env */ + n = FunctorP(*t)->arityoffe; /* arity of functor */ + p1 = getsp(SkelSz(n)); /* make term vector */ + SkelP(p1)->Fn = SkelP(t)->Fn; p3 = Addr(SkelP(p1)->Arg1); lev++; + for (; n>0; n--) /* do term arguments */ + argx = argv(++t,g,&f), *p3++ = heapify(argx,f); + lev--; + return p1; /* return heapified term */ +} + +PTR +heapifybody(t,g) +PTR t, g; +{ + PTR p1, f; + + if (IsAtomic(t) || Undef(*t)) + return heapify(t,g); + if (IsRef(t)) + g = MolP(t)->Env, t = MolP(t)->Sk; + if (SkelP(t)->Fn == commatag) { + p1 = getsp(SkelSz(2)); + SkelP(p1)->Fn = commatag; + argx = argv(Addr(SkelP(t)->Arg1),g,&f); + SkelP(p1)->Arg1 = heapify(argx,f); + argx = argv(Addr(SkelP(t)->Arg2),g,&f); + SkelP(p1)->Arg2 = heapifybody(argx,f); + return p1; + } + return heapify(t,g); +} + +static +scan(c) +PTR c; +{ + int n; + + if (IsVar(*c)) { + *c = *CellP(CharP(vn)+VarNo(*c)); + return; + } + if (IsAtomic(*c)) + return; + c = *c; n = FunctorP(SkelP(c)->Fn)->arityoffe; + for (; n > 0; n--) + scan(++c); +} +PTR +record(key, t, rk, aorz) +PTR t, rk; int key, aorz; +{ + int j; PTR proclist; + + nvars = 0; toomany = FALSE; refsflg = FALSE; + if(IsRef(t) && !Undef(*t)) + g = MolP(t)->Env, t = MolP(t)->Sk; + if (key == RECORD) + goto dbase; + /* asserting a clause */ + lev = 0; onhead = TRUE; + if (IsComp(t) && (SkelP(t)->Fn == arrowtag)) { + argx = argv(Addr(SkelP(t)->Arg1),g,&f), head = heapify(argx,f); + onhead = FALSE; + argx = argv(Addr(SkelP(t)->Arg2),g,&f), body = heapifybody(argx,f); + } else { + head = heapify(t,g); + body = NULL; + } + if (IsVar(head)) { + ErrorMess ="! Clause head is a variable (assert)"; + goto errorexit; + } + if (IsPrim(head)) { + ErrorMess = "! Clause head is an integer (assert)"; + goto errorexit; + } + if (IsPrim(body) && !InBoot) { + ErrorMess = "! Clause body is an integer (assert)"; + goto errorexit; + } + r = SkelP(head)->Fn; + if ((FunctorP(r)->flgsoffe)&RESERVED) { + ErrorMess = "! Attempt to redefine a system predicate"; + goto errorexit; + } + if (rk && (!toomany) && !refsflg) { + /* reconsulting */ + for (proclist = vra; proclist < vrz; proclist++) + if(*proclist == r) goto found; + abolish(r); + *vrz++ = r; + HighTide(vrz,Auxtide); + if (vrz > auxmax) NoSpace(AuxId); + } + found: rk = r; + + goto insert; + + dbase: /* inserting a item on the data base */ + if (IsRef(rk)) { + rk = *rk; + if(IsComp(rk)) + rk = SkelP(rk)->Fn; + } + if (IsntName(rk) || IsRef(rk)) { + ErrorMess = "! Illegal key (record)"; + return NULL; + } + head = rk; + lev = 2; + body = heapify(t,g); + + insert: + if (toomany) { + ErrorMess = "! Too many variables in term or clause being recorded"; + goto errorexit; + } + if (refsflg) { + ErrorMess = "! Term or clause being recorded contains references"; + goto errorexit; + } + r = getsp(szofcl); + Unsafe(); + ClauseP(r)->hdofcl = head; ClauseP(r)->bdyofcl = body; + ng = nl = nt = 0; + for (j = 0; j < nvars; j++) + if (Unsigned(vn[j])&Global) + vn[j] = SkelGlobal(ng++); + else if (OnBody&Unsigned(vn[j])) + vn[j] = SkelLocal(nl++); + else vn[j] = ((PTR)0)+nt++; + if (nt > 0) { + k = SkelLocal(nl); + for (j = 0; j < nvars; j++) + if (Unsigned(vn[j]) < 1024) + vn[j] = Unsigned(k)+Unsigned(vn[j]); + } + ClauseP(r)->altofcl = ClauseP(r)->prevofcl = NULL; + ClauseP(r)->infofcl = 0; + ClauseP(r)->ltofcl = nl+nt; + ClauseP(r)->lvofcl = nl; + ClauseP(r)->gvofcl = ng; + if (body) + scan(&body); + if (key == CLAUSE) + scan(&head); + rk = key == CLAUSE ? &(FunctorP(rk)->FClauses) + : &(FunctorP(rk)->FRecords); + + if (aorz) { /* store at the beginning */ + r->prevofcl = NULL; + r->altofcl = rk->First; + if (rk->First) + rk->First->prevofcl = r; + rk->First = r; + if (!(rk->Last)) + rk->Last = r; + } else { /* store at the end */ + r->prevofcl = rk->Last; + r->altofcl = NULL; + if (rk->Last) + rk->Last->altofcl = r; + rk->Last = r; + if (!(rk->First)) + rk->First = r; + } + Safe(); + return ConsDBRef(r,key); + errorexit: + Safe(); + freeterm(head); + freeterm(body); + return NULL; +} + +int +erased(r) +PTR r; +{ + PTR c; + + if (!IsDBRef(r)) { + ErrorMess = "! Erased argument is not a reference"; + return -1; + } + c = XtrDBRef(r); + return((ClauseP(c)->infofcl&ERASED) != 0); +} + +erase(r) +PTR r; +/* erase term pointed by reference r */ +{ + int key; PTR c, d; + + if (!IsDBRef(r)) { + ErrorMess = "! Erase argument is not a reference"; + return FALSE; + } + key = DBType(r); + c = XtrDBRef(r); +/* fprintf(stderr,"Erasing: %c %x\n",key ? 'R' : 'C',c); */ + if (ClauseP(c)->infofcl&ERASED) return TRUE; + d = ClauseP(c)->hdofcl; + if (key == CLAUSE) + d = SkelP(d)->Fn; + if ((FunctorP(d)->flgsoffe)&RESERVED) { + ErrorMess = "! Attempt to erase a system object"; + return FALSE; + } + ClauseP(c)->infofcl |= ERASED; + if (!InUse(c)) unchain(r); +/* At this point, if c is idle it will have been unchained, so there + will be no junk in the chain if we dispose of it */ + if (Idle(c)) { + dispose(c); +/* fprintf(stderr,"Gone\n"); */ + } + return TRUE; +} + +/* release space occupied by source term c */ + +freeterm(c) +PTR c; +{ + int n, k; PTR p; + +/* c may be 0, in which case it will be caught by IsAtomic below */ + + if (IsPrim(c) && IsDBRef(c)) { + p = XtrDBRef(c); + if (--RC(p) == 0 && Erased(p) && !InUse(p)) +/* If these conditions are true, p will no longer be in a chain, + because it will have been removed either by erase or by hide when + untrailing +*/ + dispose(p); + return; + } + if (IsAtomic(c) || IsVar(c) || IsAtomic(*c)) + return; + k = FunctorP(SkelP(c)->Fn)->arityoffe; + for (p = c, n = k; n>0; n--) + freeterm(*++p); + freeblock(c,k+1); +} + +/* unchain(p), where p is a database reference, removes the record + or clause referred to by p from its backtracking CHAIN. + Unchain is only called for things that are not in use + (either when they are erased or on backtracking by hide). +*/ +unchain(p) +PTR p; +{ + PTR c, r; + int key; + + c = XtrDBRef(p); + key = DBType(p); + r = ClauseP(c)->hdofcl; + if (key == CLAUSE) + r = SkelP(r)->Fn; + /* Choose chain header */ + r = key == CLAUSE ? Addr(FunctorP(r)->FClauses) + : Addr(FunctorP(r)->FRecords); + Unsafe(); + if (c->prevofcl) + c->prevofcl->altofcl = c->altofcl; + else /* first in chain */ + r->First = c->altofcl; + if (c->altofcl) /* not last in chain */ + c->altofcl->prevofcl = c->prevofcl; + else /* last in chain */ + r->Last = c->prevofcl; + Safe(); +} + +/* dispose(c), where c is the address of a clause (record) gets rid + of the space occupied by the clause; freeterm will recover the + space used by the terms, and update reference counts of clauses + (records) pointed to from those terms, possibly causing recursive + calls to dispose. +*/ +dispose(c) +PTR c; +{ + freeterm(ClauseP(c)->bdyofcl); + freeterm(ClauseP(c)->hdofcl); + freeblock(c,szofcl); +} + +/* hide(r), where r is a database reference, is called when an ERASED + object leaves the in-use state (on backtracking). + First, the IN_USE flag is reset. + At this point, we + know that the object's backtrack chain is not being used. + If the object is idle at this point, we can dispose of it. +*/ +hide(r) +PTR r; +{ + PTR c; + + c = XtrDBRef(r); +/* fprintf(stderr,"Hiding: %c %x\n", key ? 'R': 'C',c); */ + ClauseP(c)->infofcl &= ~IN_USE; + unchain(r); + if (RC(c)==0) dispose(c); +} + +abolish(r) +FUNCTOR *r; +{ + CLAUSEREC *oldcl, *nextold; + + if ((r->flgsoffe)&RESERVED) return FALSE; + for (oldcl = r->defsoffe; oldcl; oldcl = nextold) { + nextold = ClauseP(oldcl->altofcl); + oldcl->infofcl |= ERASED; + if (!InUse(oldcl)) unchain(ConsDBRef((PTR)oldcl,CLAUSE)); + if (Idle(oldcl)) dispose(oldcl); + } + return TRUE; +} + +PTR +recorded(key) +int key; +{ +/* key should be RECORD for the data base + or CLAUSE for clauses; + The local stack is expected to contain + ARG1 term to be matched + ARG2 var to be unified with reference into data base + ARG3 + ARG4 indirect pointer to next term to be tried for match +*/ + PTR p, sv1, v1f, t, h, b, sx, tr0; + int n; + + p = *(ARG4); + if (Signed(p) < 255) return FALSE; /* this is a $sysp */ + /* since args of $record(_,_,_) are classified as temp. */ + GrowLocal(4); + sv1 = v1f = v1; tr0 = tr; + for (; TRUE; p = ClauseP(p)->altofcl) { + if (Undef(p)) return NULL; + if (Erased(p)) continue; + sx = x; x = v-4; + if (key == RECORD) { + n = ClauseP(p)->gvofcl; + InitGlobal(n,t); + t = ClauseP(p)->bdyofcl; + n = unifyarg(Addr(FrameP(sx)->v1ofcf),t,v1f); + } else n = 1; + n &= unifyarg(Addr(FrameP(sx)->v2ofcf),ConsDBRef(p,key),v1f); + x = sx; + if (n) break; + v1 = sv1; + while (tr != tr0) **--tr = NULL; + } + ARG4 = Addr(ClauseP(p)->altofcl); + if (!InUse(p)) { + ClauseP(p)->infofcl |= IN_USE; + TrailPtr(ConsDBRef(p,key)); + } + + return ConsDBRef(p,key); +} + +static int rl; static PTR tf; + +static PTR +globalize(t,bodyflg) +PTR t; int bodyflg; +{ + PTR a, b, k; int n; + if (IsAtomic(t)) return t; + if (bodyflg && SkelP(t)->Fn == commatag) { + a = globalize(SkelP(t)->Arg1,FALSE); + b = globalize(SkelP(t)->Arg2,TRUE); + *v1 = a; *(v1+1) = b; t = v1+2; + MolP(t)->Sk = Addr(FunctorP(commatag)->gtoffe); + MolP(t)->Env = v1; + GrowGlobal(4); + return t; + } + n = FunctorP(*t)->arityoffe; + MolP(v1)->Sk = Addr(FunctorP(*t)->gtoffe); + MolP(v1)->Env = v1+2; + a = v1; b = v1+2; GrowGlobal(n+2); + while (n-- > 0) { + k = *++t; + if (IsComp(k)) { + if (IsInp(k)) { + ConsMol(k,tf,k); + } + else if (IsLocalVar(k)) + k = rl+FrameVar(tf,VarNo(k)); + else + k = FrameVar(tf,VarNo(k)); + } + *b++ = k; + } + return a; +} + +int +instance(r,argp) +PTR r, argp; +{ + PTR p, h, b; + int g, l; + + if (!IsDBRef(r)) return -1; + + p = XtrDBRef(r); + g = ClauseP(p)->gvofcl; l = ClauseP(p)->ltofcl; + InitGlobal(g+l,tf); + rl = g-szofcf; + if (DBType(r) == RECORD) h = p->bdyofcl; + else { + h = ClauseP(p)->hdofcl; b = ClauseP(p)->bdyofcl; + if (Undef(b)) b = atomtrue; + if (l>0 ) { + h = globalize(h,FALSE); + b = globalize(b,TRUE); + } else { + if (IsComp(h)) + ConsMol(h,tf,h); + if (IsComp(b)) + ConsMol(b,tf,b); + } + *v1 = h; *(v1+1) = b; + h = Addr(FunctorP(arrowtag)->gtoffe); tf = v1; + GrowGlobal(2); + } + return unifyarg(argp,h,tf); +} + diff --git a/source_code/c-prolog-1982/dbase.o b/source_code/c-prolog-1982/dbase.o new file mode 100755 index 0000000000000000000000000000000000000000..9a627792739bad771a09e5907e51b29383e0dfd6 GIT binary patch literal 22068 zcmd6PeRQ1FdFS)ajHHnfF#7a3b;3JlgvYi3*@#3*mF>u~lIlE)xTiR*fC%zqwC*CHFU6Y`jN({M7EL_Vf_ z^&CLLD(JvRq)y`ay=h{@#02v7M?}oSBn?lRd;t;syUAvAr;(3Os7z-se;≤-4=L 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 E1t~r;bpQYW literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/evalp.h b/source_code/c-prolog-1982/evalp.h new file mode 100755 index 0000000..3a83375 --- /dev/null +++ b/source_code/c-prolog-1982/evalp.h @@ -0,0 +1,154 @@ +/********************************************************************** +* * +* C Prolog evalp.h * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +/* Internal codes for the evaluable predicates. + These connect the definitions in the bootstrap file(s) to the + big case statement following the label EvalPted: in main.c. + The definitions in the bootstrap file are clauses of the form + + p(A1,...,Ak) :- n. + + or calls of the form + + :- $sysp(p(A1,...,Ak),n). + + where p is the evaluable predicate being defined, and n + is its internal code (Prolog doesn't know about the + symbolic definitions below, the actual numbers must be used). + The difference between the first and second forms of definition + is that in the first a stack frame is build for a call to the + predicate, containing the arguments, which can be accessed + in the standard way via the 'x' pointer. In other words, + the C code for the evaluable predicate will execute as + if the definition clause was its parent. In contrast, + evaluable predicates defined in the second way have no + frame pushed for them, it is up to them to find their + arguments and xecution environment. +*/ + +#define _call 1 +#define _cut 2 +#define _repeat 3 +#define _abort 4 +#define _call1 5 +#define _and 6 +#define _see 10 +#define _seeing 11 +#define _seen 12 +#define _tell 13 +#define _telling 14 +#define _told 15 +#define _close 16 +#define _read 17 +#define _write 18 +#define _nl 19 +#define _get0 20 +#define _get 21 +#define _skip 22 +#define _put 23 +#define _tab 24 +#define _fileerrors 25 +#define _nofileerrors 26 +#define _rename 27 +#define _writeq 28 +#define _sh 29 +#define _system 30 +#define _prompt 31 +#define _exists 32 +#define _save 33 +#define _is 40 +#define _ncompare 41 +/* ncompare_+NE + +LT + +GT + +LE + +GE: RESERVED */ +#define _var 50 +#define _nonvar 51 +#define _integer 52 +#define _atomic 53 +#define _eq 54 +#define _ne 55 +#define _functor 56 +#define _arg 57 +#define _univ 58 +#define _atom 59 +#define _erase 60 +#define _asst1 61 +#define _assta1 62 +#define _asst2 63 +#define _assta2 64 +#define _clause 65 +/* clause_+1 : RESERVED */ +#define _rcrded 67 +/* _rcrd_+1 : RESERVED */ +#define _instance 69 +#define _NOLC 70 +#define _LC 71 +#define _trace 72 +#define _rcrda 73 +#define _rcrdz 74 +#define _name 75 +#define _op 76 +#define _leash 78 +#define _debug 79 +#define _catom 80 +/* catom_+1: RESERVED */ +#define _cfunctor 82 +/* cfunctor_+1: RESERVED */ +#define _flags 84 +#define _compare 85 +#define _alpLT 86 +#define _alpGT 87 +#define _alpLE 88 +#define _alpGE 89 +#define _all_float 90 +#define _number 91 +#define _erased 92 +#define _statistics 93 +#define _sysp 100 +#define _sysflgs 101 +#define _brk 102 +#define _exit_break 103 +#define _xprompt 104 +#define _user_exec 105 +#define _save_vars 106 +#define _reset_vars 107 +#define _repply 108 +#define _recons 109 +#define _brkstart 110 +#define _brkend 111 +#define _asstr 112 +#define _RIP 113 +#define _user_call 114 +#define _xrepeat 115 +#define _yes 116 +#define _no 117 +#define _primitive 118 +#define _db_reference 119 +#ifdef GRAPHICS +#define _graphics 120 +#endif +#define _hidden_call 121 +#define _unary 130 +/* 131-149: reserved for unary arithmetic operators */ +#define _binary 150 +/* 151-169: reserved for binary arithmetic operators */ +#define _carith 170 +#define _hideat 171 +#define _isop 172 +#define _abolish 173 +#define _append 174 diff --git a/source_code/c-prolog-1982/hw1 b/source_code/c-prolog-1982/hw1 new file mode 100755 index 0000000..4285a26 --- /dev/null +++ b/source_code/c-prolog-1982/hw1 @@ -0,0 +1,105 @@ +/* + +Name: HW1 +Author: Kenneth Ray Barnhouse +SSN: 245-29-5485 +Date: 5-Feb-1988 +Class: CSE 511 + +Purpose: This programming assignment is a basic introduction to + PROLOG. There are four parts to the homework assignments. + Each is commented below. + +*/ + +/* + +QUESTION 1. + +Define some facts and rules in PROLOG. + +*/ + +man(fred). +man(bill). +woman(jane). +woman(mary). +dog(fido). +dog(pluto). + +animal(X) :- dog(X). +animal(X) :- human(X). +human(X) :- man(X). +human(X) :- woman(X). + +/* + +QUESTION 2. + +Define a prolog procedure called listall/1 that will list all the members of a +class of objects. + +To solve this problem, I used the "fail" function to repeatly find fact +of the form, Class(X) and write them out on the screen in a nice format. + +*/ + +listall(Class) :- Goal =.. [Class,X], + call(Goal), + write(X),write(' is a '),write(Class),nl, + fail. + +listall(_). + +/* + +QUESTION 3: + +define a procedure listof/2 that binds a list of members of a class, +Class, to the variable, List. + +To solve this problem, I first needed to define a function, member, +which would test to see if an atom is contanted in a list. I next +defined listof/2 to call a work function, listof2/3. listof2/3 is a +recursive procedure made of up two clauses. This first clause will +attempt to bind to a variable X a member of the class, Class. Next, the +clause checks to see if this member is already on the list. If not, it +calls itself to find other member of the class, Class other than the +current value of X. When listof2 clause 1 exits, it will add X to the +final list, List. The second clause of the listof2 procedure is called +only if the first clause fails. this clause also defines the List to be +null if no members of Class are found. + +Note: The way I have implemented listof will only return the full list +of members of a certain class. If you remove the cut from the listof +clause, listof will return not only the full list, but on repeated calls +will return all sublist of the full list of members of the class. + +*/ + +member(X,[X|_]). +member(X,[_|T]) :- member(X,T). + +listof(Class,List) :- listof2(Class,[],List),!. + +listof2(Class,Found,[X|List]) :- Goal =.. [Class,X], + call(Goal), + \+ member(X,Found), + listof2(Class,[X|Found],List). +listof2(_,_,List) :- List = []. + +/* + +QUESTION 4: + +define a procedure count/1 that prints the number of members of a certain class. + +To solve this problems, I used the length built-in function and the +listof function defined in Question 3. + +*/ + +count(Class) :- listof(Class,List), + length(List,Size), + write('Number of '),write(Class),write(' = '),write(Size). + diff --git a/source_code/c-prolog-1982/hw4.pl b/source_code/c-prolog-1982/hw4.pl new file mode 100755 index 0000000..b567697 --- /dev/null +++ b/source_code/c-prolog-1982/hw4.pl @@ -0,0 +1,159 @@ +/* + +Name: HW4 +Author: Kenneth Ray Barnhouse +SSN: 245-29-5485 +Date: 15-Apr-1988 +Class: CSE 511 + +Purpose: + To build a simple forward chaining production system in PROLOG. + The language will have two kind of statements, facts and rules. + Facts look just like PROLOG facts. Rules are of the form: + + when condition(s) then action(s) + + where condition(s) are one or more facts connected with 'and'. + and action(s) are one and more actions connected with 'and'. + + Actions are basically any of six verbs: store, remove, output, + input, newline, halt. + + The Top level interpreter will accept two command: run and load. + The form of the load command is: + + load 'filename'. (the single quotes are NOT optional). + + and the run command is just + + run. + + The inner interpreter executes in a basic fetch/execute cycle from + top to bottom in the rule database. This cycle will continue until + a halt statements is executed. + +*/ + +/* + +define some operators to make PROLOG do the work for me. + +*/ + +?- op(300,xfx,then). +?- op(200,fy,when). +?- op(100,xfy,and). +?- op(50,fx,store). +?- op(50,fx,remove). +?- op(50,fx,output). +?- op(50,fx,input). +?- op(50,fx,load). + +/* + +This is the highest level interpreter in my little FCPS. I display a +prompt, read a command and execute it. I then call interpreter to +loop. There are really only two good command here, "load" and "run". + +*/ + +my_interpreter :- write(' My Simple FCPS V1.0 '),nl, + write(' by Ken Barnhouse '),nl, + write(' Valid Commands are '),nl, + write(' load ''filename'' and run '),nl, + unknown(_,fail), + interpreter. + +interpreter :- write('=> '), + read(Command), + call(Command), + interpreter. +/* + +Here I implement the load command. I can't just use consult because the +PROLOG interpreter will not allow me to "retract" any initial facts read in by +"consult". By asserting all the term myself, I can retract them at will. +A little more programming, but it was clean and easy. + +*/ + +load Program :- see(Program), + read_in_terms, + seen. + +read_in_terms :- read(Term), + assert_term(Term). +read_in_terms. + +assert_term(end_of_file). +assert_term(Term) :- assert(Term), + read_in_terms. + +/* + +Here is the inner rule interpreter for my FCPS. It basically implements a +fetch/execute cycle. The first line of the first rule gets a FCPS rule from +the PROLOG database, then the second try to execute it. I used fail to loop +through the database. Then second rule of run just does a recursive call to +run to loop to the top of the database. + +*/ + +run :- when Conditions then Actions, + execute(Conditions,Actions), + fail. +run :- run. + +/* + +the execute rule does the "if conditions met then fire" part of the rule +interpreter. It checks to see if the condition part of the rule is met. +if so, it fire the action part of the rule. If not, it returns true. + +*/ + +execute(Conditions,Actions) :- conditions_met(Conditions),!, + fire_actions(Actions). +execute(_,_). + +/* + +conditions_met/1 checks to see if the conditions are met. We have to do +this recursively if we have several 'and'ed conditions. + +*/ + +conditions_met(Firstcondition and Otherconditions) :- + Firstcondition, + conditions_met(Otherconditions),!. + +conditions_met(Singlecondition) :- Singlecondition. + +/* + +first_actions/1 is basically like condition_met/1 in form, since we must +recursely execute actions that we connected with and's. + +*/ + +fire_actions(Firstaction and Otheractions) :- + call(Firstaction), + fire_actions(Otheractions),!. + +fire_actions(Singleaction) :- call(Singleaction). + +/* + +Here I define the verbs in this language. + +*/ + +store Fact :- assert(Fact). + +remove Fact :- retract(Fact). + +output Term :- write(Term). + +input Term :- read(Term). + +newline :- nl. diff --git a/source_code/c-prolog-1982/main.c b/source_code/c-prolog-1982/main.c new file mode 100755 index 0000000..053ef35 --- /dev/null +++ b/source_code/c-prolog-1982/main.c @@ -0,0 +1,1788 @@ +/********************************************************************** +* * +* C Prolog main.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +#include "pl.h" +#include "evalp.h" +#include "arithop.h" +#include "trace.h" +#include +#include + +extern int sys_nerr; +extern char *sys_errlist[]; +extern PTR HeapTop(); + +#define TEST(c,s,f) {if (c) goto s; else goto f;} +#define TRY(c) TEST(c,continuation,efail) +#define FlOffset (Addr(ClauseP(0)->altofcl)-(PTR)0) + +/* initial atoms */ + +PTR BasicAtom[BATOMS]; + +/* initial functors */ + +PTR BasicFunctor[BFUNCS]; + +/* initial terms */ + +PTR BasicTerm[BTERMS]; + +/* Variables for comunication with read, write and symbol table */ + +PTR hasha, lsp, atomfp, varfp, atprompt; +int lc, quoteia, nvars, fileerrors, reading, InBoot; +VarP varchain; + +/* start-up flag */ + +int running = FALSE; + +/* variables for communication with dbase */ + +PTR vra, vrz; + +/* general error message passing string */ + +char *ErrorMess; + +/* emergency exit */ + +typedef struct { + jmp_buf buf; +} JumpBuf; + +extern JumpBuf ZeroState; + +/* Heap management block */ + +extern char Heap[]; +extern int HeapHeader; + +/* Names of work areas */ + +char *AreaName[] = { + "atom space", "aux. stack", "trail", "heap", + "global stack", "local stack" +}; + +/* Prolog machine registers */ + +PTR x, x1, v, v1, vv, vv1, v1f, tr, tr0; + +/* main loop variables */ + +static int info; +PTR pg, c, bg; +static PTR g, fl; + +#define FL ClauseP(fl) /* failure label */ + +/* miscellaneous */ + +int brklev; + +static int n; +static PTR f, d, b, k, k1, y, p, l, arg1; +static int i, j, i1, i2, bb, modeflag; +static char ch, ch2, *bn, *plparm; + +/* Input/output diversion */ + +#define IfInput(flag,code) { \ + int savedstream = Input; \ + JumpBuf catch; \ + catch = ZeroState; \ + if (!setjmp (ZeroState.buf)) { \ + if (flag) Input = STDIN; \ + code; \ + if (flag) Input = savedstream; \ + ZeroState = catch; \ + } else { \ + if (flag) Input = savedstream; \ + ZeroState = catch; \ + longjmp (ZeroState.buf, 1); \ + } \ +} + +#define IfOutput(flag,code) { \ + int savedstream = Output; \ + JumpBuf catch; \ + catch = ZeroState; \ + if (!setjmp (ZeroState.buf)) { \ + if (flag) \ + Output = STDOUT; \ + code; \ + if (flag) \ + Output = savedstream; \ + ZeroState = catch; \ + } else { \ + if (flag) \ + Output = savedstream; \ + ZeroState = catch; \ + longjmp (ZeroState.buf, 1); \ + } \ +} + +/* Variables for the basic debugging package */ + +int debug = FALSE, lev, sklev, spy, leash = 10 /* half */, + dotrace, breakret, invokno, execsys; + +static int recons, cmparith = 0, InStat, OutStat; +static VarP vchain; +static PTR pvrz, *savead; +PTR brkp; + +/* variables to be saved on a break */ + +static PTR * BreakVars[] = { + &breakret, &brkp, &vchain, &recons, &pvrz, + &vra, &vrz, + &x, &x1, &v, &v1, &vv, &vv1, &v1f, &tr, &tr0, + &debug, &execsys, &pg, &g, &info, &lev, &c, &invokno, &fl, + &lc, + &f, &d, &b, &k, &k1, &n, &y, &p, &l, &bb, + &spy, &sklev, &dotrace, + &Input, &Output, &InStat, &OutStat +}; + +/* There must be a one-to-one correspondence between elements of + BreakVars and VarType. The VarType of a BreakVars is REMAP if + the BreakVars is a PTR, otherwise it is FIX. FIXes are converted + to Prolog integers when they are saved, therefore they cannot be + more than 29 bits. + +*/ + +#define FIX 0 +#define REMAP 1 + +static char VarType[] = { + FIX, REMAP, REMAP, FIX, REMAP, + REMAP, REMAP, + REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, + FIX, REMAP, REMAP, REMAP, REMAP, FIX, REMAP, FIX, REMAP, + FIX, + REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, REMAP, FIX, + FIX, FIX, FIX, + FIX, FIX, FIX, FIX +}; + +/* Number of locations in the Prolog environment */ + +#define BrkEnvSize (sizeof(BreakVars)/sizeof(PTR *)) + +static +savev (p, n) +PTR *p; int n; +/* saves n vars starting with p */ +{ + while (n-- > 0) + *savead++ = *p++; +} + +static +rstrv(p,n) +PTR *p; int n; +/* restores n vars starting with v */ +{ + while (n-- > 0) + *p++ = *savead++; +} + +static +savevars() +/* to enter a break */ +{ + PTR nbrkp, **p; char *tp; + + nbrkp = v+MAX_FRAME; + if (nbrkp > vmax) NoSpace(LocalId); + for (p = BreakVars, tp = VarType, savead = nbrkp; + p-BreakVars < BrkEnvSize; p++, tp++, savead++) + *savead = (*tp == FIX) ? ConsInt(Signed(**p)) : **p; + vra = vrz; v = savead; brkp = nbrkp; +} + +static +popbreak() +/* to continue from a break */ +{ + PTR **p; char *tp; + + for (p = BreakVars, tp = VarType, savead = brkp; + p-BreakVars < BrkEnvSize; p++, tp++, savead++) + **p = (*tp == FIX) ? (PTR)XtrInt(*savead) : *savead; +} + +#define latS LSave[AtomId] +#define lauxS LSave[AuxId] +#define ltrS LSave[TrailId] +#define lskelS LSave[HeapId] +#define lglbS LSave[GlobalId] +#define llclS LSave[LocalId] +#define savepS LSave[NAreas] + +static int +save() +/* save current prolog state */ +{ + int i; + unsigned LSave[NAreas+1]; + unsigned *pl; PTR ps; + FILE *fa; + int oldin, oldout; + + /* open file */ + if (!(fa = fopen(AtomToFile(ARG1),"w"))) return FALSE; + errno = 0; /* no errors right now */ + /* save state */ + oldin = Input; oldout = Output; + Input = STDIN; Output = STDOUT; + savevars(); /* create a break environ */ + savepS = savead-lcl0; + savev(BasicAtom,BATOMS); + savev(BasicFunctor,BFUNCS); + savev(BasicTerm,BTERMS); + savev(&atprompt,1); + savev(&brklev,1); + savev(&atomfp,1); + /* compute length of different stacks */ + latS = atomfp-atom0; + lauxS = vrz-auxstk0; + ltrS = tr-trbase; + lskelS = HeapTop()-skel0; + lglbS = v1-glb0; + llclS = savead-lcl0+2; + fwrite(SaveMagic,1,4,fa); /* mark with tag and version no. */ + fwrite(&saveversion,sizeof saveversion,1,fa); + fwrite(LSave,sizeof LSave,1,fa); + fwrite(Origin,sizeof(PTR),NAreas,fa); + fwrite(Limit,sizeof(PTR),NAreas,fa); + fwrite(Heap,HeapHeader,1,fa); + fwrite(&brkp,sizeof brkp,1,fa); + fwrite(&fileerrors,sizeof fileerrors,1,fa); + pl = LSave; ps = Origin; + for (i = 0; i< NAreas; i++) + fwrite(*ps++,sizeof(PTR),*pl++,fa); + fclose(fa); + popbreak(); + Input = oldin; Output = oldout; + if (errno) ErrorMess = SysError(); + return (errno == 0); /* TRUE if no errors, FALSE otherwise */ +} + +/*--------------------------------------------------------------- + + restore Prolog state + +---------------------------------------------------------------*/ + +static PTR PArea[2*NAreas]; +static int RArea[NAreas]; +static unsigned LArea[NAreas]; + +#define patom PArea[AtomId] +#define pauxstk PArea[AuxId] +#define ptr PArea[TrailId] +#define pskel PArea[HeapId] +#define pglb PArea[GlobalId] +#define plcl PArea[LocalId] + +#define ratom RArea[AtomId] +#define rauxstk RArea[AuxId] +#define rtr RArea[TrailId] +#define rskel RArea[HeapId] +#define rglb RArea[GlobalId] +#define rlcl RArea[LocalId] + +static +remap(tp) +PTR tp; +/* remap source term pointed to by tp */ +{ + PTR t; int n; + t = *tp; + if (IsVar(t)) return; + if (SC(t,<,patom)) return; + if (SC(t,<,pskel)) { + *tp = t+ratom; + return; + } + *tp = t+rskel; + tp = *tp; t = *tp+rskel; *tp = t; + n = FunctorP(t)->arityoffe; + while (n-- > 0) + remap(++tp); +} + +static int +restore(sfile) +char *sfile; +{ + FILE *fa; + int i, l; + unsigned savep; int *p; PTR *p1, *p2, s, t, r; + char magic[5]; + + /* open file */ + if (!(fa = fopen(sfile,"r"))) { + ErrorMess = SysError(); + return FALSE; + } + /* check it is a saved Prolog state */ + fread(magic,1,4,fa); magic[4] = 0; + if (strcmp(magic,SaveMagic)) { + sprintf(OutBuf,"! File %s is not a saved Prolog state",sfile); + ErrorMess = OutBuf; + return FALSE; + } + /* check version */ + fread(&i,sizeof(int),1,fa); + if (i != saveversion) { + sprintf(OutBuf, + "! File %s is not compatible with this version of Prolog", + sfile); + ErrorMess = OutBuf; + return FALSE; + } + fread(LArea,sizeof LArea,1,fa); + { + int newsize; + + for(i = 0; i < NAreas; i++) { + newsize = (1+(LArea[i]*sizeof(PTR))/K); + newsize = K*(int)(1.33*newsize); /* 33% margin */ + if (Size[i] < newsize) { + fprintf(stderr, + "[ Expanding %s from %dK to %dK ]\n", + AreaName[i], Size[i]/K, newsize/K); + Size[i] = newsize; + } + } + } + CreateStacks(); + fread(&savep,sizeof savep,1,fa); + fread(PArea,sizeof PArea,1,fa); + fread(Heap,HeapHeader,1,fa); + fread(&brkp,sizeof brkp,1,fa); + fread(&fileerrors,sizeof fileerrors,1,fa); + /* compute relocation constants */ + p1 = Origin; p2 = PArea; p = RArea; + for (i = 0; i < NAreas; i++) + *p++ = *p1++ - *p2++; + /* extract stacks from file */ + p = LArea; p2 = Origin; + for (i = 0; i < NAreas; i++, p++, p2++) { + l = *p; s = *p2; + fread(s,sizeof(PTR),l,fa); + if (i != AtomId && i != HeapId && i != AuxId) + /* relocate stack contents */ + while (l-- > 0) { + k = *s; + if (SC(k,<,ptr)) { + if (SC(k,>=,pauxstk)) k += rauxstk; + else if (SC(k,>=,patom)) k += ratom; + } else { + if (SC(k,>=,pglb)) + k += SC(k,>=,plcl) ? rlcl : rglb; + else + k += (SC(k,>=,pskel)) ? rskel : rtr; + } + *s++ = k; + } + } + savead = savep+lcl0; + rstrv(BasicAtom,BATOMS); + rstrv(BasicFunctor,BFUNCS); + rstrv(BasicTerm,BTERMS); + rstrv(&atprompt,1); + rstrv(&brklev,1); + rstrv(&atomfp,1); + brkp += rlcl; + popbreak(); + /* NB: the various registers in the Prolog machine (those + referred to in BreakVars) have already been remapped + because savevars() saves the environment in the local + stack, whose contents have been remapped above (tricky, + this one!) + */ + /* remap free space chains */ + RelocHeap(rskel); + + /* fix prompt (may have been remapped) */ + SetPlPrompt(AtomP(atprompt)->stofae); + + /* remap auxiliary stack */ + for (k = auxstk0; k < vrz;) { + /* the auxiliary stack can only contain variable records (from 'read') + or functor and atom pointers (from 'reconsult'). Variable records + are distinguished by having either NULL or an aux. stack pointer in + their first word (NextVar); they are variable length, + with the length in VarLen. */ + if (k->NextVar == NULL || + (SC(k->NextVar,>=,pauxstk) && SC(k->NextVar,<,ptr))) { + k->VarValue += rglb; + if (k->NextVar) k->NextVar += rauxstk; + k += k->VarLen; + } + else { + if (SC(*k,>=,pskel)) *k += rskel; + else *k += ratom; + k++; + } + } + /* Remap atom and heap areas */ + + /* Start from the hash table. The test in the loop is <= rather + than < because we want to remap hidden atoms as well, whose + chain is stored at hasha+HASHSIZE */ + + for (k = hasha = atom0; k <= hasha+HASHSIZE; k++) { + p = k; + /* remap hash chain */ + while (*p) { + /* remap arity chain */ + p1 = p; + while (*p1) { + t = *p1; + t += SC(t,<,pskel) ? ratom : rskel; + *p1 = t; /* remap pointer to entry */ + p1 = *p1; + FunctorP(p1)->atoffe += ratom; /* remap pointer to atom */ + if (FunctorP(p1)->FClauses.Last) + FunctorP(p1)->FClauses.Last += rskel; + if (FunctorP(p1)->FRecords.Last) + FunctorP(p1)->FRecords.Last += rskel; + /* remap chain of definitions */ + p2 = Addr(FunctorP(p1)->defsoffe); + while (SC(*p2,>=,pskel)) { + p2 = *p2 += rskel; + /* check for circularity */ + if (ClauseP(p2)->altofcl == p2) break; + remap(&(ClauseP(p2)->hdofcl)); + remap(&(ClauseP(p2)->bdyofcl)); + if (ClauseP(p2)->prevofcl) + ClauseP(p2)->prevofcl += rskel; + p2 = Addr(ClauseP(p2)->altofcl); + } + /* remap data base chain */ + p2 = Addr(FunctorP(p1)->dboffe); + while (SC(*p2,>=,pskel)) { + p2 = *p2 +=rskel; + t = ClauseP(p2)->hdofcl; /* remap key pointer */ + t += (SC(t,<,pskel)) ? ratom : rskel; + ClauseP(p2)->hdofcl = t; + remap(&(ClauseP(p2)->bdyofcl)); + if (ClauseP(p2)->prevofcl) + ClauseP(p2)->prevofcl += rskel; + p2 = Addr(ClauseP(p2)->altofcl); + } + if (SC(p1,>=,skel0)) { + t = Addr(FunctorP(p1-rskel)->gtoffe); + remap(&t); + } + p1 = Addr(FunctorP(p1)->nxtoffe); + } + p = Addr(AtomP(*p)->nxtofae); + } + } + fclose(fa); + return TRUE; +} + +static +ResetTrail(t) +register PTR t; +{ + register PTR k, xtr; register char *status; + + xtr = tr; + while (xtr-- != t) { + k = *xtr; + if (IsRef(k)) *k = NULL; + else { + status = &(ClauseP(XtrDBRef(k))->infofcl); + if (!((*status)&ERASED)) *status &= ~IN_USE; + else hide(k); + } + } + tr = xtr; +} + +static PTR +bread() +/* read initialization terms */ +{ + PTR r; + + do { + v = lcl0; v1 = glb0; + SetPlPrompt(" >> "); PromptIfUser("boot>> "); + varfp = vrz; lsp = v; + reading = FALSE; + } while (!(r = pread())); + return r; +} + +/*=============================================================== + + Prolog execution starts here + +===============================================================*/ + +int PrologEvent; + +main(ArgC,ArgV) +int ArgC; char *ArgV[]; +{ + /* our first Prolog event will be a cold start */ + Safe(); + PrologEvent = COLD_START; + /* Prolog events cause execution to resume fom here */ + setjmp(ZeroState.buf); + CatchSignals(); /* prepare to handle signals etc. */ + switch (PrologEvent) { + /* Prolog event handling + Unix signals are mapped to Prolog events, + Event(..) can also be used to force + a Prolog event to occur. */ + case ABORT: /* abort */ + aborting: + fprintf(stderr,"\n\n[ execution aborted ]\n\n"); + ResetTrail(trbase); CloseFiles(); InitIO(); + goto restart; + case IO_ERROR: /* files error */ + IoFailure: + if (fileerrors) goto efail; + debug = TRUE; + fprintf(stderr,"\n\n%s\n",ErrorMess); + goto aborting; + case END_OF_FILE: /* input ended */ + Seen(); + if (reading) { + reading = FALSE; + goto readend; + } + ErrorMess = "! Input ended"; + goto IoFailure; + case ARITH_ERROR: /* error in arithmetic expression */ + fprintf(stderr,"\n! Error in arithmetic expression: %s\n", + ErrorMess); + debug = TRUE; sklev = NEVER_SKIP; goto efail; + case GEN_ERROR: /* general error with message requiring abort */ + fprintf(stderr,"\n%s",ErrorMess); + goto aborting; + case COLD_START: /* cold start */ + break; + } + + printf("%s\n",version); + + /* process parameters */ + + for (i = 0; i < Switches; i++) + State[i] = FALSE; + plparm = NULL; + while (--ArgC > 0) + if (**++ArgV == '-') { + for (i = 0; i < NParms; i++) + if (Parameter[i] == (*ArgV)[1]) { + ArgV++; ArgC--; + if (*ArgV) Size[i] = atoi(*ArgV)*K; + } + for (i1 = 1; (*ArgV)[i1]; i1++) { + for (i = 0; i < Switches; i++) + if (Switch[i] == (*ArgV)[i1]) { + State[i] = TRUE; + break; + } + if (i > Switches) + fprintf(stderr, + "! Unknown switch: %c\n",(*ArgV)[i1]); + } + } else { + plparm = *ArgV; + break; + } + InBoot = FALSE; + if (!State[IN_BOOT]) { + if (!plparm) { + plparm = UserStartup(); + if (!Exists(plparm)) { + plparm = StandardStartup; + State[QUIET] = TRUE; + } + } + if (!Exists(plparm)) { + fprintf(stderr,"! File %s does not exist\n",plparm); + exit(BAD_EXIT); + } + if (!State[QUIET]) { + printf("[ Restoring file %s ]\n",plparm); + } + if (restore(plparm)) { + InitIO(); + Vtide = v; V1tide = v1; TRtide = tr; Auxtide = vrz; + running = TRUE; + /* the system is now up and running */ + if (brklev > 0) + printf("[ Restarting break (level %d) ]\n",brklev); + TRY(unifyarg(Addr(ARG2),ConsInt(1),0)); + } + fprintf(stderr,"%s\n",ErrorMess); + exit(BAD_EXIT); + } + + if ((!plparm) || (!Exists(plparm))) { + fprintf(stderr,"** File %s does not exist\n",plparm); + exit(BAD_EXIT); + } + printf("[ Bootstrapping session. Initializing from file %s ]\n", + plparm); + + /* create stacks */ + + CreateStacks(); + + /* initialize atom area */ + + hasha = atom0; atomfp = atom0; + for (i = 0; i <= HASHSIZE; i++) *atomfp++ = NULL; + /* hasha+HASHSIZE points to atoms that have been hidden by $hide_atom */ + + /* initialize read/print vars */ + + lc = TRUE; quoteia = FALSE; + + /* initialize heap */ + + InitHeap(); + + /* initialise i/o system */ + + InitIO(); + fileerrors = FALSE; + InBoot = TRUE; /* We are booting */ + + /* junk (otherwise unititialised) */ + + brkp = l = n = recons = spy = 0; + + /* now load bootstrap file information */ + + CSee(plparm); + + /* read required atoms */ + + for (i = 0; i < BATOMS; i++) + BasicAtom[i] = bread(); + + /* read required functors */ + + for (i = 0; i Sk)->Fn; + + /* read required terms */ + + pg = getsp(27); k = pg; + for (i = 9; i > 0; i--) { + SkelP(k)->Fn = listfunc; + SkelP(k)->Arg1 = SkelGlobal(i); + SkelP(k)->Arg2 = k+3; + k += 3; + } + *(pg+26) = SkelGlobal(i); + List10 = pg; + + for (i = 0; i < BTERMS; i++) { /* first term is the special List10 */ + if (i == 0) + pg = ConsInt(0); /* a dummy term */ + else + pg = bread(); /* read a term */ + x1 = v1; + *v1++ = pg; /* push it into global stack */ + ConsMol(Addr(FunctorP(PrivTerm)->gtoffe),x1,pg); /* encapsulate it */ + if (!(g = record(CLAUSE,pg,0,0))) { /* assert encapsulated term */ + fprintf(stderr,"Cannot create basic term: "); + Output = STDERR; + pwrite(pg,0,1200); + Put('\n'); + exit(BAD_EXIT); + } + if (i == 0) /* major hack for List10 */ + SkelP(ClauseP(XtrDBRef(g))->hdofcl)->Arg1 = List10; + else + BasicTerm[i] = SkelP(ClauseP(XtrDBRef(g))->hdofcl)->Arg1; + } + +/* Set top level termination */ + +/* On success */ + + FunctorP(Yes)->defsoffe = _yes; + +/* On failure - clause $no :- _no */ + + k = v1 = glb0; + *v1++ = No; + *v1++ = ConsInt(_no); + ConsMol(Addr(FunctorP(arrowtag)->gtoffe),k,pg); + if (!record(CLAUSE,pg,0,0)) { + fprintf(stderr,"\n! Fatal error in startup - consult guru\n"); + Stop(TRUE); + } + k = FunctorP(No)->defsoffe; /* Fail to itself */ + ClauseP(k)->altofcl = k; + + atprompt = atomnil; + running = TRUE; /* boot is now running */ + + /* restart here after an abort etc. */ + + restart: + vrz = auxstk0; + v = lcl0; + v1 = glb0; + tr = trbase; + FileAtom[STDIN] = FileAtom[STDOUT] = user; + ResetStreams(); + dotrace = FALSE; + execsys = PRIM_TAG|HIDDEN_FRAME; + brklev = 0; + if (!State[IN_BOOT]) { + pg = live; + goto go; + } + + /* main loop during bootstrap session */ + + mainloop: + pg = bread(); + if (IsRef(pg) && *pg) g = *pg; else g = pg; + if (g == EndOfFile) { + Seen(); + State[IN_BOOT] = FALSE; + goto restart; + } + + if (IsAtomic(g) || SkelP(g)->Fn != provefunc) { + if (!record(CLAUSE,pg,0,0)) { + int telling; + + fprintf(stderr,"%s\n",ErrorMess); + telling = Output; + Output = STDERR; + pwrite(pg,0,1200); + Put('\n'); + Output = telling; + } + goto mainloop; + } + + SetPlPrompt("| "); + pg = arg(Addr(SkelP(g)->Arg1),pg->Env); + + /* go - run the goal pg */ + + go: + brkp = 0; /* no break points so far */ + tr = trbase; vv = x = lcl0; vv1 = x1 = glb0; c = Yes; + VV->gofcf = No; + VV->altofcf = Addr(FunctorP(No)->defsoffe->altofcl); + VV->gfofcf = VV->lcpofcf = vv; + VV->gsofcf = vv1; + VV->trofcf = tr0 = tr; + VV->infofcf = PRIM_TAG|HIDDEN_FRAME; + VV->cofcf = c; + GrowLocal(szofcf); + dotrace = FALSE; + lev = 1; invokno = 0; execsys = HIDDEN_FRAME; + sklev = NEVER_SKIP; + +/******************************************************************** + + interpreter main loop + +********************************************************************/ + + icall: + if (IsInp(pg)) g = pg; + else { + x1 = MolP(pg)->Env; + g = MolP(pg)->Sk; + } + f = SkelP(g)->Fn; + d = FunctorP(f)->defsoffe; + if (execsys) + info = PRIM_TAG|HIDDEN_FRAME; + else { + bb = FunctorP(f)->flgsoffe; + if (!(bb&INVISIBLE)) invokno++; + info = FrameInfo(invokno,lev); + brokencall: + Trace((debug && !(bb&(INVISIBLE|UNTRACEABLE))), + v,pg,x,info,CALL_PORT); + } + if (Signed(d) > 0 && Signed(d) < 255) { + i = Signed(d); + goto EvalPred; + } + while (d && Erased(d)) d = ClauseP(d)->altofcl; + if (!d) goto efail; + + V->lcpofcf = vv; + V->gofcf = pg; + V->gfofcf = x; + V->gsofcf = v1; + V->trofcf = tr0 = tr; + V->infofcf = info; + V->cofcf = c; + vv = v; vv1 = v1; + + /* try one clause */ + alt: + n = SkelP(g)->Fn->arityoffe; + fl = Addr(ClauseP(d)->altofcl); + v1f=v1; + if ((!debug) && !*fl) { + vv = V->lcpofcf; + vv1 = VV->gsofcf; + } + InitGlobal(ClauseP(d)->gvofcl,k); + k = Addr(V->v1ofcf); + i = ClauseP(d)->ltofcl; + while (i-- > 0) *k++ = 0; + V->altofcf = fl; + if (IsComp(g)) { + register PTR ta, tb, a, b, pa, pb; int arity; + + /* in-line top level for unification */ + + ta = ClauseP(d)->hdofcl; + tb = g; + arity = SkelP(ta)->Fn->arityoffe; + + /* main loop */ + + while (arity-- > 0) { + a = *++ta; + if (IsVar (a)) { + pa = FrameVar (IsLocalVar (a) ? v : v1f, VarNo (a)); + a = *pa; + while (IsRef (a)) { + pa = a; + a = *a; + } + b = *++tb; + if (IsVar (b)) { + pb = FrameVar (IsLocalVar (b) ? x : x1, VarNo (b)); + b = *pb; + while (IsRef (b)) { + pb = b; + b = *b; + } + if (pa == pb) + continue; + if (Undef (b)) { + if (Undef (a)) { + if (pa > pb) { + *pa = pb; + TrailVar (pa); + continue; + } + *pb = pa; + TrailVar (pb); + continue; + } + if (IsComp (a)) + *pb = pa; + else + *pb = a; + TrailVar (pb); + continue; + } + + if (Undef (a)) { + if (IsComp (b)) + *pa = pb; + else + *pa = b; + TrailVar (pa); + continue; + } + + if (IsAtomic (a)) { + if (a == b) + continue; + else + goto fail; + } + if (IsAtomic (b) || + !gunify (a, MolP (pa) -> Env, b, MolP (pb) -> Env)) + goto fail; + continue; + } + if (IsAtomic (b)) { + if (Undef (a)) { + *pa = b; + TrailVar (pa); + continue; + } + if (a == b) + continue; + goto fail; + } + if (Undef (a)) { + ConsMol (b, x1, *pa); + TrailVar (pa); + continue; + } + if (IsAtomic (a) || + !gunify (a, MolP (pa) -> Env, b, x1)) + goto fail; + continue; + } + b = *++tb; + if (IsInp (b)) { + if (IsComp (a)) { + if (IsAtomic (b) || !gunify (a, v1f, b, x1)) + goto fail; + continue; + } + if (b != a) + goto fail; + continue; + } + pb = FrameVar (IsLocalVar (b) ? x : x1, VarNo (b)); + b = *pb; + while (IsRef (b)) { + pb = b; + b = *b; + } + if (Undef (b)) { + if (IsAtomic (a)) + *pb = a; + else + ConsMol (a, v1f, *pb); + TrailVar (pb); + continue; + } + if (IsComp (b)) { + if (IsAtomic (a) || + !gunify (a, v1f, b, MolP (pb) -> Env)) + goto fail; + continue; + } + if (b != a) + goto fail; + continue; + } + } + + if (v > vmax) NoSpace(LocalId); + if (v1 > v1max) NoSpace(GlobalId); + bn = &(ClauseP(d)->infofcl); + if (!((*bn)&IN_USE)) { + *bn |= IN_USE; + TrailPtr(ConsDBRef(d,CLAUSE)); + } + x = v; x1 = v1f; + GrowLocal(szofcf+ClauseP(d)->lvofcl); + if (c = ClauseP(d)->bdyofcl) { + if (!execsys && !(bb&INVISIBLE)) { + if (bb&PROTECTED) execsys = HIDDEN_FRAME; + else lev++; + } + if (IsInt(c)) { + i = XtrInt(c)&255; + modeflag = XtrInt(c)>>8; + c = NULL; + goto EvalPred; + } + } +continuation: + while (!c) { + HighTide(v,Vtide); + if (x > vv) v = x; + fromcut: + c = X->cofcf; + pg = X->gofcf; + info = X->infofcf; + execsys = SysFrame(info); + if (!execsys) lev = Level(info); + brokenexit: + Trace((debug && (!execsys)),x,pg,X->gfofcf,info,EXIT_PORT); + x = X->gfofcf; + x1 = X->gsofcf; + } + + /* nonempty continuation */ + + notfoot: + x1 = X->gsofcf; + if (IsPrim(c)) goto efail; + if (SkelP(c)->Fn != commatag) { + pg = c; c = NULL; + goto icall; + } + pg = SkelP(c)->Arg1; + c = SkelP(c)->Arg2; + if (IsPrim(pg)) goto efail; + goto icall; + + + /* shallow backtracking */ + + fail: + d = *fl; + while (tr != tr0) **--tr = NULL; + while (d && Erased(d)) d = ClauseP(d)->altofcl; + if (d) { + v1 = v1f; + goto alt; + } + vv = V->lcpofcf; + + /* deep backtracking */ + + efail: + HighTide(v,Vtide); + HighTide(v1,V1tide); + HighTide(tr,TRtide); + if (!debug) { + while(TRUE) { + for (d = *(VV->altofcf); d && Erased(d); d = ClauseP(d)->altofcl); + if (d) break; + vv = VV->lcpofcf; + } + } else { + brokenfail: + Trace((!execsys),v,pg,x,info,FAIL_PORT); + for (d = *(VV->altofcf); d && Erased(d); d = ClauseP(d)->altofcl); + } + { + int fail_parent = vv == x && !c; + + v = vv; vv1 = v1 = V->gsofcf; + x = V->gfofcf; + x1 = X->gsofcf; + pg = V->gofcf; + c = V->cofcf; + info = V->infofcf; + execsys = SysFrame(info); + tr0 = V->trofcf; + while (tr != tr0) { + k = *--tr; + if (IsRef(k)) *k = NULL; + else { + bn = &(ClauseP(XtrDBRef(k))->infofcl); + if (!((*bn)&ERASED)) *bn &= ~IN_USE; + else hide(k); + } + } + brokenback: + Trace((debug&&(!execsys)&&(!fail_parent)),v,pg,x,info,BACK_PORT); + } + if (!d) { + vv = VV->lcpofcf; + goto efail; + } else { + if (IsInp(pg)) + g = pg, x1 = X->gsofcf; + else + g = MolP(pg)->Sk, x1 = MolP(pg)->Env; + bb = FunctorP(SkelP(g)->Fn)->flgsoffe; + goto alt; + } + +/**************************************************************** +* * +* evaluable predicates * +* * +****************************************************************/ + + EvalPred: + switch (i) { + +/* control predicates */ + + case _and: /* conjunction a,b a6 */ + k = arg(Addr(SkelP(g)->Arg2),x1); + if (IsInp(k) && IsComp(k)) + ConsMol(k,x1,k); + *v1 = k; *(v1+1) = &(FunctorP(HiddenCall)->gtoffe); + *(v1+2) = v1; + k = v1+1; GrowGlobal(3); + if (!c) c = k; + else { + *v1 = commatag; *(v1+1) = k; *(v1+2) = c; + c = v1; GrowGlobal(3); + } + case _hidden_call: + pg = arg(Addr(SkelP(g)->Arg1),x1); + if (IsPrim(pg) || Undef(*pg)) goto efail; + if (IsInp(pg) && IsComp(pg)) + ConsMol(pg,x1,pg); + goto icall; + case _user_call: /* revive tracing (for setof, etc.) */ + lev++; + execsys = FALSE; + case _call: /* call(a) */ + pg = ARG1; + TEST(IsPrim(pg) || Undef(*pg),efail,icall); + case _cut: /* cut operator */ + cut: + if (x > vv) goto continuation; + HighTide(v,Vtide); + v = x+szofcf+((X->altofcf)-FlOffset)->ltofcl; + vv = X->lcpofcf; + vv1 = VV->gsofcf; + HighTide(tr,TRtide); + if (X->trofcf != tr) { + register PTR kept, old, entry ; PTR globound, locbound; + +/* If debugging, trail entries pointing to frames not being discarded + cannot be removed, otherwise the retry option would not work. + The variables globound and locbound contain the lowest discardable + entries for the global and local stack respectively */ + + if (debug) + globound = v1, locbound = v; + else + globound = vv1, locbound = vv; + kept = old = X->trofcf; + do { + entry = *old++; + if ((!IsRef(entry)) + || entry < globound + || (lcl0 <= entry && entry < locbound)) + *kept++ = entry; + } while (old != tr); + tr = kept; + } + TEST(c, notfoot, fromcut); + case _repeat: /* repeat b3 */ + repeat: + vv = x; + vv1 = x1; + *fl = d; + goto continuation; + case _abort: /* abort a4 */ + goto aborting; + case _call1: /* $call(x) */ + pg = arg(Addr(SkelP(g)->Arg1),x1); + c = X->cofcf; x = X->gfofcf; + if (IsPrim(pg) || Undef(*pg)) goto efail; + if (IsInp(pg) && IsComp(pg)) + ConsMol(pg,x1,pg); + goto icall; + +/*---------------------------------------------------------------- + + I/O predicates + +----------------------------------------------------------------*/ + case _see: /* see(f) */ + See(ARG1); + goto continuation; + case _seeing: /* seeing(x) */ + k = Seeing(); + goto unifyatom; + case _seen: /* seen */ + Seen(); + goto continuation; + case _tell: /* tell(f) */ + Tell(ARG1,"w"); + goto continuation; + case _append: /* append(f) */ + Tell(ARG1,"a"); + goto continuation; + case _telling: /* telling(x) */ + k = Telling(); + unifyatom: /* unify atom k with arg in v1ofcf */ + k1 = ARG1; + if (IsRef(k1) && Undef(*k1)) { + *k1 = k; + TrailVar(k1); + goto continuation; + } + TRY(k == k1); + case _told: /* told b15 */ + Told(); + goto continuation; + case _close: /* close(f) b16 */ + PClose(ARG1); + goto continuation; + case _read: /* read(x) */ + varfp = vrz; + lsp = v+3; + varchain = NULL; reading = TRUE; + IfInput(modeflag,k = pread()); + readunify: + reading = FALSE; + if (!k) goto efail; + TRY(unifyarg(Addr(ARG1),k,0)); + readend: /* input ended trapped while reading */ + k = EndOfFile; + goto readunify; + case _write: /* write(x) b18 */ + quoteia = FALSE; + IfOutput(modeflag,pwrite(ARG1,x1,1200)); + goto continuation; + case _writeq: /* writeq(x) b28 */ + quoteia = TRUE; + IfOutput(modeflag,pwrite(ARG1,x1,1200)); + goto continuation; + case _nl: /* nl b19 */ + IfOutput(modeflag,Put('\n')); + goto continuation; + case _get0: /* get0(n) b20 */ + IfInput(modeflag,k = ConsInt(Get())); + goto unifyatom; + case _get: /* get(n) b21 */ + IfInput(modeflag, + do ch = Get(); while (ch <= ' ' || ch >= 127); + ) + k = ConsInt(ch); + goto unifyatom; + case _skip: /* skip(n) b22 */ + ch2 = intval(&(ARG1)); + IfInput(modeflag, + do ch = Get(); while (ch != ch2); + ) + goto continuation; + case _put: /* put(n) b23 */ + IfOutput(modeflag,Put(intval(&(ARG1)))); + goto continuation; + case _tab: /* tab(n) b24 */ + i = intval(&(ARG1)); + IfOutput(modeflag,while (i-- > 0) Put(' ')); + goto continuation; + case _fileerrors: /* fileerrors b25 */ + fileerrors = FALSE; + goto continuation; + case _nofileerrors: /* nofileerrors b26 */ + fileerrors = TRUE; + goto continuation; + case _rename: /* rename(f,f1) b27 */ + if (ARG2 == atomnil) + Remove(AtomToFile(ARG1)); + else + Rename(AtomToFile(ARG1),AtomToFile(ARG2)); + goto continuation; + case _sh: /* sh b29 */ + TRY(Sh()); + case _system: /* system(_) b30 */ + TRY(CallSystem(ARG1)); + case _prompt: /* prompt(_,_) b31 */ + if (!unifyarg(Addr(ARG1),atprompt,0)) goto efail; + k = vvalue(Addr(ARG2),&l); + if (IsntName(k) || !IsAtomic(k)) goto efail; + atprompt = k; + SetPlPrompt(AtomP(atprompt)->stofae); + goto continuation; + case _carith: /* $carith(_,_) */ + if (!(unifyarg(Addr(ARG1),ConsInt(cmparith),0))) goto efail; + k = vvalue(Addr(ARG2),&l); + if (!IsInt(k)) goto efail; + cmparith = XtrInt(k); + goto continuation; + case _exists: /* exists(f) b32 */ + TRY(Exists(AtomToFile(ARG1))); + case _save: /* $save(f,i) a33 */ + if (save()) { + TRY(unifyarg(Addr(ARG2),ConsInt(0),0)); + } else goto IoFailure; + +/*--------------------------------------------------------------- + + arithmetic predicates + +---------------------------------------------------------------*/ + case _is: /* is b40 */ + k = numeval(&(ARG2)); + goto unifyatom; + case _ncompare+EQ: + case _ncompare+NE: + case _ncompare+LT: + case _ncompare+GT: + case _ncompare+LE: + case _ncompare+GE: + TRY(numcompare(i-_ncompare,&(ARG1),&(ARG2))); + + /* expanded arithmetic predicates */ + + /* unary */ + + case _unary+ID: + case _unary+UMINUS: + case _unary+NOT: + case _unary+EXP: + case _unary+LOG: + case _unary+LOG10: + case _unary+SQRT: + case _unary+SIN: + case _unary+COS: + case _unary+TAN: + case _unary+ASIN: + case _unary+ACOS: + case _unary+ATAN: + case _unary+FLOOR: + TRY(unifyarg(Addr(ARG2),Unary(i-_unary,Addr(ARG1)),0)); + + /* binary */ + + case _binary+PLUS: + case _binary+MINUS: + case _binary+TIMES: + case _binary+DIVIDE: + case _binary+MOD: + case _binary+AND: + case _binary+OR: + case _binary+LSHIFT: + case _binary+RSHIFT: + case _binary+IDIV: + case _binary+POW: + TRY(unifyarg(Addr(ARG3), + Binary(i-_binary,Addr(ARG1),Addr(ARG2)),0)); + +/*--------------------------------------------------------------*/ + + case _var: /* var(x) b50 */ + k = ARG1; + TRY(IsRef(k) && Undef(*k)); + case _nonvar:/* nonvar(x) b51 */ + k = ARG1; + TRY(!IsRef(k) || !Undef(*k)); + case _integer: /* integer(x) b52 */ + TRY(IsInt(ARG1)); + case _number: /* number(x) b91 */ + TRY(IsNumber(ARG1)); + case _primitive: /* primitive(x) */ + TRY(IsPrim(ARG1)); + case _db_reference: /* db_reference(x) */ + TRY(IsDBRef(ARG1)); + case _atomic: /* atomic(x) b53 */ + TRY(IsAtomic(ARG1)); + case _atom: /* atom(x) b59 */ + k = ARG1; + TRY(!IsPrim(k) && IsAtomic(k)); + case _eq: /* == b54 */ + TRY(!compare(&(ARG1),&(ARG2))); + case _ne: /* \== b55 */ + TRY(compare(&(ARG1),&(ARG2))); + case _functor: /* functor(t,f,n) b56 */ + k = ARG1; + if (IsAtomic(k)) { + k1 = ConsInt(0); + goto unifyfn; + } + if (IsRef(k) && !Undef(*k)) { + k = SkelP(MolP(k)->Sk)->Fn; + k1 = ConsInt(FunctorP(k)->arityoffe); + k = FunctorP(k)->atoffe; goto unifyfn; + } + i1 = intval(&(ARG3)); + if (i1 == 0) { + k = ARG2; + goto unifyt; + } + if (i1 < 0 || i1 > 100) goto efail; + InitGlobal(i1,k1); + k = ARG2; + if (IsPrim(k) || IsComp(k)) goto efail; + k = Addr(FunctorP(fentry(k,i1))->gtoffe); + unifyt: + TRY(unifyarg(Addr(ARG1),k,k1)); + unifyfn: + TRY(unifyarg(Addr(ARG2),k,0) && + unifyarg(Addr(ARG3),k1,0)); + case _arg: /* arg(n,t,a) b57 */ + i1 = intval(&(ARG1)); + k1 = ARG2; + if (IsInp(k1) || Undef(*k1)) goto efail; + y = MolP(k1)->Env; k1 = MolP(k1)->Fn; + if ( i1 <= 0 || + i1 > FunctorP(SkelP(k1)->Fn)->arityoffe) + goto efail; + k = argv(k1+i1,y,&y); + TRY(unifyarg(Addr(ARG3),k,y)); + case _univ: /* x=..l b58 */ + k = ARG1; + if (IsRef(k) && Undef(*k)) goto tcons; + k1 = v+2; + n = 2; + if (IsInp(k)) { + *k1 = k; + goto mklst; + } + y = MolP(k)->Env; k = MolP(k)->Sk; + *k1 = FunctorP(SkelP(k)->Fn)->atoffe; + i = FunctorP(SkelP(k)->Fn)->arityoffe; + n += i; + while (i-- > 0) { + b = arg(++k,y); + if (IsComp(b) && IsInp(b)) + ConsMol(b,y,b); + *++k1 = b; + } + mklst: *(k1+1) = atomnil; + k = makelist(n,v+2); v1 -= 2; + TRY(unifyarg(Addr(ARG2),MolP(k)->Sk,MolP(k)->Env)); + tcons: + k = ARG2; + if (IsInp(k) || Undef(*k)) goto efail; + y = MolP(k)->Env; k = MolP(k)->Sk; + l = v+2; n = 0; + while (k != atomnil) { + if (IsAtomic(k) || + IsVar(k) || SkelP(k)->Fn != listfunc) + goto efail; + if (n++ > 100) { + ErrorMess = "! Too many arguments in =.."; + goto aborting; + } + k1 = arg(Addr(SkelP(k)->Arg1),y); + if (IsComp(k1) && IsInp(k1)) + ConsMol(k1,y,k1); + *l++ = k1; + k = argv(Addr(SkelP(k)->Arg2),y,&y); + } + k = *(v+2); + if (IsComp(k)) goto efail; + if (n == 1) + TRY(unifyarg(Addr(ARG1),k,0)); + if (IsPrim(k)) goto efail; + k = apply(k,n-1,v+3); + v1 -= 2; + TRY(unifyarg(Addr(ARG1),MolP(k)->Sk,MolP(k)->Env)); + case _asst1: /* assert(c) */ + TEST(record(CLAUSE,ARG1,0,FALSE),continuation,dbfail); + case _assta1: /* asserta(c) */ + TEST(record(CLAUSE,ARG1,0,TRUE),continuation,dbfail); + case _asst2: /* assert(c,r) */ + i1 = FALSE; + assertr: + k = record(CLAUSE,ARG1,0,i1); + y = &(ARG2); + unfref: + if (!k) goto dbfail; + k1 = XtrDBRef(k); + ClauseP(k1)->infofcl |= IN_USE; + TrailPtr(k); + TRY(unifyarg(y,k,0)); + case _assta2: /* asserta(c,r) */ + i1 = TRUE; + goto assertr; + case _rcrda: /* recorda(k,t,r) */ + i1 = TRUE; goto recordr; + case _rcrdz: /* recordz(k,t,r) */ + i1 = FALSE; + recordr: + k = record(RECORD,ARG2,ARG1,i1); + y = &(ARG3); + goto unfref; + case _clause: /* $clause(p,r,_) */ + k = *fl; + fl = Addr(ClauseP(k)->altofcl); + *fl = k; + k = ARG3; + if (IsRef(k)) k = MolP(k)->Sk; + if ((FunctorP(SkelP(k)->Fn)->flgsoffe)&PROTECTED) goto cutfail; + ARG4 = Addr(FunctorP(SkelP(k)->Fn)->defsoffe); + case _clause+1: + k = recorded(CLAUSE); + if (!k) goto cutfail; + TRY(instance(k,Addr(ARG1))); + case _rcrded: /* $recorded(t,r,k) */ + k = *fl; + fl = Addr(ClauseP(k)->altofcl); + *fl = k; + k = ARG3; + if (IsRef(k)) k = MolP(k)->Sk; + ARG4 = Addr(FunctorP(SkelP(k)->Fn)->dboffe); + case _rcrded+1: + k = recorded(RECORD); + TEST(k,continuation,cutfail); + dbfail: + fprintf(stderr,"\n%s\n",ErrorMess); + debug = TRUE; sklev = NEVER_SKIP; + cutfail: + if (vv >= x) vv = X->lcpofcf; + goto efail; + case _instance: /* instance(r,t) */ + k = instance(ARG1,&(ARG2)); + if (!k) goto efail; + if (k == 1) goto continuation; + ErrorMess = + "! First argument of instance must be a reference"; + goto dbfail; + case _erase: /* erase(r) */ + TEST(erase(ARG1),continuation,dbfail); + case _abolish: /* abolish(a,n) */ + TRY(IsAtomic(ARG1) && (!IsPrim(ARG1)) && + IsInt(ARG2) && (i = XtrInt(ARG2)) >= 0 && + abolish(i == 0 ? ARG1 : fentry(ARG1,i))); + case _erased: /* erased(r) */ + if ((i1 = erased(ARG1)) < 0) goto dbfail; + TRY(i1); + case _NOLC: /* 'NOLC' */ + lc = FALSE; + goto continuation; + case _LC: /* 'LC' */ + lc = TRUE; + goto continuation; + case _trace: /* trace */ + debug = dotrace = TRUE; + goto continuation; + case _op: /* op(p,t,a) */ + TRY(op(ARG1,ARG2,Addr(ARG3))); + case _leash: /* $leash(x,n) */ + if (!unifyarg(Addr(ARG1),ConsInt(leash),0)) + goto efail; + leash = intval(Addr(ARG2)); + goto continuation; + case _debug: /* $debug(p,n) */ + if (!unifyarg(Addr(ARG1),ConsInt(debug),0)) + goto efail; + spy = debug = intval(&(ARG2)); + goto continuation; + case _name: /* name(x,l) */ + k = ARG1; + if (IsRef(k) && Undef(*k)) goto namecons; + if (IsComp(k)) goto nameerr; + if (IsName(k)) bn = AtomP(k)->stofae; + else { + if (!IsNumber(k)) goto nameerr; + if (IsInt(k)) + sprintf(OutBuf,"%d",XtrInt(k)); + else + sprintf(OutBuf,"%f",XtrFloat(k)); + bn = OutBuf; + } + i = strlen(bn); + if (i > 0) { + k1 = v+1; n = i+1; + while (i-- > 0) + *++k1 = ConsInt(*bn++); + goto mklst; + } else + TRY(unifyarg(Addr(ARG2),atomnil,0)); + + namecons: + if (!list_to_string(ARG2,OutBuf,255)) goto nameerr; + bn = OutBuf; + if (NumberString(&bn,&k,FALSE)) { + TRY(unifyarg(Addr(ARG1),k,0)); + } + mkname: + TRY(unifyarg(Addr(ARG1),lookup(OutBuf),0)); + nameerr: + ErrorMess = "! Illegal arguments name(atomic,list)"; + goto dbfail; + case _catom: /* current_atom(a) */ + k = ARG1; + if (IsAtomic(k) && !IsPrim(k)) goto cut; + if (IsInp(k) || !Undef(*k)) goto cutfail; + ARG2 = 0; ARG3 = NULL; + fl = *fl; FL->altofcl = fl; + case _catom+1: + GrowLocal(3); + i = ARG2; k1 = ARG3; + while (k1 == NULL) { + if (i >= HASHSIZE) goto cutfail; + k1 = *(hasha+i++); + } + ARG2 = i; ARG3 = AtomP(k1)->nxtofae; + unifyarg(Addr(ARG1),k1,0); + goto continuation; + case _cfunctor: /* $current_functor(a,n,key,mask) + mode_(+,?,+,+) */ + ARG5 = ARG1; + fl = *fl; FL->altofcl = fl; + case _cfunctor+1: + GrowLocal(5); + k1 = ARG5; + nextfunc: + if (!k1) goto cutfail; + k = k1; k1 = FunctorP(k)->nxtoffe; + i = XtrInt(ARG3)&255; + if ((XtrInt(ARG4)&(FunctorP(k)->flgsoffe)) != i) + goto nextfunc; + if ((XtrInt(ARG3)&256) && !FunctorP(k)->defsoffe) + goto nextfunc; + if (!unifyarg(Addr(ARG2), + ConsInt(FunctorP(k)->arityoffe),0)) + goto nextfunc; + ARG5 = k1; + goto continuation; + case _flags: /* $flags(p,old,new) */ + bn = &(SkelP(FunctorP(MolP(ARG1)->Sk)->Fn)->flgsoffe); + if (!unifyarg(Addr(ARG2),ConsInt(*bn),0)) goto efail; + *bn = (char)intval(&(ARG3)); + goto continuation; + + case _compare: /* compare(Op,T1,T2) */ + i = compare(&(ARG2),&(ARG3)); + k = (i < 0) ? LessThan : ((i > 0) ? GreaterThan : Equal); + goto unifyatom; + + case _alpLT: /* T1 @< T2 */ + TRY(compare(&(ARG1),&(ARG2)) < 0); + + case _alpGT: /* T1 @> T2 */ + TRY(compare(&(ARG1),&(ARG2)) > 0); + + case _alpLE: /* T1 @=< T2 */ + TRY(compare(&(ARG1),&(ARG2)) <= 0); + + case _alpGE: /* T1 @>= T2 */ + TRY(compare(&(ARG1),&(ARG2)) >= 0); + case _all_float: /* $all_float(x,y) */ + if (!unifyarg(Addr(ARG1),ConsInt(AllFloat),0)) goto efail; + k = vvalue(Addr(ARG2),&l); + if (!IsPrim(k) || !IsInt(k)) goto efail; + AllFloat = XtrInt(k); + goto continuation; + case _statistics: /* statistics. */ + Statistics(); + goto continuation; + +/*------------------------------------------------------------------ + + system private predicates + +------------------------------------------------------------------*/ + + case _sysp: /* $sysp(f,n) */ + FunctorP(SkelP(MolP(ARG1)->Sk)->Fn)->defsoffe = + XtrInt(ARG2)&255; + goto continuation; + case _sysflgs: /* $sysflgs(p,n) */ + FunctorP(SkelP(MolP(ARG1)->Sk)->Fn)->flgsoffe = + (char)XtrInt(ARG2); + goto continuation; + case _hideat: /* $hide_atom(a) */ + TRY((IsAtomic(ARG1) && (!IsPrim(ARG1)) && + hide_atom(ARG1))); + case _brk: /* $break(g) a102 */ + bg = arg(g+1,x1); + if (IsPrim(bg) || Undef(*bg)) goto efail; + if (IsComp(bg) && IsInp(bg)) ConsMol(bg,x1,bg); + breakret = CONT; + enterbreak: + InStat = SaveStream(Input); + OutStat = SaveStream(Output); + savevars(); + Output = STDOUT; + Input = STDIN; + pg = bg; + goto icall; + case _exit_break: /* $exit_break a103 */ + popbreak(); + RestStream(Input,InStat); + RestStream(Output,OutStat); + switch(breakret) { + case CALL_PORT: goto brokencall; + case EXIT_PORT: goto brokenexit; + case BACK_PORT: goto brokenback; + case FAIL_PORT: goto brokenfail; + default: goto continuation; + } + case _xprompt: /* $prompt(p) b104 */ + PromptIfUser(AtomP(ARG1)->stofae); + goto continuation; + case _user_exec: /* $user_exec(_) b105 */ + c = ARG1; + if (IsPrim(c) || Undef(*c)) goto efail; + GrowLocal(1); lev = 1; invokno = 0; + if (debug) { + spy = TRUE; + if (dotrace) { + sklev = NEVER_SKIP; + dotrace = FALSE; + } else sklev = 0; + } else sklev = 0; + execsys = FALSE; + goto continuation; + case _save_vars: /* $save_read_vars a106 */ + vchain = varchain; pvrz = vrz; vrz = varfp; + goto continuation; + case _reset_vars: /* $reset_read_vars a107 */ + vrz = pvrz; + goto continuation; + case _repply: /* $repply a108 */ + if (!vchain) goto continuation; + { + VarP var; int telling; + + telling = Output; + Output = STDOUT; + for (var = vchain; var; var = var->NextVar) { + Put('\n'); + PutString(var->VarName); PutString(" = "); + k = vvalue(var->VarValue,&k1); + pwrite(k,k1,1200); + } + PutString(" "); + Output = telling; + } + ch = ToEOL(0,0); + TRY(ch != ';' && ch != 'y' && ch != 'Y'); + case _recons: /* $recons(_) b109 */ + recons = XtrInt(ARG1); + goto continuation; + case _brkstart: /* $break_start a110 */ + printf("[ Break (level %d) ]\n",++brklev); + goto continuation; + case _brkend: /* $break_end a111 */ + printf("[ End break (level %d) ]\n",brklev--); + goto continuation; + case _asstr: /* $assertr(_) b112 */ + k = record(CLAUSE,ARG1,recons,FALSE); + if (k) goto continuation; + fprintf(stderr,"\n%s\n",ErrorMess); + goto efail; + case _isop: /* $isop(_,_,_,_,_) */ + TRY((IsAtomic(ARG1) && (!IsPrim(ARG1)) && + IsInt(ARG2) && + isop(ARG1,XtrInt(ARG2),&i,&i1,&i2) && + unifyarg(Addr(ARG3),ConsInt(i),NULL) && + unifyarg(Addr(ARG4),ConsInt(i1),NULL) && + unifyarg(Addr(ARG5),ConsInt(i2),NULL))); + case _RIP: /* $rest_in_peace a113 */ + CloseFiles(); + printf("\n[ Prolog execution halted ]\n"); + exit(GOOD_EXIT); + case _xrepeat: /* b115 $repeat */ + goto repeat; + case _yes: /* top level success in bootstrap */ + ResetTrail(trbase); + goto mainloop; + case _no: /* top level failure in bootstrap */ + PutString("no\n"); + goto mainloop; +#ifdef GRAPHICS: + case _graphics: + TRY(plgraphics()); +#endif + default: + fprintf(stderr,"\n! Undefined built-in predicate : %d\n",i); + goto efail; + } +} diff --git a/source_code/c-prolog-1982/main.o b/source_code/c-prolog-1982/main.o new file mode 100755 index 0000000000000000000000000000000000000000..8153a1d996ce30a35754c3af81d670d16a170bf0 GIT binary patch literal 70268 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

EP!b=>YErFN5>E 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 B4#WTe literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/makefile b/source_code/c-prolog-1982/makefile new file mode 100755 index 0000000..453c99c --- /dev/null +++ b/source_code/c-prolog-1982/makefile @@ -0,0 +1,51 @@ +PLSTARTUP=/usr/local/lib/pstartup1.5 +GRIND=igrind + +# Replace VAX by IEEE for IEEE floating point machines (e.g. Sun) +FLOATING=IEEE + +# Replace the right-end side by the empty string to get +# -1 as end of file character + +EOF= + +CC=cc +CFLAGS=-w -g $(EOF) -D$(FLOATING) -DSTARTUPFILE=\"$(PLSTARTUP)\" +# change define in parms.c - no mistakes then! +BIN=/usr/local/bin/prolog +OBJECTS=main.o unify.o rewrite.o dbase.o sysbits.o space.o \ + parms.o arith.o compare.o auxfn.o trace.o + +prolog : $(OBJECTS) + $(CC) -o prolog $(OBJECTS) -lm + +main.o : arithop.h evalp.h trace.h + +$(OBJECTS) : pl.h +arith.o : arithop.h +trace.o : trace.h + +clean : /tmp + rm -f $(OBJECTS) prolog startup + +startup : prolog pl/init + ./prolog -b pl/init cprolog.doc + +cprolog.doc: app.me cprolog.me + tbl cprolog.me app.me | $(TROFF) -me $(DEST) + + diff --git a/source_code/c-prolog-1982/makefile.save b/source_code/c-prolog-1982/makefile.save new file mode 100755 index 0000000..4b34076 --- /dev/null +++ b/source_code/c-prolog-1982/makefile.save @@ -0,0 +1,50 @@ +PLSTARTUP=/usr/local/bin/pstartup1.5 +GRIND=igrind + +# Replace VAX by IEEE for IEEE floating point machines (e.g. Sun) +FLOATING=VAX + +# Replace the right-end side by the empty string to get +# -1 as end of file character + +EOF=-DAsDEC10 + +CFLAGS=-w -g $(EOF) -D$(FLOATING) -DSTARTUPFILE=\"$(PLSTARTUP)\" +# change define in parms.c - no mistakes then! +BIN=/usr/local/bin/prolog +OBJECTS=main.o unify.o rewrite.o dbase.o sysbits.o space.o \ + parms.o arith.o compare.o auxfn.o trace.o + +prolog : $(OBJECTS) + $(CC) -o prolog $(OBJECTS) -lm -lg + +main.o : arithop.h evalp.h trace.h + +$(OBJECTS) : pl.h +arith.o : arithop.h +trace.o : trace.h + +clean : /tmp + rm -f $(OBJECTS) prolog startup + +startup : prolog pl/init + ./prolog -b pl/init cprolog.doc + +cprolog.doc: app.me cprolog.me + tbl cprolog.me app.me | $(TROFF) -me $(DEST) + + diff --git a/source_code/c-prolog-1982/makesys.com b/source_code/c-prolog-1982/makesys.com new file mode 100755 index 0000000..373626b --- /dev/null +++ b/source_code/c-prolog-1982/makesys.com @@ -0,0 +1,23 @@ +$ cc arith +$ cc auxfn +$ cc compare +$ cc dbase +$ cc main +$ cc parms +$ cc rewrite +$ cc space +$ cc sysbits +$ cc trace +$ cc unify +$ link/executable:prolog arith,auxfn,compare,dbase,main,parms,rewrite,space,- +$ trace,sysbits,unify +! The line below should be changed to whatever is appropriate at +! your installation +$ prolog :== $usr$:prolog.exe +$ prolog -b [.pl]init +['[.pl]vmsall']. +:-save(startup). +end_of_file. +! The file 'startup' should be moved to its final place as defined in +! parms.c + diff --git a/source_code/c-prolog-1982/man/app.me b/source_code/c-prolog-1982/man/app.me new file mode 100755 index 0000000..fdcd104 --- /dev/null +++ b/source_code/c-prolog-1982/man/app.me @@ -0,0 +1,107 @@ +.bp +.uh "Appendix I \*- Summary of Evaluable Predicates" +.TS H +l l. +.TH +\fPabolish(\fIF\fP,\fIN\fP) Abolish the procedure named \fIF\fP arity \fIN\fP. +abort Abort execution of the current directive. +arg(\fIN\fP,\fIT\fP,\fIA\fP) The \fIN\fPth argument of term \fIT\fP is \fIA\fP. +assert(\fIC\fP) Assert clause \fIC\fP. +assert(\fIC\fP,\fIR\fP) Assert clause \fIC\fP, ref. \fIR\fP. +asserta(\fIC\fP) Assert \fIC\fP as first clause. +asserta(\fIC\fP,\fIR\fP) Assert \fIC\fP as first clause, ref. \fIR\fP. +assertz(\fIC\fP) Assert \fIC\fP as last clause. +assertz(\fIC\fP,\fIR\fP) Assert \fIC\fP as last clause, ref. \fIR\fP. +atom(\fIT\fP) Term \fIT\fP is an atom. +atomic(\fIT\fP) Term \fIT\fP is an atom or integer. +bagof(\fIX\fP,\fIP\fP,\fIB\fP) The bag of \fIX\fPs such that \fIP\fP is provable is \fIB\fP. +break Break at the next procedure call. +call(\fIP\fP) Execute the procedure call \fIP\fP. +clause(\fIP\fP,\fIQ\fP) There is a clause, head \fIP\fP, body \fIQ\fP. +clause(\fIP\fP,\fIQ\fP,\fIR\fP) There is an clause, head \fIP\fP, body \fIQ\fP, ref \fIR\fP. +close(\fIF\fP) Close file \fIF\fP. +compare(\fIC\fP,\fIX\fP,\fIY\fP) \fIC\fP is the result of comparing terms \fIX\fP and \fIY\fP. +consult(\fIF\fP) Extend the program with clauses from file \fIF\fP. +current_atom(\fIA\fP) One of the currently defined atoms is \fIA\fP. +current_functor(\fIA\fP,\fIT\fP) A current functor is named \fIA\fP, m.g. term \fIT\fP. +current_predicate(\fIA\fP,\fIP\fP) A current predicate is named \fIA\fP, m.g. goal \fIP\fP. +db_reference(\fIT\fP) \fIT\fP is a database reference. +debug Switch on debugging. +debugging Output debugging status information. +display(\fIT\fP) Display term \fIT\fP on the terminal. +erase(\fIR\fP) Erase the clause or record, ref. \fIR\fP. +erased(\fIR\fP) The object with ref. \fIR\fP has been erased. +expanded_exprs(\fIO\fP,\fIN\fP) Expression expansion if \fIN\fP=on. +expand_term(\fIT\fP,\fIX\fP) Term \fIT\fP is a shorthand which expands to term \fIX\fP. +exists(\fIF\fP) The file \fIF\fP exists. +fail Backtrack immediately. +fileerrors Enable reporting of file errors. +functor(\fIT\fP,\fIF\fP,\fIN\fP) The top functor of term \fIT\fP has name \fIF\fP, arity \fIN\fP. +get(\fIC\fP) The next non-blank character input is \fIC\fP. +get0(\fIC\fP) The next character input is \fIC\fP. +halt Halt Prolog, exit to the monitor. +instance(\fIR\fP,\fIT\fP) A m.g. instance of the record ref. \fIR\fP is \fIT\fP. +integer(\fIT\fP) Term \fIT\fP is an integer. +\fIY\fP is \fIX\fP \fIY\fP is the value of arithmetic expression \fIX\fP. +keysort(\fIL\fP,\fIS\fP) The list \fIL\fP sorted by key yields \fIS\fP. +leash(\fIM\fP) Set leashing mode to \fIM\fP. +listing List the current program. +listing(\fIP\fP) List the procedure(s) \fIP\fP. +name(\fIA\fP,\fIL\fP) The name of atom or number \fIA\fP is string \fIL\fP. +nl Output a new line. +nodebug Switch off debugging. +nofileerrors Disable reporting of file errors. +nonvar(\fIT\fP) Term \fIT\fP is a non-variable. +nospy \fIP\fP Remove spy-points from the procedure(s) \fIP\fP. +number(\fIT\fP) Term \fIT\fP is a number. +op(\fIP\fP,\fIT\fP,\fIA\fP) Make atom \fIA\fP an operator of type \fIT\fP precedence \fIP\fP. +primitive(\fIT\fP) \fIT\fP is a number or a database reference +print(\fIT\fP) Portray or else write the term \fIT\fP. +prompt(\fIA\fP,\fIB\fP) Change the prompt from \fIA\fP to \fIB\fP. +put(\fIC\fP) The next character output is \fIC\fP. +read(\fIT\fP) Read term \fIT\fP. +reconsult(\fIF\fP) Update the program with procedures from file \fIF\fP. +recorda(\fIK\fP,\fIT\fP,\fIR\fP) Make term \fIT\fP the first record under key \fIK\fP, ref. \fIR\fP. +recorded(\fIK\fP,\fIT\fP,\fIR\fP) Term \fIT\fP is recorded under key \fIK\fP, ref. \fIR\fP. +recordz(\fIK\fP,\fIT\fP,\fIR\fP) Make term \fIT\fP the last record under key \fIK\fP, ref. \fIR\fP. +rename(\fIF\fP,\fIG\fP) Rename file \fIF\fP to \fIG\fP. +repeat Succeed repeatedly. +retract(\fIC\fP) Erase the first clause of form \fIC\fP. +save(\fIF\fP) Save the current state of Prolog in file \fIF\fP. +see(\fIF\fP) Make file \fIF\fP the current input stream. +seeing(\fIF\fP) The current input stream is named \fIF\fP. +seen Close the current input stream. +setof(\fIX\fP,\fIP\fP,\fIB\fP) The set of \fIX\fPs such that \fIP\fP is provable is \fIB\fP. +sh Start a recursive shell +skip(\fIC\fP) Skip input characters until after character \fIC\fP. +sort(\fIL\fP,\fIS\fP) The list \fIL\fP sorted into order yields \fIS\fP. +spy \fIP\fP Set spy-points on the procedure(s) \fIP\fP. +statistics Display execution statistics. +system(\fIS\fP) Execute command \fIS\fP. +tab(\fIN\fP) Output \fIN\fP spaces. +tell(\fIF\fP) Make file \fIF\fP the current output stream. +telling(\fIF\fP) The current output stream is named \fIF\fP. +told Close the current output stream. +trace Switch on debugging and start tracing. +true Succeed. +var(\fIT\fP) Term \fIT\fP is a variable. +write(\fIT\fP) Write the term \fIT\fP. +writeq(\fIT\fP) Write the term \fIT\fP, quoting names if necessary. +\&'LC' The following Prolog text uses lower case. +\&'NOLC' The following Prolog text uses upper case only. +! Cut any choices taken in the current procedure. +\e+ \fIP\fP Goal \fIP\fP is not provable. +\fIX\fP<\fIY\fP As numbers, \fIX\fP is less than \fIY\fP. +\fIX\fP=<\fIY\fP As numbers, \fIX\fP is less than or equal to \fIY\fP. +\fIX\fP>\fIY\fP As numbers, \fIX\fP is greater than \fIY\fP. +\fIX\fP>=\fIY\fP As numbers, \fIX\fP is greater than or equal to \fIY\fP. +\fIX\fP=\fIY\fP Terms \fIX\fP and \fIY\fP are equal (i.e. unified). +\fIT\fP=..\fIL\fP The functor and args. of term \fIT\fP comprise the list \fIL\fP. +\fIX\fP==\fIY\fP Terms \fIX\fP and \fIY\fP are strictly identical. +\fIX\fP\e==\fIY\fP Terms \fIX\fP and \fIY\fP are not strictly identical. +\fIX\fP@<\fIY\fP Term \fIX\fP precedes term \fIY\fP. +\fIX\fP@=<\fIY\fP Term \fIX\fP precedes or is identical \fIY\fP. +\fIX\fP@>\fIY\fP Term \fIX\fP follows term \fIY\fP. +\fIX\fP@>=\fIY\fP Term \fIX\fP follows or is identical to term \fIY\fP. +[\fIF\fP|\fIR\fP] Perform the (re)consult(s) specified by [\fIF\fP|\fIR\fP]. +.TE diff --git a/source_code/c-prolog-1982/man/app.out b/source_code/c-prolog-1982/man/app.out new file mode 100755 index 0000000..c35555c --- /dev/null +++ b/source_code/c-prolog-1982/man/app.out @@ -0,0 +1,131 @@ + + + + + + + +_A_p_p_e_n_d_i_x _I -- _S_u_m_m_a_r_y _o_f _E_v_a_l_u_a_b_l_e _P_r_e_d_i_c_a_t_e_s + +l l. +abolish(_F,_N) Abolish the procedure named _F arity _N. +abort Abort execution of the current directive. +arg(_N,_T,_A) The _Nth argument of term _T is _A. +assert(_C) Assert clause _C. assert(_C,_R) Assert +clause _C, ref. _R. asserta(_C) Assert _C as first clause. +asserta(_C,_R) Assert _C as first clause, ref. _R. +assertz(_C) Assert _C as last clause. +assertz(_C,_R) Assert _C as last clause, ref. _R. +atom(_T) Term _T is an atom. atomic(_T) Term _T is an +atom or integer. bagof(_X,_P,_B) The bag of _Xs such that _P +is provable is _B. break Break at the next procedure call. +call(_P) Execute the procedure call _P. clause(_P,_Q) There +is a clause, head _P, body _Q. clause(_P,_Q,_R) There is an +clause, head _P, body _Q, ref _R. close(_F) Close file +_F. compare(_C,_X,_Y) _C is the result of comparing terms _X and +_Y. consult(_F) Extend the program with clauses from +file _F. current_atom(_A) One of the currently defined atoms +is _A. current_functor(_A,_T) A current functor is named _A, +m.g. term _T. current_predicate(_A,_P) A current predicate is +named _A, m.g. goal _P. db_reference(_T) _T is a database +reference. debug Switch on debugging. +debugging Output debugging status information. +display(_T) Display term _T on the terminal. +erase(_R) Erase the clause or record, ref. _R. +erased(_R) The object with ref. _R has been erased. +expanded_exprs(_O,_N) Expression expansion if _N=on. +expand_term(_T,_X) Term _T is a shorthand which expands +to term _X. exists(_F) The file _F exists. +fail Backtrack immediately. fileerrors Enable re- +porting of file errors. functor(_T,_F,_N) The top functor of +term _T has name _F, arity _N. get(_C) The next non-blank +character input is _C. get0(_C) The next character input is +_C. halt Halt Prolog, exit to the monitor. +instance(_R,_T) A m.g. instance of the record ref. _R is _T. +integer(_T) Term _T is an integer. _Y is _X _Y is the +value of arithmetic expression _X. keysort(_L,_S) The list +_L sorted by key yields _S. leash(_M) Set leashing mode +to _M. listing List the current program. +listing(_P) List the procedure(s) _P. +name(_A,_L) The name of atom or number _A is string _L. +nl Output a new line. nodebug Switch off debugging. +nofileerrors Disable reporting of file errors. +nonvar(_T) Term _T is a non-variable. nospy _P Remove +spy-points from the procedure(s) _P. number(_T) Term _T +is a number. op(_P,_T,_A) Make atom _A an operator of +type _T precedence _P. primitive(_T) _T is a number or a da- +tabase reference print(_T) Portray or else write the +term _T. prompt(_A,_B) Change the prompt from _A to _B. +put(_C) The next character output is _C. read(_T) Read term +_T. + + + + + + + + + + + + + +reconsult(_F) Update the program with procedures from file +_F. recorda(_K,_T,_R) Make term _T the first record under key +_K, ref. _R. recorded(_K,_T,_R) Term _T is recorded under key _K, +ref. _R. recordz(_K,_T,_R) Make term _T the last record under +key _K, ref. _R. rename(_F,_G) Rename file _F to _G. +repeat Succeed repeatedly. retract(_C) Erase the first +clause of form _C. save(_F) Save the current state of Prolog +in file _F. see(_F) Make file _F the current input stream. +seeing(_F) The current input stream is named _F. +seen Close the current input stream. setof(_X,_P,_B) The +set of _Xs such that _P is provable is _B. sh Start a re- +cursive shell skip(_C) Skip input characters until after +character _C. sort(_L,_S) The list _L sorted into order +yields _S. spy _P Set spy-points on the procedure(s) _P. +statistics Display execution statistics. +system(_S) Execute command _S. tab(_N) Output _N spaces. +tell(_F) Make file _F the current output stream. +telling(_F) The current output stream is named _F. +told Close the current output stream. trace Switch on +debugging and start tracing. true Succeed. var(_T) Term +_T is a variable. write(_T) Write the term _T. +writeq(_T) Write the term _T, quoting names if neces- +sary. 'LC' The following Prolog text uses lower case. +'NOLC' The following Prolog text uses upper case only. +! Cut any choices taken in the current procedure. \+ +_P Goal _P is not provable. _X<_Y As numbers, _X is less +than _Y. _X=<_Y As numbers, _X is less than or equal to _Y. +_X>_Y As numbers, _X is greater than _Y. _X>=_Y As +numbers, _X is greater than or equal to _Y. _X=_Y Terms _X +and _Y are equal (i.e. unified). _T=.._L The functor and +args. of term _T comprise the list _L. _X==_Y Terms _X and _Y +are strictly identical. _X\==_Y Terms _X and _Y are not +strictly identical. _X@<_Y Term _X precedes term _Y. +_X@=<_Y Term _X precedes or is identical _Y. _X@>_Y Term _X +follows term _Y. _X@>=_Y Term _X follows or is identical to +term _Y. [_F|_R] Perform the (re)consult(s) specified by + + + + + + + + + + + + + + + + +9 + +9 + + + diff --git a/source_code/c-prolog-1982/man/cprolog.me b/source_code/c-prolog-1982/man/cprolog.me new file mode 100755 index 0000000..4d09a41 --- /dev/null +++ b/source_code/c-prolog-1982/man/cprolog.me @@ -0,0 +1,2891 @@ +.po 1.1i +.he 'C-Prolog\ User\'s\ Manual''%' +.ds Vn 1.5 +.tp +.(l C +.sz +4 +C-Prolog User's Manual +.sz -4 +.sp +.sp +Version \*(Vn +\*(td +.sp +Edited by Fernando Pereira\** +.(f +\**Formerly at EdCAAD, Dept. of Architecture, University of Edinburgh +.)f +SRI International, Menlo Park, California +.sp +from material by +.sp +David Warren +SRI International, Menlo Park, California +.sp +David Bowen, Lawrence Byrd +Dept. of Artificial Intelligence, University of Edinburgh +.sp +Luis Pereira +Dept. de Informatica, Universidade Nova de Lisboa +.)l +.(l C +\fIAbstract\fP +.)l +.sp +.(l F +This is a revised edition of the user's manual for C-Prolog, +a Prolog interpreter written in C for 32 bit machines. +C-Prolog is based on an earlier Prolog interpreter written +in IMP for the EMAS operating system +by Luis Damas, who borrowed many +aspects of the design from the DECsystem-10/20 Prolog system +developed by David Warren, Fernando Pereira, Lawrence Byrd +and Luis Pereira. +This manual is based on the EMAS Prolog manual, which +in turn was based on the DECsystem-10/20 Prolog manual. +.)l +.bp +.sh 1 "Using C-Prolog" +.pp +.sh 2 "Preface" +.pp +This manual describes C-Prolog, a Prolog interpreter written in C. +C-Prolog was developed at EdCAAD, Dept. of Architecture, University +of Edinburgh, and +is based on a previous interpreter, written in IMP for +the EMAS operating system by +Luis Damas of the Dept. of +Computer Science, University of Edinburgh. +C-Prolog was designed for machines with a large, uniform, address space, +and assumes a pointer cell 32 bits wide. At the time of writing, +it has been tested on VAX\** +.(f +\**VAX, VMS, PDP and DECsystem-10 are trademarks of +Digital Equipment Corporation. +.)f +machines under the \s-2UNIX\s0\** +.(f +\**\s-2UNIX\s0 is a Trademark of Bell Laboratories. +.)f +and VAX/VMS operating systems, on the Sun workstation +under 4.1/2 \s-2UNIX\s0, +and has been ported with minor changes to +other MC68000-based workstations and to the Three Rivers PERQ. +.pp +Prolog is a simple but powerful programming language +originally developed at the University of Marseilles, as +a practical tool for programming in logic. +From a user's point of view the major attraction of the language +is ease of programming. +Clear, readable, concise programs can be written quickly with few errors. +Prolog is especially suitable for high-level symbolic programming tasks +and has been applied in many areas of Artificial Intelligence research. +.pp +The system consists of a Prolog interpreter and a wide range of +builtin (system defined) procedures. +Its design was based on the (Edinburgh) DECsystem-10 Prolog system and the system +is closely compatible with DECsystem-10 Prolog and thus is also +reasonably close to PDP-11 \s-2UNIX\s0 and RT-11 Prolog. +.pp +This manual is not intended as an introduction to +the Prolog language and how to use it. +For this purpose you should study: +.(l +\fIProgramming in Prolog\fP +W. Clocksin & C. Mellish +Springer Verlag 1981 +.)l +.pp +This manual assumes that you are familiar with the principles of the +Prolog language, its purpose being to explain how to use C-Prolog, +and to describe all the evaluable predicates provided by C-Prolog. +.sh 2 "Using C-Prolog \*- Overview" +.pp +C-Prolog offers the user +an interactive programming environment with +tools for incrementally building programs, debugging programs by following +their executions, and modifying parts of programs without having to +start again from scratch. +.pp +The text of a Prolog program is normally created in a +number of files +using a text editor. +C-Prolog can then be instructed to read-in programs +from these files; this is called \fIlconsulting\fP the file. +To change parts of a program being run, it is possible +to \fIreconsult\fP files containing the changed parts. +Reconsulting means that definitions for procedures in the file will +replace any old definitions for these procedures. +.pp +It is recommended that you make use of a number of different files +when writing programs. +Since you will be editing and consulting/reconsulting +individual files it is useful to use files to group together related +procedures; +keeping collections of procedures that do different things in different files. +Thus a Prolog program will consist of a number of files, +each file containing a number of related procedures. +.pp +When your programs start to grow to a fair size, it is also a good idea +to have one file which just contains commands to the interpreter +to consult all the other files which form a program. +You will then be able to consult your entire program by just consulting +this single file. +.sh 2 "Access to C-Prolog" +.pp +In this manual, +we assume that there is a command on your computer +.(l +prolog +.)l +that invokes C-Prolog. +.pp +We assume that there are three keys or key combinations that achieve +the effects of terminating an input line, marking end of input, +and interrupting execution of a program. Because these depend +on operating system and individual tastes, they are denoted in this manual +by \s-2END-OF-LINE\s0, \s-2END-OF-INPUT\s0 and \s-2INTERRUPT\s0 respectively +(they are carriage return, control-Z and control-C on the computer +this is being written on). +.pp +Since Prolog makes syntactic use of the difference between upper and +lower case it is important that you have your terminal set up +so that it accepts lower case in the normal way. +This means, for a start, that you must be using an upper and lower case +terminal - and not, for example, an upper case only teletype. +It is possible to use Prolog using upper case only +(see Section 2.4) +but it is unnecessarily painful. +We shall assume both upper and lower case throughout this manual. + +If you type the `prolog' command, +Prolog will output a banner and prompt you for directives as follows: +.(l +C-Prolog version \*(Vn +| ?- +.)l +There will be a pause between the first line and the prompt while the +system loads itself. It is possible to type ahead during this period if +you get impatient. +.pp +If you give an argument to the `prolog' command, +C-Prolog will interpret it as the name of a file containing +a saved state created earlier, and will restore that saved state. +Saved states will be explained fully later. +.(l +prolog prog (Restore \*(lqprog\*(rq) +.)l +.pp +C-Prolog uses six major internal data areas: the \fIheap\fP, +the \fIglobal stack\fP, the \fIlocal stack\fP, the \fItrail\fP, +the \fIatom area\fP and the \fIauxiliary stack\fP. Although +the system is initially configured with reasonable allocations +for each of those areas, a particular program might exceed +one of the allocations, causing an error message. Ideally, +the system should adjust the available storage among areas +automatically, but this facility is not implemented yet. +Instead, the user may specify when starting Prolog the allocations +(in K bytes) for some or all of the areas. This is done by giving +command line switches between the program name and the optional +file argument. For example, +.(l +prolog -h 1000 -g 1000 -l 500 bigprogram +.)l +specifies heap and global stack allocations of 1000 K and a local +stack allocation of 500 K. The full set of switches is: +.(l +.TS +l l. +-h \fIN\fP heap allocation is \fIN\fP K bytes +-g \fIN\fP global stack allocation is \fIN\fP K bytes +-l \fIN\fP local stack allocation is \fIN\fP K bytes +-t \fIN\fP trail allocation is \fIN\fP K bytes +-a \fIN\fP atom area allocation is \fIN\fP K bytes +-x \fIN\fP auxiliary stack allocation is \fIN\fP K bytes +.TE +.)l +.sh 2 "Reading-in Programs" +.pp +A program is made up of a sequence of clauses, possibly +interspersed with directives to the interpreter. The clauses of a +procedure do not have to be immediately consecutive, but remember that +their relative order may be important. +.pp +To input a program from a file \fIfile\fP, give the directive: +.(l +| ?- [\fIfile\fP]. +.)l +which will instruct the interpreter to consult the program. +The file specification \fIfile\fP must be a Prolog atom. +It may be any file name, note that if this file name contains +characters which are not normally allowed in an atom +then it is necessary to surround the whole file specification with +single quotes (since quoted atoms can include any character), for example +.(l +| ?- ['people/greeks']. +.)l +The specified file is then read in. +Clauses in the file are stored in the database ready to be +executed, while any directives +are obeyed as they are encountered. +When the end of the file is found, the +interpreter displays on the terminal the time spent in reading-in and +the number of bytes occupied by the program. +.pp +In general, this directive can be any list of filenames, such as: +.(l +| ?- [myprogram, extras, testbits]. +.)l +In this case all three files would be consulted. If a filename is preceded +by a minus sign, as in: +.(l +| ?- [-testbits, -moreideas]. +.)l +then that file is reconsulted. The difference between consulting and +reconsulting is important, and works as follows: +if a file is consulted then all the clauses in the file are simply added +to C-Prolog's database. If you consult the same file twice then you will +get two copies of all the clauses. +However, if a file is reconsulted then the clauses for all +the procedures in the file will replace any existing clauses for those +procedures, that is +any such previously existing clauses in the database get thrown away. +Reconsulting is useful for telling Prolog about corrections in your program. +.pp +Clauses may also be typed in directly at the terminal. +To enter clauses at the terminal, +you must give the directive: +.(l +| ?- [user]. +.)l +The interpreter is now in a state where it expects input of clauses or +directives. +To get back to the top level of the interpreter, type the \s-2END-OF-INPUT\s0 +character. +.pp +Typing clauses directly into C-Prolog +is only recommended if the clauses will not be needed +permanently, and are few in number. +For significant bits of program you should use an editor to produce +a file containing the text of the program. +.sh 2 "Directives: Questions and Commands" +.pp +When Prolog is at top level (signified by an initial prompt of \*(lq|\ ?-\ \*(rq, +with continuation lines prompted with \*(lq|\ \ \ \ \*(rq, that is indented out from +the left margin) it reads in terms and treats them as directives to +the interpreter to try and satisfy some goals. +These directives are called questions. +Remember that Prolog terms must terminate with a period (\*(lq.\*(rq), and +that therefore Prolog will not execute anything for you until you +have typed the period (and then \s-2END-OF-LINE\s0) at the end +of the directive. +.pp +Suppose list membership has been defined by: +.(l +member(X,[X|\(ul]). +member(X,[\(ul|L]) :- member(X,L). +.)l +(Note the use of anonymous variables written \*(lq\(ul\*(rq). +.pp +If the goal(s) specified in a question can be satisfied, and if there are +no variables as in this example: +.(l +| ?- member(b,[a,b,c]). +.)l +then the system answers +.(l +yes +.)l +and execution of the question terminates. +.pp +If variables are included in the question, then the final value of each +variable is displayed (except for anonymous variables). +Thus the question +.(l +| ?- member(X,[a,b,c]). +.)l +would be answered by +.(l +X = a +.)l +At this point the interpreter is waiting for you to indicate whether +that solution is sufficient, or whether you want it to backtrack to see +if there are any more solutions. +Simply typing \s-2END-OF-LINE\s0 terminates the question, while +typing \*(lq;\*(rq followed by \s-2END-OF-LINE\s0 causes the +system to backtrack looking for alternative solutions. +If no further solutions can be found it outputs +.(l +no +.)l +The outcome of some questions is shown below, where a number +preceded by \*(lq\(ul\*(rq is a system-generated name for a variable. +.(l +| ?- member(X,[tom,dick,harry]). +X = tom ; +X = dick ; +X = harry ; +no +| ?- member(X,[a,b,f(Y,c)]),member(X,[f(b,Z),d]). +Y = b, +X = f(b,c), +Z = c + % Just \s-2END-OF-LINE\s0 typed here +yes +| ?- member(X,[f(\(ul),g]). +X = f(\(ul1728) +yes +| ?- +.)l +When C-Prolog reads terms from a file (or from the terminal following a call to +[user]), it treats them all as program clauses. In order to get the +interpreter to execute directives from a file they must be preceded by +\&`?-', for questions, or `:-', for commands. +.pp +Commands are like questions except that they do not cause +answers to be printed out. +They always start with the symbol \*(lq:-\*(rq. At top level this is simply +written after the prompted \*(lq?-\*(rq which is then effectively overridden. +Any required output must be programmed explicitly; for example, the command +.(l +:- member(3,[1,2,3]), write(ok). +.)l +directs the system to check whether 3 belongs to the list [1,2,3], and +to output \*(lqok\*(rq if so. Execution of a command terminates when all the +goals in the command have been successfully executed. Other +alternative solutions are not sought (one may imagine an implicit +\*(lqcut\*(rq at the end of the command). If no solution can be found, the +system gives: +.(l +? +.)l +as a warning. +.pp +The main use for commands (as opposed to questions) is to allow +files to contain directives which call various procedures, but for which +you don't want to have the answers printed out. +In such cases you only want to call the procedures for effect. +A useful example would be the use of a +directive in a file which consults a whole +list of other files, such as\**: +.(f +\**The extra parentheses, with the `:-' immediately +next to them, are currently essential due to a problem with +prefix operators (like `:-') and lists. They are not +required for commands that do not contain lists. +This restriction will be eventually removed. +.)f +.(l +:-([ bits, bobs, mainpart, testcases, data, junk ]). +.)l +.pp +If this directive was contained in the file `program' then typing the +following at top level would be a quick way of loading your +entire program: +.(l +| ?- [program]. +.)l +.pp +When you are +simply interacting with the top level of the Prolog interpreter +the distinction between questions and commands is not very important. +At the top level you should normally only type questions. In a file, if you +wish to execute some goals then you should use a command. +That is, to execute a +directive in a file it must be preceded by \*(lq:-\*(rq, otherwise it will be +treated as a clause. +.sh 2 "Saving A Program" +.pp +Once a program has been read, the interpreter will have available +all the information necessary for its execution. This information is +called a program \fIstate\fP. +.pp +The state of a program may be saved on a file for future execution. +To save a program into a file \fIfile\fP, perform the command: +.(l +?- save(\fIfile\fP). +.)l +\fBSave\fP can be called at top level, from within a break level (q.v.), +or from anywhere within a program. +.sh 2 "Restoring A Saved Program" +.pp +Once a program has been saved into a file \fIfile\fP, C-Prolog +can be restored to this saved state by invoking it +as follows: +.(l +prolog \fIfile\fP +.)l +After execution of this command, the interpreter will be in \fIexactly\fP the +same state as existed immediately prior to the call to \fBsave\fP, +except for open files, which are automatically closed by \fBsave\fP. +That is to say execution will start at the goal immediately following the +call to \fBsave\fP, just as if \fBsave\fP had returned successfully. +If you saved the state at top level then you will be back at top level, +but if you explicitly called \fBsave\fP from within your program then the +execution of your program will continue. +.pp +Saved states can only be restored when C-Prolog is initially run from +command level. Version \*(Vn provides no way of restoring a saved state from +inside C-Prolog. +.pp +Note that when a new version of C-Prolog is installed, +saved states created with the old version may become unusable. +You are thus advised to rely on source files for your programs and +not on some gigantic saved state. +.sh 2 "Program Execution And Interruption" +.pp +Execution of a program is started by giving the interpreter a +directive which contains a call to one of the program's procedures. +.pp +Only when execution of one directive is complete does the +interpreter become ready for another directive. However, one may +interrupt the normal execution of a directive by hitting the \s-2INTERRUPT\s0 key +on your terminal. +In response to the prompt +.(l +Action (h for help): +.)l +you can type either \*(lqa\*(rq, \*(lqt\*(rq, \*(lqd\*(rq or \*(lqc\*(rq followed by \s-2END-OF-LINE\s0. +The \*(lqa\*(rq response will force Prolog to abort back to top level, +the \*(lqt\*(rq option will switch on tracing, +the +\*(lqd\*(rq response will switch on debugging and continue the execution, +and the \*(lqc\*(rq response will just continue the execution. +.sh 2 "Nested Executions \*- Break and Abort" +.pp +C-Prolog provides a way to suspend the execution of your program +and to enter a new incarnation of the top level where you can issue +directives to solve goals etc. +When the evaluable predicate \fBbreak\fP is called, +the message +.(l +[ Break (level 1) ] +.)l +will be displayed. This signals the start of a \fIbreak\fP +and except +for the effect of \fBabort\fPs (see below), it is as if the interpreter +was at top level. +If break is called within a break, then another recursive break is +started (and the message will say (level 2) etc). +Breaks can be arbitrarily nested. +.pp +Typing the \s-2END-OF-INPUT\s0 character +will close the break and resume the execution which +was suspended, starting at the procedure call where the suspension took +place. +.pp +To abort the current execution, forcing an immediate +failure of the directive being executed +and a return to the top level of the interpreter, +call the evaluable predicate \fBabort\fP, either from the program +or by executing the directive: +.(l +| ?- abort. +.)l +within a break. In this case no \s-2END-OF-INPUT\s0 character is needed to close the +break, because \fIall\fP break levels are discarded and the system returns right +back to top level. The \*(lqa\*(rq response to \s-2INTERRUPT\s0 (described above) can also +be used to force an abort. +.sh 2 "Exiting From The Interpreter" +.pp +To exit from C-Prolog interpreter +you should give the directive: +.(l +| ?- halt. +.)l +This can be issued either at top level, or within a break, +or indeed from within your program. +.pp +If your program is still executing then you should interrupt it and abort +to return to top level +so that you can call \fBhalt\fP. +.pp +Typing +the \s-2END-OF-INPUT\s0 charater at +top level also causes C-Prolog to terminate. +.sh 1 "Prolog Syntax" +.pp +.sh 2 "Terms" +.pp +The data objects of the language are called \fIterm\fPs. +A term is either a \fIconstant\fP, a \fIvariable\fP or a \fIcompound term\fP. +.pp +The constants include \fInumber\fPs such as +.(l +0 -999 -5.23 0.23E-5 +.)l +.pp +Constants also include \fIatom\fPs such as +.(l +a void = := 'Algol-68' [] +.)l +The symbol for an atom can be any sequence of characters, +written in single quotes if there is possibility of confusion with other +symbols (such as variables or numbers). As in other programming +languages, constants are definite elementary objects. +.pp +Variables are distinguished by an initial capital letter or by +the initial character \*(lq\(ul\*(rq, for example +.(l +X Value A A1 \(ul3 \(ulRESULT +.)l +If a variable is only referred to once, it does not need to be named +and may be written as an \fIanonymous\fP variable, indicated by the +underline character \*(lq\(ul\*(rq. +.pp +A variable should be thought of as standing for some definite but +unidentified object. +A variable is not simply a writeable +storage location as in most programming languages; rather it is a +local name for some data object, cf. the variable of pure LISP and +constant declarations in Pascal. +.pp +The structured data objects of the language are the compound terms. A +compound term comprises a \fIfunctor\fP (called the \fIprincipal\fP functor of +the term) and a sequence of one or more terms called \fIarguments\fP. +A functor is characterised by its \fIname\fP, which is an atom, and its +\fIarity\fP or number of arguments. +For example the compound term whose functor is +named `point' of arity 3, with arguments X, Y and Z, is written +.(l +point(X,Y,Z) +.)l +An atom is considered to be a functor of arity 0. +.pp +One may think of a functor as a record type and the +arguments of a compound term as the fields of a record. Compound +terms are usefully pictured as trees. For example, the term +.(l +s(np(john),vp(v(likes),np(mary))) +.)l +would be pictured as the structure +.(b + s + / \e + np vp + | / \e + john v np + | | + likes mary +.)b +.pp +Sometimes it is convenient to write certain functors as \fIoperators\fP +\*- 2-ary functors may be declared as \fIinfix\fP operators and 1-ary functors +as \fIprefix\fP or \fIpostfix\fP operators. +Thus it is possible to write +.(l +X+Y (P;Q) X ]). +:- op( 1200, fx, [ :-, ?- ]). +:- op( 1100, xfy, [ ; ]). +:- op( 1050, xfy, [ -> ]). +:- op( 1000, xfy, [ ',' ]). /* See note below */ +:- op( 900, fy, [ not, \e+, spy, nospy ]). +:- op( 700, xfx, [ =, is, =.., ==, \e==, @<, @>, @=<, @>=, +\& \& \& =:=, =\e=, <, >, =<, >= ]). +:- op( 500, yfx, [ +, -, /\e, \e/ ]). +:- op( 500, fx, [ +, - ]). +:- op( 400, yfx, [ *, /, //, <<, >> ]). +:- op( 300, xfx, [ mod ]). +:- op( 200, xfy, [ ^ ]). +.TE +.)l +.pp +Operator declarations are most usefuly placed in directives at the top +of your program files. In this case the directive should be a command as +shown above. Another common method of organisation is to have one file +just containing commands to declare all the necessary operators. This file +is then always consulted first. +.pp +Note that a comma written literally as a punctuation character +can be used as though it were an infix operator of precedence 1000 and +type `xfy': +.(l +X,Y ','(X,Y) +.)l +represent the same compound term. But note that a comma written as a +quoted atom is \fInot\fP a standard operator. +.pp +Note also that the arguments of a compound term written in +standard syntax must be expressions of precedence \fIbelow\fP 1000. Thus it +is necessary to bracket the expression \*(lqP:-Q\*(rq in +.(l +assert((P:-Q)) +.)l +The following syntax restrictions serve to +remove potential ambiguity associated with prefix operators. +.ip - +In a term written in standard syntax, the principal functor and +its following \*(lq(\*(rq must \fInot\fP be separated by any blankspace. Thus +.(l +point (X,Y,Z) +.)l +is invalid syntax. +.ip - +If the argument of a prefix operator starts with a \*(lq(\*(rq, this \*(lq(\*(rq +must be separated from the operator by at least one space or other +non-printable character. Thus +.(l +:-(p;q),r. +.)l +(where `:-' is the prefix operator) is invalid syntax, and must be written as +.(l +:- (p;q),r. +.)l +.ip - +If a prefix operator is written without an argument, as an +ordinary atom, the atom is treated as an expression of the same +precedence as the prefix operator, and must therefore be bracketed +where necessary. Thus the brackets are necessary in +.(l +X = (?-) +.)l +.sh 2 "Syntax Errors" +.pp +Syntax errors are detected when reading. Each clause, +directive or in general any term read-in by the evaluable predicate +\fBread\fP that fails to comply with syntax requirements is displayed on the +terminal as soon as it is read. A mark indicates the point in the +string of symbols where the parser has failed to continue its analysis. +For example, typing +.(l +member(X,X L). +.)l +gives: +.(l +***syntax error*** +member(X,X +***here*** + L). +.)l +.pp +Syntax errors do not disrupt the (re)consulting of a file in any way +except that the clause or command +with the syntax error will be ignored\** +.(f +\**After all, it could not +be read. +.)f +All the other clauses in the file will have been read-in +properly. +If the syntax error occurs at top level then you should just retype the +question. +Given that Prolog has a very simple syntax it is usually quite +straightforward +to see what the problems is (look for missing brackets in particular). +The book \fIProgramming in Prolog\fP gives +further examples. +.sh 2 "Using a Terminal without Lower-Case" +.pp +The syntax of Prolog assumes that a full ASCII character +set is available. With this \fIfull character set\fP or `LC' convention, +variables are (normally) distinguished by an initial capital letter, +while atoms and other functors must start with a lower-case letter +(unless enclosed in single quotes). +.pp +When lower-case is not available, the \fIno lower-case\fP or `NOLC' +convention has to be adopted. With this convention, variables must be +distinguished by an initial underline character \*(lq\(ul\*(rq, and the names of +atoms and other functors, which now have to be written in upper-case, +are implicitly translated into lower-case (unless enclosed in single +quotes). For example, +.(l +\(ulVALUE2 +.)l +is a variable, while +.(l +VALUE2 +.)l +is `NOLC' convention notation for the atom which is identical to: +.(l +value2 +.)l +written in the `LC' convention. +.pp +The default convention is `LC'. To switch to the no lower-case +convention, call the evaluable predicate `NOLC': +.(l +| ?- 'NOLC'. +.)l +To switch back to the full character set convention, call the +evaluable predicate `LC': +.(l +| ?- 'LC'. +.)l +.pp +Note that the names of these two procedures consist of upper-case +letters (so that they can be referred to on all devices), and +therefore the names must \fIalways\fP be enclosed in single quotes. +.pp +It is recommended that the `NOLC' convention only be used in emergencies, +since the standard syntax is far easier to use and +is also easier +for other people to read. +.sh 1 "The Meaning of Prolog Programs" +.sh 2 "Programs" +.pp +A fundamental unit of a logic program is the \fIliteral\fP, for instance +.(l +gives(tom,apple,teacher) reverse([1,2,3],L) X/ +is used, for example \fBconcatenate\fP/3. +.pp +Certain predicates are +predefined by procedures supplied by the Prolog system. Such predicates are +called \fIevaluable predicates\fP. +.pp +As we have seen, the goals in the body +of a clause are linked by the operator `,' which can be interpreted as +conjunction (\*(lqand\*(rq). It is sometimes convenient to use an additional +operator `;', standing for disjunction (\*(lqor\*(rq) (The precedence of `;' is such +that it dominates `,' but is dominated by `:-'.). An example is the clause. +.(l +grandfather(X,Z) :- (mother(X,Y); father(X,Y)), father(Y,Z). +.)l + which can be +read as +.(l +\*(lqFor any X, Y and Z, X has Z as a grandfather if either the mother +of X is Y or the father of X is Y, and the father of Y is Z.\*(rq +.)l +Such uses of disjunction can always be eliminated by defining an +extra predicate - for instance the previous example is equivalent to +.(l +grandfather(X,Z) :- parent(X,Y), father(Y,Z). +parent(X,Y) :- mother(X,Y). +parent(X,Y) :- father(X,Y). +.)l +and so disjunction will not be mentioned further in the following, more +formal, description of the semantics of clauses. +.sh 2 "Declarative and Procedural Semantics" +.pp +The semantics of definite clauses should be fairly clear from the informal +interpretations already given. However it is useful to have a precise +definition. The \fIdeclarativesemantics\fP of definite clauses tells us which goals +can be considered true according to a given program, and is defined recursively +as follows. +.(l F +A goal is \fItrue\fP if it is the head of some clause instance and each of +the goals (if any) in the body of that clause \fIinstance\fP is true, where +an instance of a clause (or term) is obtained by substituting, for each +of zero or more of its variables, a new term for all occurrences of the +variable. +.)l +For example, if a program contains the preceding procedure for +\fBconcatenate\fP, +then the declarative semantics tells us that +.(l +concatenate([a],[b],[a,b]) +.)l +is true, because this goal is the head of a certain instance of the first +clause for \fBconcatenate\fP, namely, +.(l +concatenate([a],[b],[a,b]) :- concatenate([],[b],[b]). +.)l +and we know that the only goal in the body of this clause instance is true, +since it is an instance of the unit clause which is the second clause for +\fBconcatenate\fP. +.pp +The declarative semantics makes no reference to the sequencing of +goals within the body of a clause, nor to the sequencing of clauses within a +program. This sequencing information is, however, very relevant for the +\fIprocedural semantics\fP which Prolog gives to definite clauses. The procedural +semantics defines exactly how the Prolog system will execute a goal, and the +sequencing information is the means by which the Prolog programmer directs the +system to execute his program in a sensible way. The effect of executing a +goal is to enumerate, one by one, its true instances. Here then is an informal +definition of the procedural semantics. +.(l F +To execute a goal, the system searches forwards from the beginning of +the program for the first clause whose head \fImatches\fP or \fIunifies\fP with the +goal. The unification process finds the most general +common instance of the two terms, which is unique if it exists. If a +match is found, the matching clause instance is then activated by +executing in turn, from left to right, each of the goals (if any) in +its body. If at any time the system fails to find a match for a goal, +it \fIbacktracks\fP, that is it rejects the most recently activated clause, +undoing any substitutions made by the match with the head of the +clause. Next it reconsiders the original goal which activated the +rejected clause, and tries to find a subsequent clause which also +matches the goal. +.)l +For example, if we execute the goal in the query +.(l +:- concatenate(X,Y,[a,b]). +.)l +we find that it matches the head of the first clause for \fBconcatenate\fP, with X +instantiated to [a|X1]. The new variable X1 is constrained by the new goal +produced, which is the recursive procedure call +.(l +concatenate(X1,Y,[b]) +.)l +Again this goal matches the first clause, instantiating X1 to [b|X2], and +yielding the new goal +.(l +concatenate(X2,Y,[]) +.)l +Now this goal will only match the second clause, instantiating both X2 and Y to +[]. Since there are no further goals to be executed, we have a solution +.(l +X = [a,b] +Y = [] +.)l +representing a true instance of the original goal +.(l +concatenate([a,b],[],[a,b]) +.)l +If this solution is rejected, backtracking will generate the further +solutions +.(l +X = [a] +Y = [b] + +X = [] +Y = [a,b] +.)l +in that order, by rematching, against the second clause for \fBconcatenate\fP, goals +already solved once using the first clause. +.sh 2 "Occurs Check" +.pp +Prolog's unification does not have an \fIoccurs check\fP, i.e. when unifying a +variable against a term the system does not check whether the variable occurs +in the term. When the variable occurs in the term, unification should fail, +but the absence of the check means that the unification succeeds, producing a +\fIcircular term\fP. Trying to print a circular term, or trying to unify two +circular terms, will cause an infinite loop and possibly make Prolog +run out of stack space. +.pp +The absence of the occur check is not a bug or design oversight, but a +conscious design decision. The reason for this decision is that unification +with the occur check is at best linear on the sum of the sizes of the terms +being unified, whereas unification without the occur check is linear on the +size of the smallest of the terms being unified. In any practical programming +language, basic operations are supposed to take constant time. +Unification against a variable should be thought of as the basic +operation of Prolog, but this can take constant time only if the occur check is +omitted. Thus the absence of a occur check is essential to make Prolog into a +practical programming language. The inconvenience caused by this restriction +seems in practice to be very slight. Usually, the restriction is only felt in +toy programs. +.sh 2 "The Cut Symbol" +.pp +Besides the sequencing of goals and clauses, Prolog provides one other very +important facility for specifying control information. This is the \fIcut\fP symbol, +written \*(lq!\*(rq. It is inserted in the program just like a goal, but is not to be +regarded as part of the logic of the program and should be ignored as far as +the declarative semantics is concerned. +.pp +The effect of the cut symbol is as follows. When first encountered as a goal, +cut succeeds immediately. If backtracking should later return to the cut, the +effect is to fail the \fIparent goal\fP, the goal which matched the head of +the clause containing the cut, and caused the clause to be activated. In other +words, the cut operation commits the system to all choices made since the +parent goal was invoked, and causes other alternatives to be discarded. The +goals thus rendered \fIdeterminate\fP are the parent goal itself, any goals +occurring before the cut in the clause containing the cut, and any subgoals +which were executed during the execution of those preceding goals. +.pp +For example, the procedure +.(l +member(X,[X|L]). +member(X,[Y|L]) :- member(X,L). +.)l +can be used to test whether a given term is in a list, and the goal +.(l +:- member(b,[a,b,c]). +.)l +will succeed. +The procedure can also be used to extract elements +from a list, as in +.(l +:- member(X,[d,e,f]). +.)l +With backtracking this will successively return each element of the list. Now +suppose that the first clause had been written instead: +.(l +member(X,[X|L]) :- !. +.)l +In this case, the above call would extract only the first element of the list +(`d'). On backtracking, the cut would immediately fail the whole procedure. +.pp +A procedure of the form +.(l +\fIx\fP :- \fIp\fP, !, \fIq\fP. +\fIx\fP :- \fIr\fP. +.)l +is similar to +.(l +\fIx\fP := if \fIp\fP then \fIq\fP else \fIr\fP; +.)l +in an Algol-like language. +.pp +A cut discards all the alternatives since the parent +goal, even when the cut appears within a disjunction. This means that the +normal method for eliminating a disjunction by defining an extra predicate +cannot be applied to a disjunction containing a cut. +.sh 1 "Debugging Facilities" +.pp +This section describes the debugging facilities that are available +in C-Prolog. The purpose of these facilities is to provide +information concerning the control flow of your program. The main +features of the debugging package are as follows: +.ip - +The \fIProcedure box\fP +model of Prolog execution which provides a simple way of visualising +control flow, especially during backtracking. Control flow is viewed at +the procedure level, rather than at the level of individual clauses. +.ip - +The ability to exhaustively trace your program or to selectively set +\fIspy points\fP. Spy points allow you to nominate interesting procedures at +which the program is to pause so that you can interact. +.ip - +The wide choice of control and information options available during +debugging. +.pp +Much of the information in this chapter is similar +but not identical to that of Chapter 8 of \fIProgramming in Prolog\fP. +.sh 2 "The Procedure Box Control Flow Model" +.pp +During debugging the interpreter prints out a sequence of goals in +various states of instantiation in order to show the state the program has +reached in its execution. However, in order to understand what is +occurring it is necessary to understand when and why the interpreter prints +out goals. As in other programming languages, key points of interest +are procedure entry and return, but in Prolog there is the additional +complexity of backtracking. One of the major confusions that novice +Prolog programmers have to face is the question of what actually happens when +a goal fails and the system suddenly starts backtracking. The Procedure +Box model of Prolog execution views program control flow in terms of +movement about the program text. This model provides a basis for the +debugging mechanism in the interpreter, and enables the user to view the +behaviour of his program in a consistent way. +.pp +Let us look at an example Prolog procedure: +.(b + *--------------------------------------* + Call | | Exit + ---------> + descendant(X,Y) :- of\&fspring(X,Y). + ---------> + | | + | descendant(X,Z) :- | + <--------- + of\&fspring(X,Y), descendant(Y,Z). + <--------- + Fail | | BackTo + *--------------------------------------* +.)b +The first clause states that Y is a descendant of X if Y is an offspring of +X, and the second clause states that Z is a descendant of X if Y is an +offspring of X and if Z is a descendant of Y. In the diagram a box has been +drawn around the whole procedure and labelled arrows indicate the control +flow in and out of this box. There are four such arrows which we shall look +at in turn. +.lp +Call +.ip +This arrow represents initial invocation of the procedure. When a +\fBdescendant\fP goal of the form \fBdescendant\fP(X,Y) is required to +be satisfied, control passes through the Call \fIport\fP of the +\fBdescendant\fP box with the intention of matching a component clause and +then satisfying any subgoals in the body of that clause. Notice +that this is independent of whether such a match is possible, that is first +the box is called, and then the attempt to match takes place. Textually we +can imagine moving to the code for \fBdescendant\fP when meeting a call to +\fBdescendant\fP in some other part of the code. +.lp +Exit +.ip +This arrow represents a successful return from the procedure. This +occurs when the initial goal has been unified with one of the component +clauses and any subgoals have been satisfied. Control now passes out of +the Exit port of the \fBdescendant\fP box. Textually we stop following the +code for \fBdescendant\fP and go back to the place we came from. +.lp +BackTo +.ip +This arrow indicates that a subsequent goal has failed and that the system +has come back to this goal in an attempt to match the goal against another +clause. Control passes through the BackTo port of the \fBdescendant\fP +box in an attempt to rematch the original goal with an alternative clause +and then try to satisfy any subgoals in the body of this new clause. +Textually we follow the code backwards up the way we came looking for +new ways of succeeding, possibly dropping down on to another clause +and following that if necessary. Note that this is somewhat less informative +than the Redo port described in \fIProgramming in Prolog\fP, because it does not +show the path in the program from a failed goal back to the first goal where +alternative clauses exist, but only this goal. +.lp +Fail +.ip +This arrow represents +a failure of the initial goal, which might occur if no clause is matched, +or if subgoals are never satisfied, or if any solution produced is always +rejected by later processing. Control now passes out of the Fail port of the +\fBdescendant\fP box and the system continues to backtrack. Textually we +move back to the code which called this procedure and keep moving backwards +up the code looking for choice points. +.pp +In terms of this model, the +information we get about the procedure box is only the control flow through +these four ports. This means that at this level we are not concerned +with which clause matches, and how any subgoals are satisfied, but +rather we only wish to know the initial goal and the final outcome. +However, it can be seen that whenever we are trying to satisfy subgoals, +what we are actually doing is passing through the ports of \fItheir\fP +respective boxes. If we were to follow this, then we would have +complete information about the control flow inside the procedure box. + +Note that the box we have drawn round the procedure should really be seen as +an \fIinvocation box\fP. That is, there will be a different box for each +different invocation of the procedure. Obviously, with something like +a recursive procedure, there will be many different Calls and Exits in the +control flow, but these will be for different invocations. Since this might +get confusing each invocation box is given a unique integer identifier. +.sh 2 "Basic Debugging Predicates" +.pp +The interpreter provides a range of evaluable predicates for control of +the debugging facilities. The most basic predicates are as follows: +.lp +\fBdebug\fP +.ip +Switches \fIdebug mode\fP on. (It is initially off.) In order for the +full range of control flow information to be available it is necessary +to have this on from the start. When it is off the system does not +remember invocations that are being executed. (This is because it is +expensive and not required for normal running of programs.) You can +switch debug mode on in the middle of execution, either from within your +program or after an interrupt (see \fBtrace\fP below), but information prior +to this will just be unavailable. +.lp +\fBnodebug\fP +.ip +switches debug mode off. If there are any spy points set then they +will be removed. +.lp +\fBdebugging\fP +.ip +prints onto the terminal information about the current debugging +state. It shows whether debug mode is on or off and gives various +other information to be described later. +.sh 2 "Tracing" +.pp +The following evaluable predicate may be used to commence an exhaustive +trace of a program. +.lp +\fBtrace\fP +.ip +Switches debug mode on, if it is not on already, and ensures that +the next time control enters a procedure box, a message will be +produced and you will be asked to interact. +.pp +When stopped at a goal being traced, +you have a number of options which will be detailed later. +In particular, you can just type \s-2END-OF-LINE\s0 (carriage-return) to creep (or +single-step) into your program. If you continue to creep through your +program you will see every entry and exit to/from every invocation box. +However, you will notice that you are only given the opportunity to +interact on Call and BackTo ports, i.e. a single creep decision may take you +through several Exit ports or several Fail ports. Normally this is +desirable, as it would be tedious to go through all those ports step by step. +However, if it is not what you want, the following evaluable predicate gives +full control over the ports at which you are prompted. +.lp +\fBleash\fP(\fIMode\fP) +.ip +Sets the \fIleashing mode\fP to \fIMode\fP, where +\fIMode\fP can be one of the following +.(l +.TS +l l. +full prompt on Call, Exit, BackTo and Fail +tight prompt on Call, BackTo and Fail +half prompt on Call and BackTo +loose prompt on Call +off never prompt +.TE +.)l +or any other combination of ports as described later. +The initial \fIleashing mode\fP is `half'. +.sh 2 "Spy Points" +.pp +For programs of any size, it is clearly impractical to creep through the +entire program. Spy points make it possible to stop the program whenever it +gets to a particular procedure which is of interest. Once there, one can +set further spy points in order to catch the control flow a bit further +on, or one can start creeping. +.pp +Setting a spy-point on a procedure indicates that you wish to see all +control flow through the various ports of its invocation boxes. When +control passes through any port of a procedure with a spy-point set on it, a +message is output and the user is asked to interact. Note that the current +mode of leashing does not affect spy points: user interaction is requested on +\fIevery\fP port. +.pp +Spy points are set and removed by the following evaluable predicates which +are also standard operators: +.lp +\fBspy\fP \fIX\fP +.ip +Sets spy points on all the procedures given by \fIX\fP. \fIX\fP is either a +single predicate specification, or a list of such specifications. +A predicate specification is either of the form /, +which means the procedure with the name and an arity of + (for example member/2, foo/0, hello/27), or it is of the form +, which means all the procedures with the name that +currently have clauses in the data-base (e.g. member, foo, hello). +This latter form may refer to multiple procedures which have the +same name but different arities. If you use the form but +there are no clauses for this predicate (of any arity) then nothing +will be done. If you really want to place a spy point on a +currently non-existent procedure, then you must use the full form +/; you will get a warning message in this case. If +you set some spy points when debug mode is off then it will be +automatically switched on. +.lp +\fBnospy\fP \fIX\fP +.ip +This reverses the effect of spy \fIX\fP: all the procedures given by \fIX\fP +will have previously set spy points removed from them. +.pp +The options available when you arrive at a spy-point are described below. +.sh 2 "Format of Debugging Messages" +.pp +We will now look at the exact format of the message output by the system at +a port. All trace messages are output to the terminal regardless of where +the current output is directed. (This allows you to trace programs while +they are performing file I/O.) The basic format is as follows: +.(l +** (23) 6 Call : foo(hello,there,\(ul123) ? +.)l +The \*(lq**\*(rq indicates that this is a spy-point. If this port is not for +a procedure with a spy-point set, then there will be two spaces there +instead. If this port is the requested return from a Skip then the +second character becomes \*(lq>\*(rq. This gives four possible combinations: +.(l +.TS +l lt. +\*(lq**\*(rq This is a spy-point. +\*(lq*>\*(rq T{ +This is a spy-point, and you also did a Skip last time you were in +this box. +T} +\*(lq >\*(rq T{ +This is not a spy-point, but you did a Skip last time you were in +this box. +T} +\*(lq \*(rq This is not a spy-point. +.TE +.)l +.lp +The number in parentheses is the unique invocation identifier. This +is continuously incrementing regardless of whether or not you are actually +seeing the invocations (provided that debug mode is on). This number can +be used to cross correlate the trace messages for the various ports, since +it is unique for every invocation. It will also give an indication +of the number of procedure calls made since the start of the execution. The +invocation counter starts again for every fresh execution of a command, and +it is also reset when retries (see later) are performed. +.pp +The number following this is the current depth, that is, the number of +direct ancestors this goal has. +.pp +The next word specifies the particular port (Call, Exit, BackTo or Fail). +.pp +The goal is then printed so that you can inspect its current +instantiation state. +.pp +The final \*(lq?\*(rq is the prompt indicating that you should type in one of +the option codes allowed (see next section). If this particular port is +unleashed then you will obviously not get this prompt since you have +specified that you do not wish to interact at this point. +.pp +Notice that not all procedure calls are traced; there are a few +basic procedures which have been made invisible since it is more convenient +not to see them. These include all primitive I/O evaluable predicates +(for example \fBget\fP, \fBput\fP, \fBread\fP, \fBwrite\fP), all basic control +structures (that is, `,', `;', `->') and all debugging control evaluable +predicates (for instance, \fBdebug\fP, \fBspy\fP, \fBleash\fP, \fBtrace\fP). +This means that you will never see messages concerning these predicates +during debugging. +.sh 2 "Options Available during Debugging" +.pp +This section describes the particular options that are available when +the system prompts you after printing out a debugging message. All the +options are one letter mnemonics. They are read from the terminal with +any blanks being completely ignored up to the next end of line. +The \fIcreep\fP option needs only the new line. + +The only option which you really have to remember is \*(lqh\*(rq. This provides +help in the form of the following list of available options: +.(l +.TS +l l l l. +\s-2END-OF-LINE\s0 creep a abort +c creep f fail +l leap b break +s skip h help +r retry r retry goal +q quasi-skip n nodebug +g goal stack [ read clauses from terminal +e exit Prolog +.TE +.)l +The first three options are the basic control decisions: +.lp +\fBc\fP, \s-2END-OF-LINE\s0: Creep +.ip +Causes the interpreter to single-step to the very next port and print a +message. Then if the port is leashed the user is +prompted for further interaction. Otherwise it continues creeping. If +leashing is off, creep is the same as leap (see below) except that a +complete trace is printed on the terminal. +.lp +\fBl\fP: Leap +.ip +causes the interpreter to resume running your program, only stopping +when a spy-point is reached (or when the program terminates). Leaping +can thus be used to follow the execution at a higher level than +exhaustive tracing. All you need to do is to set spy points on an +evenly spread set of pertinent procedures, and then follow the control +flow through these by leaping from one to the other. +.lp +\fBs\fP: Skip +.ip +Skip is only valid for Call and BackTo ports. It skips over the entire +execution of the procedure. That is, you will not see anything until +control comes back to this procedure (at either the Exit port or the +Fail port). Skip is particularly useful while creeping since it +guarantees that control will be returned after the (possibly complex) +execution within the box. If you skip then no message at all will +appear until control returns. This includes calls to procedures with +spy points set; they will be masked out during the skip. There are two +ways of overriding this : there is a Quasi-skip which does not ignore +spy points, and the \*(lqt\*(rq option after an interrupt will disable the +masking. Normally, however, this masking is just what is required! +.lp +\fBq\fP: Quasi-skip +.ip +Is like Skip except that it does not mask out spy points. If there is +a spy-point within the execution of the goal then control returns at +this point and any action can be performed there. The initial skip +still guarantees an eventual return of control, though, when the +internal execution is finished. +.lp +\fBf\fP: Fail +.ip +Transfers to the Fail port of +the current box. This puts your execution in a position +where it is about to backtrack out of the current +invocation, that is, you have manually failed the initial goal. +.lp +\fBr\fP: Retry +.ip +Transfers to the Call port of the current goal, or if given a numeric +argument \fIn\fP, to the Call port of the invocation numbered \fIn\fP. +IF the invocation being retried has been deleted by the cut control primitive, +the most recent active invocation before it will be retried. If \fIn\fP +is out of range, the current invocation is retried. +This option is extremely useful to go back to an earlier state of +computation if some point of interest was overshot in a debugging +session. Note however that side effects, such as database modification, +are not undone. +.lp +\fBg\fP: Goal Stack +.ip +Shows the goal that called the current one, and the one that called +it, and so on, that is, the \fBstack\fP of pending goals. Goals +are printed one per line, from the most recent to the least recent. +Each goal is labeled by its recursion level \fIl\fP, its invocation +number \fIi\fP and the ordinal position \fIp\fP of the clause currently +used to solve the goal. +.lp +\fBa\fP: Abort +.ip +Causes an abort of the current execution. All the execution states +built so far are destroyed and you are put right back at the top level +of the interpreter. (This is the same as the evaluable predicate +\fBabort\fP.) +.lp +\fB[\fP: Read clauses from terminal +.ip +starts reading clauses typed by the user as if doing a \fIconsult(user)\fP. +An \s-2END-OF-INPUT\s0 returns to the debugger. +.lp +\fBe\fP: Exit from Prolog +.ip +causes an irreversible exit from the Prolog system. +(This is the same as the evaluable predicate \fBhalt\fP.) +.lp +\fBh\fP: Help +.ip +Displays the table of options given above. +.lp +\fBb\fP: Break +.ip +Calls the evaluable predicate \fBbreak\fP, thus putting you at interpreter +top level with the execution so far sitting underneath you. When you +end the break with the \s-2END-OF-INPUT\s0 character, you will be reprompted at the port at which you +broke. The new execution is completely separate from the suspended +one; the invocation numbers will start again from 1 during the break. +Debug mode is not switched off as you call the break, but if you do +switch it off then it will be re-switched on when you finish the break +and go back to the old execution. However, any changes to the leashing +or to spy points will remain in effect. +.lp +\fBn\fP: Nodebug +.ip +Turns off debug mode. Notice that this is the correct way to switch +debugging off at a trace point. You cannot use the \*(lqb\*(rq option +because it always restores debug mode upon return. +.sh 2 "Reconsulting during Debugging" +.pp +It is possible, and sometimes useful, to reconsult a file whilst in the +middle of a program execution. However this can lead to unexpected +behaviour under the following circumstances: a procedure has been +successfully executed; it is subsequently re-defined by a reconsult, +and is later re-activated by backtracking. When the backtracking +occurs, all the new clauses for the procedure appear to the interpreter +to be potential alternative solutions, even though identical clauses may +already have been used. Thus large amounts of (unwanted) activity takes +place on backtracking. The problem does not arise if you do the reconsult +when you are at the Call port of the procedure to be re-defined. +.sh 1 "Evaluable Predicates" +.pp +This section describes all the evaluable predicates available in +C-Prolog. +These predicates are provided in advance by the system and they cannot +be redefined by the user. +Any attempt to add clauses or delete clauses to an evaluable predicate +fails with an error +message, and leaves the evaluable predicate unchanged. +The C-Prolog provides a fairly wide range of evaluable predicates +to perform the following tasks: +.(l +Input/Output + Reading-in programs + Opening and closing files + Reading and writing Prolog terms + Getting and putting characters +Arithmetic +Affecting the flow of the execution +Classifying and operating on Prolog terms (meta-logical facilities) +Sets +Term Comparison +Manipulating the Prolog program database +Manipulating the additional indexed database +Debugging facilities +Environmental facilities +.)l +The evaluable predicates will be described according to this +classification. Appendix I +contains +a complete list of the evaluable predicates. +.sh 2 "Input and Output" +.pp +A total of 15 I/O streams may be open at any one time for input and +output. This includes a stream that is always available +for input and output to the user's +terminal. A stream to a file \fIF\fP is opened for input by the first +\fBsee\fP(\fIF\fP) executed. \fIF\fP then becomes the current input stream. +Similarly, a stream to file \fIH\fP is opened for output by the first +\fBtell\fP(\fIH\fP) executed. \fIH\fP then becomes the current output stream. +Subsequent calls to \fBsee\fP(\fIF\fP) or to \fBtell\fP(\fIH\fP) make \fIF\fP or +\fIH\fP the current input or output stream, respectively. Any input or output +is always to the current stream. +.pp +When no input or output stream has been specified, the standard +ersatz file `user', denoting the user's terminal, is utilised for +both. +When the terminal is +waiting for input on a new line, a prompt will be displayed as follows: +.(l +.TS +l l. +\*(lq| ?- \*(rq interpreter waiting for command +\*(lq| \*(rq interpreter wating for command continuation line +\*(lq| \*(rq \fBconsult\fP(user) wating for continuation line +\*(lq|:\*(rq default for waiting for other user input +.TE +.)l +When the current input (or output) stream is closed, the user's +terminal becomes the current input (or output) stream. +.pp +The only file +that can be simultaneously open +for input and output is the ersatz file `user'. +.pp +A file is referred to by its name, \fIwritten as an atom\fP, e.g. +.(l +myfile +\&'F123' +data\(ullst +\&'tom/greeks' +.)l +.pp +All I/O errors normally cause an \fBabort\fP, except for the effect +of the evaluable predicate \fBnofileerrors\fP decribed below. +.pp +End of file is signalled on the user's terminal +by typing the \s-2END-OF-INPUT\s0 character. +Any more input requests for a file whose end has been reached causes +an error failure. +.sh 3 "Reading-in Programs" +.lp +\fBconsult\fP(\fIF\fP) +.ip +Instructs +the interpreter to read-in the program which is +in file \fIF\fP. When a directive is read it is immediately executed. When +a clause is read it is put after any clauses already read by the interpreter +for that procedure. +.lp +\fBreconsult\fP(\fIF\fP) +.ip +Like +\fBconsult\fP except that any procedure defined in the +reconsulted file erases any clauses for that procedure already +present in the interpreter. +\fBreconsult\fP makes it possible to amend a program +without having to restart from scratch and consult all the files which +make up the program. +.lp +\fB[\fP\fIFile\fP\fB|\fP\fIFiles\fP\fB]\fP +.ip +This +is a shorthand way of consulting or reconsulting a list of files. +A file name may optionally be preceded by the operator `-' to +indicate that the file should be reconsulted rather than +consulted. Thus +.(l +| ?- [file1,-file2,file3]. +.)l +is merely a shorthand for +.(l +| ?- consult(file1), reconsult(file2), consult(file3). +.)l +.sh 3 "File Handling" +.lp +\fBsee\fP(\fIF\fP) +.ip +File \fIF\fP becomes the current input stream. +.lp +\fBseeing\fP(\fIF\fP) +.ip +\fIF\fP +is unified with the name of the current input file. +.lp +\fBseen\fP +.ip +Closes +the current input stream. +.lp +\fBtell\fP(\fIF\fP) +.ip +File +\fIF\fP becomes the current output stream. +.lp +\fBtelling\fP(\fIF\fP) +.ip +\fIF\fP +is unified with the name of the current output file. +.lp +\fBtold\fP +.ip +Closes +the current output stream. +.lp +\fBclose\fP(\fIF\fP) +.ip +File +\fIF\fP, currently open for input or output, is closed. +.lp +\fBfileerrors\fP +.ip +Undoes +the effect of \fBnofileerrors\fP. +.lp +\fBnofileerrors\fP +.ip +After +a call to this predicate, the I/O error conditions +\*(lqincorrect file name ...\*(rq, \*(lqcan't see file ...\*(rq, \*(lqcan't tell file +\&...\*(rq and \*(lqend of file ...\*(rq cause a call to \fBfail\fP instead of the +default action, which is to type an error message and then call +\fBabort\fP. +.lp +\fBexists\fP(\fIF\fP) +.ip +Succeeds +if the file F exists. +.lp +\fBrename\fP(\fIF\fP,\fIN\fP) +.ip +If +File \fIF\fP is renamed to \fIN\fP. +If \fIN\fP is `[]', the file is deleted. +If \fIF\fP was a currently open stream, it is closed first. +.sh 3 "Input and Output of Terms" +.lp +\fBread\fP(\fIX\fP) +.ip +The +next term, delimited by a full stop (i.e. a \*(lq.\*(rq followed by a carriage-return +or a space), is read from the current input stream and +unified with \fIX\fP. The syntax of the term must accord with current +operator declarations. If a call \fBread\fP(\fIX\fP) causes the end of the +current input stream to be reached, \fIX\fP is unified with the atom +\&`end\(ulof\(ulfile'. Further calls to \fBread\fP for the same stream will then +cause an error failure. +.lp +\fBwrite\fP(\fIX\fP) +.ip +The +term \fIX\fP is written to the current output stream according to +operator declarations in force. +.lp +\fBdisplay\fP(\fIX\fP) +.ip +The +term \fIX\fP is displayed on the terminal in standard parenthesised +prefix notation. +.lp +\fBwriteq\fP(\fITerm\fP) +.ip +Similar +to \fBwrite\fP(\fITerm\fP), but the names of atoms and functors +are quoted where necessary to make the result acceptable as input to \fBread\fP. +.lp +\fBprint\fP(\fITerm\fP) +.ip +Print \fITerm\fP onto the current output. +This predicate provides a handle for user defined pretty printing. +If \fITerm\fP is a variable then it is written, +using \fBwrite\fP(\fITerm\fP). +If \fITerm\fP is non-variable then a call is made to +the user defined procedure \fBportray\fP(\fITerm\fP). +If this succeeds then it is assumed that \fITerm\fP has been output. +Otherwise \fBprint\fP is equivalent to \fBwrite\fP. +.sh 3 "Character Input/Output" +.lp +\fBnl\fP +.ip +A new line is started on the current output stream. +.lp +\fBget0\fP(\fIN\fP) +.ip +\fIN\fP +is the ASCII code of the next character from the current input +stream. If the current input stream reaches its end of file, +the ASCII character code for control-Z is returned and +the stream closed. +.lp +\fBget\fP(\fIN\fP) +.ip +\fIN\fP +is the ASCII code of the next non-blank printable character +from the current input stream. It has the same behaviour as \fBget0\fP +on end of file. +.lp +\fBskip\fP(\fIN\fP) +.ip +Skips +to just past the next ASCII character code \fIN\fP from the +current input stream. \fIN\fP may be an integer expression. +Skipping past the end of file causes an error. +.lp +\fBput\fP(\fIN\fP) +.ip +ASCII +character code \fIN\fP is output to the current output stream. +\fIN\fP may be an integer expression. +.lp +\fBtab\fP(\fIN\fP) +.ip +\fIN\fP +spaces are output to the current output stream. \fIN\fP +may be an integer expression. +.sh 2 "Arithmetic" +.pp +Arithmetic is performed by evaluable predicates which take as +arguments \fIarithmetic expressions\fP and \fIevaluate\fP them. +An arithmetic expression is a term built from \fIevaluable functors\fP, +numbers and variables. +At the time of evaluation, each variable in an arithmetic +expression must be bound to a number or +to an arithmetic expression. +The result of evaluation will always be converted back to an integer +if possible. +.pp +Each evaluable functor stands for an arithmetic operation. +The adjective \*(lqinteger\*(rq in the descriptions below means that +the operation only makes sense for integers, and will fail +for floating point numbers. +.pp +Because arithmetic expressions are compound terms, they use up storage +that is only recovered on backtracking. The evaluable predicate +\fBexpanded\(ulexprs\fP can be used to avoid this overhead +by preexpanding arithmetic +expressions into calls to arithmetic evaluation predicates. However, +this makes program read-in slower and clauses bigger. +.pp +In general, an arithmetic operation that combines integers and +floating point numbers will return a floating point number. +However, if the result is integral, it is converted back to +integer representation, and the same applies to numbers read in +by the reader. Thus, the goal +.(l +| ?- p(2.0). +.)l +will succeed with the clause +.(l +p(2). +.)l +and the result of the query +.(l +| ?- X is 2*1.5. +.)l +is +.(l +X = 5 +.)l +.pp +Numbers may be integers +.(l +-33 0 9999 +.)l +or floating point numbers +.(l +1.333 -2.6E+7 0.555E-2 +.)l +.pp +Note that the decimal \*(lq.\*(rq cannot be confused with the end of clause because +the latter must be followed by blank space (space, tab or \s-2END-OF-LINE\s0). +However, if an operator \*(lq.\*(rq is declared as infix, it will only be possible +to apply it to two numbers if they are separated by blank space from +the operator. +.pp +The +evaluable functors are as follows, where \fIX\fP and \fIY\fP are +arithmetic expressions. +.RS +.lp +\fIX\fP+\fIY\fP +.ip +addition +.lp +\fIX\fP-\fIY\fP +.ip +subtraction +.lp +\fIX\fP*\fIY\fP +.ip +multiplication +.lp +\fIX\fP/\fIY\fP +.ip +division +.lp +\fIX\fP//\fIY\fP +.ip +integer division +.lp +\fIX\fP mod \fIY\fP +.ip +\fIX\fP (integer) modulo \fIY\fP +.lp +-\fIX\fP +.ip +unary minus +.lp +\fBexp\fP(\fIX\fP) +.ip +exponential function +.lp +\fBlog\fP(\fIX\fP) +.ip +natural logarithm +.lp +\fBlog10\fP(\fIX\fP) +.ip +base 10 logarithm +.lp +\fBsqrt\fP(\fIX\fP) +.ip +square root +.lp +\fBsin\fP(\fIX\fP) +.ip +sine +.lp +\fBcos\fP(\fIX\fP) +.ip +cosine +.lp +\fBtan\fP(\fIX\fP) +.ip +tangent +.lp +\fBasin\fP(\fIX\fP) +.ip +arc sine +.lp +\fBacos\fP(\fIX\fP) +.ip +arc cosine +.lp +\fBatan\fP(\fIX\fP) +.ip +arc tangent +.lp +\fBfloor\fP(\fIX\fP) +.ip +the largest integer not greater than \fIX\fP +.lp +\fIX\fP^\fIY\fP +.ip +\fIX\fP to the power \fIY\fP +.lp +\fIX\fP/\e\fIY\fP +.ip +integer bitwise conjunction +.lp +\fIX\fP\/\fIY\fP +.ip +integer bitwise disjunction +.lp +\fIX\fP<<\fIY\fP +.ip +integer bitwise left shift of \fIX\fP by \fIY\fP places +.lp +\fIX\fP>>\fIY\fP +.ip +integer bitwise right shift of \fIX\fP by \fIY\fP places +.lp +\e\fIX\fP +.ip +integer bitwise negation +.lp +\fBcputime\fP +.ip +CPU time since C-Prolog was started, in seconds. +.lp +\fBheapused\fP +.ip +Heap space in use, in bytes. +.lp +[\fIX\fP] +.ip +(a list of just one element) +evaluates to \fIX\fP if \fIX\fP is an integer. +Since a quoted string is just a list of integers, this allows a quoted +character to be used in place of its ASCII code; e.g. \*(lqA\*(rq behaves within +arithmetic expressions as the integer 65. +.RE +.pp +The arithmetic evaluable predicates are as follows, where \fIX\fP and +\fIY\fP stand for arithmetic expressions, and \fIZ\fP for some term. +Note that this means that \fBis\fP only evaluates one of its arguments +as an arithmetic expression (the right-hand side one), +whereas all the comparison +predicates evaluate both their arguments. +.lp +\fIZ\fP \fBis\fP \fIX\fP +.ip +Arithmetic +expression \fIX\fP is evaluated and the result, +is unified with +\fIZ\fP. Fails if \fIX\fP is not an arithmetic expression. +.lp +\fIX\fP \fB=:=\fP \fIY\fP +.ip +The +values of \fIX\fP and \fIY\fP are equal. +.lp +\fIX\fP \fB=\=\fP \fIY\fP +.ip +The +values of \fIX\fP and \fIY\fP are not equal. +.lp +\fIX\fP\fB < \fP\fIY\fP +.ip +The +value of \fIX\fP is less than the value of \fIY\fP. +.lp +\fIX\fP\fB > \fP\fIY\fP +.ip +The +value of \fIX\fP is greater than the value of \fIY\fP. +.lp +\fIX\fP\fB =<\fP \fIY\fP +.ip +The +value of \fIX\fP is less than or equal to the value of \fIY\fP. +.lp +\fIX\fP\fB >=\fP \fIY\fP +.ip +The +value of \fIX\fP is greater than or equal to the value of \fIY\fP. +.lp +\fBexpanded\(ulexprs\fP(\fIOld\fP,\fINew\fP) +.ip +Unifies \fIOld\fP to the current value of the expression expansion flag, +and sets the value of the flag to \fINew\fP. The possible values of +the flag are `off' (the default) for not expanding arithmetic expressions +into procedure calls, and `on' to do the expansion. +.sh 2 "Convenience" +.lp +\fIP\fP \fB,\fP \fIQ\fP +.ip +\fIP\fP +and \fIQ\fP. +.lp +\fIP\fP \fB;\fP \fIQ\fP +.ip +\fIP\fP +or \fIQ\fP. +.lp +\fBtrue\fP +.ip +Always +succeeds. +.lp +\fIX\fP \fB=\fP \fIY\fP +.ip +Defined as if by the clause \*(lq Z=Z. \*(rq, +that is \fIX\fP and \fIY\fP are unified. +.sh 2 "Extra Control" +.lp +\fB!\fP +.ip +Cut (discard) all choice points made since +the parent goal started execution. +.lp +\fB\\+\fP \fIP\fP +.ip +If +the goal \fIP\fP has a solution, fail, otherwise succeed. It is +defined as if by +.(l +\e+(P) :- P, !, fail. +\e+(\(ul). +.)l +.lp +\fIP\fP \fB->\fP \fIQ\fP \fB;\fP \fIR\fP +.ip +Analogous to +.(l +\*(lqif \fIP\fP then \fIQ\fP else \fIR\fP\*(rq +.)l +i.e. defined as if by +.(l +P -> Q; R :- P, !, Q. +P-> Q; R :- R. +.)l +.lp +\fIP\fP \fB->\fP \fIQ\fP +.ip +When +occurring other than as one of the alternatives of a +disjunction, is equivalent to +.(l +\fIP\fP -> \fIQ\fP; fail. +.)l +.lp +\fBrepeat\fP +.ip +Generates +an infinite sequence of backtracking choices. It +behaves as if defined by the clauses: +.(l +repeat. +repeat :- repeat. +.)l +.lp +\fBfail\fP +.ip +Always fails. +.sh 2 "Meta-Logical" +.lp +\fBvar\fP(\fIX\fP) +.ip +Tests +whether \fIX\fP is currently instantiated to a variable. +.lp +\fBnonvar\fP(\fIX\fP) +.ip +Tests +whether \fIX\fP is currently instantiated to a non-variable term. +.lp +\fBatom\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to an atom (i.e. a +non-variable term of arity 0, other than a number or database reference). +.lp +\fBnumber\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to a number. +.lp +\fBinteger\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to an integer. +.lp +\fBatomic\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to an atom, number or database +reference. +.lp +\fBprimitive\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to a number or database +reference. +.lp +\fBdb\(ulreference\fP(\fIX\fP) +.ip +Checks +that \fIX\fP is currently instantiated to a database +reference. +.lp +\fBfunctor\fP(\fIT\fP,\fIF\fP,\fIN\fP) +.ip +The +principal functor of term \fIT\fP has name \fIF\fP and arity +\fIN\fP, where \fIF\fP +is either an atom or, provided \fIN\fP is 0, a number. +Initially, +either \fIT\fP must be instantiated to a non-variable, or \fIF\fP and +\fIN\fP must +be instantiated to, respectively, either an atom and a +non-negative integer or an integer and 0. If these conditions are +not satisfied, an error message is given. In the case where \fIT\fP is +initially instantiated to a variable, the result of the call is +to instantiate \fIT\fP to the most general term having the principal +functor indicated. +.lp +\fBarg\fP(\fII\fP,\fIT\fP,\fIX\fP) +.ip +Initially, +\fII\fP must be instantiated to a positive integer and +\fIT\fP to +a compound term. The result of the call is to unify \fIX\fP with the +\fII\fPth argument of term \fIT\fP. (The arguments are numbered +from 1 +upwards.) If the initial conditions are not satisfied or \fII\fP is out +of range, the call merely fails. +.lp +\fIX\fP \fB=..\fP \fIY\fP +.ip +\fIY\fP +is a list whose head is the atom corresponding to the principal +functor of \fIX\fP and whose tail is the argument list of that functor +in \fIX\fP. E.g. +.(l +product(0,N,N-1) =.. [product,0,N,N-1] + +N-1 =.. [-,N,1] + +product =.. [product] +.)l +If \fIX\fP is instantiated to a variable, then \fIY\fP must be instantiated +either to a list of determinate length whose head is an atom, or to a list of +length 1 whose head is a number. +.lp +\fBname\fP(\fIX\fP,\fIL\fP) +.ip +If +\fIX\fP is an atom or a number then \fIL\fP is a list of the +ASCII codes of the characters comprising the name of \fIX\fP. E.g. +.(l +name(product,[112,114,111,100,117,99,116]) +.)l +i.e. name(product,"product") +.(l +name(1976,[49,57,55,54]) + +name(hello,[104,101,108,108,111]) + +name([],"[]") +.)l +If \fIX\fP is instantiated to a variable, \fIL\fP must be instantiated +to a list of ASCII character codes. E.g. +.(l +| ?- name(X,[104,101,108,108,111])). + +X = hello + +| ?- name(X,"hello"). + +X = hello +.)l +.lp +\fBcall\fP(\fIX\fP) +.ip +If +\fIX\fP is instantiated to a term which would be acceptable as body +of a clause, the goal \fBcall\fP(\fIX\fP) is executed exactly as if that +term appeared textually in place of the \fBcall\fP(\fIX\fP), except that +any cut (\*(lq!\*(rq) occurring in \fIX\fP will remove only those choice points +in \fIX\fP. +If \fIX\fP is not instantiated as +described above, an error message is printed and \fBcall\fP fails. +.lp +\fIX\fP +.ip +(where +\fIX\fP is a variable) Exactly the same as \fBcall\fP(\fIX\fP). +.sh 2 "Sets" +.pp +When there are many solutions to a problem, and when all those solutions are +required to be collected together, this can be achieved by repeatedly +backtracking and gradually building up a list of the solutions. The following +evaluable predicates are provided to automate this process. +.lp +\fBsetof\fP(\fIX\fP,\fIP\fP,\fIS\fP) +.RS +.lp +Read this as \*(lq\fIS\fP is the set of all instances of \fIX\fP such that +\fIP\fP is +provable, where that set is non-empty\*(rq. The term \fIP\fP +specifies a +goal or goals as in \fBcall\fP(\fIP\fP). +\fIS\fP is a set of terms represented as a +list of those terms, without duplicates, in the standard order for +terms (see Section 5.3). If there are no instances of \fIX\fP such that +\fIP\fP is satisfied then the predicate fails. +.lp +The variables appearing in the term \fIX\fP should not appear anywhere +else in the clause except within the term \fIP\fP. Obviously, the set to +be enumerated should be finite, and should be enumerable by Prolog +in finite time. It is possible for the provable instances to +contain variables, but in this case the list \fIS\fP will only provide an +imperfect representation of what is in reality an infinite set. +.lp +If there are uninstantiated variables in \fIP\fP which do not also appear +in \fIX\fP, then a call to this evaluable predicate may backtrack, +generating alternative values for \fIS\fP corresponding to different +instantiations of the free variables of \fIP\fP. (It is to cater for +such usage that the set S is constrained to be non-empty.) For +example, the call: +.(l +| ?- setof(X, X likes Y, S). +.)l +might produce two alternative solutions via backtracking: +.(l +Y = beer, S = [dick, harry, tom] +Y = cider, S = [bill, jan, tom ] +.)l +The call: +.(l +| ?- setof((Y,S), setof(X, X likes Y, S), SS). +.)l +would then produce: +.(l +SS = [ (beer,[dick,harry,tom]), (cider,[bill,jan,tom]) ] +.)l +.lp +Variables occurring in \fIP\fP will not be treated as free if they are +explicitly bound within \fIP\fP by an existential quantifier. An +existential quantification is written: +.(l +\fIY\fP^\fIQ\fP +.)l +meaning \*(lqthere exists a \fIY\fP such that \fIQ\fP is true\*(rq, +where \fIY\fP is some Prolog variable. +For example: +.(l +| ?- setof(X, Y^(X likes Y), S). +.)l +would produce the single result: +.(l +X = [bill, dick, harry, jan, tom] +.)l +in contrast to the earlier example. +.RE +.lp +\fBbagof\fP(\fIX\fP,\fIP\fP,\fIBag\fP) +.ip +This is exactly the same as \fBsetof\fP except that the list (or +alternative lists) returned will not be ordered, and may contain +duplicates. The effect of this relaxation is to save considerable +time and space in execution. +.lp +\fIX\fP\fB^\fP\fIP\fP +.ip +The interpreter recognises this as meaning \*(lqthere exists an \fIX\fP such +that \fIP\fP is true\*(rq, and treats it as equivalent to \fBcall\fP(\fIP\fP). +The use of this explicit existential +quantifier outside the \fBsetof\fP and \fBbagof\fP +constructs is superfluous. +.sh 2 "Comparison of Terms" +.pp +These evaluable predicates are meta-logical. They treat uninstantiated +variables as objects with values which may be compared, and they never +instantiate those variables. They should \fInot\fP be used when what you really want +is arithmetic comparison (Section 5.2) or unification. +.pp +The predicates make reference to a standard total ordering of terms, which is +as follows: +.ip - +variables, in a standard order (roughly, oldest first - the order is +\fInot\fP related to the names of variables); +.ip - +Database references, roughly in order of age; +.ip - +numbers, from -\*(lqinfinity\*(rq to +\*(lqinfinity\*(rq; +.ip - +atoms, in alphabetical (i.e. ASCII) order; +.ip - +complex terms, ordered first by arity, then by the name of principal +functor, then by the arguments (in left-to-right order). +.pp +For example, here is a list of terms in the standard order: +.(l +[ X, -9, 1, fie, foe, fum, X = Y, fie(0,2), fie(1,1) ] +.)l +These are the basic predicates for comparison of arbitrary terms: +.lp +\fIX\fP \fB==\fP \fIY\fP +.ip +Tests if the terms currently instantiating \fIX\fP and \fIY\fP +are literally +identical (in particular, variables in equivalent positions in the +two terms must be identical). For example, the question +.(l +| ?- X == Y. +.)l +fails (answers \*(lqno\*(rq) because \fIX\fP and \fIY\fP +are distinct uninstantiated +variables. However, the question +.(l +| ?- X = Y, X == Y. +.)l +succeeds because the first goal unifies the two variables (see page 42). +.lp +\fIX\fP \fB\e==\fP \fIY\fP +.ip +Tests if the terms currently instantiating \fIX\fP and \fIY\fP are +not literally identical. +.lp +\fIT1\fP \fB@<\fP \fIT2\fP +.ip +Term \fIT1\fP is before term \fIT2\fP in the standard order. +.lp +\fIT1\fP \fB@>\fP \fIT2\fP +.ip +Term \fIT1\fP is after term \fIT2\fP in the standard order. +.lp +\fIT1\fP \fB@=<\fP \fIT2\fP +.ip +Term \fIT1\fP is not after term \fIT2\fP in the standard order. +.lp +\fIT1\fP \fB@>=\fP \fIT2\fP +.ip +Term \fIT1\fP is not before term \fIT2\fP in the standard order. +.pp +Some further predicates involving comparison of terms are: +.lp +\fBcompare\fP(\fIOp\fP,\fIT1\fP,\fIT2\fP) +.ip +The result of comparing terms \fIT1\fP and \fIT2\fP is \fIOp\fP, +where the possible +values for \fIOp\fP are: +.(l +\&`=' if \fIT1\fP is identical to \fIT2\fP, + +\&`<' if \fIT1\fP is before \fIT2\fP in the standard order, + +\&`>' if \fIT1\fP is after \fIT2\fP in the standard order. +.)l +Thus \fBcompare\fP(=,\fIT1\fP,\fIT2\fP) is equivalent to +\fIT1\fP \fB==\fP \fIT2\fP. +.lp +\fBsort\fP(\fIL1\fP,\fIL2\fP) +.ip +The elements of the list \fIL1\fP are sorted into the standard order, and +any identical (i.e. `==') elements are merged, yielding the list +\fIL2\fP. (The time taken to do this is at worst order (N log N) where N +is the length of \fIL1\fP.) +.lp +\fBkeysort\fP(\fIL1\fP,\fIL2\fP) +.ip +The list \fIL1\fP must +consist of items of the form \fIKey\fP-\fIValue\fP. These +items are sorted into order according to the value of \fIKey\fP, yielding +the list \fIL2\fP. No merging takes place. (The time taken to do this is +at worst order (N log N) where N is the length of L1.) +.sh 2 "Modification of the Program" +.pp +The predicates defined in this section allow modification of the program +as it is actually running. +Clauses can be added to the program (\fIasserted\fP) or removed from the program +(\fIretracted\fP). +Some of the predicates make use of an implementation-defined identifier +or \fIdatabase reference\fP +which uniquely identifies every clause in the interpreted program. +This identifier makes it possible to access clauses directly, instead of +requiring a search through the program every time. +However these facilities are intended for more complex use of the database and +are not required (and undoubtedly should be avoided) by novice users. +.lp +\fBassert\fP(\fIC\fP) +.ip +The +current instance of \fIC\fP is interpreted as a clause and is added +to the program (with new private variables +replacing any uninstantiated variables). The position of the new +clause within the procedure concerned is implementation-defined. +\fIC\fP must be instantiated to a non-variable. +.lp +\fBassert\fP(\fIClause\fP,\fIRef\fP) +.ip +Similar +to \fBassert\fP(\fIClause\fP), but also +unifies \fIRef\fP with the database reference +of the clause asserted. +.lp +\fBasserta\fP(\fIC\fP) +.ip +Like +\fBassert\fP(\fIC\fP), except that the new clause becomes the \fIfirst\fP +clause for the procedure concerned. +.lp +\fBasserta\fP(\fIClause\fP,\fIRef\fP) +.ip +Similar to +\fBasserta\fP(\fIClause\fP), but also unifies \fIRef\fP with the database reference +of the clause asserted. +.lp +\fBassertz\fP(\fIC\fP) +.ip +Like +\fBassert\fP(\fIC\fP), except that the new clause becomes the \fIlast\fP +clause for the procedure concerned. +.lp +\fBassertz\fP(\fIClause\fP,\fIRef\fP) +.ip +Similar to +\fBassertz\fP(\fIClause\fP), but also unifies \fIRef\fP with the database reference +of the clause asserted. +.lp +\fBclause\fP(\fIP\fP,\fIQ\fP) +.ip +\fIP\fP +must be bound to a non-variable term, and the +program is searched for a clause whose head matches \fIP\fP. +The head and body of those clauses are unified with \fIP\fP and \fIQ\fP +respectively. If one of the clauses is a unit clause, \fIQ\fP will be +unified with `true'. +.lp +\fBclause\fP(\fIHead\fP,\fIBody\fP,\fIRef\fP) +.ip +Similar +to \fBclause\fP(\fIHead\fP,\fIBody\fP) but also unifies \fIRef\fP with the +database reference of the clause +concerned. If \fIRef\fP is not given at the time of the call, +\fIHead\fP must be instantiated to a non-variable term. Thus this +predicate can have two different modes of use, depending on whether the +database reference of the clause is known or unknown. +.lp +\fBretract\fP(\fIC\fP) +.ip +The first clause in the +program that matches \fIC\fP is erased. +\fIC\fP must be initially instantiated to a non-variable. +The predicate may be used in a non-determinate fashion, +i.e. it will successively retract clauses matching the argument through +backtracking. +.lp +\fBabolish\fP(\fIN\fP,\fIA\fP) +.RS +Completely +remove all clauses for the procedure with name \fIN\fP (which should be +an atom), and arity \fIA\fP (which should be an integer). +.lp +The space +occupied by retracted or abolished clauses will be recovered when +instances of the clause are no longer in use. +.lp +See also \fBerase\fP (Section 5.10) which allows a clause to be +directly erased via its database reference\**. +.(f +\**This is a lower level facility, +required only for complicated database manipulations. +.)f +.RE +.sh 2 "Information about the State of the Program" +.lp +\fBlisting\fP +.ip +Lists +in the current output stream all the clauses in the +program. +.lp +\fBlisting\fP(\fIA\fP) +.ip +The argument \fIA\fP may be a predicate specification of +the form \fIName\fP/\fIArity\fP in which case only the clauses for the +specified predicate are listed. +If \fIA\fP is just an atom, then +the interpreted procedures for all predicates of that name are listed +as for \fBlisting\fP/0. +Finally, it is possible for \fIA\fP to be a list +of predicate specifications of either type, e.g. +.(l +| ?- listing([concatenate/3, reverse, go/0]). +.)l +.lp +\fBcurrent\(ulatom\fP(\fIAtom\fP) +.ip +Generates +(through backtracking) all currently known atoms, and +returns each one as \fIAtom\fP. +.lp +\fBcurrent\(ulfunctor\fP(\fIName\fP,\fIFunctor\fP) +.ip +Generates +(through backtracking) all currently known functors, +and for each one returns its name and most general term as \fIName\fP and +\fIFunctor\fP respectively. If \fIName\fP is given, only functors with +that name are generated. +.lp +\fBcurrent\(ulpredicate\fP(\fIName\fP,\fIFunctor\fP) +.ip +Similar +to \fBcurrent\(ulfunctor\fP, but it only generates functors +corresponding to predicates for which there exists +a procedure. +.sh 2 "Internal Database" +.pp +This section describes predicates for manipulating an internal indexed database +that is kept separate from the normal program database. +They are intended for more sophisticated database applications and +are not really necessary for novice users. +For normal tasks you should be able to program quite satisfactorily +just using \fBassert\fP and \fBretract\fP. +.lp +\fBrecorded\fP(\fIKey\fP,\fITerm\fP,\fIRef\fP) +.ip +The +internal database is searched for terms recorded under the key +\fIKey\fP. These terms are successively unified with \fITerm\fP in the order +they occur in the database. At the same time, \fIRef\fP is unified with +the database reference of the recorded item. +The key must be given, and may be an atom or complex term. +If it is a complex term, only the principal functor is significant. +.lp +\fBrecorda\fP(\fIKey\fP,\fITerm\fP,\fIRef\fP) +.ip +The +term \fITerm\fP is recorded in the internal database as the first +item for the key \fIKey\fP, where \fIRef\fP is its database reference. +The key must be given, and only its principal functor is +significant. +.lp +\fBrecordz\fP(\fIKey\fP,\fITerm\fP,\fIRef\fP) +.ip +The +term \fITerm\fP is recorded in the internal database as the last +item for the key \fIKey\fP, where \fIRef\fP is its database reference. +The key must be given, and only its principal functor is +significant. +.lp +\fBerase\fP(\fIRef\fP) +.ip +The +recorded item \fIor\fP clause whose database reference +is \fIRef\fP is effectively erased from the internal +database or program. +An erased item will no longer be accessible through the predicates +that search through the database, but will still be accessible +through its database reference, if this is available in +the execution state after the call to \fBerase\fP. Only when +all instances of the item's database reference have been forgotten +through database erasures and/or backtracking will the item +be actually removed from the database. +.lp +\fBerased\fP(\fI\R\fP) +.ip +Suceeds if \fIR\fP is a database reference to a database item +that has been \fBerase\fPd, otherwise fails. +.lp +\fBinstance\fP(\fIRef\fP,\fITerm\fP) +.ip +A +(most general) instance of the recorded term whose database reference +is \fIRef\fP is unified with \fITerm\fP. \fIRef\fP must be +instantiated to a database reference. Note that \fBinstance\fP +will even pick database items that have been \fBerase\fPd. +.lp +.sh 2 "Debugging" +.lp +\fBdebug\fP +.ip +Debug +mode is switched on. Information will now +be retained for debugging purposes and executions will +require more space. +.lp +\fBnodebug\fP +.ip +Debug +mode is switched off. Information is no longer retained +for debugging, and spy points are removed. +.lp +\fBtrace\fP +.ip +Debug +mode is switched on, and the interpreter starts tracing from +the next call to a user goal. +If \fBtrace\fP was given in a command on its +own, the goal(s) traced will be those of the next command. +Since this is a once-off decision, a call to trace is necessary whenever +tracing is required right from the start of an execution, otherwise +tracing will only happen at spy points. +.lp +\fBspy\fP \fISpec\fP +.ip +Spy points +will be placed on all the procedures given by \fISpec\fP. +All control flow through the ports of these procedures will henceforth +be traced. +If debug mode was previously off, then it will be switched on. +\fISpec\fP can either be a predicate specification of the form \fIName/Arity\fP +or \fIName\fP, or a list of such specifications. +When the \fIName\fP is given without the \fIArity\fP this refers to all +predicates of that name which currently have definitions. +If there are none, then nothing will be done. +Spy points can be placed on particular undefined procedures only +by using the full form, \fIName/Arity\fP. +.lp +\fBnospy\fP \fISpec\fP +.ip +Spy points +are removed from all the procedures given by \fISpec\fP +(as for \fBspy\fP). +.lp +\fBleash\fP(\fIMode\fP) +.ip +Sets the leashing mode to \fIMode\fP, where +\fIMode\fP can be one of the following +.(l +.TS +l l. +full prompt on Call, Exit, BackTo and Fail +tight prompt on Call, BackTo and Fail +half prompt on Call and BackTo +loose prompt on Call +off never prompt +\fIN\fP T{ +\fIN\fP is an integer. If the binary notation of +\fIN\fP is 2'\fIcebf\fP, the digits \fIc\fP, \fIe\fP, \fIb\fP +and \fIf\fP correspond to the Call, Exit BackTo and Fail respectively, +and are 1 (0) if the corresponding port is leashed (unleashed). +T} +.TE +.)l +The initial \fIleashing mode\fP is `half'. +.lp +\fBdebugging\fP +.ip +Outputs +information concerning the status of the debugging package. +This will show whether debug mode is on, and if it is +.(l +what spy points have been set + +what mode of leashing is in force. +.)l +.sh 2 "Environmental" +.pp +.lp +\&'\fBNOLC\fP' +.ip +Establishes +the no lower-case convention described in Section +2.4. +.lp +\&'\fBLC\fP' +.ip +Establishes +the full character set convention described in +Section 2.4. It is the default setting. +.lp +\fBop\fP(\fIpriority\fP,\fItype\fP,\fIname\fP) +.ip +Treat +name \fIname\fP as an operator of the stated \fItype\fP and +\fIpriority\fP +(refer to Section 2.2). +\fIname\fP may also be a list of names in which +case all are to be treated as operators of the stated \fItype\fP and +\fIpriority\fP. +.lp +\fBbreak\fP +.ip +Causes +the current execution to be suspended at the next +procedure call. Then the message \*(lq[ Break (level 1) ]\*(rq is +displayed. The interpreter is then ready to accept input as +though it was at top level. +If another call of \fBbreak\fP is encountered, it moves up to level 2, and +so on. +To close the break and resume the +execution which was suspended, type the \s-2END-OF-INPUT\s0 character. +Execution will be resumed at the procedure call where +it had been suspended. Alternatively, the suspended execution +can be aborted by calling the evaluable predicate \fBabort\fP. Refer +to Section 1.9. +.lp +\fBabort\fP +.ip +Aborts +the current execution taking you back to top level. +Refer to Section 1.9. +.lp +\fBsave\fP(\fIF\fP) +.ip +The +system saves the current state of the system into file \fIF\fP. +Refer to Section 1.6. +.lp +\fBsave\fP(\fIF\fP,\fIWhen\fP) +.ip +Saves the current state of the system into file \fIF\fP. +\fBWhen\fP is unified with 0 or 1 depending on whether the +system is returning from the \fBsave\fP goal in the original Prolog +session or after the saved state in \fIF\fP has been restored +by invoking Prlog with file \fIF\fP as argument. +.lp +\fBprompt\fP(\fIOld\fP,\fINew\fP) +.ip +The +sequence of characters (prompt) which indicates that the +system is waiting for user input is represented as an atom, and +matched to \fIOld\fP; the atom bound to \fINew\fP specifies the new +prompt. In particular, the goal +.(l +prompt(X,X) +.)l +matches the current prompt to X, without changing it. +Note that this only affects the prompt issued for reads in the user's +program; it will not change the propmts used by the system at top level +etc. +.lp +\fBsystem\fP(\fIString\fP) +.ip +Calls the operating system with string \fIString\fP as argument. For +example +.(l +system("ls") +.)l +will produce a directory listing on \s-2UNIX\s0. +.lp +\fBsh\fP +.ip +Suspends C-Prolog and enters a recursive command interpreter. +On \s-2UNIX\s0, the shell used will be that specified in the environment +variable SHELL. +.lp +\fBstatistics\fP +.ip +Shows the current allocations and amounts used for each of the +six working areas of C-Prolog, and also the runtime since C-Prolog +started. For example: +.(l +| ?- statistics. +atom space: 64K (15596 bytes used) +aux. stack: 8K (0 bytes used) +trail: 64K (48 bytes used) +heap: 256K (30664 bytes used) +global stack: 256K (0 bytes used) +local stack: 256K (300 bytes used) +Runtime: 1.42 sec. +| ?- +.)l +.sh 2 "Preprocessing" +.lp +\fBexpand\(ulterm\fP(\fIT1\fP,\fIT2\fP) +.ip +Each top level term \fIT1\fP read when consulting a file is rewritten +into \fIT2\fP before being asserted or executed. The default transformations +provided by this predicate are the ones for grammar rules and for inline +expansion of arithmetic expressions. +The user may define further transformations as clauses for the +predicate \fBterm\(ulexpansion\fP/2, which has similar arguments. +User defined transformations are applied \fIbefore\fP system-defined ones. diff --git a/source_code/c-prolog-1982/man/cprolog.out b/source_code/c-prolog-1982/man/cprolog.out new file mode 100755 index 0000000..68adabd --- /dev/null +++ b/source_code/c-prolog-1982/man/cprolog.out @@ -0,0 +1,3959 @@ + + + + +. + + + + + C-Prolog User's Manual + + + Version 1.5 + February 22, 1984 + + Edited by Fernando Pereira[1] + SRI International, Menlo Park, California + + from material by + + David Warren + SRI International, Menlo Park, California + + David Bowen, Lawrence Byrd + Dept. of Artificial Intelligence, University of Edinburgh + + Luis Pereira + Dept. de Informatica, Universidade Nova de Lisboa + + + _A_b_s_t_r_a_c_t + + + + This is a revised edition of the user's manual for + C-Prolog, a Prolog interpreter written in C for 32 + bit machines. C-Prolog is based on an earlier Pro- + log interpreter written in IMP for the EMAS operat- + ing system by Luis Damas, who borrowed many aspects + of the design from the DECsystem-10/20 Prolog system + developed by David Warren, Fernando Pereira, + Lawrence Byrd and Luis Pereira. This manual is + based on the EMAS Prolog manual, which in turn was + based on the DECsystem-10/20 Prolog manual. + + + + + + + + + + + + + ____________________ + [1]Formerly at EdCAAD, Dept. of Architecture, University + of Edinburgh + + + + + + + + + + + + +. + C-Prolog User's Manual 1 + + + _1. _U_s_i_n_g _C-_P_r_o_l_o_g + + _1._1. _P_r_e_f_a_c_e + + This manual describes C-Prolog, a Prolog interpreter + written in C. C-Prolog was developed at EdCAAD, Dept. of + Architecture, University of Edinburgh, and is based on a + previous interpreter, written in IMP for the EMAS operating + system by Luis Damas of the Dept. of Computer Science, + University of Edinburgh. C-Prolog was designed for machines + with a large, uniform, address space, and assumes a pointer + cell 32 bits wide. At the time of writing, it has been + tested on VAX[2] machines under the UNIX[3] and VAX/VMS + operating systems, on the Sun workstation under 4.1/2 UNIX, + and has been ported with minor changes to other MC68000- + based workstations and to the Three Rivers PERQ. + + Prolog is a simple but powerful programming language + originally developed at the University of Marseilles, as a + practical tool for programming in logic. From a user's + point of view the major attraction of the language is ease + of programming. Clear, readable, concise programs can be + written quickly with few errors. Prolog is especially suit- + able for high-level symbolic programming tasks and has been + applied in many areas of Artificial Intelligence research. + + The system consists of a Prolog interpreter and a wide + range of builtin (system defined) procedures. Its design + was based on the (Edinburgh) DECsystem-10 Prolog system and + the system is closely compatible with DECsystem-10 Prolog + and thus is also reasonably close to PDP-11 UNIX and RT-11 + Prolog. + + This manual is not intended as an introduction to the + Prolog language and how to use it. For this purpose you + should study: + + _P_r_o_g_r_a_m_m_i_n_g _i_n _P_r_o_l_o_g + W. Clocksin & C. Mellish + Springer Verlag 1981 + + + This manual assumes that you are familiar with the + principles of the Prolog language, its purpose being to + explain how to use C-Prolog, and to describe all the evalu- + able predicates provided by C-Prolog. + + ____________________ + [2]VAX, VMS, PDP and DECsystem-10 are trademarks of Digi- + tal Equipment Corporation. + [3]UNIX is a Trademark of Bell Laboratories. + + + + + + + + + + + + +. + C-Prolog User's Manual 2 + + + _1._2. _U_s_i_n_g _C-_P_r_o_l_o_g -- _O_v_e_r_v_i_e_w + + C-Prolog offers the user an interactive programming + environment with tools for incrementally building programs, + debugging programs by following their executions, and modi- + fying parts of programs without having to start again from + scratch. + + The text of a Prolog program is normally created in a + number of files using a text editor. C-Prolog can then be + instructed to read-in programs from these files; this is + called _l_c_o_n_s_u_l_t_i_n_g the file. To change parts of a program + being run, it is possible to _r_e_c_o_n_s_u_l_t files containing the + changed parts. Reconsulting means that definitions for pro- + cedures in the file will replace any old definitions for + these procedures. + + It is recommended that you make use of a number of dif- + ferent files when writing programs. Since you will be edit- + ing and consulting/reconsulting individual files it is use- + ful to use files to group together related procedures; keep- + ing collections of procedures that do different things in + different files. Thus a Prolog program will consist of a + number of files, each file containing a number of related + procedures. + + When your programs start to grow to a fair size, it is + also a good idea to have one file which just contains com- + mands to the interpreter to consult all the other files + which form a program. You will then be able to consult your + entire program by just consulting this single file. + + _1._3. _A_c_c_e_s_s _t_o _C-_P_r_o_l_o_g + + In this manual, we assume that there is a command on + your computer + + prolog + + that invokes C-Prolog. + + We assume that there are three keys or key combinations + that achieve the effects of terminating an input line, mark- + ing end of input, and interrupting execution of a program. + Because these depend on operating system and individual + tastes, they are denoted in this manual by END-OF-LINE, + END-OF-INPUT and INTERRUPT respectively (they are carriage + return, control-Z and control-C on the computer this is + being written on). + + Since Prolog makes syntactic use of the difference + between upper and lower case it is important that you have + your terminal set up so that it accepts lower case in the + + + + + + + + + + +. + C-Prolog User's Manual 3 + + + normal way. This means, for a start, that you must be using + an upper and lower case terminal - and not, for example, an + upper case only teletype. It is possible to use Prolog + using upper case only (see Section 2.4) but it is unneces- + sarily painful. We shall assume both upper and lower case + throughout this manual. + + If you type the `prolog' command, Prolog will output a + banner and prompt you for directives as follows: + + C-Prolog version 1.5 + | ?- + + There will be a pause between the first line and the prompt + while the system loads itself. It is possible to type ahead + during this period if you get impatient. + + If you give an argument to the `prolog' command, C- + Prolog will interpret it as the name of a file containing a + saved state created earlier, and will restore that saved + state. Saved states will be explained fully later. + + prolog prog (Restore "prog") + + + C-Prolog uses six major internal data areas: the _h_e_a_p, + the _g_l_o_b_a_l _s_t_a_c_k, the _l_o_c_a_l _s_t_a_c_k, the _t_r_a_i_l, the _a_t_o_m _a_r_e_a + and the _a_u_x_i_l_i_a_r_y _s_t_a_c_k. Although the system is initially + configured with reasonable allocations for each of those + areas, a particular program might exceed one of the alloca- + tions, causing an error message. Ideally, the system should + adjust the available storage among areas automatically, but + this facility is not implemented yet. Instead, the user may + specify when starting Prolog the allocations (in K bytes) + for some or all of the areas. This is done by giving command + line switches between the program name and the optional file + argument. For example, + + prolog -h 1000 -g 1000 -l 500 bigprogram + + specifies heap and global stack allocations of 1000 K and a + local stack allocation of 500 K. The full set of switches + is: + + + -h _N heap allocation is _N K bytes + -g _N global stack allocation is _N K bytes + -l _N local stack allocation is _N K bytes + -t _N trail allocation is _N K bytes + -a _N atom area allocation is _N K bytes + -x _N auxiliary stack allocation is _N K bytes + + + + + + + + + + + + +. + C-Prolog User's Manual 4 + + + _1._4. _R_e_a_d_i_n_g-_i_n _P_r_o_g_r_a_m_s + + A program is made up of a sequence of clauses, + possibly interspersed with directives to the inter- + preter. The clauses of a procedure do not have to be + immediately consecutive, but remember that their relative + order may be important. + + To input a program from a file _f_i_l_e, give the direc- + tive: + + | ?- [_f_i_l_e]. + + which will instruct the interpreter to consult the program. + The file specification _f_i_l_e must be a Prolog atom. It may + be any file name, note that if this file name contains char- + acters which are not normally allowed in an atom then it is + necessary to surround the whole file specification with sin- + gle quotes (since quoted atoms can include any character), + for example + + | ?- ['people/greeks']. + + The specified file is then read in. Clauses in the file are + stored in the database ready to be executed, while any + directives are obeyed as they are encountered. When the end + of the file is found, the interpreter displays on the ter- + minal the time spent in reading-in and the number of + bytes occupied by the program. + + In general, this directive can be any list of + filenames, such as: + + | ?- [myprogram, extras, testbits]. + + In this case all three files would be consulted. If a + filename is preceded by a minus sign, as in: + + | ?- [-testbits, -moreideas]. + + then that file is reconsulted. The difference between con- + sulting and reconsulting is important, and works as follows: + if a file is consulted then all the clauses in the file are + simply added to C-Prolog's database. If you consult the same + file twice then you will get two copies of all the clauses. + However, if a file is reconsulted then the clauses for all + the procedures in the file will replace any existing clauses + for those procedures, that is any such previously existing + clauses in the database get thrown away. Reconsulting is + useful for telling Prolog about corrections in your program. + + Clauses may also be typed in directly at the terminal. + To enter clauses at the terminal, you must give the + + + + + + + + + + +. + C-Prolog User's Manual 5 + + + directive: + + | ?- [user]. + + The interpreter is now in a state where it expects input of + clauses or directives. To get back to the top level of + the interpreter, type the END-OF-INPUT character. + + Typing clauses directly into C-Prolog is only recom- + mended if the clauses will not be needed permanently, + and are few in number. For significant bits of program you + should use an editor to produce a file containing the text + of the program. + + _1._5. _D_i_r_e_c_t_i_v_e_s: _Q_u_e_s_t_i_o_n_s _a_n_d _C_o_m_m_a_n_d_s + + When Prolog is at top level (signified by an initial + prompt of "| ?- ", with continuation lines prompted with + "| ", that is indented out from the left margin) it reads + in terms and treats them as directives to the interpreter to + try and satisfy some goals. These directives are called + questions. Remember that Prolog terms must terminate with a + period ("."), and that therefore Prolog will not execute + anything for you until you have typed the period (and then + END-OF-LINE) at the end of the directive. + + Suppose list membership has been defined by: + + member(X,[X|_]). + member(X,[_|L]) :- member(X,L). + + (Note the use of anonymous variables written "_"). + + If the goal(s) specified in a question can be satis- + fied, and if there are no variables as in this example: + + | ?- member(b,[a,b,c]). + + then the system answers + + yes + + and execution of the question terminates. + + If variables are included in the question, then the + final value of each variable is displayed (except for + anonymous variables). Thus the question + + | ?- member(X,[a,b,c]). + + would be answered by + + X = a + + + + + + + + + + +. + C-Prolog User's Manual 6 + + + At this point the interpreter is waiting for you to indicate + whether that solution is sufficient, or whether you want it + to backtrack to see if there are any more solutions. Simply + typing END-OF-LINE terminates the question, while typing ";" + followed by END-OF-LINE causes the system to backtrack look- + ing for alternative solutions. If no further solutions can + be found it outputs + + no + + The outcome of some questions is shown below, where a + number preceded by "_" is a system-generated name for a + variable. + + | ?- member(X,[tom,dick,harry]). + X = tom ; + X = dick ; + X = harry ; + no + | ?- member(X,[a,b,f(Y,c)]),member(X,[f(b,Z),d]). + Y = b, + X = f(b,c), + Z = c + % Just END-OF-LINE typed here + yes + | ?- member(X,[f(_),g]). + X = f(_1728) + yes + | ?- + + When C-Prolog reads terms from a file (or from the terminal + following a call to [user]), it treats them all as program + clauses. In order to get the interpreter to execute direc- + tives from a file they must be preceded by `?-', for ques- + tions, or `:-', for commands. + + Commands are like questions except that they do not + cause answers to be printed out. They always start with the + symbol ":-". At top level this is simply written after the + prompted "?-" which is then effectively overridden. Any + required output must be programmed explicitly; for example, + the command + + :- member(3,[1,2,3]), write(ok). + + directs the system to check whether 3 belongs to the list + [1,2,3], and to output "ok" if so. Execution of a command + terminates when all the goals in the command have been + successfully executed. Other alternative solutions + are not sought (one may imagine an implicit "cut" at the + end of the command). If no solution can be found, the + system gives: + + + + + + + + + + + +. + C-Prolog User's Manual 7 + + + ? + + as a warning. + + The main use for commands (as opposed to questions) is + to allow files to contain directives which call various pro- + cedures, but for which you don't want to have the answers + printed out. In such cases you only want to call the pro- + cedures for effect. A useful example would be the use of a + directive in a file which consults a whole list of other + files, such as[4]: + + :-([ bits, bobs, mainpart, testcases, data, junk ]). + + + If this directive was contained in the file `program' + then typing the following at top level would be a quick way + of loading your entire program: + + | ?- [program]. + + + When you are simply interacting with the top level of + the Prolog interpreter the distinction between questions and + commands is not very important. At the top level you should + normally only type questions. In a file, if you wish to exe- + cute some goals then you should use a command. That is, to + execute a directive in a file it must be preceded by ":-", + otherwise it will be treated as a clause. + + _1._6. _S_a_v_i_n_g _A _P_r_o_g_r_a_m + + Once a program has been read, the interpreter will have + available all the information necessary for its execution. + This information is called a program _s_t_a_t_e. + + The state of a program may be saved on a file for + future execution. To save a program into a file _f_i_l_e, per- + form the command: + + ?- save(_f_i_l_e). + + Save can be called at top level, from within a break level + (q.v.), or from anywhere within a program. + + ____________________ + [4]The extra parentheses, with the `:-' immediately next + to them, are currently essential due to a problem with pre- + fix operators (like `:-') and lists. They are not required + for commands that do not contain lists. This restriction + will be eventually removed. + + + + + + + + + + + + +. + C-Prolog User's Manual 8 + + + _1._7. _R_e_s_t_o_r_i_n_g _A _S_a_v_e_d _P_r_o_g_r_a_m + + Once a program has been saved into a file _f_i_l_e, C- + Prolog can be restored to this saved state by invoking it as + follows: + + prolog _f_i_l_e + + After execution of this command, the interpreter will be in + _e_x_a_c_t_l_y the same state as existed immediately prior to the + call to save, except for open files, which are automati- + cally closed by save. That is to say execution will start + at the goal immediately following the call to save, just as + if save had returned successfully. If you saved the state + at top level then you will be back at top level, but if you + explicitly called save from within your program then the + execution of your program will continue. + + Saved states can only be restored when C-Prolog is ini- + tially run from command level. Version 1.5 provides no way + of restoring a saved state from inside C-Prolog. + + Note that when a new version of C-Prolog is installed, + saved states created with the old version may become unus- + able. You are thus advised to rely on source files for your + programs and not on some gigantic saved state. + + _1._8. _P_r_o_g_r_a_m _E_x_e_c_u_t_i_o_n _A_n_d _I_n_t_e_r_r_u_p_t_i_o_n + + Execution of a program is started by giving the + interpreter a directive which contains a call to one of the + program's procedures. + + Only when execution of one directive is complete + does the interpreter become ready for another direc- + tive. However, one may interrupt the normal execution of a + directive by hitting the INTERRUPT key on your terminal. In + response to the prompt + + Action (h for help): + + you can type either "a", "t", "d" or "c" followed by END- + OF-LINE. The "a" response will force Prolog to abort back + to top level, the "t" option will switch on tracing, the "d" + response will switch on debugging and continue the execu- + tion, and the "c" response will just continue the execution. + + _1._9. _N_e_s_t_e_d _E_x_e_c_u_t_i_o_n_s -- _B_r_e_a_k _a_n_d _A_b_o_r_t + + C-Prolog provides a way to suspend the execution of + your program and to enter a new incarnation of the top level + where you can issue directives to solve goals etc. When the + evaluable predicate break is called, the message + + + + + + + + + + +. + C-Prolog User's Manual 9 + + + [ Break (level 1) ] + + will be displayed. This signals the start of a _b_r_e_a_k and + except for the effect of aborts (see below), it is as if + the interpreter was at top level. If break is called within + a break, then another recursive break is started (and the + message will say (level 2) etc). Breaks can be arbitrarily + nested. + + Typing the END-OF-INPUT character will close the + break and resume the execution which was suspended, + starting at the procedure call where the suspension took + place. + + To abort the current execution, forcing an immedi- + ate failure of the directive being executed and a return to + the top level of the interpreter, call the evaluable predi- + cate abort, either from the program or by executing the + directive: + + | ?- abort. + + within a break. In this case no END-OF-INPUT character is + needed to close the break, because _a_l_l break levels are dis- + carded and the system returns right back to top level. The + "a" response to INTERRUPT (described above) can also be used + to force an abort. + + _1._1_0. _E_x_i_t_i_n_g _F_r_o_m _T_h_e _I_n_t_e_r_p_r_e_t_e_r + + To exit from C-Prolog interpreter you should give the + directive: + + | ?- halt. + + This can be issued either at top level, or within a break, + or indeed from within your program. + + If your program is still executing then you should + interrupt it and abort to return to top level so that you + can call halt. + + Typing the END-OF-INPUT charater at top level also + causes C-Prolog to terminate. + + _2. _P_r_o_l_o_g _S_y_n_t_a_x + + _2._1. _T_e_r_m_s + + The data objects of the language are called _t_e_r_ms. A + term is either a _c_o_n_s_t_a_n_t, a _v_a_r_i_a_b_l_e or a _c_o_m_p_o_u_n_d _t_e_r_m. + + + + + + + + + + + + +. + C-Prolog User's Manual 10 + + + The constants include _n_u_m_b_e_rs such as + + 0 -999 -5.23 0.23E-5 + + + Constants also include _a_t_o_ms such as + + a void = := 'Algol-68' [] + + The symbol for an atom can be any sequence of characters, + written in single quotes if there is possibility of confu- + sion with other symbols (such as variables or numbers). As + in other programming languages, constants are definite + elementary objects. + + Variables are distinguished by an initial capital + letter or by the initial character "_", for example + + X Value A A1 _3 _RESULT + + If a variable is only referred to once, it does not need to + be named and may be written as an _a_n_o_n_y_m_o_u_s variable, + indicated by the underline character "_". + + A variable should be thought of as standing for some + definite but unidentified object. A variable is not + simply a writeable storage location as in most pro- + gramming languages; rather it is a local name for some data + object, cf. the variable of pure LISP and constant + declarations in Pascal. + + The structured data objects of the language are the + compound terms. A compound term comprises a _f_u_n_c_t_o_r (called + the _p_r_i_n_c_i_p_a_l functor of the term) and a sequence of one or + more terms called _a_r_g_u_m_e_n_t_s. A functor is characterised by + its _n_a_m_e, which is an atom, and its _a_r_i_t_y or number of argu- + ments. For example the compound term whose functor is named + `point' of arity 3, with arguments X, Y and Z, is written + + point(X,Y,Z) + + An atom is considered to be a functor of arity 0. + + One may think of a functor as a record type and + the arguments of a compound term as the fields of a + record. Compound terms are usefully pictured as trees. + For example, the term + + s(np(john),vp(v(likes),np(mary))) + + would be pictured as the structure + + + + + + + + + + + + +. + C-Prolog User's Manual 11 + + + s + / \ + np vp + | / \ + john v np + | | + likes mary + + + Sometimes it is convenient to write certain functors as + _o_p_e_r_a_t_o_r_s -- 2-ary functors may be declared as _i_n_f_i_x opera- + tors and 1-ary functors as _p_r_e_f_i_x or _p_o_s_t_f_i_x operators. + Thus it is possible to write + + X+Y (P;Q) X ]). + :- op( 1200, fx, [ :-, ?- ]). + :- op( 1100, xfy, [ ; ]). + :- op( 1050, xfy, [ -> ]). + :- op( 1000, xfy, [ ',' ]). /* See note below */ + :- op( 900, fy, [ not, \+, spy, nospy ]). + :- op( 700, xfx, [ =, is, =.., ==, \==, @<, @>, @=<, @>=, + =:=, =\=, <, >, =<, >= ]). + :- op( 500, yfx, [ +, -, /\, \/ ]). + :- op( 500, fx, [ +, - ]). + :- op( 400, yfx, [ *, /, //, <<, >> ]). + :- op( 300, xfx, [ mod ]). + :- op( 200, xfy, [ ^ ]). + + + + + + + + + + + +. + C-Prolog User's Manual 15 + + + Operator declarations are most usefuly placed in direc- + tives at the top of your program files. In this case the + directive should be a command as shown above. Another common + method of organisation is to have one file just containing + commands to declare all the necessary operators. This file + is then always consulted first. + + Note that a comma written literally as a punctuation + character can be used as though it were an infix operator of + precedence 1000 and type `xfy': + + X,Y ','(X,Y) + + represent the same compound term. But note that a comma + written as a quoted atom is _n_o_t a standard operator. + + Note also that the arguments of a compound term + written in standard syntax must be expressions of pre- + cedence _b_e_l_o_w 1000. Thus it is necessary to bracket the + expression "P:-Q" in + + assert((P:-Q)) + + The following syntax restrictions serve to remove potential + ambiguity associated with prefix operators. + + - In a term written in standard syntax, the principal + functor and its following "(" must _n_o_t be + separated by any blankspace. Thus + + point (X,Y,Z) + + is invalid syntax. + + - If the argument of a prefix operator starts with a "(", + this "(" must be separated from the operator by at + least one space or other non-printable character. Thus + + :-(p;q),r. + + (where `:-' is the prefix operator) is invalid syntax, + and must be written as + + :- (p;q),r. + + + - If a prefix operator is written without an argu- + ment, as an ordinary atom, the atom is treated + as an expression of the same precedence as the prefix + operator, and must therefore be bracketed where + necessary. Thus the brackets are necessary in + + X = (?-) + + + + + + + + + + +. + C-Prolog User's Manual 16 + + + _2._3. _S_y_n_t_a_x _E_r_r_o_r_s + + Syntax errors are detected when reading. Each + clause, directive or in general any term read-in by the + evaluable predicate read that fails to comply with syntax + requirements is displayed on the terminal as soon as it + is read. A mark indicates the point in the string of sym- + bols where the parser has failed to continue its analysis. + For example, typing + + member(X,X L). + + gives: + + ***syntax error*** + member(X,X + ***here*** + L). + + + Syntax errors do not disrupt the (re)consulting of a + file in any way except that the clause or command with the + syntax error will be ignored[5] All the other clauses in the + file will have been read-in properly. If the syntax error + occurs at top level then you should just retype the ques- + tion. Given that Prolog has a very simple syntax it is usu- + ally quite straightforward to see what the problems is (look + for missing brackets in particular). The book _P_r_o_g_r_a_m_m_i_n_g + _i_n _P_r_o_l_o_g gives further examples. + + _2._4. _U_s_i_n_g _a _T_e_r_m_i_n_a_l _w_i_t_h_o_u_t _L_o_w_e_r-_C_a_s_e + + The syntax of Prolog assumes that a full ASCII charac- + ter set is available. With this _f_u_l_l _c_h_a_r_a_c_t_e_r _s_e_t or `LC' + convention, variables are (normally) distinguished by an + initial capital letter, while atoms and other functors + must start with a lower-case letter (unless enclosed in sin- + gle quotes). + + When lower-case is not available, the _n_o _l_o_w_e_r-_c_a_s_e or + `NOLC' convention has to be adopted. With this convention, + variables must be distinguished by an initial underline + character "_", and the names of atoms and other functors, + which now have to be written in upper-case, are implicitly + translated into lower-case (unless enclosed in single + quotes). For example, + + _VALUE2 + + ____________________ + [5]After all, it could not be read. + + + + + + + + + + + + +. + C-Prolog User's Manual 17 + + + is a variable, while + + VALUE2 + + is `NOLC' convention notation for the atom which is identi- + cal to: + + value2 + + written in the `LC' convention. + + The default convention is `LC'. To switch to the no + lower-case convention, call the evaluable predicate `NOLC': + + | ?- 'NOLC'. + + To switch back to the full character set convention, + call the evaluable predicate `LC': + + | ?- 'LC'. + + + Note that the names of these two procedures consist of + upper-case letters (so that they can be referred to + on all devices), and therefore the names must _a_l_w_a_y_s be + enclosed in single quotes. + + It is recommended that the `NOLC' convention only be + used in emergencies, since the standard syntax is far easier + to use and is also easier for other people to read. + + _3. _T_h_e _M_e_a_n_i_n_g _o_f _P_r_o_l_o_g _P_r_o_g_r_a_m_s + + _3._1. _P_r_o_g_r_a_m_s + + A fundamental unit of a logic program is the _l_i_t_e_r_a_l, + for instance + + gives(tom,apple,teacher) reverse([1,2,3],L) X/ + is used, for example concatenate/3. + + Certain predicates are predefined by procedures sup- + plied by the Prolog system. Such predicates are called + _e_v_a_l_u_a_b_l_e _p_r_e_d_i_c_a_t_e_s. + + As we have seen, the goals in the body of a clause are + linked by the operator `,' which can be interpreted as + conjunction ("and"). It is sometimes convenient to use + an additional operator `;', standing for disjunction ("or") + (The precedence of `;' is such that it dominates `,' but is + dominated by `:-'.). An example is the clause. + + + + + + + + + + + +. + C-Prolog User's Manual 20 + + + grandfather(X,Z) :- (mother(X,Y); father(X,Y)), father(Y,Z). + + which can be read as + + "For any X, Y and Z, X has Z as a grandfather if either the mother + of X is Y or the father of X is Y, and the father of Y is Z." + + Such uses of disjunction can always be eliminated by + defining an extra predicate - for instance the previous + example is equivalent to + + grandfather(X,Z) :- parent(X,Y), father(Y,Z). + parent(X,Y) :- mother(X,Y). + parent(X,Y) :- father(X,Y). + + and so disjunction will not be mentioned further in the + following, more formal, description of the semantics of + clauses. + + _3._2. _D_e_c_l_a_r_a_t_i_v_e _a_n_d _P_r_o_c_e_d_u_r_a_l _S_e_m_a_n_t_i_c_s + + The semantics of definite clauses should be fairly + clear from the informal interpretations already given. + However it is useful to have a precise definition. + The _d_e_c_l_a_r_a_t_i_v_e_s_e_m_a_n_t_i_c_s of definite clauses tells us which + goals can be considered true according to a given program, + and is defined recursively as follows. + + A goal is _t_r_u_e if it is the head of some clause + instance and each of the goals (if any) in the body + of that clause _i_n_s_t_a_n_c_e is true, where an instance + of a clause (or term) is obtained by substituting, + for each of zero or more of its variables, a new + term for all occurrences of the variable. + + For example, if a program contains the preceding pro- + cedure for concatenate, then the declarative semantics tells + us that + + concatenate([a],[b],[a,b]) + + is true, because this goal is the head of a certain + instance of the first clause for concatenate, namely, + + concatenate([a],[b],[a,b]) :- concatenate([],[b],[b]). + + and we know that the only goal in the body of this + clause instance is true, since it is an instance of the unit + clause which is the second clause for concatenate. + + The declarative semantics makes no reference to the + sequencing of goals within the body of a clause, nor to the + sequencing of clauses within a program. This + + + + + + + + + + +. + C-Prolog User's Manual 21 + + + sequencing information is, however, very relevant for + the _p_r_o_c_e_d_u_r_a_l _s_e_m_a_n_t_i_c_s which Prolog gives to definite + clauses. The procedural semantics defines exactly how + the Prolog system will execute a goal, and the sequencing + information is the means by which the Prolog programmer + directs the system to execute his program in a sensible + way. The effect of executing a goal is to enumerate, one by + one, its true instances. Here then is an informal defini- + tion of the procedural semantics. + + To execute a goal, the system searches forwards from + the beginning of the program for the first clause + whose head _m_a_t_c_h_e_s or _u_n_i_f_i_e_s with the goal. The + unification process finds the most general common + instance of the two terms, which is unique if it ex- + ists. If a match is found, the matching + clause instance is then activated by executing in + turn, from left to right, each of the goals (if + any) in its body. If at any time the system fails + to find a match for a goal, it _b_a_c_k_t_r_a_c_k_s, that is + it rejects the most recently activated clause, + undoing any substitutions made by the match + with the head of the clause. Next it reconsiders + the original goal which activated the rejected + clause, and tries to find a subsequent clause + which also matches the goal. + + For example, if we execute the goal in the query + + :- concatenate(X,Y,[a,b]). + + we find that it matches the head of the first clause for + concatenate, with X instantiated to [a|X1]. The new variable + X1 is constrained by the new goal produced, which is + the recursive procedure call + + concatenate(X1,Y,[b]) + + Again this goal matches the first clause, instantiat- + ing X1 to [b|X2], and yielding the new goal + + concatenate(X2,Y,[]) + + Now this goal will only match the second clause, instantiat- + ing both X2 and Y to []. Since there are no further goals to + be executed, we have a solution + + X = [a,b] + Y = [] + + representing a true instance of the original goal + + concatenate([a,b],[],[a,b]) + + + + + + + + + + +. + C-Prolog User's Manual 22 + + + If this solution is rejected, backtracking will generate the + further solutions + + X = [a] + Y = [b] + + X = [] + Y = [a,b] + + in that order, by rematching, against the second clause for + concatenate, goals already solved once using the first + clause. + + _3._3. _O_c_c_u_r_s _C_h_e_c_k + + Prolog's unification does not have an _o_c_c_u_r_s _c_h_e_c_k, + i.e. when unifying a variable against a term the system + does not check whether the variable occurs in the term. + When the variable occurs in the term, unification should + fail, but the absence of the check means that the unifica- + tion succeeds, producing a _c_i_r_c_u_l_a_r _t_e_r_m. Trying to print a + circular term, or trying to unify two circular terms, + will cause an infinite loop and possibly make Prolog run out + of stack space. + + The absence of the occur check is not a bug or + design oversight, but a conscious design decision. + The reason for this decision is that unification with the + occur check is at best linear on the sum of the sizes of + the terms being unified, whereas unification without + the occur check is linear on the size of the smallest of the + terms being unified. In any practical programming + language, basic operations are supposed to take constant + time. Unification against a variable should be thought of + as the basic operation of Prolog, but this can take constant + time only if the occur check is omitted. Thus the absence + of a occur check is essential to make Prolog into a practi- + cal programming language. The inconvenience caused by this + restriction seems in practice to be very slight. Usually, + the restriction is only felt in toy programs. + + _3._4. _T_h_e _C_u_t _S_y_m_b_o_l + + Besides the sequencing of goals and clauses, Prolog + provides one other very important facility for specifying + control information. This is the _c_u_t symbol, written "!". + It is inserted in the program just like a goal, but is not + to be regarded as part of the logic of the program and + should be ignored as far as the declarative semantics is + concerned. + + The effect of the cut symbol is as follows. When + first encountered as a goal, cut succeeds immediately. If + + + + + + + + + + +. + C-Prolog User's Manual 23 + + + backtracking should later return to the cut, the effect is + to fail the _p_a_r_e_n_t _g_o_a_l, the goal which matched the head of + the clause containing the cut, and caused the clause to be + activated. In other words, the cut operation commits the + system to all choices made since the parent goal was + invoked, and causes other alternatives to be discarded. The + goals thus rendered _d_e_t_e_r_m_i_n_a_t_e are the parent goal + itself, any goals occurring before the cut in the + clause containing the cut, and any subgoals which were exe- + cuted during the execution of those preceding goals. + + For example, the procedure + + member(X,[X|L]). + member(X,[Y|L]) :- member(X,L). + + can be used to test whether a given term is in a list, and + the goal + + :- member(b,[a,b,c]). + + will succeed. The procedure can also be used to extract + elements from a list, as in + + :- member(X,[d,e,f]). + + With backtracking this will successively return each ele- + ment of the list. Now suppose that the first clause had + been written instead: + + member(X,[X|L]) :- !. + + In this case, the above call would extract only the first + element of the list (`d'). On backtracking, the cut would + immediately fail the whole procedure. + + A procedure of the form + + _x :- _p, !, _q. + _x :- _r. + + is similar to + + _x := if _p then _q else _r; + + in an Algol-like language. + + A cut discards all the alternatives since the parent + goal, even when the cut appears within a disjunction. + This means that the normal method for eliminating a + disjunction by defining an extra predicate cannot be applied + to a disjunction containing a cut. + + + + + + + + + + + +. + C-Prolog User's Manual 24 + + + _4. _D_e_b_u_g_g_i_n_g _F_a_c_i_l_i_t_i_e_s + + This section describes the debugging facilities + that are available in C-Prolog. The purpose of these facil- + ities is to provide information concerning the control + flow of your program. The main features of the debug- + ging package are as follows: + + - The _P_r_o_c_e_d_u_r_e _b_o_x model of Prolog execution which pro- + vides a simple way of visualising control flow, + especially during backtracking. Control flow is viewed + at the procedure level, rather than at the level of + individual clauses. + + - The ability to exhaustively trace your program or to + selectively set _s_p_y _p_o_i_n_t_s. Spy points allow you to + nominate interesting procedures at which the program + is to pause so that you can interact. + + - The wide choice of control and information options + available during debugging. + + Much of the information in this chapter is similar but + not identical to that of Chapter 8 of _P_r_o_g_r_a_m_m_i_n_g _i_n _P_r_o_l_o_g. + + _4._1. _T_h_e _P_r_o_c_e_d_u_r_e _B_o_x _C_o_n_t_r_o_l _F_l_o_w _M_o_d_e_l + + During debugging the interpreter prints out a + sequence of goals in various states of instantiation in + order to show the state the program has reached in its + execution. However, in order to understand what is + occurring it is necessary to understand when and why the + interpreter prints out goals. As in other programming + languages, key points of interest are procedure entry and + return, but in Prolog there is the additional complexity of + backtracking. One of the major confusions that novice + Prolog programmers have to face is the question of what + actually happens when a goal fails and the system sud- + denly starts backtracking. The Procedure Box model of Pro- + log execution views program control flow in terms of move- + ment about the program text. This model provides a basis + for the debugging mechanism in the interpreter, and enables + the user to view the behaviour of his program in a con- + sistent way. + + Let us look at an example Prolog procedure: + + + + + + + + + + + + + + + + + +. + C-Prolog User's Manual 25 + + + *--------------------------------------* + Call | | Exit + ---------> + descendant(X,Y) :- offspring(X,Y). + ---------> + | | + | descendant(X,Z) :- | + <--------- + offspring(X,Y), descendant(Y,Z). + <--------- + Fail | | BackTo + *--------------------------------------* + + The first clause states that Y is a descendant of X if Y is + an offspring of X, and the second clause states that Z is a + descendant of X if Y is an offspring of X and if Z is a + descendant of Y. In the diagram a box has been drawn around + the whole procedure and labelled arrows indicate the control + flow in and out of this box. There are four such arrows + which we shall look at in turn. + + Call + + This arrow represents initial invocation of the pro- + cedure. When a descendant goal of the form + descendant(X,Y) is required to be satisfied, control + passes through the Call _p_o_r_t of the descendant box with + the intention of matching a component clause and then + satisfying any subgoals in the body of that + clause. Notice that this is independent of whether + such a match is possible, that is first the box is + called, and then the attempt to match takes place. + Textually we can imagine moving to the code for descen- + dant when meeting a call to descendant in some other + part of the code. + + Exit + + This arrow represents a successful return from the pro- + cedure. This occurs when the initial goal has + been unified with one of the component clauses and any + subgoals have been satisfied. Control now passes + out of the Exit port of the descendant box. Textually + we stop following the code for descendant and go back + to the place we came from. + + BackTo + + This arrow indicates that a subsequent goal has failed + and that the system has come back to this goal in an + attempt to match the goal against another clause. + Control passes through the BackTo port of the des- + cendant box in an attempt to rematch the original goal + with an alternative clause and then try to satisfy + any subgoals in the body of this new clause. Textu- + ally we follow the code backwards up the way we + came looking for new ways of succeeding, possibly + + + + + + + + + + +. + C-Prolog User's Manual 26 + + + dropping down on to another clause and following + that if necessary. Note that this is somewhat less + informative than the Redo port described in _P_r_o_g_r_a_m_m_i_n_g + _i_n _P_r_o_l_o_g, because it does not show the path in the + program from a failed goal back to the first goal where + alternative clauses exist, but only this goal. + + Fail + + This arrow represents a failure of the initial goal, + which might occur if no clause is matched, or if + subgoals are never satisfied, or if any solution pro- + duced is always rejected by later processing. Control + now passes out of the Fail port of the descendant box + and the system continues to backtrack. Textually we + move back to the code which called this procedure and + keep moving backwards up the code looking for choice + points. + + In terms of this model, the information we get about + the procedure box is only the control flow through these + four ports. This means that at this level we are not + concerned with which clause matches, and how any + subgoals are satisfied, but rather we only wish to know the + initial goal and the final outcome. However, it can be + seen that whenever we are trying to satisfy subgoals, what + we are actually doing is passing through the ports of + _t_h_e_i_r respective boxes. If we were to follow this, + then we would have complete information about the control + flow inside the procedure box. + + Note that the box we have drawn round the procedure should + really be seen as an _i_n_v_o_c_a_t_i_o_n _b_o_x. That is, there will be + a different box for each different invocation of the + procedure. Obviously, with something like a recursive + procedure, there will be many different Calls and Exits + in the control flow, but these will be for different invoca- + tions. Since this might get confusing each invocation box + is given a unique integer identifier. + + _4._2. _B_a_s_i_c _D_e_b_u_g_g_i_n_g _P_r_e_d_i_c_a_t_e_s + + The interpreter provides a range of evaluable + predicates for control of the debugging facilities. The + most basic predicates are as follows: + + debug + + Switches _d_e_b_u_g _m_o_d_e on. (It is initially off.) In + order for the full range of control flow infor- + mation to be available it is necessary to have this + on from the start. When it is off the system + does not remember invocations that are being + + + + + + + + + + +. + C-Prolog User's Manual 27 + + + executed. (This is because it is expensive and not + required for normal running of programs.) You can + switch debug mode on in the middle of execution, either + from within your program or after an interrupt (see + trace below), but information prior to this will + just be unavailable. + + nodebug + + switches debug mode off. If there are any spy points + set then they will be removed. + + debugging + + prints onto the terminal information about the + current debugging state. It shows whether debug mode + is on or off and gives various other information to be + described later. + + _4._3. _T_r_a_c_i_n_g + + The following evaluable predicate may be used to com- + mence an exhaustive trace of a program. + + trace + + Switches debug mode on, if it is not on already, and + ensures that the next time control enters a procedure + box, a message will be produced and you will be + asked to interact. + + When stopped at a goal being traced, you have a number + of options which will be detailed later. In particular, you + can just type END-OF-LINE (carriage-return) to creep + (or single-step) into your program. If you continue to + creep through your program you will see every entry and exit + to/from every invocation box. However, you will notice + that you are only given the opportunity to interact on + Call and BackTo ports, i.e. a single creep decision may + take you through several Exit ports or several Fail + ports. Normally this is desirable, as it would be tedi- + ous to go through all those ports step by step. However, if + it is not what you want, the following evaluable predicate + gives full control over the ports at which you are + prompted. + + leash(_M_o_d_e) + + Sets the _l_e_a_s_h_i_n_g _m_o_d_e to _M_o_d_e, where _M_o_d_e can be one + of the following + + + full prompt on Call, Exit, BackTo and Fail + tight prompt on Call, BackTo and Fail + half prompt on Call and BackTo + loose prompt on Call + off never prompt + + + + + + +. + C-Prolog User's Manual 28 + + + or any other combination of ports as described later. + The initial _l_e_a_s_h_i_n_g _m_o_d_e is `half'. + + _4._4. _S_p_y _P_o_i_n_t_s + + For programs of any size, it is clearly impractical to + creep through the entire program. Spy points make it possi- + ble to stop the program whenever it gets to a particular + procedure which is of interest. Once there, one can set + further spy points in order to catch the control flow a + bit further on, or one can start creeping. + + Setting a spy-point on a procedure indicates that you + wish to see all control flow through the various ports + of its invocation boxes. When control passes through any + port of a procedure with a spy-point set on it, a message is + output and the user is asked to interact. Note that the + current mode of leashing does not affect spy points: user + interaction is requested on _e_v_e_r_y port. + + Spy points are set and removed by the following evalu- + able predicates which are also standard operators: + + spy _X + + Sets spy points on all the procedures given by _X. _X + is either a single predicate specification, or a list + of such specifications. A predicate specification + is either of the form /, which means the + procedure with the name and an arity of + (for example member/2, foo/0, hello/27), + or it is of the form , which means all the pro- + cedures with the name that currently have + clauses in the data-base (e.g. member, foo, hello). + This latter form may refer to multiple procedures + which have the same name but different arities. + If you use the form but there are no clauses for + this predicate (of any arity) then nothing will be + done. If you really want to place a spy point + on a currently non-existent procedure, then you must + use the full form /; you will get a warn- + ing message in this case. If you set some spy + points when debug mode is off then it will be + automatically switched on. + + nospy _X + + This reverses the effect of spy _X: all the procedures + given by _X will have previously set spy points removed + from them. + + The options available when you arrive at a spy-point + are described below. + + + + + + + + + + +. + C-Prolog User's Manual 29 + + + _4._5. _F_o_r_m_a_t _o_f _D_e_b_u_g_g_i_n_g _M_e_s_s_a_g_e_s + + We will now look at the exact format of the message + output by the system at a port. All trace messages are out- + put to the terminal regardless of where the current out- + put is directed. (This allows you to trace programs while + they are performing file I/O.) The basic format is as fol- + lows: + + ** (23) 6 Call : foo(hello,there,_123) ? + + The "**" indicates that this is a spy-point. If this + port is not for a procedure with a spy-point set, then + there will be two spaces there instead. If this port is the + requested return from a Skip then the second character + becomes ">". This gives four possible combinations: + + + "**" This is a spy-point. + "*>" + + This is a spy-point, and you also did a Skip last time you were in + this box. + " >" + + This is not a spy-point, but you did a Skip last time you were in + this box. + " " This is not a spy-point. + + + + The number in parentheses is the unique invocation + identifier. This is continuously incrementing regardless of + whether or not you are actually seeing the invocations + (provided that debug mode is on). This number can be used + to cross correlate the trace messages for the various ports, + since it is unique for every invocation. It will + also give an indication of the number of procedure calls + made since the start of the execution. The invocation + counter starts again for every fresh execution of a com- + mand, and it is also reset when retries (see later) are per- + formed. + + The number following this is the current depth, that + is, the number of direct ancestors this goal has. + + The next word specifies the particular port (Call, + Exit, BackTo or Fail). + + The goal is then printed so that you can inspect + its current instantiation state. + + The final "?" is the prompt indicating that you should + type in one of the option codes allowed (see next sec- + tion). If this particular port is unleashed then you will + obviously not get this prompt since you have specified that + you do not wish to interact at this point. + + + + + + + + + + +. + C-Prolog User's Manual 30 + + + Notice that not all procedure calls are traced; + there are a few basic procedures which have been made + invisible since it is more convenient not to see them. + These include all primitive I/O evaluable predicates (for + example get, put, read, write), all basic control structures + (that is, `,', `;', `->') and all debugging control + evaluable predicates (for instance, debug, spy, leash, + trace). This means that you will never see messages con- + cerning these predicates during debugging. + + _4._6. _O_p_t_i_o_n_s _A_v_a_i_l_a_b_l_e _d_u_r_i_n_g _D_e_b_u_g_g_i_n_g + + This section describes the particular options + that are available when the system prompts you after print- + ing out a debugging message. All the options are one letter + mnemonics. They are read from the terminal with any + blanks being completely ignored up to the next end of line. + The _c_r_e_e_p option needs only the new line. + + The only option which you really have to remember is "h". + This provides help in the form of the following list of + available options: + + + END-OF-LINE creep a abort + c creep f fail + l leap b break + s skip h help + r retry r retry goal + q quasi-skip n nodebug + g goal stack [ read clauses from terminal + e exit Prolog + + + The first three options are the basic control decisions: + + c, END-OF-LINE: Creep + + Causes the interpreter to single-step to the very next + port and print a message. Then if the port is + leashed the user is prompted for further interaction. + Otherwise it continues creeping. If leashing is off, + creep is the same as leap (see below) except that a + complete trace is printed on the terminal. + + l: Leap + + causes the interpreter to resume running your pro- + gram, only stopping when a spy-point is reached (or + when the program terminates). Leaping can thus be + used to follow the execution at a higher level + than exhaustive tracing. All you need to do is to + set spy points on an evenly spread set of pertinent + + + + + + + + + + +. + C-Prolog User's Manual 31 + + + procedures, and then follow the control flow through + these by leaping from one to the other. + + s: Skip + + Skip is only valid for Call and BackTo ports. It + skips over the entire execution of the procedure. + That is, you will not see anything until control comes + back to this procedure (at either the Exit port or + the Fail port). Skip is particularly useful + while creeping since it guarantees that control will be + returned after the (possibly complex) execution + within the box. If you skip then no message at all + will appear until control returns. This includes calls + to procedures with spy points set; they will be + masked out during the skip. There are two ways of + overriding this : there is a Quasi-skip which does not + ignore spy points, and the "t" option after an inter- + rupt will disable the masking. Normally, however, + this masking is just what is required! + + q: Quasi-skip + + Is like Skip except that it does not mask out spy + points. If there is a spy-point within the execution + of the goal then control returns at this point and + any action can be performed there. The initial skip + still guarantees an eventual return of control, + though, when the internal execution is finished. + + f: Fail + + Transfers to the Fail port of the current box. This + puts your execution in a position where it is about to + backtrack out of the current invocation, that is, + you have manually failed the initial goal. + + r: Retry + + Transfers to the Call port of the current goal, or if + given a numeric argument _n, to the Call port of the + invocation numbered _n. IF the invocation being retried + has been deleted by the cut control primitive, the most + recent active invocation before it will be retried. If + _n is out of range, the current invocation is retried. + This option is extremely useful to go back to an ear- + lier state of computation if some point of interest was + overshot in a debugging session. Note however that side + effects, such as database modification, are not undone. + + g: Goal Stack + + + + + + + + + + + + +. + C-Prolog User's Manual 32 + + + Shows the goal that called the current one, and the one + that called it, and so on, that is, the stack of pend- + ing goals. Goals are printed one per line, from the + most recent to the least recent. Each goal is labeled + by its recursion level _l, its invocation number _i and + the ordinal position _p of the clause currently used to + solve the goal. + + a: Abort + + Causes an abort of the current execution. All the + execution states built so far are destroyed and you are + put right back at the top level of the interpreter. + (This is the same as the evaluable predicate abort.) + + [: Read clauses from terminal + + starts reading clauses typed by the user as if doing a + _c_o_n_s_u_l_t(_u_s_e_r). An END-OF-INPUT returns to the + debugger. + + e: Exit from Prolog + + causes an irreversible exit from the Prolog system. + (This is the same as the evaluable predicate halt.) + + h: Help + + Displays the table of options given above. + + b: Break + + Calls the evaluable predicate break, thus putting + you at interpreter top level with the execution so far + sitting underneath you. When you end the break + with the END-OF-INPUT character, you will be + reprompted at the port at which you broke. The new + execution is completely separate from the suspended + one; the invocation numbers will start again from 1 + during the break. Debug mode is not switched off as + you call the break, but if you do switch it off + then it will be re-switched on when you finish the + break and go back to the old execution. However, any + changes to the leashing or to spy points will remain in + effect. + + n: Nodebug + + Turns off debug mode. Notice that this is the correct + way to switch debugging off at a trace point. You + cannot use the "b" option because it always restores + debug mode upon return. + + + + + + + + + + + +. + C-Prolog User's Manual 33 + + + _4._7. _R_e_c_o_n_s_u_l_t_i_n_g _d_u_r_i_n_g _D_e_b_u_g_g_i_n_g + + It is possible, and sometimes useful, to reconsult a + file whilst in the middle of a program execution. How- + ever this can lead to unexpected behaviour under the follow- + ing circumstances: a procedure has been successfully exe- + cuted; it is subsequently re-defined by a reconsult, + and is later re-activated by backtracking. When the + backtracking occurs, all the new clauses for the pro- + cedure appear to the interpreter to be potential alternative + solutions, even though identical clauses may already have + been used. Thus large amounts of (unwanted) activity takes + place on backtracking. The problem does not arise if you do + the reconsult when you are at the Call port of the pro- + cedure to be re-defined. + + _5. _E_v_a_l_u_a_b_l_e _P_r_e_d_i_c_a_t_e_s + + This section describes all the evaluable predicates + available in C-Prolog. These predicates are provided in + advance by the system and they cannot be redefined by the + user. Any attempt to add clauses or delete clauses to an + evaluable predicate fails with an error message, and leaves + the evaluable predicate unchanged. The C-Prolog provides a + fairly wide range of evaluable predicates to perform the + following tasks: + + Input/Output + Reading-in programs + Opening and closing files + Reading and writing Prolog terms + Getting and putting characters + Arithmetic + Affecting the flow of the execution + Classifying and operating on Prolog terms (meta-logical facilities) + Sets + Term Comparison + Manipulating the Prolog program database + Manipulating the additional indexed database + Debugging facilities + Environmental facilities + + The evaluable predicates will be described according to this + classification. Appendix I contains a complete list of the + evaluable predicates. + + _5._1. _I_n_p_u_t _a_n_d _O_u_t_p_u_t + + A total of 15 I/O streams may be open at any one time + for input and output. This includes a stream that is always + available for input and output to the user's terminal. A + stream to a file _F is opened for input by the first see(_F) + executed. _F then becomes the current input stream. + + + + + + + + + + +. + C-Prolog User's Manual 34 + + + Similarly, a stream to file _H is opened for output by the + first tell(_H) executed. _H then becomes the current output + stream. Subsequent calls to see(_F) or to tell(_H) make _F or + _H the current input or output stream, respectively. Any + input or output is always to the current stream. + + When no input or output stream has been specified, the + standard ersatz file `user', denoting the user's termi- + nal, is utilised for both. When the terminal is waiting for + input on a new line, a prompt will be displayed as follows: + + + "| ?- " interpreter waiting for command + "| " interpreter wating for command continuation line + "| " consult(user) wating for continuation line + "|:" default for waiting for other user input + + + When the current input (or output) stream is closed, the + user's terminal becomes the current input (or output) + stream. + + The only file that can be simultaneously open for + input and output is the ersatz file `user'. + + A file is referred to by its name, _w_r_i_t_t_e_n _a_s _a_n _a_t_o_m, + e.g. + + myfile + 'F123' + data_lst + 'tom/greeks' + + + All I/O errors normally cause an abort, except for the + effect of the evaluable predicate nofileerrors decribed + below. + + End of file is signalled on the user's terminal by typ- + ing the END-OF-INPUT character. Any more input requests + for a file whose end has been reached causes an error + failure. + + _5._1._1. _R_e_a_d_i_n_g-_i_n _P_r_o_g_r_a_m_s + + consult(_F) + + Instructs the interpreter to read-in the program which + is in file _F. When a directive is read it is immedi- + ately executed. When a clause is read it is put after + any clauses already read by the interpreter for that + procedure. + + + + + + + + + + + +. + C-Prolog User's Manual 35 + + + reconsult(_F) + + Like consult except that any procedure defined + in the reconsulted file erases any clauses for that + procedure already present in the interpreter. recon- + sult makes it possible to amend a program without hav- + ing to restart from scratch and consult all the files + which make up the program. + + [_F_i_l_e|_F_i_l_e_s] + + This is a shorthand way of consulting or reconsulting a + list of files. A file name may optionally be preceded + by the operator `-' to indicate that the file + should be reconsulted rather than consulted. + Thus + + | ?- [file1,-file2,file3]. + + is merely a shorthand for + + | ?- consult(file1), reconsult(file2), consult(file3). + + + _5._1._2. _F_i_l_e _H_a_n_d_l_i_n_g + + see(_F) + + File _F becomes the current input stream. + + seeing(_F) + + _F is unified with the name of the current input file. + + seen + + Closes the current input stream. + + tell(_F) + + File _F becomes the current output stream. + + telling(_F) + + _F is unified with the name of the current output file. + + told + + Closes the current output stream. + + close(_F) + + + + + + + + + + + + +. + C-Prolog User's Manual 36 + + + File _F, currently open for input or output, is closed. + + fileerrors + + Undoes the effect of nofileerrors. + + nofileerrors + + After a call to this predicate, the I/O error + conditions "incorrect file name ...", "can't see file + ...", "can't tell file ..." and "end of file ..." cause + a call to fail instead of the default action, which + is to type an error message and then call abort. + + exists(_F) + + Succeeds if the file F exists. + + rename(_F,_N) + + If File _F is renamed to _N. If _N is `[]', the file is + deleted. If _F was a currently open stream, it is + closed first. + + _5._1._3. _I_n_p_u_t _a_n_d _O_u_t_p_u_t _o_f _T_e_r_m_s + + read(_X) + + The next term, delimited by a full stop (i.e. a "." + followed by a carriage-return or a space), is read + from the current input stream and unified with _X. The + syntax of the term must accord with current operator + declarations. If a call read(_X) causes the end of the + current input stream to be reached, _X is unified with + the atom `end_of_file'. Further calls to read for + the same stream will then cause an error failure. + + write(_X) + + The term _X is written to the current output stream + according to operator declarations in force. + + display(_X) + + The term _X is displayed on the terminal in standard + parenthesised prefix notation. + + writeq(_T_e_r_m) + + Similar to write(_T_e_r_m), but the names of atoms and + functors are quoted where necessary to make the result + acceptable as input to read. + + + + + + + + + + + +. + C-Prolog User's Manual 37 + + + print(_T_e_r_m) + + Print _T_e_r_m onto the current output. This predicate + provides a handle for user defined pretty printing. If + _T_e_r_m is a variable then it is written, using + write(_T_e_r_m). If _T_e_r_m is non-variable then a call is + made to the user defined procedure portray(_T_e_r_m). If + this succeeds then it is assumed that _T_e_r_m has been + output. Otherwise print is equivalent to write. + + _5._1._4. _C_h_a_r_a_c_t_e_r _I_n_p_u_t/_O_u_t_p_u_t + + nl + + A new line is started on the current output stream. + + get0(_N) + + _N is the ASCII code of the next character from the + current input stream. If the current input stream + reaches its end of file, the ASCII character code for + control-Z is returned and the stream closed. + + get(_N) + + _N is the ASCII code of the next non-blank printable + character from the current input stream. It has the + same behaviour as get0 on end of file. + + skip(_N) + + Skips to just past the next ASCII character code _N + from the current input stream. _N may be an integer + expression. Skipping past the end of file causes an + error. + + put(_N) + + ASCII character code _N is output to the current output + stream. _N may be an integer expression. + + tab(_N) + + _N spaces are output to the current output stream. _N + may be an integer expression. + + _5._2. _A_r_i_t_h_m_e_t_i_c + + Arithmetic is performed by evaluable predicates which + take as arguments _a_r_i_t_h_m_e_t_i_c _e_x_p_r_e_s_s_i_o_n_s and _e_v_a_l_u_a_t_e + them. An arithmetic expression is a term built from + _e_v_a_l_u_a_b_l_e _f_u_n_c_t_o_r_s, numbers and variables. At the time + of evaluation, each variable in an arithmetic expression + + + + + + + + + + +. + C-Prolog User's Manual 38 + + + must be bound to a number or to an arithmetic expression. + The result of evaluation will always be converted back to an + integer if possible. + + Each evaluable functor stands for an arithmetic opera- + tion. The adjective "integer" in the descriptions below + means that the operation only makes sense for integers, and + will fail for floating point numbers. + + Because arithmetic expressions are compound terms, they + use up storage that is only recovered on backtracking. The + evaluable predicate expanded_exprs can be used to avoid this + overhead by preexpanding arithmetic expressions into calls + to arithmetic evaluation predicates. However, this makes + program read-in slower and clauses bigger. + + In general, an arithmetic operation that combines + integers and floating point numbers will return a floating + point number. However, if the result is integral, it is + converted back to integer representation, and the same + applies to numbers read in by the reader. Thus, the goal + + | ?- p(2.0). + + will succeed with the clause + + p(2). + + and the result of the query + + | ?- X is 2*1.5. + + is + + X = 5 + + + Numbers may be integers + + -33 0 9999 + + or floating point numbers + + 1.333 -2.6E+7 0.555E-2 + + + Note that the decimal "." cannot be confused with the + end of clause because the latter must be followed by blank + space (space, tab or END-OF-LINE). However, if an operator + "." is declared as infix, it will only be possible to apply + it to two numbers if they are separated by blank space from + the operator. + + + + + + + + + + + +. + C-Prolog User's Manual 39 + + + The evaluable functors are as follows, where _X + and _Y are arithmetic expressions. + + _X+_Y + + addition + + _X-_Y + + subtraction + + _X*_Y + + multiplication + + _X/_Y + + division + + _X//_Y + + integer division + + _X mod _Y + + _X (integer) modulo _Y + + -_X + + unary minus + + exp(_X) + + exponential function + + log(_X) + + natural logarithm + + log10(_X) + + base 10 logarithm + + sqrt(_X) + + square root + + sin(_X) + + sine + + cos(_X) + + + + + + + + + + + +. + C-Prolog User's Manual 40 + + + cosine + + tan(_X) + + tangent + + asin(_X) + + arc sine + + acos(_X) + + arc cosine + + atan(_X) + + arc tangent + + floor(_X) + + the largest integer not greater than _X + + _X^_Y + + _X to the power _Y + + _X/\_Y + + integer bitwise conjunction + + _X/_Y + + integer bitwise disjunction + + _X<<_Y + + integer bitwise left shift of _X by _Y places + + _X>>_Y + + integer bitwise right shift of _X by _Y places + + \_X + + integer bitwise negation + + cputime + + CPU time since C-Prolog was started, in seconds. + + heapused + + + + + + + + + + + + +. + C-Prolog User's Manual 41 + + + Heap space in use, in bytes. + + [_X] + + (a list of just one element) evaluates to _X if _X is an + integer. Since a quoted string is just a list of + integers, this allows a quoted character to be used in + place of its ASCII code; e.g. "A" behaves within arith- + metic expressions as the integer 65. + + The arithmetic evaluable predicates are as follows, + where _X and _Y stand for arithmetic expressions, and _Z for + some term. Note that this means that is only evaluates one + of its arguments as an arithmetic expression (the right-hand + side one), whereas all the comparison predicates evaluate + both their arguments. + + _Z is _X + + Arithmetic expression _X is evaluated and the result, is + unified with _Z. Fails if _X is not an arithmetic expres- + sion. + + _X =:= _Y + + The values of _X and _Y are equal. + + _X == _Y + + The values of _X and _Y are not equal. + + _X < _Y + + The value of _X is less than the value of _Y. + + _X > _Y + + The value of _X is greater than the value of _Y. + + _X =< _Y + + The value of _X is less than or equal to the value of _Y. + + _X >= _Y + + The value of _X is greater than or equal to the value of + _Y. + + expanded_exprs(_O_l_d,_N_e_w) + + Unifies _O_l_d to the current value of the expression + expansion flag, and sets the value of the flag to _N_e_w. + The possible values of the flag are `off' (the default) + + + + + + + + + + +. + C-Prolog User's Manual 42 + + + for not expanding arithmetic expressions into procedure + calls, and `on' to do the expansion. + + _5._3. _C_o_n_v_e_n_i_e_n_c_e + + _P , _Q + + _P and _Q. + + _P ; _Q + + _P or _Q. + + true + + Always succeeds. + + _X = _Y + + Defined as if by the clause " Z=Z. ", that is _X and _Y + are unified. + + _5._4. _E_x_t_r_a _C_o_n_t_r_o_l + + ! + + Cut (discard) all choice points made since the parent + goal started execution. + + \+ _P + + If the goal _P has a solution, fail, otherwise + succeed. It is defined as if by + + \+(P) :- P, !, fail. + \+(_). + + + _P -> _Q ; _R + + Analogous to + + "if _P then _Q else _R" + + i.e. defined as if by + + P -> Q; R :- P, !, Q. + P-> Q; R :- R. + + + _P -> _Q + + + + + + + + + + + + +_. + C-Prolog User's Manual 43 + + + When occurring other than as one of the alterna- + tives of a disjunction, is equivalent to + + _P -> _Q; fail. + + + repeat + + Generates an infinite sequence of backtracking + choices. It behaves as if defined by the clauses: + + repeat. + repeat :- repeat. + + + fail + + Always fails. + + _5._5. _M_e_t_a-_L_o_g_i_c_a_l + + var(_X) + + Tests whether _X is currently instantiated to a vari- + able. + + nonvar(_X) + + Tests whether _X is currently instantiated to a non- + variable term. + + atom(_X) + + Checks that _X is currently instantiated to an atom + (i.e. a non-variable term of arity 0, other than a + number or database reference). + + number(_X) + + Checks that _X is currently instantiated to a number. + + integer(_X) + + Checks that _X is currently instantiated to an integer. + + atomic(_X) + + Checks that _X is currently instantiated to an atom, + number or database reference. + + primitive(_X) + + + + + + + + + + + + +. + C-Prolog User's Manual 44 + + + Checks that _X is currently instantiated to a number or + database reference. + + db_reference(_X) + + Checks that _X is currently instantiated to a database + reference. + + functor(_T,_F,_N) + + The principal functor of term _T has name _F and arity _N, + where _F is either an atom or, provided _N is 0, a + number. Initially, either _T must be instantiated to a + non-variable, or _F and _N must be instantiated to, + respectively, either an atom and a non-negative + integer or an integer and 0. If these conditions are + not satisfied, an error message is given. In the case + where _T is initially instantiated to a variable, the + result of the call is to instantiate _T to the most + general term having the principal functor indicated. + + arg(_I,_T,_X) + + Initially, _I must be instantiated to a positive integer + and _T to a compound term. The result of the call is + to unify _X with the _Ith argument of term _T. (The + arguments are numbered from 1 upwards.) If the ini- + tial conditions are not satisfied or _I is out of range, + the call merely fails. + + _X =.. _Y + + _Y is a list whose head is the atom corresponding to the + principal functor of _X and whose tail is the argument + list of that functor in _X. E.g. + + product(0,N,N-1) =.. [product,0,N,N-1] + + N-1 =.. [-,N,1] + + product =.. [product] + + If _X is instantiated to a variable, then _Y must be + instantiated either to a list of determinate length + whose head is an atom, or to a list of length 1 whose + head is a number. + + name(_X,_L) + + If _X is an atom or a number then _L is a list of the + ASCII codes of the characters comprising the name of _X. + E.g. + + + + + + + + + + + +. + C-Prolog User's Manual 45 + + + name(product,[112,114,111,100,117,99,116]) + + i.e. name(product,"product") + + name(1976,[49,57,55,54]) + + name(hello,[104,101,108,108,111]) + + name([],"[]") + + If _X is instantiated to a variable, _L must be instan- + tiated to a list of ASCII character codes. E.g. + + | ?- name(X,[104,101,108,108,111])). + + X = hello + + | ?- name(X,"hello"). + + X = hello + + + call(_X) + + If _X is instantiated to a term which would be accept- + able as body of a clause, the goal call(_X) is exe- + cuted exactly as if that term appeared textually in + place of the call(_X), except that any cut ("!") occur- + ring in _X will remove only those choice points in _X. + If _X is not instantiated as described above, an error + message is printed and call fails. + + _X + + (where _X is a variable) Exactly the same as call(_X). + + _5._6. _S_e_t_s + + When there are many solutions to a problem, and when + all those solutions are required to be collected + together, this can be achieved by repeatedly back- + tracking and gradually building up a list of the solutions. + The following evaluable predicates are provided to automate + this process. + + setof(_X,_P,_S) + + Read this as "_S is the set of all instances of _X such that + _P is provable, where that set is non-empty". The term + _P specifies a goal or goals as in call(_P). _S is a set of + terms represented as a list of those terms, without dupli- + cates, in the standard order for terms (see Section 5.3). + If there are no instances of _X such that _P is satisfied + + + + + + + + + + +. + C-Prolog User's Manual 46 + + + then the predicate fails. + + The variables appearing in the term _X should not appear + anywhere else in the clause except within the term _P. Obvi- + ously, the set to be enumerated should be finite, and should + be enumerable by Prolog in finite time. It is possi- + ble for the provable instances to contain variables, but in + this case the list _S will only provide an imperfect + representation of what is in reality an infinite set. + + If there are uninstantiated variables in _P which do not also + appear in _X, then a call to this evaluable predicate + may backtrack, generating alternative values for _S + corresponding to different instantiations of the free vari- + ables of _P. (It is to cater for such usage that the + set S is constrained to be non-empty.) For example, the + call: + + | ?- setof(X, X likes Y, S). + + might produce two alternative solutions via backtracking: + + Y = beer, S = [dick, harry, tom] + Y = cider, S = [bill, jan, tom ] + + The call: + + | ?- setof((Y,S), setof(X, X likes Y, S), SS). + + would then produce: + + SS = [ (beer,[dick,harry,tom]), (cider,[bill,jan,tom]) ] + + + Variables occurring in _P will not be treated as free if + they are explicitly bound within _P by an existential + quantifier. An existential quantification is written: + + _Y^_Q + + meaning "there exists a _Y such that _Q is true", where _Y is + some Prolog variable. For example: + + | ?- setof(X, Y^(X likes Y), S). + + would produce the single result: + + X = [bill, dick, harry, jan, tom] + + in contrast to the earlier example. + + bagof(_X,_P,_B_a_g) + + + + + + + + + + + +. + C-Prolog User's Manual 47 + + + This is exactly the same as setof except that + the list (or alternative lists) returned will not be + ordered, and may contain duplicates. The effect of + this relaxation is to save considerable time and space + in execution. + + _X^_P + + The interpreter recognises this as meaning "there + exists an _X such that _P is true", and treats it as + equivalent to call(_P). The use of this explicit + existential quantifier outside the setof and bagof con- + structs is superfluous. + + _5._7. _C_o_m_p_a_r_i_s_o_n _o_f _T_e_r_m_s + + These evaluable predicates are meta-logical. + They treat uninstantiated variables as objects with + values which may be compared, and they never instan- + tiate those variables. They should _n_o_t be used when what + you really want is arithmetic comparison (Section 5.2) or + unification. + + The predicates make reference to a standard total + ordering of terms, which is as follows: + + - variables, in a standard order (roughly, oldest first - + the order is _n_o_t related to the names of variables); + + - Database references, roughly in order of age; + + - numbers, from -"infinity" to +"infinity"; + + - atoms, in alphabetical (i.e. ASCII) order; + + - complex terms, ordered first by arity, then by the + name of principal functor, then by the arguments (in + left-to-right order). + + For example, here is a list of terms in the standard + order: + + [ X, -9, 1, fie, foe, fum, X = Y, fie(0,2), fie(1,1) ] + + These are the basic predicates for comparison of arbitrary + terms: + + _X == _Y + + Tests if the terms currently instantiating _X and _Y are + literally identical (in particular, variables in + equivalent positions in the two terms must be identi- + cal). For example, the question + + + + + + + + + + +. + C-Prolog User's Manual 48 + + + | ?- X == Y. + + fails (answers "no") because _X and _Y are distinct + uninstantiated variables. However, the question + + | ?- X = Y, X == Y. + + succeeds because the first goal unifies the two vari- + ables (see page 42). + + _X \== _Y + + Tests if the terms currently instantiating _X and + _Y are not literally identical. + + _T_1 @< _T_2 + + Term _T_1 is before term _T_2 in the standard order. + + _T_1 @> _T_2 + + Term _T_1 is after term _T_2 in the standard order. + + _T_1 @=< _T_2 + + Term _T_1 is not after term _T_2 in the standard order. + + _T_1 @>= _T_2 + + Term _T_1 is not before term _T_2 in the standard order. + + Some further predicates involving comparison of terms + are: + + compare(_O_p,_T_1,_T_2) + + The result of comparing terms _T_1 and _T_2 is _O_p, where + the possible values for _O_p are: + + `=' if _T_1 is identical to _T_2, + + `<' if _T_1 is before _T_2 in the standard order, + + `>' if _T_1 is after _T_2 in the standard order. + + Thus compare(=,_T_1,_T_2) is equivalent to _T_1 == _T_2. + + sort(_L_1,_L_2) + + The elements of the list _L_1 are sorted into the stan- + dard order, and any identical (i.e. `==') elements are + merged, yielding the list _L_2. (The time taken to do + this is at worst order (N log N) where N is the length + + + + + + + + + + +. + C-Prolog User's Manual 49 + + + of _L_1.) + + keysort(_L_1,_L_2) + + The list _L_1 must consist of items of the form _K_e_y- + _V_a_l_u_e. These items are sorted into order according to + the value of _K_e_y, yielding the list _L_2. No merging + takes place. (The time taken to do this is at worst + order (N log N) where N is the length of L1.) + + _5._8. _M_o_d_i_f_i_c_a_t_i_o_n _o_f _t_h_e _P_r_o_g_r_a_m + + The predicates defined in this section allow modifica- + tion of the program as it is actually running. Clauses can + be added to the program (_a_s_s_e_r_t_e_d) or removed from the pro- + gram (_r_e_t_r_a_c_t_e_d). Some of the predicates make use of an + implementation-defined identifier or _d_a_t_a_b_a_s_e _r_e_f_e_r_e_n_c_e + which uniquely identifies every clause in the interpreted + program. This identifier makes it possible to access + clauses directly, instead of requiring a search through the + program every time. However these facilities are intended + for more complex use of the database and are not required + (and undoubtedly should be avoided) by novice users. + + assert(_C) + + The current instance of _C is interpreted as a clause + and is added to the program (with new private variables + replacing any uninstantiated variables). The position + of the new clause within the procedure concerned is + implementation-defined. _C must be instantiated to a + non-variable. + + assert(_C_l_a_u_s_e,_R_e_f) + + Similar to assert(_C_l_a_u_s_e), but also unifies _R_e_f with + the database reference of the clause asserted. + + asserta(_C) + + Like assert(_C), except that the new clause becomes + the _f_i_r_s_t clause for the procedure concerned. + + asserta(_C_l_a_u_s_e,_R_e_f) + + Similar to asserta(_C_l_a_u_s_e), but also unifies _R_e_f with + the database reference of the clause asserted. + + assertz(_C) + + Like assert(_C), except that the new clause becomes + the _l_a_s_t clause for the procedure concerned. + + + + + + + + + + + +. + C-Prolog User's Manual 50 + + + assertz(_C_l_a_u_s_e,_R_e_f) + + Similar to assertz(_C_l_a_u_s_e), but also unifies _R_e_f with + the database reference of the clause asserted. + + clause(_P,_Q) + + _P must be bound to a non-variable term, and the + program is searched for a clause whose head matches _P. + The head and body of those clauses are unified with _P + and _Q respectively. If one of the clauses is a unit + clause, _Q will be unified with `true'. + + clause(_H_e_a_d,_B_o_d_y,_R_e_f) + + Similar to clause(_H_e_a_d,_B_o_d_y) but also unifies _R_e_f with + the database reference of the clause concerned. If _R_e_f + is not given at the time of the call, _H_e_a_d must be + instantiated to a non-variable term. Thus this predi- + cate can have two different modes of use, depending on + whether the database reference of the clause is known + or unknown. + + retract(_C) + + The first clause in the program that matches _C is + erased. _C must be initially instantiated to a non- + variable. The predicate may be used in a non- + determinate fashion, i.e. it will successively retract + clauses matching the argument through backtracking. + + abolish(_N,_A) Completely remove all clauses for the procedure + with name _N (which should be an atom), and arity _A (which + should be an integer). + + The space occupied by retracted or abolished clauses will be + recovered when instances of the clause are no longer in use. + + See also erase (Section 5.10) which allows a clause to be + directly erased via its database reference[6]. + + _5._9. _I_n_f_o_r_m_a_t_i_o_n _a_b_o_u_t _t_h_e _S_t_a_t_e _o_f _t_h_e _P_r_o_g_r_a_m + + listing + + Lists in the current output stream all the clauses in + the program. + + ____________________ + [6]This is a lower level facility, required only for com- + plicated database manipulations. + + + + + + + + + + + + +. + C-Prolog User's Manual 51 + + + listing(_A) + + The argument _A may be a predicate specification of the + form _N_a_m_e/_A_r_i_t_y in which case only the clauses for the + specified predicate are listed. If _A is just an atom, + then the interpreted procedures for all predicates of + that name are listed as for listing/0. Finally, it is + possible for _A to be a list of predicate specifications + of either type, e.g. + + | ?- listing([concatenate/3, reverse, go/0]). + + + current_atom(_A_t_o_m) + + Generates (through backtracking) all currently known + atoms, and returns each one as _A_t_o_m. + + current_functor(_N_a_m_e,_F_u_n_c_t_o_r) + + Generates (through backtracking) all currently known + functors, and for each one returns its name and most + general term as _N_a_m_e and _F_u_n_c_t_o_r respectively. If _N_a_m_e + is given, only functors with that name are generated. + + current_predicate(_N_a_m_e,_F_u_n_c_t_o_r) + + Similar to current_functor, but it only generates func- + tors corresponding to predicates for which there exists + a procedure. + + _5._1_0. _I_n_t_e_r_n_a_l _D_a_t_a_b_a_s_e + + This section describes predicates for manipulating an + internal indexed database that is kept separate from the + normal program database. They are intended for more sophis- + ticated database applications and are not really necessary + for novice users. For normal tasks you should be able to + program quite satisfactorily just using assert and retract. + + recorded(_K_e_y,_T_e_r_m,_R_e_f) + + The internal database is searched for terms recorded + under the key _K_e_y. These terms are successively unified + with _T_e_r_m in the order they occur in the database. At + the same time, _R_e_f is unified with the database refer- + ence of the recorded item. The key must be given, and + may be an atom or complex term. If it is a complex + term, only the principal functor is significant. + + recorda(_K_e_y,_T_e_r_m,_R_e_f) + + + + + + + + + + + + +. + C-Prolog User's Manual 52 + + + The term _T_e_r_m is recorded in the internal database as + the first item for the key _K_e_y, where _R_e_f is its data- + base reference. The key must be given, and only its + principal functor is significant. + + recordz(_K_e_y,_T_e_r_m,_R_e_f) + + The term _T_e_r_m is recorded in the internal database as + the last item for the key _K_e_y, where _R_e_f is its data- + base reference. The key must be given, and only its + principal functor is significant. + + erase(_R_e_f) + + The recorded item _o_r clause whose database reference is + _R_e_f is effectively erased from the internal database or + program. An erased item will no longer be accessible + through the predicates that search through the data- + base, but will still be accessible through its database + reference, if this is available in the execution state + after the call to erase. Only when all instances of the + item's database reference have been forgotten through + database erasures and/or backtracking will the item be + actually removed from the database. + + erased(_R) + + Suceeds if _R is a database reference to a database item + that has been erased, otherwise fails. + + instance(_R_e_f,_T_e_r_m) + + A (most general) instance of the recorded term whose + database reference is _R_e_f is unified with _T_e_r_m. _R_e_f + must be instantiated to a database reference. Note that + instance will even pick database items that have been + erased. + + _5._1_1. _D_e_b_u_g_g_i_n_g + + debug + + Debug mode is switched on. Information will now be + retained for debugging purposes and executions will + require more space. + + nodebug + + Debug mode is switched off. Information is no longer + retained for debugging, and spy points are removed. + + trace + + + + + + + + + + + +. + C-Prolog User's Manual 53 + + + Debug mode is switched on, and the interpreter starts + tracing from the next call to a user goal. If trace + was given in a command on its own, the goal(s) traced + will be those of the next command. Since this is a + once-off decision, a call to trace is necessary when- + ever tracing is required right from the start of an + execution, otherwise tracing will only happen at spy + points. + + spy _S_p_e_c + + Spy points will be placed on all the procedures given + by _S_p_e_c. All control flow through the ports of these + procedures will henceforth be traced. If debug mode + was previously off, then it will be switched on. _S_p_e_c + can either be a predicate specification of the form + _N_a_m_e/_A_r_i_t_y or _N_a_m_e, or a list of such specifications. + When the _N_a_m_e is given without the _A_r_i_t_y this refers to + all predicates of that name which currently have defin- + itions. If there are none, then nothing will be done. + Spy points can be placed on particular undefined pro- + cedures only by using the full form, _N_a_m_e/_A_r_i_t_y. + + nospy _S_p_e_c + + Spy points are removed from all the procedures given by + _S_p_e_c (as for spy). + + leash(_M_o_d_e) + + Sets the leashing mode to _M_o_d_e, where _M_o_d_e can be one + of the following + + + full prompt on Call, Exit, BackTo and Fail + tight prompt on Call, BackTo and Fail + half prompt on Call and BackTo + loose prompt on Call + off never prompt + _N + + _N is an integer. If the binary notation of + _N is 2'_c_e_b_f, the digits _c, _e, _b + and _f correspond to the Call, Exit BackTo and Fail respectively, + and are 1 (0) if the corresponding port is leashed (unleashed). + + + The initial _l_e_a_s_h_i_n_g _m_o_d_e is `half'. + + debugging + + Outputs information concerning the status of the debug- + ging package. This will show whether debug mode is on, + and if it is + + + + + + + + + + + +. + C-Prolog User's Manual 54 + + + what spy points have been set + + what mode of leashing is in force. + + + _5._1_2. _E_n_v_i_r_o_n_m_e_n_t_a_l + + 'NOLC' + + Establishes the no lower-case convention described in + Section 2.4. + + 'LC' + + Establishes the full character set convention + described in Section 2.4. It is the default setting. + + op(_p_r_i_o_r_i_t_y,_t_y_p_e,_n_a_m_e) + + Treat name _n_a_m_e as an operator of the stated _t_y_p_e and + _p_r_i_o_r_i_t_y (refer to Section 2.2). _n_a_m_e may also be a + list of names in which case all are to be treated as + operators of the stated _t_y_p_e and _p_r_i_o_r_i_t_y. + + break + + Causes the current execution to be suspended at + the next procedure call. Then the message "[ Break + (level 1) ]" is displayed. The interpreter is then + ready to accept input as though it was at top + level. If another call of break is encountered, it + moves up to level 2, and so on. To close the break and + resume the execution which was suspended, type the + END-OF-INPUT character. Execution will be resumed at + the procedure call where it had been suspended. Alter- + natively, the suspended execution can be aborted by + calling the evaluable predicate abort. Refer to Section + 1.9. + + abort + + Aborts the current execution taking you back to top + level. Refer to Section 1.9. + + save(_F) + + The system saves the current state of the system into + file _F. Refer to Section 1.6. + + save(_F,_W_h_e_n) + + Saves the current state of the system into file _F. + When is unified with 0 or 1 depending on whether the + + + + + + + + + + +. + C-Prolog User's Manual 55 + + + system is returning from the save goal in the original + Prolog session or after the saved state in _F has been + restored by invoking Prlog with file _F as argument. + + prompt(_O_l_d,_N_e_w) + + The sequence of characters (prompt) which indicates + that the system is waiting for user input is + represented as an atom, and matched to _O_l_d; the atom + bound to _N_e_w specifies the new prompt. In particular, + the goal + + prompt(X,X) + + matches the current prompt to X, without changing it. + Note that this only affects the prompt issued for reads + in the user's program; it will not change the propmts + used by the system at top level etc. + + system(_S_t_r_i_n_g) + + Calls the operating system with string _S_t_r_i_n_g as argu- + ment. For example + + system("ls") + + will produce a directory listing on UNIX. + + sh + + Suspends C-Prolog and enters a recursive command inter- + preter. On UNIX, the shell used will be that specified + in the environment variable SHELL. + + statistics + + Shows the current allocations and amounts used for each + of the six working areas of C-Prolog, and also the run- + time since C-Prolog started. For example: + + | ?- statistics. + atom space: 64K (15596 bytes used) + aux. stack: 8K (0 bytes used) + trail: 64K (48 bytes used) + heap: 256K (30664 bytes used) + global stack: 256K (0 bytes used) + local stack: 256K (300 bytes used) + Runtime: 1.42 sec. + | ?- + + + + + + + + + + + + + + +. + C-Prolog User's Manual 56 + + + _5._1_3. _P_r_e_p_r_o_c_e_s_s_i_n_g + + expand_term(_T_1,_T_2) + + Each top level term _T_1 read when consulting a file is + rewritten into _T_2 before being asserted or executed. + The default transformations provided by this predicate + are the ones for grammar rules and for inline expansion + of arithmetic expressions. The user may define further + transformations as clauses for the predicate + term_expansion/2, which has similar arguments. User + defined transformations are applied _b_e_f_o_r_e system- + defined ones. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +. + C-Prolog User's Manual 57 + + + _A_p_p_e_n_d_i_x _I -- _S_u_m_m_a_r_y _o_f _E_v_a_l_u_a_b_l_e _P_r_e_d_i_c_a_t_e_s + + abolish(_F,_N) Abolish the procedure named _F arity _N. + abort Abort execution of the current directive. + arg(_N,_T,_A) The _Nth argument of term _T is _A. + assert(_C) Assert clause _C. + assert(_C,_R) Assert clause _C, ref. _R. + asserta(_C) Assert _C as first clause. + asserta(_C,_R) Assert _C as first clause, ref. _R. + assertz(_C) Assert _C as last clause. + assertz(_C,_R) Assert _C as last clause, ref. _R. + atom(_T) Term _T is an atom. + atomic(_T) Term _T is an atom or integer. + bagof(_X,_P,_B) The bag of _Xs such that _P is provable is _B. + break Break at the next procedure call. + call(_P) Execute the procedure call _P. + clause(_P,_Q) There is a clause, head _P, body _Q. + clause(_P,_Q,_R) There is an clause, head _P, body _Q, ref _R. + close(_F) Close file _F. + compare(_C,_X,_Y) _C is the result of comparing terms _X and _Y. + consult(_F) Extend the program with clauses from file _F. + current_atom(_A) One of the currently defined atoms is _A. + current_functor(_A,_T) A current functor is named _A, m.g. term _T. + current_predicate(_A,_P) A current predicate is named _A, m.g. goal _P. + db_reference(_T) _T is a database reference. + debug Switch on debugging. + debugging Output debugging status information. + display(_T) Display term _T on the terminal. + erase(_R) Erase the clause or record, ref. _R. + erased(_R) The object with ref. _R has been erased. + expanded_exprs(_O,_N) Expression expansion if _N=on. + expand_term(_T,_X) Term _T is a shorthand which expands to term _X. + exists(_F) The file _F exists. + fail Backtrack immediately. + fileerrors Enable reporting of file errors. + functor(_T,_F,_N) The top functor of term _T has name _F, arity _N. + get(_C) The next non-blank character input is _C. + get0(_C) The next character input is _C. + halt Halt Prolog, exit to the monitor. + instance(_R,_T) A m.g. instance of the record ref. _R is _T. + integer(_T) Term _T is an integer. + _Y is _X _Y is the value of arithmetic expression _X. + keysort(_L,_S) The list _L sorted by key yields _S. + leash(_M) Set leashing mode to _M. + listing List the current program. + listing(_P) List the procedure(s) _P. + name(_A,_L) The name of atom or number _A is string _L. + nl Output a new line. + nodebug Switch off debugging. + nofileerrors Disable reporting of file errors. + nonvar(_T) Term _T is a non-variable. + nospy _P Remove spy-points from the procedure(s) _P. + + + + + + + + + + + +. + C-Prolog User's Manual 58 + + + number(_T) Term _T is a number. + op(_P,_T,_A) Make atom _A an operator of type _T precedence _P. + primitive(_T) _T is a number or a database reference + print(_T) Portray or else write the term _T. + prompt(_A,_B) Change the prompt from _A to _B. + put(_C) The next character output is _C. + read(_T) Read term _T. + reconsult(_F) Update the program with procedures from file _F. + recorda(_K,_T,_R) Make term _T the first record under key _K, ref. _R. + recorded(_K,_T,_R) Term _T is recorded under key _K, ref. _R. + recordz(_K,_T,_R) Make term _T the last record under key _K, ref. _R. + rename(_F,_G) Rename file _F to _G. + repeat Succeed repeatedly. + retract(_C) Erase the first clause of form _C. + save(_F) Save the current state of Prolog in file _F. + see(_F) Make file _F the current input stream. + seeing(_F) The current input stream is named _F. + seen Close the current input stream. + setof(_X,_P,_B) The set of _Xs such that _P is provable is _B. + sh Start a recursive shell + skip(_C) Skip input characters until after character _C. + sort(_L,_S) The list _L sorted into order yields _S. + spy _P Set spy-points on the procedure(s) _P. + statistics Display execution statistics. + system(_S) Execute command _S. + tab(_N) Output _N spaces. + tell(_F) Make file _F the current output stream. + telling(_F) The current output stream is named _F. + told Close the current output stream. + trace Switch on debugging and start tracing. + true Succeed. + var(_T) Term _T is a variable. + write(_T) Write the term _T. + writeq(_T) Write the term _T, quoting names if necessary. + 'LC' The following Prolog text uses lower case. + 'NOLC' The following Prolog text uses upper case only. + ! Cut any choices taken in the current procedure. + \+ _P Goal _P is not provable. + _X<_Y As numbers, _X is less than _Y. + _X=<_Y As numbers, _X is less than or equal to _Y. + _X>_Y As numbers, _X is greater than _Y. + _X>=_Y As numbers, _X is greater than or equal to _Y. + _X=_Y Terms _X and _Y are equal (i.e. unified). + _T=.._L The functor and args. of term _T comprise the list _L. + _X==_Y Terms _X and _Y are strictly identical. + _X\==_Y Terms _X and _Y are not strictly identical. + _X@<_Y Term _X precedes term _Y. + _X@=<_Y Term _X precedes or is identical _Y. + _X@>_Y Term _X follows term _Y. + _X@>=_Y Term _X follows or is identical to term _Y. + [_F|_R] Perform the (re)consult(s) specified by [_F|_R]. + + + + + + + + diff --git a/source_code/c-prolog-1982/man/makefile b/source_code/c-prolog-1982/man/makefile new file mode 100755 index 0000000..1eb0e07 --- /dev/null +++ b/source_code/c-prolog-1982/man/makefile @@ -0,0 +1,5 @@ +TROFF=psroff -Tpsc +DEST=>cprolog.doc + +cprolog.doc: app.me cprolog.me + tbl cprolog.me app.me | $(TROFF) -me diff --git a/source_code/c-prolog-1982/man/makefile.save b/source_code/c-prolog-1982/man/makefile.save new file mode 100755 index 0000000..664cf63 --- /dev/null +++ b/source_code/c-prolog-1982/man/makefile.save @@ -0,0 +1,5 @@ +TROFF=ptroff -Tlp +DEST=>cprolog.doc + +cprolog.doc: app.me cprolog.me + tbl cprolog.me app.me | $(TROFF) -me diff --git a/source_code/c-prolog-1982/parms.c b/source_code/c-prolog-1982/parms.c new file mode 100755 index 0000000..e3a0974 --- /dev/null +++ b/source_code/c-prolog-1982/parms.c @@ -0,0 +1,84 @@ +/********************************************************************** +* * +* C Prolog parms.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +#include "pl.h" + +/* Declaration and properties of work areas */ + +#define AtomSize (128*K) +#define AuxSize (8*K) +#define TrailSize (64*K) +#define HeapSize (256*K) +#define GlobalSize (256*K) +#define LocalSize (128*K) + + +int Size[] = { AtomSize, AuxSize, TrailSize, + HeapSize, GlobalSize, LocalSize }; + +PTR Origin[7]; +PTR Limit[6]; +PTR Tide[6]; + +/* + Switches: b = boot, q = quiet start-up, d = dump on error, T = trace, + a = atom area size, + x = aux " " , + t = trail " " , + h = heap " " , + g = global " " , + l = local " " + +*/ + +char Parameter[] = { 'a', 'x', 't', 'h', 'g', 'l' }; +int NParms = 6; + +char Switch[] = { 0, 0, 'b', 'q', 'd', 'T' }; +int State[] = { 0, 0, 0, 0, 0, 0 }; + +int Switches = 6; + +#ifdef vms +#define STARTUPFILE "STARTUP" +#endif + +char StandardStartup[] = STARTUPFILE; + +char * +UserStartup() +{ + static char buf[256]; +#ifdef unix + static char format[] = "%s/prolog.bin"; + char *env = getenv("HOME"); +#else +#ifdef vms + static char format[] = "%sPROLOG.BIN"; + char *env = getenv("HOME"); +#else + static char format[] = "%sPROLOG.BIN"; + char *env = NULL; +#endif +#endif + sprintf(buf,format,env); + return buf; +} + +char version[] = "C-Prolog version 1.5"; +int saveversion = 26; + + diff --git a/source_code/c-prolog-1982/parms.o b/source_code/c-prolog-1982/parms.o new file mode 100755 index 0000000000000000000000000000000000000000..f2906b1115a729773ef3d43a81408ed3a58cdd65 GIT binary patch literal 6800 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 + +#define TRUE 1 +#define FALSE 0 + +#define K 1024 + +/* the representable integers are in the interval [MinInt,MaxInt] */ + +#define MaxInt 268435455 /* largest integer = 2^28-1 */ +#define MinInt -268435456 /* smallest integer = -2^28 */ + + +/* SIGNED must be defined as the type of integers with the same width + as a pointer (int on a VAX). This type is used to interpret pointers + as signed numbers in comparisons related to the internal representation + of terms (see picture below). Despite attempts to parameterise as + much as possible, the sistem still depends on pointers being 32 bits + wide and numbers being held in two's-complement. +*/ + +typedef int SIGNED; + +/* The original EMAS Prolog in IMP relies too much on pointers being + just addresses, independently of the type pointed to, for me to be + able to do anything about it. To help satisfy the compiler's view + of typing, addresses are objects of type PTR, which are then cast + into the appopriate types. +*/ + +typedef unsigned **PTR; + +#define CellP(p) ((PTR*)(p)) +#define AtomP(p) ((ATOM*)(p)) +#define FunctorP(p) ((FUNCTOR*)(p)) +#define FrameP(p) ((FRAME*)(p)) +#define ClauseP(p) ((CLAUSEREC*)(p)) +#define MolP(p) ((MOL*)(p)) +#define SkelP(p) ((SKEL*)(p)) +#define Signed(p) ((SIGNED)(p)) +#define Unsigned(p) ((unsigned)(p)) +#define CharP(p) ((char*)(p)) + +#define Addr(p) ((PTR)&(p)) /* PTRise an address */ + +/* Prolog registers as cell pointers */ + +/* Words(number) converts a number of bytes to a number of PTRs */ + +#define Words(v) (((v)+sizeof(PTR))/sizeof(PTR)) + +#define SC(x,o,y) (Signed(x) o Signed(y)) /* signed pointer comparison */ + +/* Origin of input variables */ + +#define VAR0 0x40000000 /* all variables */ +#define LOCAL0 0x41000000 /* local variables */ +#define VMASK 0xf0000000 /* variable bit mask */ +#define LVMASK 0xff000000 /* local variable bit mask */ + +#ifdef COMMENT + + The definitions that follow depend crucially on the relative + positions of stacks and other work areas. Values of type PTR + whose most significant bit is 1 (negative as integers) are not + pointers but values of some primitive type (integers or + database pointers, floats sometime in the future). Positive + PTRs are pointers into the stacks/work areas. Therefore, the + top of the topmost area must be below address 2^30-1. If + Unix could cope with widely scattered segments (promised for + 4.2 BSD), I might be able to implement these things more + nicely in terms of tagged pointers. As it is, type checking + is done by signed comparisons, and the stacks/work areas + occupy a contiguous region in memory. This region is allocated + by CreateStacks() (sysbits.c), and area sizes are defined in + parms.c. + + The layout is as follows: + + atom0: *----------------------* + | Atoms | + auxstk0: *----------------------* + | Auxiliary stack | + trbase: *----------------------* + | Trail | + skel0: *----------------------* + | Heap (input terms) | + glb0: *----------------------* + | Global stack | + lcl0: *----------------------* + | Local stack | + *----------------------* + +#endif + +#define NAreas 6 /* number of work areas/stacks */ + +#define IsRef(c) SC(c,>=,glb0) /* reference */ +#define IsAtomic(c) SC(c,<,skel0) /* atomic term */ +#define IsInp(c) SC(c,<,glb0) /* input term */ +#define IsComp(c) SC(c,>=,skel0) /* compound or constructed term */ +#define IsLocal(c) SC(c,>=,lcl0) /* local address */ +#define IsPrim(c) SC(c,<,0) /* number or db reference */ +#define IsDBRef(c) ((Unsigned(c)&NUM0) == DB_REF0) /* db reference */ +#define IsNumber(c) ((Unsigned(c)&NUM0) == NUM0) /* number */ +#define IsInt(c) ((Unsigned(c)&INT0) == INT0) /* integer */ +#define IsFloat(c) ((Unsigned(c)&INT0) == FLOAT_TAG) /* float */ +#define Undef(c) (Unsigned(c) == 0) /* undefined cell */ +#define IsntName(c) SC(c,<,atom0) /* isn't atom or functor */ +#define IsName(c) SC(c,>=,atom0) /* not primitive */ +#define IsVar(c) ((Unsigned(c)&VMASK) == VAR0) /* input variable */ +#define IsLocalVar(c) ((Unsigned(c)&LVMASK) == LOCAL0)/* input local */ +#define VarNo(x) (Signed(x)&0xffff) /* var. offset */ + +#define FrameVar(v,n) ((PTR)(CharP(v)+(n))) /* var. cell address */ + +/* skeleton representation of the nth local variable */ + +#define SkelLocal(n) ((PTR)((Addr(FrameP(LOCAL0)->v1ofcf)+(n)))) + +/* ditto global variable */ + +#define SkelGlobal(n) (((PTR)VAR0)+n) + +/* extract and construct integer */ + +#define XtrInt(c) ((Signed(c)&SIGN) ? Signed(c) : Signed(c)&~INT0) +#define ConsInt(i) ((PTR)(INT0|(i))) + +/* extract and construct database pointer */ + +#define XtrDBRef(c) (skel0+(Unsigned(c)&~(NUM0|RECORD))) +#define DBType(c) (Unsigned(c)&RECORD) +#define ConsDBRef(p,k) ((PTR)(((p)-skel0)|DB_REF0|(k))) + +/* extract and construct float */ + +extern float XtrFloat(); +extern PTR ConsFloat(); + +/* Grow pointer p by n agains limit l on area i. */ + +#define Grow(p,l,n,i) {if ((p += (n)) > l) NoSpace(i); } + +/* Grow atom space */ + +#define GrowAtom(n) Grow(atomfp,atmax,n,AtomId) + +/* Grow stacks. */ + +#define GrowLocal(n) (v += (n)) + +#define GrowGlobal(n) (v1 += (n)) + +#define InitGlobal(n,k) { register PTR p; \ + p = v1+(n); \ + k = v1; \ + while (p > v1) *--p = NULL; \ + GrowGlobal(n); } + +/* construct molecule */ + +#define ConsMol(s,e,m) { MolP(v1)->Sk=(s); \ + MolP(v1)->Env=(e); \ + m = v1; \ + GrowGlobal(MolSz); } + +/* trail an assignment */ + +#define TrailPtr(t) {if (tr > trmax) NoSpace(TrailId); else *tr++ = (t);} + +#define TrailVar(t) { PTR tt; \ + tt = (t); \ + if (tt < vv1 || (lcl0 <= tt && tt < vv)) \ + TrailPtr(tt); \ + } + +/* Headers for doubly linked definition chains */ + +typedef struct { + PTR First; + PTR Last; +} Header; + +/* atom entry */ + +#define infofae AInfo.Infofae +#define arityofae AInfo.ABytes.Arityofae +#define flgsofae AInfo.Abytes.Flgsofae +#define infxofae AInfo.ABytes.InfixOfAE +#define defsofae AClauses.First +#define dbofae ARecords.First + +typedef struct ATOM { + PTR atofae; /* self pointer */ + union { + unsigned Infofae; /* information */ + struct { + char Arityofae; /* arity ( = 0 ) */ + char Flgsofae; /* flags field */ + short InfixOfAE; /* infix priority */ + } ABytes; + } AInfo; + Header AClauses; /* chain of definitions */ + Header ARecords; /* chain of records */ + PTR fcofae; /* functor chain */ + PTR nxtofae; /* hash chain */ + short prfxofae, psfxofae; /* prefix and postfix priorities */ + char stofae[1]; /* string for atom */ +} ATOM; + +/* size of atom entry (excluding string) */ + +#define szofae sizeof(ATOM) + +/* Size of hashtable */ + +#define HASHSIZE 269 /* a prime */ + +/* functor entry */ + +#define infoffe FInfo.Infoffe +#define arityoffe FInfo.FBytes.Arityoffe +#define flgsoffe FInfo.FBytes.Flgsoffe +#define defsoffe FClauses.First +#define dboffe FRecords.First + +typedef struct FUNCTOR { + PTR atoffe; /* atom for this functor */ + union { + unsigned Infoffe; /* general information field */ + struct { + char Arityoffe; /* arity */ + char Flgsoffe; /* flags field */ + } FBytes; + } FInfo; + Header FClauses; /* clauses for this functor */ + Header FRecords; /* data base entries under functor */ + PTR nxtoffe; /* chain of functors with same name */ + PTR gtoffe; /* start of general skeleton for this */ + /* term. points to this entry. */ +} FUNCTOR; + +/* size of functor entry (+ arity) in PTRs */ + +#define szoffe (sizeof(FUNCTOR)/sizeof(PTR)) + +/* clause */ + +#define MAX_VAR 255 /* highest variable number */ + +typedef struct CLAUSEREC { + unsigned char ltofcl; /* no. of local and temp. variables */ + unsigned char lvofcl; /* no. of local vars */ + unsigned char gvofcl; /* no. of global vars */ + char infofcl; /* general inf. */ + int refcofcl; /* reference count */ + PTR hdofcl; /* clause head */ + PTR bdyofcl; /* body of clause */ + PTR altofcl; /* alternatives */ + PTR prevofcl; /* previous clause */ +} CLAUSEREC; + +/* size of entry in PTRs */ + +#define szofcl (sizeof(CLAUSEREC)/sizeof(PTR)) + +/* local frame */ + +typedef struct { + PTR Lcpofcf; /* preyious choice point */ + PTR Gofcf; /* goal */ + PTR Gfofcf; /* goal's local frame */ + PTR Gsofcf; /* global frame associated with this frame */ + PTR Trofcf; /* tr at entry */ + unsigned Infofcf; /* general information */ + PTR Cofcf; /* continuation on entry */ + PTR Altofcf; /* alternatives */ +} FRAMECTL; + +/* size in cells */ + +#define szofcf sizeof(FRAMECTL)/sizeof(PTR) +#define MAX_FRAME szofcf+MAX_VAR+1 + +typedef struct FRAME { + FRAMECTL FCTL; + PTR v1ofcf; /* variables */ + PTR v2ofcf; + PTR v3ofcf; + PTR v4ofcf; + PTR v5ofcf; +} FRAME; + +/* Fields of the frame information word */ + +#define HIDDEN_FRAME NUM_TAG /* system frame, not traceable */ +#define LEVEL_WIDTH 12 /* width of the level field */ +#define CALL_NUMBER 0x3ffff /* invocation number mask */ +#define LEVEL 0xfff /* recursion level mask */ + +/* build the information for the current frame, faking a + primitive object */ + +#define FrameInfo(i,l) (((i&CALL_NUMBER)<>LEVEL_WIDTH)&CALL_NUMBER) +#define Level(info) ((info)&LEVEL) +#define SysFrame(info) ((info)&HIDDEN_FRAME) + +/* Evaluable predicate arguments */ + +#define ARG1 (X->v1ofcf) +#define ARG2 (X->v2ofcf) +#define ARG3 (X->v3ofcf) +#define ARG4 (X->v4ofcf) +#define ARG5 (X->v5ofcf) + +/* Frame locations */ + +#define lcpofcf FCTL.Lcpofcf +#define gofcf FCTL.Gofcf +#define gfofcf FCTL.Gfofcf +#define gsofcf FCTL.Gsofcf +#define trofcf FCTL.Trofcf +#define infofcf FCTL.Infofcf +#define cofcf FCTL.Cofcf +#define altofcf FCTL.Altofcf + +/* Prolog registers as frame pointers */ + +#define X FrameP(x) +#define V FrameP(v) +#define VV FrameP(vv) + +/* skeleton layout - add argument fields as required by code + (could define an arg. array instead, the generality is hardly worth + the bother) +*/ + +typedef struct SKEL { + PTR Fn; + PTR Arg1; + PTR Arg2; + } SKEL; + +#define SkelSz(n) ((n)+1) /* size of n arg. skeleton */ + + +/* molecule layout - the Sk field MUST be the first! */ + +typedef struct MOL { + PTR Sk; + PTR Env; + } MOL; + +#define MolSz 2 /* NB: size in PTRs, not in bytes */ + +/* entry is read's variable dictionary */ + +typedef struct VarEntry { + struct VarEntry *NextVar; /* must be the first */ + PTR VarValue; + int VarLen; + char VarName[1]; + } VarEntry; + +typedef VarEntry *VarP; + +/* Primitive objects (ints, floats and database pointers at present) + are distinguished by tag bits. Any primitive object will have + bit 31 (sign bit) set. The tags are as follows: + + tag bits + 31 30 29 + =============+==+==+== + int 1 1 1 + float 1 1 0 + ptr to clause 1 0 0 + ptr to record 1 0 1 + +*/ +#define PRIM_TAG 0x80000000 /* tag for primitive types */ +#define NUM_TAG 0x40000000 /* tag for numbers */ +#define NUM0 0xc0000000 /* origin of primitive types */ +#define INT0 0xe0000000 /* origin of integers */ +#define SIGN 0x10000000 /* sign bit on a constructed number */ +#define FLOAT_TAG NUM0 /* float tag bits */ +#define DB_REF0 0x80000000 /* origin of database references */ +#define RECORD 0x20000000 /* reference to a record */ +#define CLAUSE 0 /* reference to a clause (clear) */ + +/* clause/record flags */ + +#define ERASED 1 /* erased but not yet removed */ +#define IN_USE 2 /* in use in a proof, cannot be + deleted yet */ + +#define Erased(c) ((ClauseP(c)->infofcl)&ERASED) +#define InUse(c) ((ClauseP(c)->infofcl)&IN_USE) +#define RC(c) (ClauseP(c)->refcofcl) +#define Idle(c) (RC(c) == 0 && !InUse(c)) + +/* Flags in a functor entry - apply to the corresponding predicate */ + +#define RESERVED 0xe0 /* cannot be modified */ +#define HIDDEN 0xc0 /* Protected or invisible */ +#define PROTECTED 0x80 /* cannot be listed, traced, or modified */ +#define INVISIBLE 0x40 /* invisible to tracing and recursion level */ +#define UNTRACEABLE 0x20 /* cannot be traced */ +#define SPY_ME 0x10 /* is a spypoint */ + +/* NB. The low order 4 bits of the flags field in a functor or + atom entry, if non-zero, represent the internal code of that + functor or atom as an arithmetic operator. This means that + the maximum number of different arithmetic operators for each + arity is 15 (see arith.c). This could be changed by redefining + the layout of functor and atom entries, taking care with + the way unions are used in them (left-overs from the original + code in IMP). +*/ + +/* Internal event conditions */ + +#define COLD_START 0 /* first thing in the morning */ +#define ABORT 1 /* 'abort' evaluable predicate */ +#define IO_ERROR 2 /* every STDIO failure that is not */ +#define END_OF_FILE 3 /* end of file on input */ +#define ARITH_ERROR 4 /* incorrect args. to 'is", =:=, etc. */ +#define GEN_ERROR 5 /* all others report here */ + +/* Initial state flags (set by switches: see parms.c) */ + +#define IN_BOOT 2 +#define QUIET 3 +#define DEBUG 4 +#define TRACE 5 + +/* predefined I/O streams */ + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +/* Work areas */ + +/* Indices of areas */ + +#define AtomId 0 +#define AuxId 1 +#define TrailId 2 +#define HeapId 3 +#define GlobalId 4 +#define LocalId 5 + +/* origins of work areas */ + +#define atom0 (Origin[AtomId]) +#define auxstk0 (Origin[AuxId]) +#define trbase (Origin[TrailId]) +#define skel0 (Origin[HeapId]) +#define glb0 (Origin[GlobalId]) +#define lcl0 (Origin[LocalId]) + +/* limits of work areas */ + +#define atmax Limit[AtomId] +#define auxmax Limit[AuxId] +#define trmax Limit[TrailId] +#define hpmax Limit[HeapId] +#define v1max Limit[GlobalId] +#define vmax Limit[LocalId] + +/* Tide marks */ + +#define HighTide(reg,mark) if (reg > mark) mark = reg + +#define Auxtide Tide[AuxId] +#define TRtide Tide[TrailId] +#define V1tide Tide[GlobalId] +#define Vtide Tide[LocalId] + +/* initial atoms */ + +#define BATOMS 15 + +#define atomnil BasicAtom[0] +#define commafunc BasicAtom[1] +#define assertatom BasicAtom[2] +#define EndOfFile BasicAtom[3] +#define atomtrue BasicAtom[4] +#define user BasicAtom[5] +#define live BasicAtom[6] +#define breakat BasicAtom[7] +#define LessThan BasicAtom[8] +#define Equal BasicAtom[9] +#define GreaterThan BasicAtom[10] +#define Yes BasicAtom[11] +#define No BasicAtom[12] +#define Minus BasicAtom[13] +#define semicatom BasicAtom[14] + +/* initial functors */ + +#define BFUNCS 8 + +#define calltag BasicFunctor[0] +#define commatag BasicFunctor[1] +#define assertfunc BasicFunctor[2] +#define listfunc BasicFunctor[3] +#define arrowtag BasicFunctor[4] +#define provefunc BasicFunctor[5] +#define HiddenCall BasicFunctor[6] +#define PrivTerm BasicFunctor[7] + +/* basic terms */ + +#define BTERMS 2 + +#define List10 BasicTerm[0] /* not read in from init file */ +#define CsltUser BasicTerm[1] + +/* Magic sequence that starts saved states */ + +#define SaveMagic "PLGS" + +/* Exit codes */ + +#ifdef unix +# define GOOD_EXIT 0 +# define BAD_EXIT 1 +#else +# define GOOD_EXIT 1 +# define BAD_EXIT 0 +#endif + +/* public data */ + +extern PTR v, x, vv, v1, vv1, x1, v1f, tr, tr0, + atomfp, hasha, vra, vrz, varfp, lsp, brkp, + Origin[], Limit[], Tide[], BasicFunctor[], BasicAtom[], + BasicTerm[], FileAtom[]; + +extern char Switch[], StandardStartup[], Parameter[], + *ErrorMess, OutBuf[], PlPrompt[], *AreaName[], version[]; + +extern VarP varchain; + +extern int crit, running, debug, sklev, quoteia, nvars, lc, errno, + saveversion, Switches, Size[], State[], NParms, + Input, Output, AllFloat; + +/* public functions */ + +extern int See(), Tell(), CSee(), CTell(), gunify(), instance(), + intval(), Statistics(), Safe(), Unsafe(); +extern PTR fentry(), apply(), makelist(), deref(), arg(), argv(), recorded(), + lookup(), lookupvar(), pread(), record(), getsp(), Telling(), + Seeing(), NoSpace(), Unary(), Binary(), scanstack(), findinv(); + +extern char Get(), ToEOL(), *SysError(), *AtomToFile(); + +extern float CPUTime(); diff --git a/source_code/c-prolog-1982/pl/all b/source_code/c-prolog-1982/pl/all new file mode 100755 index 0000000..31507af --- /dev/null +++ b/source_code/c-prolog-1982/pl/all @@ -0,0 +1,17 @@ +/* all: Load all the current bits of the standard Prolog system + + Fernando Pereira + Updated: 30 December 82 +*/ + +:-([ + 'pl/arith', % Arithmetic compilation + 'pl/grammar', % DCG grammar rule translation + 'pl/setof', % Setof and sorting + 'pl/tracing', % Debugging evaluable predicates + 'pl/listing' % Listing the database + ]). + + +:-([ 'pl/protect' ]). % Lock things up + diff --git a/source_code/c-prolog-1982/pl/arith b/source_code/c-prolog-1982/pl/arith new file mode 100755 index 0000000..2605ed2 --- /dev/null +++ b/source_code/c-prolog-1982/pl/arith @@ -0,0 +1,106 @@ +/* pl/arith: preprocess arithmetic expressions */ + +$compile_arith(P0,P) :- + $carith(1,1), !, + $expand_arith(P0,P). +$compile_arith(P,P). + +$expand_arith(P,P) :- var(P), !. +$expand_arith(P0,P) :- $expand_arith0(P0,P). + +$expand_arith0((P0,Q0),(P,Q)) :- !, + $expand_arith(P0,P), + $expand_arith(Q0,Q). +$expand_arith0((P0;Q0),(P;Q)) :- !, + $expand_arith(P0,P), + $expand_arith(Q0,Q). +$expand_arith0(X is Y, X is Y) :- var(Y), !. +$expand_arith0(X is Y, P) :- !, + $expand_expression(Y,P0,X0), + $drop_is(X0,X,P1), + $and(P0,P1,P). +$expand_arith0(Comp0,R) :- + functor(Comp0,Op,2), + $comp_op(Op), !, + arg(1,Comp0,E), + arg(2,Comp0,F), + functor(Comp,Op,2), + arg(1,Comp,U), + arg(2,Comp,V), + $expand_expression(E,P,U), + $expand_expression(F,Q,V), + $and(P,Q,R0), + $and(R0,Comp,R). +$expand_arith0(P,P). + +$expand_expression(V,true,V) :- var(V), !. +$expand_expression(A,true,A) :- atomic(A), !. +$expand_expression(T,P,V) :- + $op_to_pred(T,N,V,P0), + $expand_expression_args(N,T,P0,true,Q), + $and(Q,P0,P). + +$expand_expression_args(0,_,_,P,P) :- !. +$expand_expression_args(N,T,G,P0,P) :- + arg(N,T,E), + arg(N,G,V), + $expand_expression(E,Q,V), + M is N-1, + $and(P0,Q,P1), + $expand_expression_args(M,T,G,P1,P). + +$comp_op(<). +$comp_op(>). +$comp_op(=<). +$comp_op(>=). +$comp_op(=:=). +$comp_op(=\=). + +$and(true,P,P) :- !. +$and(P,true,P) :- !. +$and(P,Q,(P,Q)). + +$rename_op(Op0,N,Op) :- + $rename_op0(Op0,N,Op), !. +$rename_op(Op,_,Op). + +% Unary operations + +$rename_op0(+,1,'$+'). +$rename_op0(-,1,'$-'). +$rename_op0(\,1,'$\'). +$rename_op0(exp,1,$exp). +$rename_op0(log,1,$log). +$rename_op0(log10,1,$log10). +$rename_op0(sqrt,1,$sqrt). +$rename_op0(sin,1,$sin). +$rename_op0(cos,1,$cos). +$rename_op0(tan,1,$tan). +$rename_op0(asin,1,$asin). +$rename_op0(acos,1,$acos). +$rename_op0(atan,1,$atan). +$rename_op0(floor,1,$floor). + +% Binary operations + +$rename_op0(+,2,'$+'). +$rename_op0(-,2,'$-'). +$rename_op0(*,2,'$*'). +$rename_op0(/,2,'$/'). +$rename_op0(mod,2,$mod). +$rename_op0(/\,2,'$/\'). +$rename_op0(\/,2,'$\/'). +$rename_op0(<<,2,'$<<'). +$rename_op0(>>,2,'$>>'). +$rename_op0(//,2,'$//'). +$rename_op0(^,2,'$^'). + +$op_to_pred(T,N,V,P) :- + functor(T,Op0,N), + $rename_op(Op0,N,Op), + M is N+1, + functor(P,Op,M), + arg(M,P,V). + +$drop_is(V,V,true) :- var(V), !. +$drop_is(V,X,X is V). diff --git a/source_code/c-prolog-1982/pl/grammar b/source_code/c-prolog-1982/pl/grammar new file mode 100755 index 0000000..bb6d8df --- /dev/null +++ b/source_code/c-prolog-1982/pl/grammar @@ -0,0 +1,51 @@ +% grammar: translation of grammar rules - 30 December 82 + +$translate_rule((LP-->[]),H) :- !, $t_lp(LP,S,S,H). +$translate_rule((LP-->RP),(H:-B)):- + $t_lp(LP,S,SR,H), + $t_rp(RP,S,SR,B1), + $tidy(B1,B). + +$t_lp((LP,List),S,SR,H):- !, + $append(List,SR,List2), + $add_extra_args([S,List2],LP,H). + +$t_lp(LP,S,SR,H) :- $add_extra_args([S,SR],LP,H). + +$t_rp(!,S,S,!) :- !. +$t_rp([],S,S1,S=S1) :- !. +$t_rp([X],S,SR,c(S,X,SR)) :- !. +$t_rp([X|R],S,SR,(c(S,X,SR1),RB)) :- !, $t_rp(R,SR1,SR,RB). +$t_rp({T0},S,S,T) :- !, $compile_arith(T0,T). +$t_rp((T,R),S,SR,(Tt,Rt)) :- !, + $t_rp(T,S,SR1,Tt), + $t_rp(R,SR1,SR,Rt). +$t_rp((T;R),S,SR,(Tt;Rt)) :- !, + $t_or(T,S,SR,Tt), + $t_or(R,S,SR,Rt). +$t_rp(T,S,SR,Tt) :- $add_extra_args([S,SR],T,Tt). + +$t_or(X,S0,S,P) :- + $t_rp(X,S0a,S,Pa), + ( var(S0a), S0a \== S, !, S0=S0a, P=Pa; + P=(S0=S0a,Pa) ). + +$add_extra_args(L,T,T1) :- + T=..Tl, + $append(Tl,L,Tl1), + T1=..Tl1. + +$append([],L,L) :- !. +$append([X|R],L,[X|R1]) :- $append(R,L,R1). + +$tidy((P1;P2),(Q1;Q2)) :- !, + $tidy(P1,Q1), + $tidy(P2,Q2). +$tidy(((P1,P2),P3),Q) :- $tidy((P1,(P2,P3)),Q). +$tidy((P1,P2),(Q1,Q2)) :- !, + $tidy(P1,Q1), + $tidy(P2,Q2). +$tidy(A,A) :- !. + +c([X|S],X,S). + diff --git a/source_code/c-prolog-1982/pl/init b/source_code/c-prolog-1982/pl/init new file mode 100755 index 0000000..58dc209 --- /dev/null +++ b/source_code/c-prolog-1982/pl/init @@ -0,0 +1,541 @@ +/* init : Initial boot file for building the Prolog system + + Fernando Pereira + Updated: 27 July 83 +*/ + + % Atoms that the code requires +[]. +','. +'{}'. +end_of_file. +true. +user. +$live. +$break. +< . += . +> . +$yes. +$no. +- . +; . + + % Functors that the code requires +call(_). +','(_,_). +'{}'(_). +'.'(_,_). +':-'(_,_). +':-'(_). +$hidden_call(_). +$hidden_term(_). + + % Terms that the code requires + +% The first term is List10 which must be constructed specially */ + +$ttynl,$csult(0,user). + + % And now we start properly + + % Predicates are attached to evaluable predicates defined in the + % code by one of two methods: + % + % 1) pred(....) :- N. + % 2) :- $sysp(pred(....),N). + % + % where N is an integer specifying the evaluable + % predicate - N is the value of the switch label in "main.c". + % The difference between these is that with the first method a + % (local) frame will be built which will contain the arguments to the + % procedure; whereas in the second case no frame is built. + + % Set up the Operators + + :-(op(P,T,A),76). + + :-(op(1200,fx,[ :- , ?- ])). + :-op(1200,xfx,[ (:-) , --> ]). + :-op(1100,xfy,';'). + :-op(1050,xfy,'->'). + :-op(1000,xfy,','). + :-op(900,fy,[ \+ , not , spy , nospy ]). + :-op(700,xfx,[ =, is, =.. , ==, \==, @<, @>, @=<, @>=, =:=, =\=, <, > , =<, >= ]). + :-op(500,yfx,[+,-,/\,\/]). + :-op(500,fx,[(+),(-),\]). + :-op(400,yfx,[*,/,//,<<,>>]). + :-op(300,xfx,[mod]). + :-op(200,xfy,'^'). + + + % And now all the evaluable predicates + + $sysp(F,N) :- 100. + $sysflgs(F,N) :- 101. + $hide_atom(A) :- 171. + + :-$sysp((A,B),6). +call(P) :- 1. +:-$sysp($hidden_call(P),121). +:-$sysp(!,2). +true. + repeat :- 3. + :-$sysp(abort,4). + :-$sysp($call(_),5). + +$not(X) :- $user_call(X), !, fail. +$not(X). + +\+(X) :- $not(X). +not(X) :- $not(X). + +(A -> B ; C) :- !, $cond(A,B,C). + + $cond(A,B,C) :- $user_call(A), !, $user_call(B). + $cond(A,B,C) :- $user_call(C). + +(A;B) :- $call(A). +(A;B) :- $call(B). +(A -> B) :- $user_call(A), !, $user_call(B). + + see(F) :- 10. + seeing(F) :- 11. + seen :- 12. + tell(F) :- 13. + append(F) :- 174. + telling(F) :- 14. + told :- 15. + close(F) :- 16. + read(T) :- 17. + write(T) :- 18. display(T) :- 274. % + 256 + nl :- 19. ttynl :- 275. $ttynl :- 275. + get0(C) :- 20. ttyget0(C) :- 276. + get(C) :- 21. ttyget(C) :- 277. + skip(C) :- 22. ttyskip(C) :- 278. + put(C) :- 23. ttyput(C) :- 279. + tab(C) :- 24. ttytab(C) :- 280. + fileerrors :- 25. + nofileerrors :- 26. + rename(F,F1) :- 27. + writeq(T) :- 28. + sh :- 29. + system(S) :- 30. + +print(V) :- var(V), !, write(V). + +print(X) :- portray(X), !. + +print(X) :- write(X). + + % define arithmetic operators + + % nullary ops + + :-$sysflgs(cputime,1). + :-$sysflgs(heapused,2). + :-$sysflgs(breaklevel,3). + % unary operations + + :-$sysflgs([A|B],1). + :-$sysflgs(+(A),1). + :-$sysflgs(-(A),2). + :-$sysflgs(\(A),3). + :-$sysflgs(exp(A),4). + :-$sysflgs(log(A),5). + :-$sysflgs(log10(A),6). + :-$sysflgs(sqrt(A),7). + :-$sysflgs(sin(A),8). + :-$sysflgs(cos(A),9). + :-$sysflgs(tan(A),10). + :-$sysflgs(asin(A),11). + :-$sysflgs(acos(A),12). + :-$sysflgs(atan(A),13). + :-$sysflgs(floor(A),14). + + % binary operations + :-$sysflgs(A+B,1). + :-$sysflgs(A-B,2). + :-$sysflgs(A*B,3). + :-$sysflgs(A/B,4). + :-$sysflgs(A mod B,5). + :-$sysflgs(A /\ B,6). + :-$sysflgs(A\/B,7). + :-$sysflgs(A<>B,9). + :-$sysflgs(A//B,10). + :-$sysflgs(A^B,11). + +% Unary predicates + +'$+'(A,X) :- 131. +'$-'(A,X) :- 132. +'$\'(A,X) :- 133. +$exp(A,X) :- 134. +$log(A,X) :- 135. +$log10(A,X) :- 136. +$sqrt(A,X) :- 137. +$sin(A,X) :- 138. +$cos(A,X) :- 139. +tan(A,X) :- 140. +$asin(A,X) :- 141. +$acos(A,X) :- 142. +$atan(A,X) :- 143. +$floor(A,X) :- 144. + +% Binary operations + +'$+'(A,B,X) :- 151. +'$-'(A,B,X) :- 152. +'$*'(A,B,X) :- 153. +'$/'(A,B,X) :- 154. +$mod(A,B,X) :- 155. +'$/\'(A,B,X) :- 156. +'$\/'(A,B,X) :- 157. +'$<<'(A,B,X) :- 158. +'$>>'(A,B,X) :- 159. +'$//'(A,B,X) :- 160. +'$^'(A,B,X) :- 161. + +X is Y :- 40. +X =:= Y :- 41. +X =\= Y :- 42. +X < Y :- 43. +X > Y :- 44. +X =< Y :- 45. +X >= Y :- 46. + +var(X) :- 50. +nonvar(X) :- 51. +integer(X) :- 52. +number(X) :- 91. +atomic(X) :- 53. +atom(X) :- 59. +primitive(X) :- 118. +db_reference(X) :- 119. + +statistics :- 93. + +prompt(_,_) :- 31. +exists(user) :- !. +exists(_) :- 32. +$save(F,I) :- 33. + +save(F) :- $save(F,_). +save(F,I) :- $save(F,I). + +X=X. +functor(T,F,N) :- 56. +arg(N,T,A) :- 57. +X=..L :- 58. +name(X,L) :- 75. + +A == B :- 54. +A \== B :- 55. +A @< B :- 86. +A @> B :- 87. +A @=< B :- 88. +A @>= B :- 89. + +clause(P,Q) :- !, $checkkey(P), $clause((P:-Q),R,P). +clause(P,Q,R) :- var(R), !, $checkkey(P), $clause((P:-Q),R,P). +clause(P,Q,R) :- instance(R,(P:-Q)). +assert(C) :- 61. assertz(C) :- 61. +asserta(C) :- 62. +assert(C,R) :- 63. assertz(C,R) :- 63. +asserta(C,R) :- 64. +$clause(_,_,_) :- 65. $clause(_,_,_):-66. + +retract(C) :- $retract(C). + +$retract(V) :- var(V), !, fail. +$retract( (Head :- Body) ) :- + !, + clause(Head,Body,ID), + erase(ID). +$retract( UnitClause ) :- + clause(UnitClause,true,ID), + erase(ID). + +abolish(Pred,Arity) :- 173. + +$recorded(_,_,_) :- 67. $recorded(_,_,_):-68. +recorded(K,T,R) :- $checkkey(K), $recorded(T,R,K). +$checkkey(K) :- (var(K);primitive(K)),!, + ttynl,display('! invalid key to data base'),ttynl,trace,fail. +$checkkey(_). +recorda(K,T,R) :- $checkkey(K), $recorda(K,T,R). +recordz(K,T,R) :- $checkkey(K), $recordz(K,T,R). +$recorda(_,_,_) :- 73. +$recordz(_,_,_) :- 74. +instance(R,T) :- 69. +erase(R) :- 60. +erased(R) :- 92. + +$leash(P,N) :- 78. +$debug(P,N) :- 79. +current_atom(A) :- 80. +current_atom(A) :- 81. +$current_functor(A,N,K,M) :- 82. +$current_functor(A,N,K,M) :- 83. +current_functor(A,P) :- nonvar(P),!, functor(P,A,_). +current_functor(A,P) :- + current_atom(A), + $current_functor(A,N,0,0), + functor(P,A,N). +current_predicate(A,P) :- + current_atom(A), + $current_functor(A,N,256,2'11100000), + functor(P,A,N). + +$flags(F,P,N) :- 84. +compare(Op,T1,T2) :- 85. +trace :- 72. + +'NOLC' :- 70. +'LC' :- 71. + + % Various hacky system predicates + + :-$sysp($break(_),102). + :-$sysp($exit_break,103). + $prompt(_) :- 104. + $user_exec(_) :- 105. + :-$sysp($save_read_vars,106). + :-$sysp($reset_read_vars,107). + :-$sysp($repply,108). + $recons(_) :- 109. + :-$sysp($break_start,110). + :-$sysp($break_end,111). + $assertr(_) :- 112. + :-$sysp($rest_in_peace,113). + $user_call(_) :- 114. + $repeat :- 3. + $read(X) :- 17. + + % How to get out (various mnemonics) + + :- $sysp(halt,113). + +%----------------------------------------------------------------------- + +% Interpreter control + +$live:- $cycle(0), $rest_in_peace. % this is the Prolog session goal + +$cycle(0):- + prompt(Old,'| '), + $repeat, + $prompt('| ?- '), $read(C), + $interpret(C,0), + prompt(_,Old), + !. + +$cycle(Status):- + prompt(Old,'| '), + $repeat, + $read(C), + $interpret(C,Status), + prompt(_,Old), + !. + +$interpret(C,Status) :- + var(C), + !, + display('! Statement is a variable'), + ttynl, + fail. + +$interpret(end_of_file,_):-!. + +$interpret(C,Status):- + $directive(C,Status,D,T), + !, + prompt(Old,'|: '), + $dogoal(T,D), + prompt(_,Old), + fail. + +$interpret(C,Status):- + expand_term(C,C1), + $assert(C1), + !, + fail. + +$assert(C):-$assertr(C),!. +$assert(C):- + seeing(user), + !. +$assert(C):- + display('! clause: '), + display(C). + +$directive(:-(X),_,X,command) :- !. +$directive(?-(X),_,X,question) :- !. +$directive(X,0,X,question). + +$dogoal(command,C) :- + $user_exec(C), + !. + +$dogoal(command,_) :- + !, + ttynl, display('?'), + ttynl. + +$dogoal(question,Q) :- + $save_read_vars, + $user_exec(Q), + $repply, + ttynl, + $show_break_level, + display(yes), + $reset_read_vars, + ttynl, + !. + +$dogoal(question,_) :- + ttynl, + $show_break_level, + display(no), + $reset_read_vars, + ttynl, + !. + + +/* consult and reconsult */ + +consult(X):-!, $break($csult(0,X)). + +reconsult(X) :- $break($csult(1,X)). + +[X|Rest] :- $conlist([X|Rest]). + + $conlist([]) :- !. + $conlist([-X|Rest]) :- !, reconsult(X), $conlist(Rest). + $conlist([X|Rest]) :- !, consult(X), $conlist(Rest). + + +$csult(R,F) :- + S0 is heapused, + T0 is cputime, + $recons(R), + $checkfile(F), + $read_file(F,consult), + Tt is cputime-T0, + Ts is heapused-S0, + display(F), $dpr(R), display(Ts), display(' bytes '), + display(Tt), display(' sec.'), ttynl, + fail. +$csult(R,F) :- $exit_break. + +$dpr(0) :- !, display(' consulted '). +$dpr(1) :- display(' reconsulted '). + +$read_file(F,S) :- + seeing(I), + telling(O), + see(F), + $cycle(S), + close(F), + see(I), + tell(O), + fail. +$read_file(_,_). + +$checkfile(F) :- + (atom(F); + ttynl, display('! Invalid file name: '), + display(F), ttynl, fail + ), + !, + (exists(F); + ttynl, display('! The file '), display(F), + display(' does not exist.'), ttynl, fail + ), + !. + +/* break */ + +break :- $break($break). + +$break :- + $break_start, + $read_file(user,0), + $break_end, + $exit_break. +$break :- $exit_break. % just to make sure + +$show_break_level :- + B is breaklevel, + $shb(B). + +$shb(0) :- !. +$shb(N) :- ttyput("["), display(N), ttyput("]"), ttyput(" "). + +/* Arithmetic expansion */ + +expand_exprs(X,Y) :- + $carith(X0,X0), + $flag_code(X0,X), + nonvar(Y), + $flag_code(Y0,Y), + $carith(_,Y0). + +$carith(X,Y) :- 170. + +$isop(A,P,M,L,R) :- 172. + +current_op(Prio,Type,Atom) :- + $gen_atom(Atom), + $gen_pos(Type,Pos), + $isop(Atom,Pos,Prio,Left,Right), + $op_code(Type,Pos,Prio,Left,Right). + +$gen_atom(Atom) :- atom(Atom), !. +$gen_atom(Atom) :- var(Atom), !, current_atom(Atom). + +$gen_pos(Type,Pos) :- + atom(Type), !, + $type_to_pos(Type,Pos,_,_,_). +$gen_pos(_,Pos) :- + $op_pos(Pos). + +$op_code(Type,Pos,Prio,Left,Right) :- + $type_to_pos(Type,Pos,Prio,LeftExpr,RightExpr), + Left is LeftExpr, Right is RightExpr, !. + +$op_pos(0). % PREFIX (must be the same as in rewrite.c) +$op_pos(1). % INFIX +$op_pos(2). % POSTFIX + +$type_to_pos(fx,0,Prio,Prio,Prio-1). +$type_to_pos(fy,0,Prio,Prio,Prio). +$type_to_pos(xfx,1,Prio,Prio-1,Prio-1). +$type_to_pos(xfy,1,Prio,Prio-1,Prio). +$type_to_pos(yfx,1,Prio,Prio,Prio-1). +$type_to_pos(yf,2,Prio,Prio,Prio). +$type_to_pos(xf,2,Prio,Prio-1,Prio). + +all_float(X,Y) :- + $all_float(X0,X0), + $flag_code(X0,X), + nonvar(Y), + $flag_code(Y0,Y), + $all_float(_,Y0). + +$all_float(X,Y) :- 90. + +$flag_code(1,on). +$flag_code(0,off). + +expand_term(T0,T) :- + term_expansion(T0,T1), !, + $expand_term(T1,T). +expand_term(T0,T) :- $expand_term(T0,T). + +$expand_term(T0,T) :- $translate_rule(T0,T), !. +$expand_term((H:-B0),(H:-B)) :- $compile_arith(B0,B), !. +$expand_term(T,T). + +end_of_file. % needed here for a special reason... diff --git a/source_code/c-prolog-1982/pl/listing b/source_code/c-prolog-1982/pl/listing new file mode 100755 index 0000000..9b93479 --- /dev/null +++ b/source_code/c-prolog-1982/pl/listing @@ -0,0 +1,64 @@ +/* listing : Listing clauses in the database + + Lawrence + Updated: 6 October 81 +*/ + +listing :- + current_predicate(_,Pred), + $list_clauses(Pred). +listing. + + +listing(V) :- var(V), !. % ignore variables +listing([]) :- !. +listing([X|Rest]) :- + !, + listing(X), + listing(Rest). +listing(X) :- + $functorspec(X,Name,Arity), + current_predicate(Name,Pred), + functor(Pred,Name,Arity), + $list_clauses(Pred). +listing(_). + + +$list_clauses(Pred) :- + nl, + clause(Pred,Body), + $write_clause(Pred,Body), + fail. + +$write_clause(Head,Body) :- + writeq(Head), + ( Body = true ; + tab(1), write((:-)), + $write_body(Body,3,',') + ), + put("."), nl, + !. + +$write_body(X,I,T) :- var(X), !, $beforelit(T,I), writeq(X). +$write_body((P,Q), IO, T) :- + !, + $write_body(P,IO,T), + put(","), + $aftercomma(T,IO,I), + $write_body(Q,I,','). +$write_body((P;Q),I,T) :- + !, + nl, tab(I-2), put("("), + $write_body(P,I,'('), + put(";"), + $write_body(Q,I,';'), + tab(1), put(")"). +$write_body(X,I,T) :- + $beforelit(T,I), + writeq(X). + +$aftercomma(',',I,I) :- !. +$aftercomma(_,IO,I) :- I is IO + 3. + +$beforelit('(',_) :- !, tab(1). +$beforelit(_,I) :- nl, tab(I). diff --git a/source_code/c-prolog-1982/pl/protect b/source_code/c-prolog-1982/pl/protect new file mode 100755 index 0000000..20046a4 --- /dev/null +++ b/source_code/c-prolog-1982/pl/protect @@ -0,0 +1,64 @@ +/* protect : Setting the flags for the system predicates + + Fernando Pereira + Updated: 30 December 82 +*/ + + +$mem(X,[X|_]). +$mem(X,[_|Rest]) :- $mem(X,Rest). + +$protected(P,A) :- $unprotected(P,A), !, fail. +$protected(P,A). + +% Predicate flags used here: +% +% +% 128 (PROTECTED) +% 64 (INVISIBLE) +% 32 (UNTRACEABLE) + + +% Cut must be transparent due to the way it is currently +% implemented (this fixes bug that prevented tracing +% past cuts). +% Note that transparent also seem to imply untracable, +% which means you don't see cuts at all. + + :- $sysflgs(!,64). + + + % This list are all transparent and untracable. + + :-(( $mem(X,[ call(_),(A,B),(A;B),$call(_),$hidden_call(_),(A->B)]), + $sysflgs(X,96), fail ; true )). + + % The following predicates are better off invisible so + % they are made untracable as well. + + :-(( $mem(X,[ + write(_), writeq(_), nl, get0(_), get(_), skip(_), put(_), tab(_), + display(_), ttynl(_), ttytab(_), read(_), spy(_), nospy(_), + leash(_), trace, debug, nodebug, debugging + ]), + $sysflgs(X,32), fail ; true )). + + % ALL current predicates but those specified + % by $unprotected are turned into + % system predicates (which cannot be redefined, seen + % by listing etc). + + :-(( current_atom(A), $current_functor(A,Arity,256,0), $protected(A,Arity), + functor(Pred,A,Arity), $flags(Pred,Flags,Flags\/128), fail ; true )). + :- $flags(fail,Flags,Flags\/128). % Must be specially protected (no clauses) + + % Finally, ALL predicates whose names start with a + % dollar are made untraceable and their atoms hidden. + + :-(( current_atom(A), name(A,[36|_]), + $hide_atom(A), % THIS MUST BE IN THE LAST GOAL IN THE BOOT LOAD!! + $current_functor(A,Arity,256,0), + functor(Pred,A,Arity), + $flags(Pred,Flags,Flags\/32), fail ; true )). + + diff --git a/source_code/c-prolog-1982/pl/setof b/source_code/c-prolog-1982/pl/setof new file mode 100755 index 0000000..78caf89 --- /dev/null +++ b/source_code/c-prolog-1982/pl/setof @@ -0,0 +1,166 @@ +/* setof : 'setof', 'bagof' and sorting. */ + +:- op(200,xfy,^). + +setof(X,P,Set) :- + $setof(X,P,Set). + +$setof(X,P,Set) :- + $bagof(X,P,Bag), + sort(Bag,Set0), + Set=Set0. + +bagof(X,P,Bag) :- + $bagof(X,P,Bag). + +$bagof(X,P,Bag) :- + $excess_vars(P,X,[],L), $nonempty(L), !, + Key =.. [$|L], + $bagof(X,P,Key,Bag). +$bagof(X,P,Bag) :- + $tag('$bag','$bag'), + $user_call(P), + $tag('$bag',X), + fail. +$bagof(X,P,Bag) :- $reap([],Bag), $nonempty(Bag). + +$bagof(X,P,Key,Bag) :- + $tag('$bag','$bag'), + $user_call(P), + $tag('$bag',Key-X), + fail. +$bagof(X,P,Key,Bag) :- + $reap([],Bags0), + keysort(Bags0,Bags), + $pick(Bags,Key,Bag). + +$nonempty([_|_]). + +$reap(L0,L) :- + $untag('$bag',X), !, + $reap1(X,L0,L). + +$reap1(X,L0,L) :- X \== '$bag', !, $reap([X|L0],L). +$reap1(_,L,L). + +$pick(Bags,Key,Bag) :- + $nonempty(Bags), + $parade(Bags,Key1,Bag1,Bags1), + $decide(Key1,Bag1,Bags1,Key,Bag). + +$parade([Item|L1],K,[X|B],L) :- $item(Item,K,X), !, + $parade(L1,K,B,L). +$parade(L,K,[],L). + +$item(K-X,K,X). + +$decide(Key,Bag,Bags,Key,Bag) :- (Bags=[], ! ; true). +$decide(_,_,Bags,Key,Bag) :- $pick(Bags,Key,Bag). + +$excess_vars(T,X,L0,L) :- var(T), !, + ( $no_occurrence(T,X), !, $introduce(T,L0,L) + ; L = L0 ). +$excess_vars(X^P,Y,L0,L) :- !, $excess_vars(P,(X,Y),L0,L). +$excess_vars(setof(X,P,S),Y,L0,L) :- !, $excess_vars((P,S),(X,Y),L0,L). +$excess_vars(bagof(X,P,S),Y,L0,L) :- !, $excess_vars((P,S),(X,Y),L0,L). +$excess_vars(T,X,L0,L) :- functor(T,_,N), $rem_excess_vars(N,T,X,L0,L). + +$rem_excess_vars(0,_,_,L,L) :- !. +$rem_excess_vars(N,T,X,L0,L) :- + arg(N,T,T1), + $excess_vars(T1,X,L0,L1), + N1 is N-1, + $rem_excess_vars(N1,T,X,L1,L). + +$introduce(X,L,L) :- $included(X,L), !. +$introduce(X,L,[X|L]). + +$included(X,L) :- $doesnt_include(L,X), !, fail. +$included(X,L). + +$doesnt_include([],X). +$doesnt_include([Y|L],X) :- Y \== X, $doesnt_include(L,X). + +$no_occurrence(X,Term) :- $contains(Term,X), !, fail. +$no_occurrence(X,Term). + +$contains(T,X) :- var(T), !, T == X. +$contains(T,X) :- functor(T,_,N), $upto(N,I), arg(I,T,T1), $contains(T1,X). + +$upto(N,N) :- N > 0. +$upto(N,I) :- N > 0, N1 is N-1, $upto(N1,I). + +/*---------------------------------------------------------------------------- */ +/* Sorting by bisecting and merging. */ + +sort(L,R) :- length(L,N), $sort(N,L,_,R1), R=R1. + +$sort(2,[X1|L1],L,R) :- !, $comprises(L1,X2,L), + compare(Delta,X1,X2), + (Delta = (<) , !, R = [X1,X2] + ; Delta = (>) , !, R = [X2,X1] + ; R = [X2] + ). +$sort(1,[X|L],L,[X]) :- !. +$sort(0,L,L,[]) :- !. +$sort(N,L1,L3,R) :- + N1 is N//2, N2 is N-N1, + $sort(N1,L1,L2,R1), + $sort(N2,L2,L3,R2), + $merge(R1,R2,R). + +$merge([],R,R) :- !. +$merge(R,[],R) :- !. +$merge(R1,R2,[X|R]) :- + $comprises(R1,X1,R1a), $comprises(R2,X2,R2a), + compare(Delta,X1,X2), + (Delta = (<) , !, X = X1, $merge(R1a,R2,R) + ; Delta = (>) , !, X = X2, $merge(R1,R2a,R) + ; X = X1, $merge(R1a,R2a,R) + ). + +$comprises([X|L],X,L). + +/*------------------------------------------------------------------------ */ +/* Sorting on keys by bisecting and merging. */ + +keysort(L,R) :- length(L,N), $keysort(N,L,_,R1), R=R1. + +$keysort(2,[X1|L1],L,R) :- !, + $comprises(L1,X2,L), + $compare_keys(Delta,X1,X2), + (Delta = (>) , !, R = [X2,X1] ; R = [X1,X2] ). +$keysort(1,[X|L],L,[X]) :- !. +$keysort(0,L,L,[]) :- !. +$keysort(N,L1,L3,R) :- + N1 is N//2, N2 is N-N1, + $keysort(N1,L1,L2,R1), + $keysort(N2,L2,L3,R2), + $keymerge(R1,R2,R). + +$keymerge([],R,R) :- !. +$keymerge(R,[],R) :- !. +$keymerge(R1,R2,[X|R]) :- + $comprises(R1,X1,R1a), $comprises(R2,X2,R2a), + $compare_keys(Delta,X1,X2), + (Delta = (>) , !, X = X2, $keymerge(R1,R2a,R) + ; X = X1, $keymerge(R1a,R2,R) + ). + +$compare_keys(Delta,K1-X1,K2-X2) :- compare(Delta,K1,K2). + +/*======================================================================*/ + +X^P :- P. + +/*======================================================================*/ + +$tag(Key,Value) :- + recorda(Key,Value,_). + +$untag(Key,Value) :- + recorded(Key,Value,Ref), + erase(Ref). + +length([],0) :- !. +length([_|L],N) :- !, length(L,N0), N is N0+1. diff --git a/source_code/c-prolog-1982/pl/tracing b/source_code/c-prolog-1982/pl/tracing new file mode 100755 index 0000000..88f038d --- /dev/null +++ b/source_code/c-prolog-1982/pl/tracing @@ -0,0 +1,147 @@ +% tracing : trace control + +debug :- + $debug(P,1), + ( P=1 ; + display('Debug mode switched on.'), ttynl + ), !. + +nodebug :- + $debug(P,0), + ( P=0 ; + ( $someleft, $allspyremove, + display('All spy-points removed.'), ttynl ; + true + ), + display('Debug mode switched off.'), ttynl + ), !. + +spy(X) :- $spy(X,on), $someleft, debug, fail. +spy(_). + +nospy(X) :- $spy(X,off), fail. +nospy(_). + +leash(X) :- nonvar(X), + $leashcode(X,N), + $leash(P,N), + $prleash(N), !. +leash(X) :- + display('! Invalid leash specification : '), + display(X), ttynl, fail. + +$leashcode(full,2'1111) :- !. +$leashcode(on,2'1111):- !. +$leashcode(half,2'1010) :- !. +$leashcode(loose,2'1000) :- !. +$leashcode(off,2'0000) :- !. +$leashcode(N,N) :- integer(N), N>=0, N=<2'1111, !. + + +$prleash(0) :- !, display('No leashing.'), ttynl. +$prleash(N) :- + $leashcode(Code,N), + display('Leashing set to '), display(Code), + display(' ('),$pcl(Had,2'1000,N,call), + $pcl(Had,2'0100,N,exit), + $pcl(Had,2'0010,N,backto), + $pcl(Had,2'0001,N,fail), + display(').'),ttynl. + +$pcl(Had,M,N,W) :- N/\M =:= 0, !. +$pcl(Had,_,_,W) :- + ( var(Had),Had=yes ; + display(',') + ), + display(W), !. + +debugging :- $debug(D,D), + ( D=0, !, + display('Debug mode is switched off.'), + ttynl, ! ; + display('Debug mode is switched on.'), ttynl, + ( $someleft, !, + display('Spy-points set on : '),ttynl, + ( current_atom(Functor), + $current_functor(Functor,Arity,2'100010000,2'11110000), + ttytab(8), $prspy(Functor,Arity), ttynl, fail ; + true + ) ; + display('There are no spy-points set.'), ttynl + ), + $leash(L,L), $prleash(L) ), !. + +$spy(V,_) :- var(V), !, + display('! Invalid procedure specification : '), + display(V),ttynl. +$spy([],_) :- !. +$spy([HD|TL]):- !, + $spy(HD), + $spy(TL). +$spy(X,off) :- + $functorspec(X,Functor,Arity), + ( var(Arity) ; A=Arity ), + ( $current_functor(Functor,A,2'100010000,2'11110000), + !, + ( $current_functor(Functor,Arity,2'100010000,2'11110000), + functor(T,Functor,Arity), $flags(T,P,P/\2'11101111), + display('Spy-point on '), $prspy(Functor,Arity), + display(' removed.'), ttynl, fail + ; true + ) + ; display('There is no spy point on'), + display(X), display('.'), ttynl + ), !. + +$spy(X,on) :- + $functorspec(X,Functor,Arity), + ( atom(X), + ( $current_functor(Functor,Arity,2'100000000,2'11110000), + functor(Head,Functor,Arity), + $enter(Head,Functor,Arity), + fail + ; ( $current_functor(Functor,_,2'100000000,2'11100000) ; + display('You have no clauses for '), display(X), + display(' - nothing done.'), ttynl + ) ) + ; functor(Head,Functor,Arity), + ( $current_functor(Functor,Arity,256,2'111100000) + ; display('[ Warning: you have no clauses for '), + $prspy(Functor,Arity), display(' ]'), ttynl + ), + $enter(Head,Functor,Arity) + ), + !. + +$spy(_,_). + + +$enter(Head,Functor,Arity) :- + ( $current_functor(Functor,Arity,2'100010000,2'11110000), + display('There already is a spy-point on '); + $flags(Head,P,P), + ( P/\2'11100000 =:= 0, $flags(Head,P,P\/2'10000) ; true), + display('Spy-point placed on ') + ), + $prspy(Functor,Arity), + display('.'), ttynl, !. + +$prspy(Functor,Arity) :- + display(Functor), display(/), display(Arity). + +$someleft :- current_atom(A), $current_functor(A,_,2'10000,2'10000), !. + +$allspyremove :- + current_atom(F), + $current_functor(F,A,2'100010000,2'11110000), + functor(T,F,A), $flags(T,P,P/\2'11101111), fail. +$allspyremove. + +$functorspec(V,_,_) :- var(V),!, $badspec(V). +$functorspec(X,X,_) :- atom(X),!. +$functorspec(F/N,F,N) :- atom(F), integer(N), !. +$functorspec(X,_,_) :- $badspec(X). + +$badspec(X) :- display('! Invalid procedure specification : '), + display(X), ttynl, fail. + diff --git a/source_code/c-prolog-1982/pl/vmsall b/source_code/c-prolog-1982/pl/vmsall new file mode 100755 index 0000000..fd53a1a --- /dev/null +++ b/source_code/c-prolog-1982/pl/vmsall @@ -0,0 +1,17 @@ +/* PL_ALL : Load all the current bits of the standard Prolog system + + Fernando + Updated: 16 Nov 82 +*/ + +:-([ + '[.pl]arith', % arithmetic expansion + '[.pl]grammar', % DCG grammar rule translation + '[.pl]setof', % Setof and sorting + '[.pl]tracing', % Debugging evaluable predicates + '[.pl]listing' % Listing the database + ]). + + +:-([ '[.pl]protect' ]). % Lock things up + diff --git a/source_code/c-prolog-1982/prolog b/source_code/c-prolog-1982/prolog new file mode 100755 index 0000000000000000000000000000000000000000..c690b533508d77762e330dd79b2c2958a4c282c8 GIT binary patch literal 230240 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�!%9Fg|#T`h%r^> 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 G*Z&vcYIwB( literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/read.me b/source_code/c-prolog-1982/read.me new file mode 100755 index 0000000..be3124a --- /dev/null +++ b/source_code/c-prolog-1982/read.me @@ -0,0 +1,258 @@ +*********************************************************************** +* * +* C Prolog * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +*********************************************************************** + + ********* WARNING ********* + +Both the location (defined in parms.c) and the contents of the startup save +state (startup) on this tape are unlikely to be correct for your +installation. Please follow the instructions below to adapt parms.c to your +installation and to build a new startup save state. + + -------------------------- +C-Prolog 1.5 20 Feb 84 + +Extended manual, many bug fixes and improvements. +In particular, the debugger has been almost entirely rewritten and +now has the `retry' command a la DEC-10 Prolog. This should make +debugging much smoother. The command line switches that specify +the sizes of working areas have been changed to be lower-case to +avoid a problem with the VMS C implementation. The system has +been checked under VMS, Eunice, and Berkeley Unix on VAXes and Suns. + +Identifiers have been changed to avoid name clashes in systems with +Version 7 or System III C compilers. The system has not been tested +on those systems, but it should now run in them with few modifications +if any. + +The printout of the 'g' debugger command has been changed. Goals +shown are preceded by + + l (i)->(c) + +where l is the recursion level, i the invocation number and c +the position of the clause being used within its procedure. + +C-Prolog 1.4 28 July 83 + + +Revised and expanded manual. + +The compilation switch IEEE (see makefile) allows compilation of +C-Prolog for implementations of 4.1/2 BSD Unix on machines with +IEEE floating point (such as the SUN workstation). + +There are command line switches to specify the sizes of the various +work areas of C-Prolog; adjustment between the sizes in a saved state +and a starting C-Prolog is automatic. +The switches are -H (heap), -G (global stack), -L (local stack), +-T (trail), -A (atom space) and -X (auxiliary stack). each such switch +should be followed by an integer argument that specifies the size in +K bytes (see new version of the manual). + +There is a 'statistics' evaluable predicate that prints out the +sizes and used amounts of the various work areas. + +The operation of expand_term has been cleaned up and as a result +a new name, term_expansion, has been given to the user defined +part of expand_term. + +Several bugs have been fixed. + +C-Prolog 1.3 24 June 83 + +The 'g' command to the debugger prints a stack backtrace in reverse +order, with goals labeled by the distance from the current goal and +by the position with its procedure of the clause being used to satisfy +the goal. + +The debugger now shows and stops at FAIL ports, like the one on DEC-10/20 +Prolog. + +Several bugs have been fixed. + +--------------------------------------------------------------------- + +CProlog 1.2b 9 May 83 + +To install CProlog: + +Decide on names and locations for the interpreter and its startup file. +Let's say you have decided on /usr/local/prolog for the interpreter +and /usr/local/prolog-startup for the startup file, and that you have +write access to the relevant directories, etc. Then you just need to +type the following command + + make install BIN=/usr/local/prolog PLSTARTUP=/usr/local/prolog-startup + +When this finishes, the system will be ready to use. +These instructions supersede the previous ones below. + +================================================================ + +Differences between CProlog 1.2a and 1.2 - 17 February 83 + +- A bug which reported a syntax error in \+ (p,q) has been fixed. + +- A bug which caused atoms containing % to be printed without quotes by +'writeq' has been fixed + +- A serious bug in the interaction between nested conjunctions and cut has +been cured. + +- Bugs that caused the system to crash when returning from some functions in +sysbits.c have been fixed. + +Outstanding problems: + +The types and casts in the sources of the system should be cleaned up to +comform to the requirements of C compilers that are more strict than the +Berkeley 4.1 compiler. + +News: + +The system has now been ported to the Apollo M68000-based workstation and to +the 3 Rivers PERQ. + +Differences between CProlog 1.2 and previous versions +Fernando Pereira, 6 Jan 83 + +New evaluable predicates: + +primitive(X) + + Tests whether X is a primitive object (number or database reference). + +db_reference(X) + + Tests whether X is a database reference. + +sh (UNIX only) + + Forks a sub-shell (the one specified in the environment variable + SHELL, or "/bin/sh" if that is undefined) + +system(S) (UNIX only) + + Similar to the 'system' function defined in Section 3 of the UNIX + manual. S should be a Prolog string, for example + + sh("ls") + + +Changed features + +The operation of the debugger has been somewhat improved: + + It is no longer necessary to call 'trace' to see spy points. + + 'trace' starts tracing from the next call to a user goal, even + if that user goal is called from the command immediately after the + command that invoked 'trace'. In previous versions, 'trace' had + to be called in the same command as the goal(s) to be traced. + +Cuts inside "metacalled" goals (goals called through the evaluable predicate +'call' or a variable goal) no longer behave as if they appeared on the +calling clause. That is, in previous versions, the program + + p(X) :- X = 1, P = !, call(P). + p(2). + +would have just one solution X = 1, and now has the two solutions X = 1 and X += 2. The reason for the referentially non-transparent behaviour of the +earlier versions was a bogus definition of the effect of 'call' in the +DEC-10/20 Prolog manual, on which CProlog is based. The DEC-10/20 system DOES +NOT behave as its manual states. CProlog version 1.2 and DEC-10/20 Prolog +(version 3 or above) are therefore compatible in this respect. + +Numbers preceded by '-', eg. + + -1.2 -1 + +are treated by the reader as negative numbers, instead of as the unary +operator '-' applied to a positive number. + +Bugs fixed + +Lots! I've not kept track... + +================================================================ + +Things to know about CProlog version 1.1: + +When it starts, CProlog reads in a saved state with essential initialisation +data. In the distributed version, this file should be placed in + + /usr/local/lib/prolog/.plstartup + +If you want to change this, edit parms.c and recompile the system. The +actual file is in this directory with name PLSTARTUP. + +The startup saved state can be reconstructed in the following way: + + cd into this directory + prolog -b pl/init + ['pl/all']. + :-save(startup). + halt. + +The startup file is now 'startup' in this directory, and you should move it +to its final place as described above. + +Various system parameters, such as the name of the startup file and the +sizes of work areas, are defined in the file parms.c. To change any of these +parameters, edit this file and recompile the system using 'make'. If you +change these parameters, old saved states should still work with the new +system. However, I suspect there may be bugs in this area. + + +Differences between this system and other similar Prolog systems (DEC-10/20 +Prolog, EMAS Prolog and PDP-11 Prolog): + +* Floating point! In particular, / is floating divide and // integer divide. +Beware of this if you are moving programs from other Prologs. Most of the +math functions in the C library are available as arithmetic operators, eg. +you may write a goal + + X is 3.5e2+sin(sqrt(Y)) + +* database references returned by recorda/z and friends can be used in +terms/clauses to be recorded/asserted; + +* prompting for alternatives at top level is like on DEC-10 Prolog, not like +on EMAS or PDP-11 Prolog. + +* setof, bagof, compare, sort, keysort, @<, @=<, @>, @>= are available, and +the same as in DEC-10 Prolog. Setof and bagof are very slow, though. + +A preliminary version of the user's manual for CProlog is in the directory +'man'. A printable version can be made with the makefile there. The manual +will print better if your output device can produce bold-face (we have a +local version of 'nroff' that produces "bold" on line-printers by +overstriking). + +Known Bugs +========== + +***** FIXED in 1.2 ***** +The system accepts without complaint clauses whose body is a single integer, +and then behaves strangely when such clauses are used. The cause of this is +the mechanism for linking from Prolog to C to implement the evaluable +predicates, which relies on clauses of that form. Some check should be made +to forbid such clauses except when bootstrapping the system. +********* + +Saved states should survive a change in the sizes of the work areas. They +seem to survive sometimes, but not always. No known cure at present. diff --git a/source_code/c-prolog-1982/rewrite.c b/source_code/c-prolog-1982/rewrite.c new file mode 100755 index 0000000..62dfe71 --- /dev/null +++ b/source_code/c-prolog-1982/rewrite.c @@ -0,0 +1,818 @@ +/********************************************************************** +* * +* C Prolog rewrite.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +#include "pl.h" + +#define Isatoz(a) ('a' <= (AtomP(a)->stofae)[1] && \ + (AtomP(a)->stofae)[1] <= 'z') + +#define PREFIX 0 +#define INFIX 1 +#define POSTFIX 2 + +/* decrease left priority flag */ + +#define dlprflg 0x2000 + +/* decrease rigth priority flag */ + +#define drprflg 0x1000 + +/* priority field */ + +#define mskprty 0x0fff + +/* Character types for tokeniser */ + +#define UC 1 /* Upper case alphabetic */ +#define UL 2 /* Underline */ +#define LC 3 /* Lower case alphabetic */ +#define N 4 /* Digit */ +#define QT 5 /* Single quote */ +#define DC 6 /* Double quote */ +#define SY 7 /* Symbol character */ +#define SL 8 /* Solo character */ +#define BK 9 /* Brackets & friends */ +#define BS 10 /* Blank space */ + +static char chtyp[] = { +/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ + BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, + +/* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ + BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, + +/* sp ! " # $ % & ' ( ) * + , - . / */ + BS, SL, DC, SY, LC, SL, SY, QT, BK, BK, SY, SY, BK, SY, SY, SY, + +/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + N, N, N, N, N, N, N, N, N, N, SY, SL, SY, SY, SY, SY, + +/* @ A B C D E F G H I J K L M N O */ + SY, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, + +/* P Q R S T U V W X Y Z [ \ ] ^ _ */ + UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, BK, SY, BK, SY, UL, + +/* ` a b c d e f g h i j k l m n o */ + SY, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, + +/* p q r s t u v w x y z { | } ~ del */ + LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, BK, BK, BK, SY, BS }; + +PTR term(); + + +int +isop(atom,optype,p,lp,rp) +PTR atom; int optype, *p, *lp, *rp; +{ + short oe; + + switch (optype) { + case PREFIX: + oe = AtomP(atom)->prfxofae; + break; + case INFIX: + oe = AtomP(atom)->infxofae; + break; + case POSTFIX: + oe = AtomP(atom)->psfxofae; + break; + default: + return FALSE; + } + if (oe < 0) return FALSE; + *p = oe&mskprty; + *lp = !(oe&dlprflg) ? *p : *p-1; + *rp = !(oe&drprflg) ? *p : *p-1; + return TRUE; +} + +op(prio,optype,spec) +PTR prio, optype, spec; +/* processes op declarations */ +{ + int c, i, pr, typ; PTR spf, at; + static char + *OpTypes[] = { "xfx", "xfy", "yfx", "xf", "yf", "fx", "fy" }; + static int + optyp[] = { INFIX, INFIX, INFIX, POSTFIX, POSTFIX, PREFIX, PREFIX }; + char *ops; + + if (!IsInt(prio)) return FALSE; + pr = XtrInt(prio); + if (pr > 1200 || pr <= 0) return FALSE; + if (!IsAtomic(optype) || IsPrim(optype)) return FALSE; + ops = AtomP(optype)->stofae; + c = -1; + for (i = 0;i < 7; i++) + if (!strcmp(ops,OpTypes[i])) { + c = i; + break; + } + if (c < 0) return FALSE; + typ = optyp[c]; + c = 1<<(c+1); + if (c&0x16) pr |= dlprflg; + if (c&0x4a) pr |= drprflg; + spec = vvalue(spec,&spf); + do { + if (IsntName(spec) || IsRef(spec)) return FALSE; + if (IsComp(spec)) { + if (SkelP(spec)->Fn != listfunc) return FALSE; + at = arg(Addr(SkelP(spec)->Arg1),spf); + if (IsntName(at) || IsRef(at)) return FALSE; + spec = argv(Addr(SkelP(spec)->Arg2),spf,&spf); + } else + at = spec, spec = atomnil; + switch (typ) { + case PREFIX: + AtomP(at)->prfxofae = pr; + break; + case INFIX: + AtomP(at)->infxofae = pr; + break; + case POSTFIX: + AtomP(at)->psfxofae = pr; + } + } while (spec != atomnil); + return TRUE; +} + +static +legalatom(s) +char *s; +{ + char c; + + c = chtyp[*s]; + if (c == LC) { + while (c = chtyp[*s], *s++) if (c > N) return FALSE; + return TRUE; + } + if (c == SL) return (s[0] != '%' && !s[1]); + if (c != SY) return FALSE; + if (!strcmp(s,"/*") || !strcmp(s,".")) return FALSE; + while (c = chtyp[*s], *s++) if (c != SY) return FALSE; + return TRUE; +} + +static +patom(at) +PTR at; +{ + char ch, *s; + s = AtomP(at)->stofae; + if (!quoteia || legalatom(s)) { + PutString(s); + return; + } + Put('\''); + while ((ch = *s++)) { + if (ch == '\'') Put(ch); + Put(ch); + } + Put('\''); +} + +/* pwrite - write a prolog term */ + +pwrite(t,g,p) +PTR t, g; int p; +/* write term t in context of priority p + with global frame g +*/ +{ + int i, m, mr, ml; PTR ax, f, a; + if (IsPrim(t)) { + if (IsInt(t)) { + sprintf(OutBuf,"%d",XtrInt(t)); PutString(OutBuf); + return; + } + if (IsFloat(t)) { + sprintf(OutBuf,"%g",XtrFloat(t)); PutString(OutBuf); + return; + } + sprintf(OutBuf,"%x",t); + PutString(OutBuf); + return; + } + if (IsAtomic(t)) { + patom(t); + return; + } + if (Undef(*t)) { + sprintf(OutBuf,"_%d",t-glb0); PutString(OutBuf); + return; + } + if (IsRef(t)) + g = MolP(t)->Env, t = MolP(t)->Sk; + if (SkelP(t)->Fn == listfunc) { + Put('['); + do { + ax = argv(Addr(SkelP(t)->Arg1),g,&a); + pwrite(ax,a,999); + t = argv(Addr(SkelP(t)->Arg2),g,&g); + } while (IsComp(t) && (MolP(t)->Sk == listfunc) && (Put(','),TRUE)); + if (t != atomnil) { + Put('|'); + pwrite(t,g,999); + } + Put(']'); + return; + } + if (MolP(t)->Sk == assertfunc) { + Put('{'); + ax = argv(Addr(SkelP(t)->Arg1),g,&g); pwrite(ax,g,1200); + Put('}'); + return; + } + f = SkelP(t)->Fn; + i = FunctorP(f)->arityoffe; + a = FunctorP(f)->atoffe; + if (i == 1) { + if (isop(a,PREFIX,&m,&ml,&mr)) { + if (m > p) Put('('); + patom(a); + if (Isatoz(a)) Put(' '); + ax = argv(Addr(SkelP(t)->Arg1),g,&f); + pwrite(ax,f,mr); + if (m > p) Put(')'); + return; + } + if (isop(a,POSTFIX,&m,&ml,&mr)) { + if (m > p) Put('('); + ax = argv(Addr(SkelP(t)->Arg1),g,&f); + pwrite(ax,f,ml); + if (Isatoz(a)) Put(' '); + patom(a); + if (m > p) Put(')'); + return; + } + } + if (i == 2 && isop(a,INFIX,&m,&ml,&mr)) { + if (m > p) Put('('); + ax = argv(Addr(SkelP(t)->Arg1),g,&f); + pwrite(ax,f,ml); + if (Isatoz(a)) Put(' '); + patom(a); + if (Isatoz(a)) Put(' '); + ax = argv(Addr(SkelP(t)->Arg2),g,&f); pwrite(ax,f,mr); + if (m > p) Put(')'); + return; + } + patom(a); + Put('('); + while (i-- > 0) { + ax = argv(++t,g,&f); pwrite(ax,f,999); + if (i > 0) Put(','); + } + Put(')'); + return; +} + + +/*------------------------------------------------------------------- + + pread - read a prolog term + (this function has lots of auxiliary functions, which are listed first) + +*/ + +static int e; + +/* Token types */ + +#define NAME 1 +#define PRIMITIVE 2 +#define VAR 3 +#define STRING 4 +#define PUNCTUATION 5 +#define FULLSTOP 6 + +static int retoken, tokentype, rechar, chtype, errflg; +static char *line, *lp, *lpmax, ch; +static char nam[255]; +static PTR slsp; + +union { + PTR AsPTR; + char AsChar; + char * AsString; +} tokeninfo; + +/* next character from input buffer (in read) +/* allows for single char lookahead */ + +static char +nextch() +{ + if (rechar) { + rechar = FALSE; + return chtype; + } + chtype = chtyp[ch = *++lp]; + if (lp >= lpmax) lp = lpmax-2; + return chtype; +} + + +/* look up variable name in variable table (in read) */ + +PTR +lookupvar(id) +char *id; +{ + PTR p; VarP r, q; int l; + + if (!strcmp(id,"_")) { + p = v1; *v1 = NULL; GrowGlobal(1); + return p; + } + for (q = varchain, r = NULL; q; r = q, q = q->NextVar) + if (!strcmp(q->VarName,id)) return q->VarValue; + l = Words(sizeof(VarEntry)+strlen(id))+1; + q = (VarP)varfp; + varfp += l; + HighTide(varfp,Auxtide); + if (varfp > auxmax) NoSpace(AuxId); + Unsafe(); + nvars++; + if (r) + r->NextVar = q; + else + varchain = q; + strcpy(q->VarName,id); + q->NextVar = NULL; + q->VarValue = p = v1; *v1 = NULL; + q->VarLen = l; + Safe(); + GrowGlobal(1); + return p; +} + + +/* report a syntax error and wind things up (in read) */ + +static +SyntaxError() +{ + char *i; + + rechar = FALSE; retoken = FALSE;; + if (errflg) { + lp = lpmax-2; + return; + } + fprintf(stderr,"\n***Syntax error***\n"); + for (i = line; i <= lpmax; i++) { + if (i == lp) + fprintf(stderr,"\n**here**\n"); + putc(*i,stderr); + } + lp = lpmax-2; errflg = TRUE; +} + + +/* token - tokeniser (in read) */ + +static int +token() +{ + int v, l; + + if (retoken) { + retoken = FALSE; + return tokentype; + } + start: + switch (nextch()) { + case BS: goto start; + + case UC: /* uppercase letter */ + v = lc; goto id; + + case UL: /* underline */ + v = 1; goto id; + case LC: /* lowercase letter */ + v = 0; + id: /* common to both variables and atoms */ + rechar = TRUE; l = 0; + while (nextch() <= N) { + if ((!lc) && (!v) && ch>='A' && ch<='Z') ch += 32; + nam[l++]=ch; + } + nam[l] = 0; + rechar = TRUE; + if (v) { + tokentype = VAR; + tokeninfo.AsPTR = lookupvar(nam); + return VAR; + } + tokentype = NAME; + tokeninfo.AsPTR = lookup(nam); + return NAME; + case N: /* digit */ + if (*(lp+1) == '\'') { + lp++; v = ch-'0'; l = 0; + while (nextch() == N) + l = l*v+ch-'0'; + tokeninfo.AsPTR = ConsInt(l); + rechar = TRUE; + return tokentype = PRIMITIVE; + } + if (!NumberString(&lp,&tokeninfo.AsPTR,TRUE)) + SyntaxError(); + return tokentype = PRIMITIVE; + case QT: /* single quote */ + v = QT; goto quoted; + + case DC: /* double quote */ + v = DC; + quoted: + l = 0; + while (nextch() != v || nextch() == v) { + nam[l++] = ch; + if (l >= 228) SyntaxError(); + } + nam[l] = 0; + rechar = TRUE; + if (v == QT) { + tokentype = NAME; tokeninfo.AsPTR = lookup(nam); + return NAME; + } + tokentype = STRING; tokeninfo.AsString = nam; + return STRING; + + case SY: /* symbol char */ + if (ch =='/' && *(lp+1) == '*') { + do + chtype = nextch(); + while (ch != '*' || *(lp+1) != '/'); + lp++; goto start; + } + l = 1; nam[0] = ch; + if (ch == '.') { /* full stop is a special case */ + if (nextch() == BS ) { + tokentype = FULLSTOP; lp--; + return FULLSTOP; + } + rechar = TRUE; + } + while (nextch() == SY) + nam[l++] = ch; + nam[l] = 0; + rechar = TRUE; + tokentype = NAME; tokeninfo.AsPTR = lookup(nam); + return NAME; + + case SL: /* solo char */ + nam[0] = ch; nam[1] = 0; + tokentype = NAME; tokeninfo.AsPTR = lookup(nam); + return NAME; + + case BK: /* ponctuation char */ + if (ch == '[' && *(lp+1) == ']') { + tokentype = NAME; strcpy(nam,"[]"); lp++; + if (atomnil) + tokeninfo.AsPTR = atomnil; + else tokeninfo.AsPTR = lookup(nam); + return NAME; + } + tokentype = PUNCTUATION; tokeninfo.AsChar = ch; + return PUNCTUATION; + } +} /* end of tokeniser */ + +/* readargs - parse arguments of a term (in read) */ + +static PTR +readargs(atom) +PTR atom; +{ + PTR savelsp, e; int a; + + savelsp = lsp; a = 0; + chtype = nextch(); /* pass over ( */ + do { + *lsp++ = term(999); a++; + } while (token() == PUNCTUATION && tokeninfo.AsChar == ','); + if (tokentype != PUNCTUATION || tokeninfo.AsChar != ')') + SyntaxError(); + e = apply(atom,a,savelsp); + lsp = savelsp; + return e; +} + + +/* stringtolist - string to list of chars (in read) */ + +static PTR +stringtolist() +{ + PTR savelsp; int n; register char c, *l; + + if (nam[0]==0) return atomnil; + savelsp = lsp; + for (l = nam; c = *l; l++) + *lsp++ = ConsInt(c); + n = l-nam; + *lsp = atomnil; lsp = savelsp; + return makelist(n+1,savelsp); +} + +/* readlist - parse a prolog list (in read) */ + +PTR +readlist() +{ + PTR savelsp, e; int n; + + savelsp = lsp; n = 1; + while (TRUE) { + *lsp++ = term(999); n++; + if (token() == PUNCTUATION && tokeninfo.AsChar == ',') { + if (token() == NAME && !strcmp(nam,"..")) { + e = term(999); + break; + } + else retoken = TRUE; + } + else { + if (tokentype == PUNCTUATION && tokeninfo.AsChar == '|') + e = term(999); + else { + e = atomnil; retoken = TRUE; + } + break; + } + } + *lsp = e; lsp = savelsp; + return makelist(n,savelsp); +} + + +/* term - parse token stream to get term (in read) */ + +static PTR +term(n) +int n; +{ + int m, m1, ml, mr; PTR e[2], s; + + if (errflg) return NULL; + m = 0; + switch (token()) { + case NAME: /* a name */ + if (*lp == '(') { + e[0] = readargs(tokeninfo.AsPTR); + break; + } + if (isop(tokeninfo.AsPTR,PREFIX,&m,&ml,&mr)) { + e[0] = s = tokeninfo.AsPTR; + if (token() == PUNCTUATION && + (tokeninfo.AsChar != '(' && + tokeninfo.AsChar != '{' && + tokeninfo.AsChar != '[') + || tokentype == FULLSTOP) { + if (m > n) SyntaxError(); + retoken = TRUE; + break; + } + retoken = TRUE; + e[0] = term(mr); + e[0] = (s == Minus && IsNumber(e[0])) ? + (IsFloat(e[0]) ? ConsFloat(-(XtrFloat(e[0]))) + : ConsInt(-(XtrInt(e[0])))) : + apply(s,1,e); + break; + } + e[0] = tokeninfo.AsPTR; + break; + + case PRIMITIVE: /* a primitive type (already encoded) */ + e[0] = tokeninfo.AsPTR; + break; + + case VAR: /* a variable */ + e[0] = tokeninfo.AsPTR; + break; + + case STRING: /* a string */ + e[0] = stringtolist(); + break; + + case PUNCTUATION: /* ponctuation char */ + if (tokeninfo.AsChar == '(') { + e[0] = term(1200); + if (token() != PUNCTUATION || tokeninfo.AsChar != ')') + SyntaxError(); + break; + } + if (tokeninfo.AsChar == '[') { + e[0] = readlist(); + if (token() != PUNCTUATION || + tokeninfo.AsChar != ']') SyntaxError(); + break; + } + if (tokeninfo.AsChar == '{') { + e[0] = term(1200); + if (token() != PUNCTUATION || tokeninfo.AsChar != '}') + SyntaxError(); + e[0] = apply(assertatom,1,e); + break; + } + + case FULLSTOP: /* other poctuation chars or fullstop */ + SyntaxError(); return NULL; + + } + on: + if (errflg) return NULL; + if (token() == NAME) { + if (isop(tokeninfo.AsPTR,INFIX,&m1,&ml,&mr)) { + if (m1 <= n && ml >= m) { + s = tokeninfo.AsPTR; + e[1] = term(mr); + e[0] = apply(s,2,e); + m = m1; + goto on; + } + } + if (isop(tokeninfo.AsPTR,POSTFIX,&m1,&ml,&mr)) { + if (m1 <= n && ml >= m) { + s = tokeninfo.AsPTR; + e[0] = apply(s,1,e); + m = m1; + goto on; + } + } + retoken = TRUE; + return e[0]; + } + + if (tokentype == FULLSTOP) { + retoken = TRUE; + return e[0]; + } + if (tokentype != PUNCTUATION || + tokeninfo.AsChar == '(' || tokeninfo.AsChar == '[') { + SyntaxError(); + return NULL; + } + if (tokeninfo.AsChar == ',' && n >= 1000 && m <= 999) { + e[1] = term(1000); + e[0] = apply(commafunc,2,e); + m = 1000; + if (m < n) goto on; + return e[0]; + } + retoken = TRUE; + return e[0]; + +} /* end of term */ + + +/* the read predicate */ + +PTR +pread() +{ + varchain = NULL; errflg = FALSE; nvars = 0; + lpmax = line = CharP(lsp); + slsp = lsp; + + loop: + ch = Get(); + l1: + chtype = chtyp[ch]; + if (chtype == BS) { + do ch = Get(); while(chtyp[ch] == BS); + *lpmax++ = ' '; + goto l1; + } + if (ch == '%') { + ch = Get(); + if (ch == '(') { + ch = '{'; goto l1; + } + if (ch == ')') { + ch = '}'; goto l1; + } + while (ch != '\n') ch = Get(); + goto loop; + } + *lpmax++ = ch; + if (chtype == QT && lpmax-line > 1 && chtyp[*(lpmax-2)] == N) + chtype = N; + if (ch == '*' && lpmax-line > 1 && *(lpmax-2) == '/') { + lpmax -= 2; + ch = Get(); + do { + while (ch != '*') ch = Get(); + ch = Get(); + while (ch == '*') ch = Get(); + } while (ch != '/'); + goto loop; + } + if ((CharP(vmax)) < lpmax) { + fprintf(stderr, + "! Term too long to read (%d characters)\n",lpmax-CharP(lsp)); + Event(ABORT); + } + if (chtype == QT || chtype == DC) { + do { + ch = Get(); *lpmax++ = ch; + } while(chtyp[ch] != chtype); + goto loop; + } + if (ch == '.' && lpmax-line >= 2 && chtyp[*(lpmax-2)] != SY) { + ch = Get(); + if (chtyp[ch] == BS) goto end; else goto l1; + } + goto loop; + + end: + *lpmax = '\n'; *(lpmax+1) = 0; + lp = line-1; + rechar = retoken = FALSE; + lsp += Words(lpmax-line+1); + e = term(1200); + if (token() != FULLSTOP) SyntaxError(); + if (errflg) e = NULL; +/* for (lp = line; lp <= lpmax; lp++) putchar(*lp); */ + lsp = slsp; + return e; +} + +int +NumberString(s,p,free) +/* Scans the string *s to see if it is a number. If yes, *p takes + the constructed number, and TRUE is returned, otherwise FALSE. + If free is FALSE, the number must reach the end of the string + to be accepted. In all cases, *s is updated to point to the + last character used for the number (oddity courtesy of nextch()) +*/ + +char **s; PTR *p; int free; +{ + double d; int i; char *t, *u, c; + + u = t = *s; + if (*t == '-' || *t == '+') t++; + if (!digits(&t)) goto no; + if (*t == '.') { + t++; + if (!digits(&t)) { + t--; + goto stop; + } + } + if (!*t) goto yes; + if (*t != 'e' && *t != 'E') goto stop; + if (*++t == '-' || *t == '+') t++; + if (!digits(&t)) goto no; + yes: + *s = t-1; + c = *t; + *t = ' '; + sscanf(u,"%F",&d); + *t = c; + if (Narrow(d,&i)) + *p = ConsInt(i); + else + *p = ConsFloat(d); + return TRUE; + stop: + if (free || !*t) goto yes; + no: + *s = t-1; + return FALSE; +} + +static +digits(s) +char **s; +{ + char *t; + + t = *s; + if (chtyp[*t] != N) return FALSE; + while (chtyp[*++t] == N); + *s = t; + return TRUE; +} diff --git a/source_code/c-prolog-1982/rewrite.o b/source_code/c-prolog-1982/rewrite.o new file mode 100755 index 0000000000000000000000000000000000000000..cbb309880819b26acfb8bedbccef6b75a3359eef GIT binary patch literal 27340 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 BHDUk& literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/space.c b/source_code/c-prolog-1982/space.c new file mode 100755 index 0000000..d616b88 --- /dev/null +++ b/source_code/c-prolog-1982/space.c @@ -0,0 +1,405 @@ +/* C Prolog space.c */ + +#include "pl.h" + +#ifdef ERRCHECK +int ReleaseCheck = TRUE; +#endif + +#define CHAINS 16 +#define BUCKET_SIZE 1024 + +typedef struct BLOCK +{ + struct BLOCK *NextBlock; + int BlockSize; +} Block, *BlockP; + +typedef struct +{ + BlockP FirstBlock, LastBlock; +} GCPair, *GCPairP; + +#define MIN_SIZE sizeof(Block)/sizeof(PTR) + +struct { + BlockP free[CHAINS+1]; + PTR top, bottom; + int used, maxused; +} Heap; + +int HeapHeader = sizeof(Heap); + +static int size; +static GCPairP Garbage; +static int Buckets; + +#define FreeChain Heap.free +#define Top Heap.top +#define Bottom Heap.bottom + +#define FreeMisc FreeChain[CHAINS] + +ClearMem(loc,num) +char *loc; +{ +#ifdef vax +#ifdef unix + asm(" movc5 $0,*4(ap),$0,8(ap),*4(ap) "); +#else + register char *l = loc; + register int n = num; + + while (n-- > 0) *l++ = NULL; +#endif +#else + register char *l = loc; + register int n = num; + + while (n-- > 0) *l++ = NULL; +#endif +} + +CopyMem(from,to,cc) +char *from, *to; +{ +#ifdef vax +#ifdef unix + asm(" movc3 12(ap),*4(ap),*8(ap) "); +#else + register char *f = from, *t = to; + register int n = cc; + + if (f < t) { + f += n; + t += n; + while (n-- > 0) *--t = *--f; + } + else while (n-- > 0) *t++ = *f++; +#endif +#else + register char *f = from, *t = to; + register int n = cc; + + if (f < t) { + f += n; + t += n; + while (n-- > 0) *--t = *--f; + } + else while (n-- > 0) *t++ = *f++; +#endif +} + +#define WDPtr(c) ((PTR)(c)) + +InitHeap() +/* Initialize space tables. Do it only once */ +{ + Top = Bottom = skel0; + ClearMem(FreeChain,(CHAINS+1)*sizeof(PTR)); + Heap.used = Heap.maxused = 0; +} + +#ifdef ERRCHECK + +#define NOOVERLAP 0 +#define SAME 1 +#define OVERLAP 2 + +static +overlap(a,b) +PTR a, b; +/* Check for overlap of space in error checking version */ +{ + register BlockP n; int i; + + for (i = CHAINS; i >= 0; i--) { + for (n = FreeChain[i]; n; n = n->NextBlock) { + if (b < (PTR)n) + continue; + if (a >= ((PTR)n)+n->BlockSize) + continue; + if (a == (PTR)n) + return SAME; + return OVERLAP; + } + } + return NOOVERLAP; +} + +check_free() +{ + int i; BlockP b, a; + for (i = 0; i <= CHAINS; i++) { + a = &FreeChain[i]; + for (b = a->NextBlock; b; a = b, b = a->NextBlock) + if (b < Bottom || b > Top) { + fprintf(stderr,"Invalid block %d: %x\n",i,a); + abort(); + } + } +} + +#endif + +PTR +freeblock(base,size) +BlockP base; int size; +{ + BlockP *list; +#ifdef ERRCHECK + if (ReleaseCheck) { + if (size < MIN_SIZE) { + fprintf(stderr,"%s\n","size < MIN_SIZE"); + abort(); + } + else if (base < Bottom || WDPtr(base)+size > Top) { + fprintf(stderr,"%s\n","out of bounds"); + abort(); + } + else + switch(overlap((PTR)base,((PTR)base)+size-1)) { + case NOOVERLAP: + break; + case SAME: + fprintf(stderr,"%s\n","space freed twice"); + abort(); + case OVERLAP: + fprintf(stderr,"%s\n","space overlap"); + abort(); + } + } +#endif + list = (size < CHAINS+MIN_SIZE) ? &FreeChain[size-MIN_SIZE] : &FreeMisc; + Unsafe(); + base->NextBlock = *list; + base->BlockSize = size; + *list = base; + Heap.used -= size; + Safe(); +#ifdef ERRCHECK + check_free(); +#endif +} + +static PTR +GetExact() +/* Get exact fit from specified list */ +{ + register BlockP b; + + if (!(b = FreeChain[size-MIN_SIZE])) + return NULL; + FreeChain[size-MIN_SIZE] = b->NextBlock; + Heap.used += size; + if (Heap.used > Heap.maxused) Heap.maxused = Heap.used; + return WDPtr(b); +} + +static PTR +GetMixed() +/* Get first fit from misc list */ +{ + register BlockP *l, n; + + l = &FreeMisc; + while (n = *l) { + if (n->BlockSize == size) { + *l = n->NextBlock; + Heap.used += size; + if (Heap.used > Heap.maxused) Heap.maxused = Heap.used; + return WDPtr(n); + } + else if (n->BlockSize >= size+MIN_SIZE) { + *l = n->NextBlock; + Heap.used += n->BlockSize; + freeblock(WDPtr(n)+size,n->BlockSize-size); + if (Heap.used > Heap.maxused) Heap.maxused = Heap.used; + return WDPtr(n); + } else { + l = &(n->NextBlock); + } + } + return NULL; +} + +static PTR +GetTop() +/* Get space from top of table */ +{ + PTR s; + + s = Top; + if (s+size > hpmax) + return NULL; + else { + Top += size; + Heap.used += size; + if (Heap.used > Heap.maxused) Heap.maxused = Heap.used; + return s; + } +} + +#define try(rtn) if (x = rtn()); + +PTR +getsp(sz) +/* allocate space of size sz */ +{ + PTR x; int gc = 0; + + if (sz < MIN_SIZE) { + fprintf(stderr,"! Internal error: heap request too small"); + Stop(TRUE); + } + Unsafe(); + while (gc < 2) { + size = sz; + if (size < CHAINS+MIN_SIZE) { + try(GetExact) else + try(GetTop) else + try(GetMixed); + } + else { + try(GetMixed) else + try(GetTop); + } + Safe(); + if (x) { + ClearMem(x,size*sizeof(PTR)); +#ifdef ERRCHECK + check_free(); +#endif + return x; + } else { + CollectGarbage(); + gc++; + } + } + Safe(); + NoSpace(HeapId); +} + +static +SortGarbage() +/* Sort all free lists onto Garbage by address */ +{ + register BlockP c, *p, q; register GCPairP s; int i; + + for (i = CHAINS; i >= 0; i--) + while (c = FreeChain[i]) { + FreeChain[i] = c->NextBlock; + s = &Garbage[(WDPtr(c)-Bottom)/BUCKET_SIZE]; + p = &(s->FirstBlock); + for (q = *p; q && q < c; q = *p) + p = &(q->NextBlock); + if (!q) s->LastBlock = c; + c->NextBlock = q; + *p = c; + Heap.used += c->BlockSize; + if (Heap.used > Heap.maxused) Heap.maxused = Heap.used; + } +} + +static +MergeGarbage() +/* Merge adjacent pieces of space on the sorted list Garbage */ +{ + register BlockP c, p; int i; + + for(i = Buckets-1; i >= 0; i--) + if (!(Garbage[i].FirstBlock)) { + Garbage[i] = Garbage[i+1]; + Garbage[i+1].FirstBlock = Garbage[i+1].LastBlock = NULL; + } + else if (Garbage[i+1].FirstBlock) { + Garbage[i].LastBlock->NextBlock = Garbage[i+1].FirstBlock; + Garbage[i+1].FirstBlock = Garbage[i+1].LastBlock = NULL; + } + p = Garbage[0].FirstBlock; + while (p) + if ((BlockP)(WDPtr(p)+(p->BlockSize)) != p->NextBlock) + p = p->NextBlock; + else { + c = p->NextBlock; + p->BlockSize += c->BlockSize; + p->NextBlock = c->NextBlock; + } +} + +static +RelGarbage() +/* Release all items on the merged, sorted list Garbage */ +{ + register BlockP c, p; +#ifdef ERRCHECK + int t = ReleaseCheck; + + ReleaseCheck = FALSE; +#endif + p = Garbage[0].FirstBlock; + while (p) { + c = p->NextBlock; + if (!c && WDPtr(p)+(p->BlockSize) == Top) { + Top = WDPtr(p); + Heap.used -= p->BlockSize; + } + freeblock(p,p->BlockSize); + p = c; + } +#ifdef ERRCHECK + ReleaseCheck = t; +#endif +} + +CollectGarbage() +/* The garbage collection driver */ +{ + int i; + + Buckets = (Top-Bottom)/BUCKET_SIZE; + if ((Top-Bottom)%BUCKET_SIZE) Buckets++; + Garbage = (GCPairP)(vrz ? vrz : auxstk0); + if (Garbage+Buckets+1 > auxmax) + return; + for (i = 0; i <= Buckets; i++) + Garbage[i].FirstBlock = Garbage[i].LastBlock = NULL; + SortGarbage(); + MergeGarbage(); + RelGarbage(); +} + +RelocHeap(delta) +int delta; +/* Relocates the free space chains, where the actual free space + has already been moved. +*/ +{ + int i; PTR p; + + for (i = 0; i <= CHAINS; i++) { + p = WDPtr(&FreeChain[i]); + while (*p) + p = WDPtr(&(((BlockP)(*p += delta))->NextBlock)); + } + Top += delta; + Bottom += delta; +} + +int +HeapUsed() +{ + return Heap.used*sizeof(PTR); +} + +int HeapTide() +{ + return Heap.maxused*sizeof(PTR); +} + +PTR +HeapTop() +{ + return Heap.top; +} + diff --git a/source_code/c-prolog-1982/space.o b/source_code/c-prolog-1982/space.o new file mode 100755 index 0000000000000000000000000000000000000000..695138e9424e87095875cc42dd7c4734d66d39e0 GIT binary patch literal 14776 zcmd5@eRP~vnSb8-NG2t;N%}#mfxgqGboxP?7Lcm(IQeKY(zFd}s#Q6X>12|OohHM~ zB&5hW4v1PIZ3@eA>mJ;lR?r|VDd?_vw(5Xrl8RDTc2EDnLqK%v9#$#`cdN^u+28Np z`zDiVE9?HX_w>Hc^Ly@d?|trb?|tsg`%d>*9{Ej6-Kx75iFAp`X5><9nKfN55(Hm? z>?F$St`zx?y!$(jY=#~bS)Yy$r^U7%8TH=;D4(w-6CgJ7`tEQ#3_X^sHX(Z+?KZ;( zCk4T*Pie&pl&K8ayGBpzdPH2*+mlM6JsV}rg*JDqHr*mnJ)i%dL?Qw~&`v z{&w5)Nf2$WUYXDTF2i>6dEZKr`A1pyr+g4?uU>hDX}eHgf6OuXwXJ30K2bKW5F&d<}X>P-fL< zf=k8k3qW@>`Y1!+s}I_l`&8fl-D|8iSqphN#(X9Gc;aB2jHt1!@g29k#xI&nm7JsXRnGw}@Ru>XG$_?93=^5UG|I z7L#IkDji6kaC~HE4rn`Pd^8VsUI9Dz!p@tGou4hRvmAEPey)ji$FEa%+AjLdBi9{r z$qOsj`o^tm#8&>gRG%IRzz(b4Z~COKJhJXkX7@b!e61@4XRQd_hoR3e@EO;s$Qs`h z1-2}JEpHiHHXNU4Z1HDo>}u_gALQ*Ntf&2nUZFz_ACAI@Siet>(zgNlmh;a(o7Ftf zhfj>#nIo`m96l<;URixGGg*zj`bTT6FJQUN+$~f6a!uS1y?LmA^TA9Pb}7f$*Jd@# zb(nuWzidy*htFbNY=E45!3SUZ;O`HjjAL9{Fh;$eSf?Fp*dxbAITq?UV{z6-;r^?Z z?6|W>Tm}1&Yg@!yKVAN)+TQ`Q&n@vN%yz5Qco`aBTaEp$`m)Xbg8lFb*FN{Pe?yHa zAD-E-$HuXjRXOaeq#hosjSF*h9y2<&((xIcqjPk=t#m92&S__^&f}(?t~u?@?Thh) z{>msFu;s)xh$Eyv$tt;>`6A-TBb1eA0$!9K8^vZ)w%_B@b*fF=v9QkJC+tBTcU)qv z{fE4>=Cv-{al^09JTYDt#v8`r3YlNab*9&tNT*DDX_H5_i#WvfW`7M59fz7FqwMhr z{dZu5>mt)$hWN7vIsvSwa>VkHgSA+TEBZz-hey4BUlwcCU;BlG1^f(f&dR%i@3bVB zTY&Ry*zyOaQU9B0kIu=dKGyo4lQJ{E{y=V~+*45gM>A%Zp1L@ zub^G*h2Uz$VcN(TQ;zjKQV?VAD_HYaVqc#y`}#VpdB*zLnC$rChj|^7J)+k@K0mw? zeuFQ+&pDJQ^8Qj%$N$_XJg;~b2UMIF$>(1{opIFB^Y~F*Us%V3HC&5zo(uWJ-@Y14 zS)V_PrAx(957tg?W@I#%xKjMXhj4DccCcJ7z~H?|ms#Z!gp76W zAI){4P9lyvxfAa<>x=VWi`bBx#C+gP^hueDcMHWc_@cw1MS_5sEI6tXXekn8Onz z8Rd`1;Gb<~FFiWq+($6y(4p@hAMwbD;yF(Ai8&utSY-V8oB6C-D~0pIJ5ur4R%_-+ z@NEW#W{)dt#;6 z@Xk7BJPKq+(Wah1EZBt{J?~cjj5_}6JyN0kR+~9I9>{!Ul7=%!P(>AJr8Rn zj`MpR?6%ds<4{nv2ImRmrPJRU-_NbZ=8Wgvs}^^ST!?4mZ!zC;q6T}i7Uz0y@(QfI zPr{uU$aK85wB4{d->b`H-dK=i7$vHnG>46UI^aUY*;Fr`*rw zu&>;#?MiuO^$KHuxjM`AeN(LswYSE`eJXy^Lu-`Z=bJOeC*K^+bYTSYGrfKTadi8W z<38MHea3!77FFk+d``sz-3Q~$g_Y%qKjkL=REmG?t21YUS)U=cjaZ17&@5}PF0a7+ z@5Oz=$ot|}2=@hNtc+RQ8#s*-6B|c(_Gc=vy3D+=oTFfQ`+Jl(n{sMjTwla*f2=

eU(fW+SgRIAn0p;AVqw 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 literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/startup b/source_code/c-prolog-1982/startup new file mode 100755 index 0000000000000000000000000000000000000000..5f7b541067a32cadd3fb052ac58b85c19dc579ef GIT binary patch literal 59624 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 G*Z&vcYIwB( literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/sysbits.c b/source_code/c-prolog-1982/sysbits.c new file mode 100755 index 0000000..1fb1596 --- /dev/null +++ b/source_code/c-prolog-1982/sysbits.c @@ -0,0 +1,650 @@ +/********************************************************************** +* * +* C Prolog sysbits.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +/* + Interface with Unix -- apart from trivial STDIO calls, other + modules do not call Unix directly. +*/ + +#include "pl.h" +#include +#include +#include + +#ifdef vms +# include +# include "times.h" + +# define TIMESCALE (0.001) /* 10 msec. per times() unit in VMS */ + +#else +# include +# include +/* # include */ +# define HZ 60 + +# define TIMESCALE (1.0/HZ) /* times() units in 1/HZ sec. */ + +#endif + +#ifdef vms + +# include stdio +# include ssdef +# include descrip + +# define AsDEC10 + +#endif + +#define READ 1 +#define WRITE 2 +#define DIR 3 +#define PROT 4 +#define LOCK 8 +#define FREE 0 + +#define PromptSize 81 + +#define MaxFile 15 +#define NSigs 16 + +#define SAFE 0 +#define UNSAFE 1 +#define ABORTED 2 + +#ifdef AsDEC10 + +/* end of file character -- ^Z to simulate DEC-10 Prolog */ + +#define PlEOF '\032' + +#else + +/* -1 to be like STDIO */ + +#define PlEOF (-1) + +#endif + +char PlPrompt[PromptSize]; +static int NewLine, crit; +static int (*OldSignal[NSigs])(); + +typedef struct { jmp_buf buf; } JumpBuf; + +JumpBuf ZeroState; + +extern int sys_nerr, PrologEvent; +extern char *sys_errlist[]; + +/* stream information */ + +FILE *File[MaxFile]; +PTR FileAtom[MaxFile]; +int FileStatus[MaxFile]; + +int Input, Output; /* current I/O streams */ + +char OutBuf[256]; /* general purpose buffer */ + +InitIO() +{ + int i; + + for (i = 0; i < MaxFile; i++) { + File[i] = NULL; + FileAtom[i] = NULL; + FileStatus[i] = FREE; + } + File[STDIN] = stdin; + File[STDOUT] = stdout; + File[STDERR] = stderr; + FileStatus[STDIN] = READ|PROT; + FileStatus[STDOUT] = WRITE|PROT; + FileStatus[STDERR] = WRITE|PROT; + FileAtom[STDIN] = FileAtom[STDOUT] = user; + Input = STDIN; Output = STDOUT; + NewLine = FALSE; +} + +char * +AtomToFile(file) +PTR file; +{ + if (IsntName(file) || IsComp(file)) + IODie("Invalid file specification"); + return AtomP(file)->stofae; +} + +int +See(file) +PTR file; +{ + int i; + + if (file == user) + return Input = STDIN; + for (i = 0; i < MaxFile; i++) + if (FileAtom[i] == file) break; + if (i >= MaxFile) { /* not already open */ + i = CSee(AtomToFile(file)); + FileAtom[i] = file; + } + else if ((FileStatus[i]&DIR) != READ) {/* open but not right */ + if (i == Output) + Told(); + else + CClose(i); + i = CSee(AtomToFile(file)); + FileAtom[i] = file; + } else Input = i; + return i; +} + +int +Tell(file,mode) +PTR file; char *mode; +{ + int i; + + if (file == user) + return Output = STDOUT; + for (i = 0; i < MaxFile; i++) + if (FileAtom[i] == file) break; + if (i >= MaxFile) { /* not already open */ + i = CTell(AtomToFile(file),mode); + FileAtom[i] = file; + } + else if ((FileStatus[i]&DIR) != WRITE) { /* open but not right */ + if (i == Input) + Seen(); + else + CClose(i); + i = CTell(AtomToFile(file),mode); + FileAtom[i] = file; + } else Output = i; + return i; +} + +int +CSee(s) +char *s; +{ + return Input = COpen(s,"r",READ); +} + +int +CTell(s, mode) +char *s, *mode; +{ + return Output = COpen(s,mode,WRITE); +} + +static int +COpen(s,m,st) +char *s, *m; int st; +{ + int i; + + for (i = 0; i < MaxFile; i++) + if (FileStatus[i] == FREE) break; + if (i >= MaxFile) + IODie("Too many open files"); + if (!(File[i] = fopen(s,m))) + IOError(); + FileStatus[i] = st; + return i; +} + +Seen() +{ + int inp; + + CClose(Input); + Input = STDIN; +} + +Told() +{ + if (Output == STDOUT || Output == STDERR) return; + CClose(Output); + Output = STDOUT; +} + +PClose(file) +PTR file; +{ + int i; + + if (file == user) return; + for (i = 0; i < MaxFile; i++) + if (FileAtom[i] == file) { + CClose(i); + if (Input == i) + Input = STDIN; + else if (Output == i) + Output = STDOUT; + break; + } +} + +CloseFiles() +{ +int i; + + for (i = 0; i < MaxFile; i++) + if (!(FileStatus[i]&PROT) && (FileStatus[i]&DIR)) { + CClose(i); + if (Input == i) + Input = STDIN; + else if (Output == i) + Output = STDOUT; + } +} + +static +CClose(i) +int i; +{ + if (!(FileStatus[i]&PROT)) { + fclose(File[i]); + FileStatus[i] = FREE; + File[i] = NULL; + FileAtom[i] = NULL; + } else clearerr(File[i]); +} + +PTR +Seeing() +{ + return FileAtom[Input]; +} + +PTR +Telling() +{ + return FileAtom[Output]; +} + +SetPlPrompt(s) +char *s; +{ + if (s) strncpy(PlPrompt,s,PromptSize-1); + PlPrompt[PromptSize-1] = 0; +} + +Put(c) +char c; +{ + if (Output == STDOUT) NewLine = (c == '\n'); + putc(c,File[Output]); +} + +PutString(s) +char *s; +{ + register char c; + + while (c = *s++) Put(c); +} + +char +Get() +{ +int c; + + if (feof(File[Input])) { + Seen(); + Event(END_OF_FILE); +} + if (NewLine) + PromptIfUser(PlPrompt); + c = getc(File[Input]); + if (c == EOF) c = PlEOF; + else if (Input == STDIN) NewLine = (c == '\n'); + return c; +} + +Prompt(s) +char *s; +{ + fputs(s,stdout); + fflush(stdout); + NewLine = FALSE; +} + +PromptIfUser(s) +char *s; +{ + if (Input == STDIN) + Prompt(s); +} + +char +ToEOL(reply,count) +register char *reply; int count; +{ + char c0, c; + + while ((c0 = getchar()) <= ' ' && c0 != '\n'); + c = c0; + while (c0 != '\n') { + c0 = getchar(); + if (reply && --count>0) *reply++ = c0; + } + if (reply) *reply = '\0'; + if (c >= 'A' && c <= 'Z') c += 'a'-'A'; + return c; +} + +Exists(s) +char *s; +{ + return (access(s,0) == 0); +} + +Rename(f1,f2) +char *f1, *f2; +{ +int r; +#ifdef unix + if ((r = link(f1,f2)) == 0) { + if ((r = unlink(f1)) != 0) + unlink(f2); + } +#endif +#ifdef vms + fprintf(stderr,"! Rename not supported in this version of CProlog\n"); + r = -1; +#endif + if (r) IOError(); +} + +Remove(f) +char *f; +{ +#ifdef unix + if (unlink(f) != 0) + IOError(); +#endif +#ifdef vms + if (delete(f) !=0) + IOError(); +#endif +} + +/* create stacks */ + +CreateStacks() +{ + char *r; + int i, s = 0; + + for (i = 0; i < NAreas; i++) + s += Size[i]; + if ((r = malloc(s)) == NULL) { + perror("Prolog"); + exit(BAD_EXIT); + } + for (i = 0; i < NAreas; i++) { + Origin[i] = (PTR)r; + r += Size[i]; + } + Origin[NAreas] = r; + atmax = auxstk0-100; + auxmax = trbase-1; + trmax = skel0-1; + hpmax = glb0-100; + v1max = lcl0-500; + vmax = ((PTR)r)-500; +} + +/* Signals and events */ + +Event(n) +int n; +{ + if (State[TRACE]) + fprintf(stderr,"\n Prolog event %d\n",n); + if (!running) { + if (errno) + perror("Prolog"); + fputs("\nError while starting up Prolog -- cannot continue\n",stderr); + exit(BAD_EXIT); + } + if (crit != SAFE) { + fprintf(stderr,"%s\n",OutBuf); + fputs("\nCan't recover from this error - bye\n",stderr); + Stop(State[DEBUG]); + } + PrologEvent = n; + Unwind(); +} + +/* Signals */ + +TakeSignal(s) +int s; +{ + if (State[TRACE]) + fprintf(stderr,"\nSignal %d\n"); + switch (s) { + case SIGINT: + Interrupt(); + break; + case SIGQUIT: + Stop(FALSE); + case SIGFPE: + signal(SIGFPE,TakeSignal); + ArithError("Floating point exception"); + case SIGSEGV: + NoSpace(-1); + default: + fprintf(stderr,"\nUnexpected signal: %d\n",s); + Stop(TRUE); + } +} + +Stop(dump) +int dump; +{ + if (dump || State[DEBUG]) { + fputs("\nDisaster! Dumping core...\n",stderr); + abort(); + } + exit(GOOD_EXIT); +} + +Safe() +{ + if (crit == ABORTED) { + crit = SAFE; + Event(ABORT); + } + crit = SAFE; +} + + +Unsafe() +{ + crit = UNSAFE; +} + +Interrupt() +{ + while (TRUE) { + Prompt("Action (h for help): "); + switch(ToEOL(0,0)) { + case 'a': + if (crit == SAFE) + Event(ABORT); + crit = ABORTED; + goto cont; + case 't': + debug = TRUE; + sklev = 1000000; + goto cont; + case 'd': + debug = TRUE; + goto cont; + case 'h': + puts("a\tabort\nc\tcontinue\nd\tdebug\nt\ttrace\n"); + break; + case 'c': + goto cont; + default: + puts("Unknown option\n"); + } + } + cont: + signal(SIGINT,TakeSignal); +} + +PTR +NoSpace(s) +int s; +{ + char *n; + + n = (s >= 0 && s < NAreas) ? AreaName[s] : "?"; + sprintf(OutBuf,"\n! Out of %s during execution\n",AreaName[s]); + ErrorMess = OutBuf; + Event(GEN_ERROR); + return NULL; +} + + +CatchSignals() +{ + signal(SIGINT,TakeSignal); + signal(SIGFPE,TakeSignal); +/* signal(SIGSEGV,TakeSignal); + signal(SIGBUS,TakeSignal); */ +} + +/* Emergency exit */ + +Unwind() +{ + longjmp(ZeroState.buf,1); +} + +/* Errors */ + +static IOError() +{ + IODie(SysError()); +} + +static +IODie(s) +char *s; +{ + ErrorMess = s; + Event(IO_ERROR); +} + +char * +SysError() +{ + return errno < sys_nerr ? sys_errlist[errno] : "Unknown Unix error"; +} + +int +Sh() +{ +#ifndef vms + char *shell; int p; + if (!(shell=getenv("SHELL"))) + shell = "/bin/sh"; + if ((p=fork())==0) { + if (execl(shell,shell,0)<0) + return FALSE; + } else if (p<0) return FALSE; + wait(0); + return TRUE; +#else + return lib$spawn(); +#endif +} + +int +CallSystem(cmd) +PTR cmd; +{ + char command[256]; +#ifdef vms + struct dsc$descriptor_s s_d; +#endif + + if (!list_to_string(cmd,command,255)) + return FALSE; +#ifdef unix + return !system(command); +#else +#ifdef vms + s_d.dsc$w_length = strlen(command); + s_d.dsc$b_dtype = DSC$K_DTYPE_T; + s_d.dsc$b_class = DSC$K_CLASS_S; + s_d.dsc$a_pointer = command; + return lib$spawn(&s_d); +#endif +#endif +} + +suspend() +{ + signal(SIGINT,SIG_DFL); + kill(0,SIGINT); + signal(SIGINT,TakeSignal); +} + +float +CPUTime() +{ + struct tms Time; float t; + + times(&Time); + t = Time.tms_utime; + return t*TIMESCALE; +} + +int +SaveStream(stream) +int stream; +{ + int oldstate; + + if (!((oldstate = FileStatus[stream])&PROT)) + FileStatus[stream] |= PROT|LOCK; + return oldstate; +} + +RestStream(stream,oldstate) +int stream, oldstate; +{ + FileStatus[stream] = oldstate; +} + +ResetStreams() +{ + register int stream; + + for (stream = 0; stream < MaxFile; stream++) + if (FileStatus[stream]&LOCK) + FileStatus[stream] &= ~(LOCK|PROT); +} diff --git a/source_code/c-prolog-1982/sysbits.o b/source_code/c-prolog-1982/sysbits.o new file mode 100755 index 0000000000000000000000000000000000000000..e45e9e2e58112d1f8fcd88c5755c2a37885c3884 GIT binary patch literal 28192 zcmd6PeSDl(b>^85$zxfuC0Vk^AmUe!gyqDsWyb-Bs-O>hJi#Uww!&s1TWLHRS%b&Y zFf;N8&}E#s#ef})kRNrrfhxw(p(wEkZr2pkDrt&kHzjU1u-UCCB2B5GX`=d(S=h-0$;#X_s%F{4mnA^6D)j-6FCPah`9vZ|E%|lRl9S z@NQt*P_4+mspa2b+WSl9xmnWmh{&2;;y_Lu$4#Vs4|KfrHk0y2(9B$u>51iH;;25z zG$HNkTScC~*~pa5yw)8Q!QUDq=CDr~TU;Rz=0RVZ`u578 z44)3l5!~KnKI~j?=i{+F%w;z!_DOq*0$UndchZ*P7gMJuSCk7+Qao> zIe9z){q@pT@74p|$HSwmt{-RmiB;iMAheY@I=QwuW-F`$N!GhY_j8IMvEo z+mF6mYV0`G>X^)L&T~wnji_=J^!$O!1>|PcgL$iCTI(5?T8vArXI%c#j!Ug)E>zg| z!Or7tBIUHGF5e;>eNtZMh`&}&s!fhNSH{Db19w1b?FeRvt+N1I%9``hkkobD3H#oA z%qPD3fNWh?E3r!Ige{OcrZ$(zF}3**PzUpZ(|S%FZ}OY8H@1iK8FTjl?O6*gYcMBW zdpL&~9)|5^tjKxC3S)AdW94AXykk`_U%u{mmDus}Nf>kN#OeQnx_sitmcTJH^@i(W9MDhSlh>=`QKXkA=u}WQjF7mrxA6nQloeLy=&F0qZZ>&J;3AC z<9`!+iswOi{yV-A`^FvG_JBA`Y46OMHhtog`IsMHMZcJ} zzerkF{nPZCHv91+iLEN$v&PLgsT*5_>1xjDpe(x$K8>!Ku=Z8ZoJG#3FpCc##gESC zu&x`-<$KC7-|0*_BVipUq}erK(%iEJ_2}8+jJR_ztoteS^Bi;@o~7SACf@zU?4N#P zcg1#;X*&wz_3U)Zxa;7}$iB93L`r2$#|@`yb6D5=VT^&4cj!LmYwi$d*sZg8t&G8E zsfUl$g1&a-4Ep;CjMX=E53821V~ow(EETgJTjccp(2afS+8sC-*LLPlK<44&B30(R z8H)Nvc052Cc73w)cr-)%qIdYpa$ z+6Le43C!Pb97ns=FK8+93+ThS`-aG+Lq2)7VLloPzv%R5;Iq`hS2AZUYLkllY1h9@ z$r1xJXzu)3M`xEj9YYOJTJDIfNG zpRV7jsb%%t2Unxt%y_C{x-X$Ft-nmxV!pj{YiIsA%AdSH0C~2??Pv5U#&i^8`gI-4 zCXD6mwQ>r2N-)2qyjs4D{s~(8F#2)k+M#%Tcy*X{%Kjcx+vqd2X@AeyQCyyTGv^WJ zpdjxw&g9edH*J5T?|jWuQ_nV($pnVkTptB>kK;AYGR&#@E2l6AmP_GF5J3O(ddS$$ zab7MbzqDNbK*y#IzQJ<4=a-2Oerl`T7ZyO*9$Qxmb>*RIHT2wo>#4^yUF31h?{79t z$+PR0%V}HJ9oMO=VC(YH=g=`=T|b`kX`d{YvzmXSoP}Lqy`On2q|Vw=20P4k+|<-o z*wGC;Zb2R8u;Zw;;{n)ltjLaAUt({nmW8%G@7lV+b`n0Filsq0?gtH(9CW9#(E^e^W^6`dpz3;LN_e}0k+ncU!#2&P9q+aKRues^kPa3MB-#g}w*YV5ge{r9x zmhWP1;y#_n&){AfmaiOt{w>@~rMywkoa5TYg)(9L`GoTBTvIvickW*$xDRB?Uct2r z^EehAdHNFE+#Q{tX0I!S{CDb29a7$e>phb`qoek%)Ddj1z*!Tr*D}U0q_!iczh%?B zZT9+W#p~AFZm)kuyEnacrp*q{9Na3@`ErM?qt5cQqt0RdCCwWan=&D^(bx|E3^v~f znW-r^t)$sOpQb$ese}E3#jSPxa%$1r%j8G5{(Q>J(fol$(C=&J+#Gt#+M}!uekGbY z`%Ln#MemvB-VZ|??U*e>9~yrPdhEVEd%O;7Uz_~~)o2^%>Q}d}j{F11d0mHVJguh# zXDM`Cge89YJBXb3y}Q|=9!rjFWb3FUxfP= z&UfrxpVqN0fo;^q` z;eFmZ`19U+ynX4`GjmOfnsA-Vxl}v`Ui)}2-uR7XZ?yNFO}~$^--FF{&I#b*>FYzL zmDe7&eV3o^JI;OH*LKfRGxw!@Blc8t&Y3ZG=Xp#1IMPpJeVDcC;4E~nS8fnd-<$qZ zT@%hN$H7o>-8cbruKRFpzcBfx({%?d5`pZ{m3(B;+N*0 zyyLU}k?+)TN4|_c!aj)W)qu3Qe^N+SkT~Z~ zd+X$UJpe675YH6FArC(S+6|op1J2%9|3POUo#=OZlc_{j%AAhOKx$yOlh~K&&p8b} zxL_>XoXHGioc(=}aI(2rCYS8r?F^<}(OYkI;<5hzft(W`=ttgQqD;!#WBn_0P9_l_ z*q6vSy_tc%POdMRbrP!UR%h2iNJ00`jQU9tJGT?3h1S$zJqy*=}L61xU>m*wW?GO;);ySsl+|G@r!bPaW&J$26Z!JISD z>ojDYp1}+&N*qYU2Tk_0{N4S@1E!54clPg#rIJ0`vrZPqCwr4|w9vE&cMUXr_C0JL zgX#GhY{-@gGj~QeZ`%f3yDQnhHrpo|3L`j(d$3Ga8!T)9-VDCQU?B=jf$ua}_&5+@ zIIkdu!$6ilVz7Y2hGBTfVBsMk^SNsR3y+xe;bDV?Qzm`5V6ZR>WPN807S36I%<|)w zf5!5cfQ^uU-eBPcAnm_wurOiymn?q;*eWtQ32Xyi1!8k-s>VX7N4c=ULX+h;SUw8G z;&wU=Hf{srFMI?)tpBLN!Z5HEddGpZ<9UOH)qW$t(c(5B^Y1ZO=mWCdIfI3xz&7Z4 z1PB%3QH$p+j$6D8q@F7V3$FrMKc806u4aRUPGB3-KMth)5rc&ZAoWjL3T4_iC|WId-07R~}$|0EE9O;_>5@~;A^PcR6?W+2ly0VyA~ zI1Hp6cnD1_yb6TLP7o&_u#tDiSgyk02?xk|*JQA;!RBuQQcs7$LLSI^58M2smLCPO z{^u>eVDn$Hd^rwN_HTv3LKMjMb{Z_CfV3wEr2eB8hk(>uuvi^3_BaL$n}9604ajmm z7W;rKm$!Hc$aY*dShxygdj$sp*I5v_4-Y~sfRw8>Sg1Go!%YSY8-cWYlfgo#&F{AP zJ;43Ya~Mc_jsPkDkio(zkanH1>0>ti8nB7>lqnX1z=P0JZusE}o4yUm@+lyOv?*=* z9FXnF8!S9x(}!*Ph)o}}>1S>FC7b@TO`o*suiEtB0+ElwjvgTUc?8IIjRNkY#RL>P7q7HWZqAXjhGSKIVP;C)DM0U zey!zsu}t}G!1qAD!(gEs$oZ8sSm*(ApH3NUOaqUhUk(7_Adema{u=NRAp7qGko`9d zWVum;ji-RrTQFD{0doGI0kWUZ0Xg5FG5NzU7%WTxsrM3aEy_P{uy7ejJ6-~^o~s5M zuK-!k%LWURK-O~&$acPJut0B{^P>Wog#Fc)-vp#w)L`KrAocYbEZhrZecc8ddw|*> zK>65b@{dU$jZm@6`Nck~?jZXtv-!nkU zPXhhOzhkhlj>jpB1t9Ai zwfrTElR)afX0Y)pkaB`MPs9o!^*EMaZTV*4JJ9b@Aa4GQ-edV5AocO7KCrP5_z>*L z+w>zg{jg1+0HPk}C4-Gufb8cDc++AX+SzQd5Cw7`^#D1Kas~^1K&{VUV<(X1x(yc6 zKrFEn2Y@X1af5|Ca1HD}3}idc7e}O4*1`IXMkS-J_GzBFo+v%Y)1uf7#Ie!ziSOPIyOHFd=&X9AY7S^X^W?TDHI(s zSQxYX)0P+9&}DweU}1yhn=RjA`A*C8y;9U)@sPz679X)VZ1I%Eg2fSwqZZFtgsrmz zbn6X3tSNC2(U*$oL&Z{yaR2B>u&vU9SZ)!=ioREi@ zKzu9WBw{ThZsy2xpuKhxUaPzvd>*&~I0`Jbmv*tv7Q_z3`RV1pQ!ug{vYo4uU<1iB zw~BlV>8IY|rix_H(7vrmLxY;`7C8rn&);k68H&xweHrAXIDT%guC5L*Uc9)fs;Z`{ zVzECQ01>#oswV6U2ba`ThN~B^SW;76RTI2@v8F9GX-k>rUs@AbT2pd+Si-@ou&=VF zs>ZjzqQ)1ls;u$9vnE_sU0GdO*;wMcJ?vMyvBV!R_Dx_ogJ)YSxPAiuO~uqMz@neaIc z;n32`%7&USYGqhlflf=`s#dS>_1v5k$^k-Xz8LDi;u6 zugs&!{X@i?5hpO8IJfb>E5n?&{V_7nA;Pzk`V!nr1oBN+ggMJRiOfGkY(-3=%t|2M zDMXmNJ>$szABdX}4`7{OPZz$sjxc8*d>@&Ajre}V0?KeL;@w(?Ic@tJWWI=qCB=t% z`tJSM8`Se-i2fY$gNTzT!@hX+4a)p8WPFh61&(2Iv;*;;9K)Qpl|udo#E(FT*M(7F z%#>j{@y;FcoClSVUyOJVJg*tI0aI^KW+~+PWcg!|y^J#4pZ33jZEu6TgZP_}U5!c2 z{=@q}2+Q*?70uBWq|&x}$ge~^1ipEJ>Az>S%-r+f7Rawf{4~luf->E}zt=K>{L4l4 zG$D`m+y?m;#0S8KZV*WT@hpsC&c5CRdER^aB80Y~%!h$^Z-`;eGQ2mn9q~&LI*Kv_ zKs;wdn7cilkncwPeMo&A3wuBChi_1(2lBm$--7Hpl=(RD6>HmE`vKo#-jDbvklluj z5*O-a+KrtHnw8O$g&% z7KFLm)4)0q`4Uej%6uErcz(z*XFa@EyB2XB${acfyvBXS>k1ZB7;cAGL<@OphP2>Fj8 zaxZxmWnP5jC*~+aC2Y?pAb$w)Kch_TTSTrP{gZQ)ar^o(u(QWh(j^G1_hX5Uz`8 zhu-_pH4>=^s2@+c_H}0SD+j%00zU}%AV$ZGe46yI-uF=dDbf;A~MIYHh_)zID=l)a!-&-;UVrg1*Bx0-w`1=%v; z*XLT^HeN+~bkyi9XB#o8b4a7_7U?$jP|ud8fchrhveX%sfXb_#m?!ir=)*WH>0FB8|}gq$#WO;ZwdLqEQyd@W^$jEv3)^vPpLqkk7^^2kqm?Me-$b-Yr{a2nVob$du)t5=|RqUl3)SqXm z_9u;e13QFC^qjO1L+S&oKp4qwQQ@W?1Z5kDL-c9TSyO= z$}fQQ3nS3;Z=l)6z(-2;I)EeP&W$kWE#33*&9Cw4H=!TOK=WuK&F}*Fs54J>PLiH1 zhn{s{ZV6&_U$MpGJ@KM2V#_O0Uu4zlN!+UB_pGyQVW`){jW-8IcT-* zM;<*+NLC=-+s_9eAH_nUo*~j>^VGkmuNi@D^c@)5D~%0mPdcP&P56y=gj8O~x+x^L zLY_Wn1Z`xXKAc0~nH#N`ukyN&O@{PZfWB!2eYLZwthOa@%0ADsc!kn(H8Sey2R_6@&~cnJGA-bv6Z7@kZu+T_OGch@ zTRMz9`!L#6rZSvkQKwAyKtFxd$fS{1d+@Mt5b3-}ySaj;aGwl(G;QSTNq3jYM}hQJ zBk7Rb2by74f5J21^@Gln&l){PArrl1%AO)US|+~@8Tzl0VI#xeEiG8w2#ttQXMxJJ zkgixDpMyMo*T|ShK5yi;UEM~;%&P_RyO5{fdKcyogSK(Z$UESp!$xK!>7fO367uv} z?~?ga0L{=|XU0g&R`3^NiWr?V@>=%N0=>UL-!;-?&BaxqOdxQBTFpoY~TWO$$N$6Aw5k6Qw*Jiv9pJecMQr zM}G7Mz5bbGUGFcGpF)Pd_@5J-8J6*xt)Px9v=07_ain-x(5P zL2V|CqwOz)bPzAB56aJgEu?n^^-Rx`elRFO*gi)3DSd(4wD&oWp67hiXY|DvgYs6$ zW7)}h*xvw};lh2mmj+sG1I_zbIxe7j4pN@>w}Ey@w~1^8-J*1f>;TBj@N2^Oi+()|$X&dzME8FO^!c`+?(rau;`$>b|!D^m+6frniO* zPn61e(ufycES2v99nwE5)qSajw11vl26mIKnkT#;lPA5xoN-h%z9Xpn66uTU=js1d z;VylCeTn=6vJ4jnM9ZFv3)nQqcA zdUQTmBJZ(fFSfxCap}x_f%zJu_;u;6!{!+QTmZ~H-WxE1`d5H-5P2=X64*l8?~_}B z-J~JI>*73VtXb|eL!?>IhViPIx@Ohu%#q$?U%Ezl?v1XUv&;JR#cUm~UAX^c>!O{j zKtr|Kwhq{0X@CaW^Da}c$Rg;IP`xM4A=1a7k%lc2{)W54Qm=^ufHE2HT@1?gD&pFy`+nj#G2XcvZ94%g!TW4pQT z$Xj|5()mAip2D>}NDZ^cCBVnR8ZO=^Qs>eSnsFg}@uYcnB7rICT>3{Xm?w~TA z_uCja794k_p@+|gT$;~(l!p9GE)AJgE{$~F%hf*d2i#|g*h>SZAb!W6^GmBM@5k59 zHfPqn%8Smc3gpp8nqKeF--t8^k#inZON*s{9oTJYfQI6|h>1KyX&-fyb`Ys^H6r&2 z?u(f6d^bzy0^C>)c#bVoys>A)4xod``7*T}KL}nrgtt??@>IgP*u-?m`$2p2>6tRW zxE`iEi1bQnFD}_(Kkunl>N8%Zk*3Wq&HOscljdH|JkpG7i+HX{=5Mt4Zj025EkW}* zK9t#p$n*}2ciVL8{h+10J!uKh?C%eI(gr;Aew)woANQnlU3zUk;^B{b=!Y!*utn~t zEO*l4S1f+bVsZa+TpZ-_Sqj@lJO0qh(#NE(Z(DrIB4xe4AlNb!~uy#4<+4H&gy~Y*77pn0LLpTsx=x zmsYvcf!FBvrhDaGTJyWizBgB0n*Pe%GMc}=u|XCKX_$2&gm z-sLUppzK`f$a+)zhIc-4Z)0p?`KWZ3j@EC+{`X$+)md=4x zk94%B2C~!olwnO->M~hc0v{e~WyGC{Tt^CD4em|nptWN#CvpDn%<=O?q{L-QLer*2 zl(@6^?rb81{LX>R+qX$3kxm_y_`qO4WSdZE^MPbGmqq@LM1O2AOj;+s>v30ZM`ABN z=EUn}?U_U@m)Mz$#rI^9o`mRTel9Bg(iz*6FrRcHac6EIEj{Q(*%|9i;2X&-;m&@1 zu9+Ex&HVgQ?i$#c#wV8$@0a#iF5YK~XCb~n+212~Zr9IGft!+)+IcW*5_a}U79Vw{ zaDCPuOQn#WOYD{S-X7@Pi|<-{Bs++&E`jYGcXuYy5dF!)n0+uFZQwX4p#Sk*Yc7E% zX4!pnWF>4K`o_q}nziZFnm*Zi=a#!RZ<3DA9h^PuB$CWvgty_tREZ{HJ?QM#&h77$ zSZ<&}Y-8=Jw8QhL8x! zed|j@PSxrFhOD));!=YE-auC1kr(e8iU!)+GKw`HQ19_o6Yqk2Qam|k^|g}y5d+W zUFlp#x^~5|O>`kKoBXJB^`>IG@yqRKwgRlNekz!qnoZ~+pOM*TwE%7UpvmY;_Z`f}U}HvH zDizz6NOk1|pOcGAcYS0q)}tv(^sp%qiCawe4}jaPznD6pv-@|Y_7IaFO#pJ(5CJ`j zefY)7#jkb;a8KeOe&eZuIOTbA0s2$PezJqf9{i^Dcenob_Lva^Vs=SyPqvFEDG24S z(~qc{{g~UEW$eN?^jHj}veOhlthb4AlZyLuSPIh1e^vn91~Li7wEpJyrga_k=6EV( z5_){VBu;Y!y`0C19GZf!{d=W%cLH|m5B{-0W^WQl2WCnJh@&Kp!w*&|WYaiObG>p; zE~EdY0GmpG)=>L!PjKHp>>>DFCkFuQdIjq=muccQyBAZmFP80#$-WHZM=@p@q@}PJ zc4hXYWqT&MJJ~PWl6x`zI+Ji7+G5#cJTllH&kbY@(+WL?>V%m%UQ!87+POc80~6;g z)@Ur#1I*+G)6x;kV0%G}L{G~1C9+w;e=lf5lc)WKRvdD=3E|%}Wce=%U>2q|EYWq4 z8SL+;6QTbWL9%;NiGA{s!GT;N858_lgG^RZanUUXtA8K`%i%ffRLb-oy(D#!)L$~*((b|jWbZ+EM%X9%;TfRkIrFIvj!7~O?H+fc z7mf$^+E|)i%wD)3DG0%CoGcQ{>}K4D$-u)h(IcsWfj#IU189d}>%clP`8pNgj$!&3 z_bNef9hAHKW2mPssgRAw>^9a5CnbrUpRSg1sHQy>j*;~jT^9tKCjQ-pd@zw2Fueo6 zv#TE+Y5)6!@uQfCG;Ik7TSuJogX~B3MvXh9o}+aS)txjhrt33VpVH$@;%udt8BZl* z8P>Yf>q6!-{qgicbtJKSXSqaX+(~1Z@iwgo$zw-_jDOjSk;Ss_O=16Yoyb@`&e>-@ zN$w#ss9On=)SH~;OYVgqHxQRJEW^}K9Kede-mWW8eM##QdYsHVr=3aqP<@-Vp#FOg zQEO&-l-!(g?g>0cEcyfn4gVNq59&$4(IpZ#xYZG3xFucQF@cxrwh2Lz=1YY5qXEifvhU&Ho2-NXDMC#a8EC`-j z9!Fg0Rtnld^af_(AHqs2kngzhesFQ19=P zK8KtuP)`-chVNk=LR^0xLF#ePVBXVqgX0nwspo^Z85;%iT^-)nC=S#UhaO(nyTNe@ z#hG3`#1C@N%kI5^-~K=R-pen%?q(>(OEcu%K5}{Yxthy6Dm^35`zs7?{u;wh^L$Rr z;N~|QcAAeA@$WC<`8<@tEq||Jr}>^DK2^l$iujLN-n8F0{oKvy_wie14KDwAaF`b2 z8^!}m%#sr>KWg~jb@?&Ff5GK18GhL1Ck%heN|J=T9{6HEEz=_39wX368*Uhw?(Gcrke^Zu`XgTT!n;Rk>T zD2$95{zZU(6Hvju$0t`zvR$wEFVRIj-*aJb*W1)A9_I_x=zFNTez4bp*Y`~Adf>Y& z-tuoN;%_SAR~PZ?i+J~(b?y1JqWn!o{MI7=?jrs}Mf|Q=Jies{&#fdf#!)ff;OP7J zdBgMjM}60I)U3Zx%qov}JBs+DMf~Sy@%Z)(yuQCK#(_8qUf&JJyV48=@=IZl!}W;g zk>L4EJ~FJV@c&Widzal@k0tUncm}hdiu?umZIEw0YzFds;Mo$hUPS(;i2tcAf5=YU ze+IAn0Y4Z+_&1k-$nd2BO~!kx25+$ZLc9aZuo%34uhC*M!ft+(>Cffh^;-~p+rhxO z%&-vemN4Ax@SiK z!<@{iqWm0q_qzqw_g}%c;E;|?8js*Gc>OM5*o+@O2h!k<$HU@0&B6Da!vAczs`g%;Y~+lz+a6|1Nla7r)8a`#tdbetq8XFBZxFq=?6-EgIbR z{Gy2eckt#Ncb=#4U@*-3j&_F`zxm+x{rMJ?UkzU0JJ<6N?{t`HF+G0x$LSi}`qmcl z8^G&3;}u3fK2w?{exium6s;^W};{pvBJufHh&H;eeg;PpLf nhwBq-xhVg$Mf~r8*Y}^tjQmOP`W`dhMP_&myuOc&_ly4n68ZJk literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/trace.c b/source_code/c-prolog-1982/trace.c new file mode 100755 index 0000000..13bfefd --- /dev/null +++ b/source_code/c-prolog-1982/trace.c @@ -0,0 +1,275 @@ +#include "pl.h" +#include "trace.h" + +static char *portname[] = { + "Call: ", "Exit: ", "Back to: ", "Fail: " +}; + +int trace(frame,goal,goalenv,info,port) +PTR frame, goal, goalenv; unsigned info; int port; +{ + PTR realx = x, realx1 = x1, target; + char flags, arg[10]; + int level, telling, iarg; + + level = Level(info); + x = goalenv; + x1 = X->gsofcf; + if (IsRef(goal)) + x1 = MolP(goal)->Env, goal = MolP(goal)->Sk; + flags = FunctorP(SkelP(goal)->Fn)->flgsoffe; + if (port == CALL_PORT) { + if (dotrace) { + dotrace = FALSE; + sklev = NEVER_SKIP; + } + FrameP(frame)->infofcf = info; + } + if ((level > sklev-(port==BACK_PORT) && !(spy && (flags&SPY_ME))) || + (flags&(INVISIBLE|UNTRACEABLE))) { + x = realx; x1 = realx1; + return NORMAL; + } + message: + if (flags&SPY_ME) putchar('*'); else putchar(' '); + if (level == sklev) putchar('>'); else putchar(' '); + printf(" (%d) %d %s",InvNo(info),level,portname[port-1]); + telling = Output; + Output = STDOUT; + pwrite(goal,x1,999); + if (!(leash&(1<<(4-port)))) { + Put('\n'); + Output = telling; + x = realx; x1 = realx1; + return NORMAL; + } else PutString(" ? "); + Output = telling; + switch (ToEOL(arg,10)) { + case '\n': + case 'c': /* creep */ + sklev = NEVER_SKIP; spy = FALSE; + break; + case 'l': /* leap */ + sklev = 0; spy = TRUE; + break; + case 's': /* skip */ + if (port == EXIT_PORT || port == FAIL_PORT) goto notapp; + sklev = level; spy = FALSE; + break; + case 'q': /* quasi-skip */ + if (port == EXIT_PORT || port == FAIL_PORT) goto notapp; + sklev = level; spy = TRUE; + break; + case 'r': /* retry */ + spy = FALSE; sklev = NEVER_SKIP; + if (sscanf(arg,"%d",&iarg) == 1 + && iarg != InvNo(info) + && (target = findinv(iarg,frame,vv)) != frame) { + fprintf(stderr,"[** JUMP **]\n"); + failto(target); /* long retry */ + } else { + fprintf(stderr,"[ retry ]\n"); + if (port != EXIT_PORT) { + x = realx; + x1 = realx1; + lev = level; + invokno = InvNo(info); + if (port == BACK_PORT) + vv = VV->lcpofcf; /* this is essential !!! */ + } else failto(frame); /* fail to frame */ + } + invokno--; /* the Call port increments this again */ + return ICALL; + case 'f': /* fail */ + if (port == FAIL_PORT) goto notapp; + x = realx; + x1 = realx1; + lev = level; + invokno = InvNo(info); + if (port == EXIT_PORT) failto(frame); + else if (port == BACK_PORT) vv = VV->lcpofcf; /* essential */ + spy = FALSE; sklev = NEVER_SKIP; + return EFAIL; + case 'a': /* abort */ + return ABORTING; + case 'b': /* break */ + x = realx; + x1 = realx1; + breakret = port; bg = breakat; + return BREAK; + case '[': /* consult user */ + x = realx; + x1 = realx1; + breakret = port; ConsMol(CsltUser,x1,bg); + return BREAK; + case 'g': /* backtrace */ + backtrace(x); + goto message; + case 'e': + suspend(); + goto message; + default: + printf("Unknown option; these are the known ones: "); + case 'h': + puts("\ +\n creep a abort\ +\nc creep f fail\ +\nr retry r retry call \ +\nl leap b break\ +\ns skip h help\ +\nq quasi-skip n nodebug\ +\ng goal stack [ consult user\ +\ne exit Prolog\n"); + goto message; + case 'n': /* turn debug mode off */ + debug = FALSE; + break; + } + x1 = realx1; x = realx; + return NORMAL; + + notapp: + printf("Option not applicable at this port\n"); + goto message; +} + +int +clausenumber(fr) +PTR fr; +{ + PTR g, cp, np, onp, fp; int pos = 1; + + g = FrameP(fr)->gofcf; + if (!IsInp(g)) g = MolP(g)->Sk; + cp = FunctorP(SkelP(g)->Fn)->defsoffe; + fp = fr->altofcf; onp = NULL; + for (;(np = Addr(ClauseP(cp)->altofcl)) != fp; cp = *np) { + if (!*np) return 0; + if (onp == np) return 0; + onp = np; + if (!Erased(cp)) pos++; + } + return pos; +} + +backtrace(fr) +PTR fr; +{ PTR ofr, frg, fre, out, oldx; unsigned info; int clno; + + oldx = x; ofr = NULL; + out = Output; Output = STDOUT; + for (; fr != ofr; fr = x) { + ofr = fr; + x = fr->gfofcf; + info = fr->infofcf; + if (info== (PRIM_TAG|NUM_TAG)) continue; + frg = fr->gofcf; + if (IsInp(frg)) + fre = x->gsofcf; + else { + fre = MolP(frg)->Env; frg = MolP(frg)->Sk; + } + printf("%4d (%d)->",Level(info),InvNo(info)); + clno = clausenumber(fr); + if (clno) + printf("%d: ",clno); + else + printf("?: "); + pwrite(frg,fre,999); + printf("\n"); + } + x = oldx; + Output = out; +} + +/* scanstack(frame,choice,fun,all) scans stack frames backwards from frame + and last choice point choice calling fun with each as an argument until + fun returns TRUE or the stack for the current execution is exhausted. + If all is true, the entire stack is scanned; otherwise, only the stack + since the last breakpoint. + Return the last frame scanned or 0 if stack exhausted. +*/ + +PTR +scanstack(frame,choice,fun,all) +FRAME *frame, *choice; int (*fun)(); +{ + register FRAME *alt, *par; int result; + + par = frame; + alt = choice; + while ((alt != FrameP(alt->lcpofcf)) && + (all || (PTR)alt > brkp)) { + while (par > alt) { + if ((*fun)(par)) return (PTR)par; + par = FrameP(par->gfofcf); + } + if((*fun)(alt)) return (PTR)alt; + par = FrameP(alt->gfofcf); + alt = FrameP(alt->lcpofcf); + } + return (PTR)0; +} + +/* findinv(invno,frame,choice) finds the most recent user frame with + invocation number =< invno in the current execution (that is, it + does not search past break points). If no such frame is found, + findinv returns the oldest user frame in the execution. +*/ + +static PTR theframe; +static int target; + +static +invoked(frame) +FRAME *frame; +{ + unsigned int info = frame->infofcf; int frameno; + + if (SysFrame(info)) return FALSE; + theframe = frame; + frameno = InvNo(info); /* helps debugging */ + return frameno <= target; +} + +PTR +findinv(invno,frame,choice) +int invno; FRAME *frame, *choice; +{ + PTR found; + + target = invno; + theframe = frame; + found = scanstack(frame,choice,invoked,FALSE); + return (found ? found : theframe); +} + +/* failto(frame) simulates a failure back to frame. */ + +static failto(frame) +PTR frame; +{ register PTR p; register char *flagp; unsigned info; + + v = frame; + x = V->gfofcf; + v1 = V->gsofcf; + x1 = X->gsofcf; + vv = V->lcpofcf; + vv1 = VV->gsofcf; + pg = V->gofcf; + c = V->cofcf; + info = V->infofcf; + lev = Level(info); + invokno = InvNo(info); + execsys = SysFrame(info); + tr0 = V->trofcf; + while (tr != tr0) { + p = *--tr; + if (IsRef(p)) *p = NULL; + else { + flagp = &(ClauseP(XtrDBRef(p))->infofcl); + if (!((*flagp)&ERASED)) *flagp &= ~IN_USE; + else hide(p); + } + } +} diff --git a/source_code/c-prolog-1982/trace.h b/source_code/c-prolog-1982/trace.h new file mode 100755 index 0000000..0d33412 --- /dev/null +++ b/source_code/c-prolog-1982/trace.h @@ -0,0 +1,26 @@ +#define NEVER_SKIP 1000000 + +#define CONT 0 +#define CALL_PORT 1 +#define EXIT_PORT 2 +#define BACK_PORT 3 +#define FAIL_PORT 4 + +#define NORMAL 0 +#define EFAIL 1 +#define ICALL 2 +#define ABORTING 3 +#define BREAK 4 +#define Trace(when,frame,goal,goalenv,info,port) if (when) { \ + switch (trace(frame,goal,goalenv,info,port)) { \ + case EFAIL: goto efail; \ + case ICALL: goto icall; \ + case ABORTING: goto aborting; \ + case BREAK: goto enterbreak; \ + case NORMAL: break; \ + } \ + } + +extern int debug, lev, sklev, invokno, + spy, leash, dotrace, breakret, execsys; +extern PTR pg, bg, c; diff --git a/source_code/c-prolog-1982/trace.o b/source_code/c-prolog-1982/trace.o new file mode 100755 index 0000000000000000000000000000000000000000..261ddc6e8aa68685ec786ab6dbf27a2df78cc55d GIT binary patch literal 15612 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 PoWD=E2UY!Bi^~5GueV#! literal 0 HcmV?d00001 diff --git a/source_code/c-prolog-1982/unify.c b/source_code/c-prolog-1982/unify.c new file mode 100755 index 0000000..028ffad --- /dev/null +++ b/source_code/c-prolog-1982/unify.c @@ -0,0 +1,341 @@ +/********************************************************************** +* * +* C Prolog unify.c * +* ======== * +* * +* By Fernando Pereira, July 1982. * +* EdCAAD, Dept. of Architecture, University of Edinburgh. * +* * +* Based on the Prolog system written in IMP by Luis Damas * +* for ICL 2900 computers, with some contributions by * +* Lawrence Byrd. * +* * +* Copyright (C) 1982 Fernando Pereira, Luis Damas and Lawrence Byrd * +* * +**********************************************************************/ + +#include "pl.h" + +int +gunify(ta, ga, tb, gb) + PTR ta, + ga, + tb, + gb; +{ +/* Unifies term t1 with global frame g1 and local frame v + with term t2 with global frame g2 and local frame x + result is TRUE if unification succeeds and FALSE otherwise. +*/ + + int arity; + PTR a, + b, + pa, + pb; + +/* check same functor */ +start: + if (*tb != (a = *ta)) + return FALSE; + + arity = FunctorP (a) -> arityoffe; + +/* main loop */ + + while (--arity > 0) { + a = *++ta; + if (IsVar (a)) { + pa = FrameVar (ga, VarNo (a)); + a = *pa; + while (IsRef (a)) { + pa = a; + a = *a; + } + b = *++tb; + if (IsVar (b)) { + pb = FrameVar ( gb, VarNo (b)); + b = *pb; + while (IsRef (b)) { + pb = b; + b = *b; + } + if (pa == pb) + continue; + if (Undef (b)) { + if (Undef (a)) { + if (pa > pb) { + *pa = pb; + TrailVar (pa); + continue; + } + *pb = pa; + TrailVar (pb); + continue; + } + if (IsComp (a)) + *pb = pa; + else + *pb = a; + TrailVar (pb); + continue; + } + + if (Undef (a)) { + if (IsComp (b)) + *pa = pb; + else + *pa = b; + TrailVar (pa); + continue; + } + + if (IsAtomic (a)) { + if (a == b) + continue; + else + return FALSE; + } + if (IsAtomic (b) || + !gunify (a, MolP (pa) -> Env, b, MolP (pb) -> Env)) + return FALSE; + continue; + } + if (IsAtomic (b)) { + if (Undef (a)) { + *pa = b; + TrailVar (pa); + continue; + } + if (a == b) + continue; + return FALSE; + } + if (Undef (a)) { + ConsMol (b, gb, *pa); + TrailVar (pa); + continue; + } + if (IsAtomic (a) || !gunify (a, MolP (pa) -> Env, b, gb)) + return FALSE; + continue; + } + b = *++tb; + if (IsInp (b)) { + if (IsComp (a)) { + if (IsAtomic (b) || !gunify (a, ga, b, gb)) + return FALSE; + continue; + } + if (b != a) + return FALSE; + continue; + } + pb = FrameVar ( gb, VarNo (b)); + b = *pb; + while (IsRef (b)) { + pb = b; + b = *b; + } + if (Undef (b)) { + if (IsAtomic (a)) + *pb = a; + else + ConsMol (a, ga, *pb); + TrailVar (pb); + continue; + } + if (IsComp (b)) { + if (IsAtomic (a) || !gunify (a, ga, b, MolP (pb) -> Env)) + return FALSE; + continue; + } + if (b != a) + return FALSE; + continue; + } + ta = *++ta; + if (IsVar (ta)) { + pa = FrameVar (ga, VarNo (ta)); + ta = *pa; + while (IsRef (ta)) { + pa = ta; + ta = *ta; + } + tb = *++tb; + if (IsVar (tb)) { + pb = FrameVar (gb, VarNo (tb)); + tb = *pb; + while (IsRef (tb)) { + pb = tb; + tb = *tb; + } + if (pa == pb) + return TRUE; + if (Undef (tb)) { + if (Undef (ta)) { + if (pa > pb) { + *pa = pb; + TrailVar (pa); + return TRUE; + } + *pb = pa; + TrailVar (pb); + return TRUE; + } + *pb = IsComp (ta) ? pa : ta; + TrailVar (pb); + return TRUE; + } + if (Undef (ta)) { + *pa = IsComp (tb) ? pb : tb; + TrailVar (pa); + return TRUE; + } + if (IsAtomic (ta)) + return (ta == tb); + if (IsAtomic (tb)) + return FALSE; + ga = MolP (pa) -> Env; + gb = MolP (pb) -> Env; + goto start; + } + if (IsAtomic (tb)) { + if (Undef (ta)) { + *pa = tb; + TrailVar (pa); + return TRUE; + } + return (ta == tb); + } + if (Undef (ta)) { + ConsMol (tb, gb, *pa); + TrailVar (pa); + return TRUE; + } + if (IsAtomic (ta)) + return FALSE; + ga = MolP (pa) -> Env; + goto start; + } + tb = *++tb; + if (IsInp (tb)) { + if (IsComp (ta)) { + if (IsAtomic (tb)) + return FALSE; + goto start; + } + return (tb == ta); + } + pb = FrameVar (gb, VarNo (tb)); + tb = *pb; + while (IsRef (tb)) { + pb = tb; + tb = *tb; + } + if (Undef (tb)) { + if (IsAtomic (ta)) + *pb = ta; + else + ConsMol (ta, ga, *pb); + TrailVar (pb); + return TRUE; + } + if (IsComp (tb)) { + if (IsAtomic (ta)) + return FALSE; + gb = MolP (pb) -> Env; + goto start; + } + return (tb == ta); +} + +int +unifyarg(a,t,tf) +PTR a, t; PTR tf; +{ + if(IsVar(t)) { + t=FrameVar(tf,VarNo(t)); + while(IsRef(*t)) t = *t; + } + while (IsRef(*a)) a = *a; + if (Undef(*a)) { + if (IsInp(t) && IsComp(t)) { + ConsMol(t,tf,*a); + TrailVar(a); + return TRUE; + } + if (IsRef(t) && Undef(*t) && t >= a) { + if (t == a) return TRUE; + *t = a; + TrailVar(t); + return TRUE; + } + *a = t; + TrailVar(a); + return TRUE; + } + if (IsRef(t) && Undef(*t)) { + *t = IsComp(*a) ? CellP(a) : CellP(*a); + TrailVar(t); + return TRUE; + } + if (t == *a && IsAtomic(t)) return TRUE; + if (IsAtomic(t) || IsAtomic(*a)) return FALSE; + if (!IsInp(t)) { + tf = MolP(t)->Env; + t = MolP(t)->Sk; + } + return gunify(MolP(a)->Sk,MolP(a)->Env,t,tf); +} + +PTR +deref(vp) +register PTR vp; +{ + while (IsRef(*vp)) vp = *vp; + return vp; +} + +PTR +vvalue(vp,tf) +register PTR vp; PTR *tf; +{ + vp = deref(vp); + if (Undef(*vp)) return vp; + if (IsComp(*vp)) *tf = MolP(vp)->Env; + return *vp; +} + +PTR +arg(argp,tf) +register PTR argp; PTR tf; +{ + register PTR a; + a = *argp; + if (IsVar(a)) { + if (IsLocalVar(a)) + argp = x; + else + argp = tf; + argp = deref(FrameVar(argp,VarNo(a))); + a = *argp; + if (Undef(a) || IsComp(a)) return argp; + } + return a; +} + +PTR +argv(argp,tf,af) +register PTR argp; PTR tf, *af; +{ + register PTR a; + a = arg(argp,tf); + if (IsRef(a)) { + if (Undef(*a)) return a; + *af = MolP(a)->Env; + return MolP(a)->Sk; + } + *af = tf; + return a; +} diff --git a/source_code/c-prolog-1982/unify.o b/source_code/c-prolog-1982/unify.o new file mode 100755 index 0000000000000000000000000000000000000000..f11cd720b90e165ec6776a539caf6315fbc0b04f GIT binary patch literal 18644 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 Pw!-uS@a8v?iW2#M!~D5e literal 0 HcmV?d00001