E-PROLOG -------- (ver. 2.3 -- August 1, 1985) This is a small Prolog system for CP/M-80 Z-80 computer. The current code occupies less than 6K bytes of space, so that there is a lot of space left over for the database and for the VERY deep subroutine stack. The executable version of E-Prolog is called EPRO.COM. This version was prepared under CP/M 2.2, but if you do not use APPEND, it should run under CP/M 1.4. The source code is intended for Microsoft's Macro-80 compiler. The source files are: EPRO.Z80, CLASS.Z80, SYMB.Z80, HEAP.Z80, DATBADD.Z80, UNIFY.Z80, CMD.Z80, PROVE.Z80, INPUT.Z80, OUTPUT.Z80, ERROR.Z80, ASSEM.Z80, INIT.Z80 . Some E-Prolog sample programs are included on the disk, also: STD.PRO some standard connectives SAMPLE.PRO a sample database - see below SCIAM.PRO a logic puzzle from Scientific American VALGOL.PRO a compiler written in Prolog (from May, 1985, Dr. Dobb's Journal) --------------------------------------------------------------- EXPLANATION ----------- This DOC file DOES NOT teach Prolog. See the appropriate books for that. 1. W. F. Clocksin & C. S. Mellish, Programming in Prolog, Springer-Verlag, 1981. 2. K. L. Clark and F. G. McCabe, Micro-PROLOG: Programming in Logic, Prentice-Hall, 1984. E-Prolog does not have the special features of the large systems described in these books, but neither does it have the large price tags of those systems. Here are the peculiarities of E-Prolog. (Mostly things were done this way to save space.) TOKENS are the smallest elements recognized by the language. They are used to identify individuals (constants) and relations (predicate symbols), and some of them have special uses as well. The most common tokens are strings consisting of letters (upper and lower case are different), digits, and the characters '-', '_' , and '?' . Most other printable characters usually represent tokens of a single character. Exceptions to this can be enforced by enclosing a string in quotation marks (either " or ' ). Inside such a string, control characters are indicated as usual with the escape character '^'. Text enclosed in square brackets [ and ] is a comment, and is ignored. Space, Tab, Carriage return, Linefeed and comments separate one token from the next. Examples: Here there is one token on each line: ken Ken / "A long string with spaces." But this line has eight tokens: How-to-tell.where one/token[really]ends. They are: How-to-tell . where one / token ends . VARIABLES are represented as strings beginning with the character '?'. Examples: ?X ?who ?mother-in-law LISTS are represented by placing the items of the list between a pair of parentheses. Examples: (A B C D E) a list with 5 items () the empty list (A (B C D E)) a list with 2 items (LOAD A:SAMPLE.PRO) a list with 6 items (LOAD A : SAMPLE . PRO) the same list PAIRS are represented using the vertical '|'. Example: (A | B) Technically, lists are built from the empty list up as pairs. The list (A B C D) is (A | (B | (C| (D | ())))) . Example: if (?X | ?Y) matches (first second third fourth) then ?X must be first and ?Y must be (second third fourth) This idea is extended to work with longer lists, too: If (?a ?b ?c | ?d) matches (alpha beta gamma) then ?a is alpha, ?b is beta, ?c is gamma, and ?d is (). NUMBERS are not really implemented in E-Prolog. Numbers from 0 to about 5500 can be used. They can be compared using LESS, but no arithmetic has been implemented. ATOMS are what Prolog asserions and rules are built from. They are lists: the first item in the list is the "predicate symbol" or "relation name", the others are the arguments. Example: (father jack ken) means that the relation "father" holds between the individuals "jack" and "ken". In Clocksin & Mellish, this is written: father(jack,ken). It might have the interpretation (if we choose) that Jack is the father of Ken. CLAUSES are lists of atoms. This is how Prolog rules are stored in the database. The first atom is the conclusion, and the others are the conditions. Example: ((grandparent ?A ?C) (parent ?A ?B) (parent ?B ?C)) This clause represents the Prolog rule: A is the grandparent of C if A is the parent of B and B is the parent of C. In Clocksin & Mellish it would be: grandparent(A,C) :- parent(A,B) , parent(B,C). --------------------------------------------------------------- BUILT-IN PREDICATES ------------------- Certain predicates are built into E-Prolog. These have to be special so that they can have "side effects", such as printing out information to the outside world. Here are brief descriptions of these special predicates. LESS This compares two strings (or two numbers). Examples: (LESS help hurt) succeeds (LESS help help) fails LIST This sends the entire database to the console (or other current output device). Example: (LIST) READ This is used to input a token from the console (or the current input file). Example: (READ ?X) will read one token and unify it with ?X. READLIST This is used to input a list from the console (or the current input file). Examples: (READ ?X), where ?X is a variable that does not have a current value, will read one item from the console, and assign it to ?X. But (READ (?X A : C)) will read one item from the console, and attempt to unify it with the list (?X A : C). Try it! READCHAR This inputs one character, which is treated internally as a number between 0 and 255. Example: (READCHAR ?x) WRITE This writes items to the console (or other output device). Examples: (WRITE ?X ?Y ?Z) (WRITE "Now is the time.") (WRITE "The father's name is " ?father ".^M^J") WRITECHAR This outputs as one character a number between 0 and 255. This number presumably was obtained using a READCHAR. Example: (WRITECHAR ?x) OPEN This opens a file for input. After an OPEN atom is verified, input is taken from that file instead of from the console. Any remaining input in the previous input file (or the input line from the console) is ignored. When EOF is reached, input reverts to the console. The input device may also be altered by a LOAD or OPEN command in the file. This command requires a file name. The name may be CON for the console. Examples: (OPEN A:FILE.INP) (OPEN CON) CREATE This opens a previously nonexistent file for output. (If the file already exists, then it will be deleted, and a new file opened with the same name.) After a CREATE atom is verified, output goes to the file instead of to the console. To end output to the file, use CLOSE, or CREATE another file. This command requires a file name, as in OPEN. The file name may be CON for the console, or NULL for Never-Never Land. Examples: (CREATE A:FILE.OUT) (CREATE | ?file) the variable should be matched before this is attempted APPEND This is used to open an existing file for output. It is like CREATE, except that output starts at the end of the existing information. Requires a file name. Examples: (APPEND A:SAMPLE.PRO) (APPEND FAM) no filetype CLOSE This closes the output file. Further output will go to the console. Output sent to a file that is never closed will probably be lost. Example: (CLOSE) SAVE This writes the current database to a file. Requires a file name. The default file type is 'PRO'. Example: (SAVE A) is roughly equivalent to the following commands, in order: (CREATE A.PRO) (LIST) (CLOSE). LOAD This loads input from a given file. Usually used to add to the database. Use this only at command level, not from a program. (Use OPEN to get commands from a file.) Requires a file name. When EOF is reached, the input device reverts to the console. Loading may also be prematurely terminated with another LOAD or OPEN command in the file. Requires a file name. The file type 'PRO' is the default. / This is the CUT. It prohibits backtracking of the current predicate past the point it marks. See example below. --------------------------------------------------------------- SAMPLE SESSION -------------- In the sample session below, the comments are written flush left, and the actual input and output is indented. We will use the sample database SAMPLE.PRO. If you have a working E-Prolog, follow along yourself. Begin from CP/M. The tail of the command line is the first input to E-Prolog. (Remember that CP/M converts the command line to upper case.) A> EPRO (LOAD SAMPLE) E-Prolog ver. 2.3 (August 1, 1985) > This is the E-Prolog prompt. It is only shown when the input device is the console. To ask E-Prolog to attempt to prove a statement, just enter the atom. > (father jack ken) Yes. > The statement was proved. (The 'Yes' response is shown only when the input and output devices are both the console.) > (mother jack ken) > If the statement was not proved, no response is printed. Now let's try one with variables. > (father jack ?who) Yes. ?who = ken One solution was found. E-Prolog asks whether to try for other solutions: More?> y Yes. ?who = karen More?> y > The commands are entered just like other atoms. > (LIST) ((father jack ken)) ((father jack karen)) ((grandparent ?grandparent ?grandchild) (parent ?grandparent ?parent) (parent ?parent ?grandchild)) ((mother el ken)) ((mother cele jack)) ((parent ?parent ?child) (mother ?parent ?child)) ((parent ?parent ?child) (father ?parent ?child)) Yes. > Let's try something more difficult to solve: > (grandparent ?001 ?002) Yes. ?001 = cele ?002 = ken More?> y Yes. ?001 = cele ?002 = karen More?> y > Here is another variation. Try this one on your expensive Prolog system! > (?relation jack karen) Yes. ?relation = father More?> y Yes. ?relation = parent More?> y > To add to the database, enter a clause in the form of a list of atoms. > ((father carl jack)) > (LIST) ((father jack ken)) ((father jack karen)) ((father carl jack)) ((grandparent ?grandparent ?grandchild) (parent ?grandparent ?parent) (parent ?parent ?grandchild)) ((mother el ken)) ((mother cele jack)) ((parent ?parent ?child) (mother ?parent ?child)) ((parent ?parent ?child) (father ?parent ?child)) Yes. > Now let's add a rule to the database. (The prompt '1>' indicates that there is one open parenthesis that has not been closed.) > ((z ?x ?y) 1> (father jack ?x) 1> (father jack ?y) 1> ) This one illustrates backtracking. > (z | ?u) ?u = (ken ken) More?> y Yes. ?u = (ken karen) More?> y Yes. ?u = (karen ken) More?> y Yes. ?u = (karen karen) More?> y > Here is one with a cut to prohibit backtracking. > ((zz ?x ?y) (father jack ?x) (/) (father jack ?y)) > (zz | ?v) Yes. ?v = (ken ken) More?> y Yes. ?v = (ken karen) More?> y > Isn't the next one interesting: > ?x Yes. ?x = (father jack ken) More?> y Yes. ?x = (father jack karen) More?> y Yes. ?x = (grandparent cele ken) More?> y Yes. ?x = (grandparent cele karen) More?> y Yes. ?x = (grandparent carl ken) More?> n > If we didn't cut it off, it would go ahead and list all the facts that can be deduced from these rules! Some standard connectives are in the file STD.PRO. (Currently EQ , AND , OR , NOT, IF, IFF .) > (LOAD STD) > (EQ 3 6) > (EQ 3 3) Yes. > (AND (parent ?x ?y)(parent ?y ?z)) Yes. ?x = cele ?y = jack ?z = ken More?> y Yes. ?x = cele ?y = jack ?z = karen More?> n > ^C This is the way to leave E-Prolog. Don't forget to (CLOSE) first if you have been writing to the disk. --------------------------------------------------------------- G. A. Edgar CompuServe 70715,1324 107 W. Dodridge St. Columbus, OH 43202