home *** CD-ROM | disk | FTP | other *** search
- {+ PASCAL/Z COMPILER OPTIONS +}
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- {$C- <<< CONTROL-C KEYPRESS CHECKING OFF >>> }
- {$F- <<< FLOATING POINT ERROR CHECKING OFF >>> }
- {$M- <<< INTEGER MULT & DIVD ERROR CHECKING OFF >>> }
- {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
- PROGRAM LISP {VERSION 1.7};
- {
- + PROGRAM TITLE: THE ESSENCE OF A LISP INTERPRETER.
- + WRITTEN BY: W. TAYLOR AND L. COX
- +
- + WRITTEN FOR: US DEPT OF ENERGY
- + CONTRACT # W-7405-ENG-48
- +
- + FIRST DATA STARTED : 10/29/76
- + LAST DATE MODIFIED : 12/10/76
- +
- + ENTERED BY RAY PENLEY 8 DEC 80.
- + -SOME IDENTIFIERS HAVE BEEN SLIGHTLY MODIFIED BECAUSE OF THE
- + LIMITATION ON IDENTIFIER LENGTH OF 8 CHARACTERS.
- +
- + MODIFIED BY LANFRANCO EMILIANI IN THE PERIOD MARS-MAY 1983 :
- + - TO REMOVE THE TWO JUMPS OUT OF PROCEDURES PRESENT IN THE
- + ZUG VOL # 14 VERSION;
- + - TO REMOVE TWO BUGS PRESENT IN THAT VERSION;
- + - TO PROVIDE ADDITIONAL FEATURES.
- +
- + REFER TO LISP.DOC FOR A DESCRIPTION OF THE MAIN FEATURES OF THE
- + INTERPRETER AND HOW TO OPERATE IT.
- +
- + REFER TO THE COMMENTS IN THE ZUG VOL # 14 VERSION FOR SPECIFIC
- + EXPLANATORY NOTES CONCERNING THE MOST SIGNIFICANT PROCEDURES OR
- + FUNCTIONS.
- +
- }
- LABEL
- 1, { USED TO RECOVER AFTER AN ERROR BY THE USER }
- 2; { IN CASE THE END OF FILE IS REACHED BEFORE A FIN CARD }
-
- CONST
- MAXNODE = 1000;
- {}INPUT = 0; { Pascal/Z = console as input }
- {}IDLENGTH = 10;
-
- TYPE
- {}ALFA = ARRAY [1..IDLENGTH] OF CHAR;
- INPUTSYMBOL = (ATOM, PERIOD, LPAREN, RPAREN);
- RESERVEWORDS = ( ANDSYM,
- APPENDSYM,
- ATOMSYM,
- HEADSYM,
- TAILSYM,
- CONDSYM,
- CONSSYM,
- COPYSYM,
- DEFEXPSYM,
- DEFFEXPSYM,
- DEFMACSYM,
- EQSYM,
- EQUALSYM,
- EVALSYM,
- FLAMBDASYM,
- FUNARGSYM,
- FUNCTSYM,
- GOSYM,
- LABELSYM,
- LAMBDASYM,
- LASTSYM,
- LENGTHSYM,
- LISTSYM,
- NOTSYM,
- NULLSYM,
- ORSYM,
- PROGSYM,
- PROG2SYM,
- PROGNSYM,
- QUOTESYM,
- RELACEHSYM,
- RELACETSYM,
- REMOBSYM,
- RETURNSYM,
- REVERSESYM,
- SETSYM,
- SETQSYM,
- TRACESYM,
- UNTRACESYM );
- STATUSTYPE = (UNMARKED, LEFT, RIGHT, MARKED);
- SYMBEXPPTR = ^SYMBOLICEXPRESSION;
- SYMBOLICEXPRESSION = RECORD
- STATUS : STATUSTYPE;
- NEXT : SYMBEXPPTR;
- CASE ANATOM: BOOLEAN OF
- TRUE: (NAME: ALFA;
- CASE ISARESERVEDWORD: BOOLEAN OF
- TRUE: (RESSYM: RESERVEWORDS));
- FALSE: (HEAD, TAIL: SYMBEXPPTR)
- END;
-
- VAR
- END_FREELIST : BOOLEAN;
- ERR_COND : BOOLEAN;
- TRACE_ON : BOOLEAN;
- NESTCOUNT : INTEGER;
-
- { VARIABLES WHICH PASS INFORMATION FROM THE SCANNER TO THE READ ROUTINE }
-
- LOOKAHEADSYM, { USED TO SAVE A SYMBOL WHEN WE BACK UP }
- SYM : INPUTSYMBOL; { THE SYMBOL THAT WAS LAST SCANNED }
- ID : ALFA; { NAME OF THE ATOM THAT WAS LAST READ }
- ALREADYPEEKED : BOOLEAN; { TELLS 'NEXTSYM' WHETHER WE HAVE PEEKED }
- CH : CHAR; { THE LAST CHAR READ FROM INPUT }
- PTR : SYMBEXPPTR; { POINTER TO THE EXPRESSION BEING EVALUATED }
- TEMP : SYMBEXPPTR;
-
- { THE GLOBAL LISTS OF LISP NODES }
-
- FREELIST, { POINTER TO THE LINEAR LIST OF FREE NODES }
- NODELIST, { POINTER USED TO MAKE A LINEAR SCAN OF ALL}
- { THE NODES DURING GARBAGE COLLECTION. }
- ALIST : SYMBEXPPTR;{ POINTER TO THE ASSOCIATION LIST }
-
- { TWO NODES WHICH HAVE CONSTANT VALUES }
-
- NILNODE,
- TNODE : SYMBOLICEXPRESSION;
-
- { VARIABLES USED TO IDENTIFY ATOMS WITH PRE-DEFINED MEANINGS }
-
- RESWORD : RESERVEWORDS;
- RESERVED : BOOLEAN;
- RESWORDS : ARRAY [RESERVEWORDS] OF ALFA;
- FREENODES : INTEGER; { NUMBER OF CURRENTLY FREE NODES KNOWN }
- NUMBEROFGCS : INTEGER; { # OF GARBAGE COLLECTIONS MADE }
-
- INFILE : TEXT;
-
-
- PROCEDURE GARBAGEMAN;
-
- PROCEDURE MARK(LIST: SYMBEXPPTR);
- VAR
- FATHER, SON, CURRENT: SYMBEXPPTR;
- BEGIN
- FATHER := NIL;
- CURRENT := LIST;
- SON := CURRENT;
- WHILE ( CURRENT<>NIL ) DO
- WITH CURRENT^ DO
- CASE STATUS OF
- UNMARKED:
- IF ( ANATOM ) THEN
- STATUS := MARKED
- ELSE
- IF (HEAD^.STATUS <> UNMARKED) OR (HEAD = CURRENT) THEN
- IF (TAIL^.STATUS <> UNMARKED) OR (TAIL = CURRENT) THEN
- STATUS := MARKED
- ELSE BEGIN
- STATUS := RIGHT; SON := TAIL; TAIL := FATHER;
- FATHER := CURRENT; CURRENT := SON
- END
- ELSE BEGIN
- STATUS := LEFT; SON := HEAD; HEAD := FATHER;
- FATHER := CURRENT; CURRENT := SON
- END;
- LEFT:
- IF ( TAIL^.STATUS <> UNMARKED ) THEN BEGIN
- STATUS := MARKED; FATHER := HEAD; HEAD := SON;
- SON := CURRENT
- END
- ELSE BEGIN
- STATUS := RIGHT; CURRENT := TAIL; TAIL := HEAD;
- HEAD := SON; SON := CURRENT
- END;
- RIGHT:
- BEGIN
- STATUS := MARKED; FATHER := TAIL; TAIL := SON;
- SON := CURRENT
- END;
- MARKED: CURRENT := FATHER
- END { OF CASE }
- END { OF MARK };
-
- PROCEDURE COLLECTFREENODES;
- VAR
- TEMP: SYMBEXPPTR;
- BEGIN
- {
- WRITELN(' NUMBER OF FREE NODES BEFORE COLLECTION = ', FREENODES:1, '.');
- }
- FREELIST := NIL; FREENODES := 0; TEMP := NODELIST;
- WHILE ( TEMP <> NIL ) DO BEGIN
- IF ( TEMP^.STATUS <> UNMARKED ) THEN
- TEMP^.STATUS := UNMARKED
- ELSE BEGIN
- FREENODES := FREENODES + 1; TEMP^.HEAD := FREELIST;
- FREELIST := TEMP
- END;
- TEMP := TEMP^.NEXT;
- END {WHILE};
- {
- WRITELN(' NUMBER OF FREE NODES AFTER COLLECTION = ', FREENODES:1,'.');
- }
- END { OF COLLECTFREENODES };
-
- BEGIN{ GARBAGEMAN }
- NUMBEROFGCS := NUMBEROFGCS + 1;
- { WRITELN; WRITELN(' GARBAGE COLLECTION. '); WRITELN; }
- MARK(ALIST);
- IF ( PTR <> NIL ) THEN MARK(PTR);
- COLLECTFREENODES
- END{ OF GARBAGEMAN };
-
- PROCEDURE POP(VAR SPTR: SYMBEXPPTR);
- LABEL 1;
- BEGIN
- IF ( FREELIST = NIL ) THEN BEGIN
- WRITELN(' NOT ENOUGH SPACE TO EVALUATE THE EXPRESSION.');
- END_FREELIST := TRUE;
- GOTO 1;
- END;
- FREENODES := FREENODES - 1;
- SPTR := FREELIST;
- FREELIST := FREELIST^.HEAD;
- 1:
- END{ OF POP };
-
-
- PROCEDURE ERROR(NUMBER: INTEGER);
- BEGIN
- WRITELN; WRITE(' ERROR ', NUMBER:1, ', ');
- CASE NUMBER OF
- 1: WRITELN('ATOM OR LPAREN EXPECTED IN THE S-EXPR.');
- 2: WRITELN('ATOM, LPAREN, OR RPAREN EXPECTED IN THE S-EXPR.');
- 3: WRITELN('LABEL, LAMBDA, FLAMBDA, ETC. ARE NOT FUNCTIONS NAMES.');
- 4: WRITELN('RPAREN EXPECTED IN THE S-EXPR.');
- 5: WRITELN('1ST ARGUMENT OF REPLACEH IS AN ATOM.');
- 6: WRITELN('1ST ARGUMENT OF REPLACET IS AN ATOM.');
- 7: WRITELN('ARGUMENT HEAD IS AN ATOM.');
- 8: WRITELN('ARGUMENT TAIL IS AN ATOM.');
- 9: WRITELN('1ST ARGUMENT OF APPEND IS NOT A LIST.');
- 10: WRITELN('LABEL OR LAMBDA OR FLAMBDA ETC. EXPECTED.');
- 11: WRITELN('NAME OF VARIABLE IS NOT AN ATOM.');
- 12: WRITELN('ARGUMENT OF LENGTH IS NOT A LIST.');
- 13: WRITELN('ARGUMENT OF PROG IS NOT A LIST.');
- 14: WRITELN('LOOP IDENTIFIER NOT FOUND.');
- END{CASE};
- ERR_COND := TRUE
- END { OF ERROR };
-
- PROCEDURE BACKUPINPUT;
- BEGIN
- ALREADYPEEKED := TRUE; LOOKAHEADSYM := SYM; SYM := LPAREN
- END{ OF BACKUPINPUT };
-
- PROCEDURE NEXTSYM1;
- VAR I: INTEGER;
- BEGIN
- IF ( ALREADYPEEKED ) THEN BEGIN
- SYM := LOOKAHEADSYM; ALREADYPEEKED := FALSE
- END
- ELSE
- BEGIN
- WHILE ( CH=' ' ) DO BEGIN
- IF ( EOLN(INFILE) ) THEN READLN(INFILE);
- READ(INFILE, CH);
- END{WHILE};
- IF ( CH IN ['(','.',')'] ) THEN BEGIN
- CASE CH OF
- '(': SYM := LPAREN;
- '.': SYM := PERIOD;
- ')': SYM := RPAREN
- END{CASE};
- IF ( EOLN(INFILE) ) THEN READLN(INFILE);
- READ(INFILE, CH);
- END
- ELSE BEGIN
- SYM := ATOM; ID := ' ';
- I := 0;
- REPEAT
- I := I + 1;
- IF ( I < (IDLENGTH+1) ) THEN ID[I] := CH;
- IF ( EOLN(INFILE) ) THEN READLN(INFILE);
- READ(INFILE, CH);
- UNTIL ( CH IN [' ','(','.',')'] );
- RESWORD := ANDSYM;
- WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> UNTRACESYM) DO
- RESWORD := SUCC(RESWORD);
- RESERVED := ( ID=RESWORDS[RESWORD] )
- END
- END
- END{ OF NEXTSYM1 };
-
- PROCEDURE READEXP1(VAR SPTR: SYMBEXPPTR);
- LABEL 1;
- VAR NXT: SYMBEXPPTR;
- BEGIN
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(SPTR);
- IF END_FREELIST THEN GOTO 1;
- NXT := SPTR^.NEXT;
- CASE SYM OF
- RPAREN, PERIOD: BEGIN ERROR(1); GOTO 1 END;
- ATOM:
- WITH SPTR^ DO BEGIN { <ATOM> }
- ANATOM := TRUE; NAME := ID; ISARESERVEDWORD := RESERVED;
- IF ( RESERVED ) THEN RESSYM := RESWORD
- END;
- LPAREN:
- WITH SPTR^ DO BEGIN
- NEXTSYM1;
- IF ( SYM=PERIOD ) THEN BEGIN ERROR(2); GOTO 1 END
- ELSE
- IF ( SYM=RPAREN ) THEN SPTR^ := NILNODE { () = NIL }
- ELSE BEGIN
- ANATOM := FALSE; READEXP1(HEAD); NEXTSYM1;
- IF ( SYM=PERIOD ) THEN BEGIN { ( <S-EXPR> . <S-EXPR> ) }
- NEXTSYM1; READEXP1(TAIL); NEXTSYM1;
- IF (SYM<>RPAREN) THEN BEGIN ERROR(4); GOTO 1 END
- END
- ELSE BEGIN { ( <S-EXPR> <S-EXPR> ... <S-EXPR> ) }
- BACKUPINPUT; READEXP1(TAIL)
- END
- END
- END{WITH}
- END{CASE};
- SPTR^.NEXT := NXT;
- END;
- 1:
- END{ OF READEXP1 };
-
- PROCEDURE NEXTSYM;
- VAR I: INTEGER;
- BEGIN
- IF ( ALREADYPEEKED ) THEN BEGIN
- SYM := LOOKAHEADSYM; ALREADYPEEKED := FALSE
- END
- ELSE
- BEGIN
- WHILE ( CH=' ' ) DO BEGIN
- IF ( EOLN(INPUT) ) THEN READLN;
- READ(CH);
- END{WHILE};
- IF ( CH IN ['(','.',')'] ) THEN BEGIN
- CASE CH OF
- '(': SYM := LPAREN;
- '.': SYM := PERIOD;
- ')': SYM := RPAREN
- END{CASE};
- IF ( EOLN(INPUT) ) THEN READLN;
- READ(CH);
- END
- ELSE BEGIN
- SYM := ATOM; ID := ' ';
- I := 0;
- REPEAT
- I := I + 1;
- IF ( I < (IDLENGTH+1) ) THEN ID[I] := CH;
- IF (EOLN (INPUT) ) THEN READLN;
- READ(CH);
- UNTIL ( CH IN [' ','(','.',')'] );
- RESWORD := ANDSYM;
- WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> UNTRACESYM) DO
- RESWORD := SUCC(RESWORD);
- RESERVED := ( ID=RESWORDS[RESWORD] )
- END
- END
- END{ OF NEXTSYM };
-
- PROCEDURE READEXPR(VAR SPTR: SYMBEXPPTR);
- LABEL 1;
- VAR NXT: SYMBEXPPTR;
- BEGIN
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(SPTR);
- IF END_FREELIST THEN GOTO 1;
- NXT := SPTR^.NEXT;
- CASE SYM OF
- RPAREN, PERIOD: BEGIN ERROR(1); GOTO 1 END;
- ATOM:
- WITH SPTR^ DO BEGIN { <ATOM> }
- ANATOM := TRUE; NAME := ID; ISARESERVEDWORD := RESERVED;
- IF ( RESERVED ) THEN RESSYM := RESWORD
- END;
- LPAREN:
- WITH SPTR^ DO BEGIN
- NEXTSYM;
- IF ( SYM=PERIOD ) THEN BEGIN ERROR(2); GOTO 1 END
- ELSE
- IF ( SYM=RPAREN ) THEN SPTR^ := NILNODE { () = NIL }
- ELSE BEGIN
- ANATOM := FALSE; READEXPR(HEAD); NEXTSYM;
- IF ( SYM=PERIOD ) THEN BEGIN { ( <S-EXPR> . <S-EXPR> ) }
- NEXTSYM; READEXPR(TAIL); NEXTSYM;
- IF (SYM<>RPAREN) THEN BEGIN ERROR(4); GOTO 1 END
- END
- ELSE BEGIN { ( <S-EXPR> <S-EXPR> ... <S-EXPR> ) }
- BACKUPINPUT; READEXPR(TAIL)
- END
- END
- END{WITH}
- END{CASE};
- SPTR^.NEXT := NXT;
- END;
- 1:
- END{ OF READEXPR };
-
- PROCEDURE PRINTNAME(NAME: ALFA);
- VAR I: INTEGER;
- BEGIN
- I := 0;
- REPEAT
- I := I + 1;
- WRITE(NAME[I])
- UNTIL (NAME[I]=' ') OR ( I=IDLENGTH );
- IF ( I=IDLENGTH ) THEN WRITE(' ')
- END{ OF PRINTNAME };
-
- PROCEDURE PRINTEXPR(SPTR : SYMBEXPPTR);
- LABEL 1, 2;
- BEGIN
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 2 ELSE
- BEGIN
- IF ( SPTR^.ANATOM ) THEN
- PRINTNAME(SPTR^.NAME)
- ELSE BEGIN
- WRITE('(');
- 1: PRINTEXPR(SPTR^.HEAD);
- IF ( SPTR^.TAIL^.ANATOM ) AND ( SPTR^.TAIL^.NAME='NIL ') THEN
- WRITE(')')
- ELSE IF ( SPTR^.TAIL^.ANATOM ) THEN BEGIN
- WRITE('.'); PRINTEXPR(SPTR^.TAIL); WRITE(')')
- END
- ELSE BEGIN
- SPTR := SPTR^.TAIL;
- GOTO 1
- END
- END
- END;
- 2:
- END{ OF PRINTEXPR };
-
-
- PROCEDURE TRACENTER(ID : ALFA);
- VAR J : INTEGER;
- BEGIN
- NESTCOUNT := NESTCOUNT + 1;
- FOR J := 0 TO NESTCOUNT DO WRITE(' ');
- WRITE('ENTERING : ');
- FOR J := 1 TO IDLENGTH DO WRITE(ID[J]);
- WRITELN
- END{ OF TRACENTER };
-
- PROCEDURE TRACEXIT(ID : ALFA);
- VAR J : INTEGER;
- BEGIN
- FOR J := 0 TO NESTCOUNT DO WRITE(' ');
- WRITE('EXITING : ');
- FOR J := 1 TO IDLENGTH DO WRITE(ID[J]);
- WRITELN;
- NESTCOUNT := NESTCOUNT - 1
- END{ OF TRACEXIT };
-
- FUNCTION EVAL( E : SYMBEXPPTR; VAR ALIST : SYMBEXPPTR ): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, CAROFE, CAAROFE: SYMBEXPPTR;
-
- FUNCTION MKATOM(ID : ALFA): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('MKATOM ');
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- RESWORD := APPENDSYM;
- WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> SETQSYM) DO
- RESWORD := SUCC(RESWORD);
- RESERVED := ( ID = RESWORDS[RESWORD] );
- WITH TEMP^ DO BEGIN
- ANATOM := TRUE;
- NAME := ID;
- ISARESERVEDWORD := RESERVED;
- IF (RESERVED) THEN RESSYM := RESWORD
- END;
- MKATOM := TEMP;
- 1:
- IF TRACE_ON THEN TRACEXIT('MKATOM ')
- END{ OF MKATOM };
-
- FUNCTION REPLACEH(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- BEGIN
- IF TRACE_ON THEN TRACENTER('REPLACEH ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR1^.ANATOM ) THEN BEGIN ERROR(5); GOTO 1 END
- ELSE SPTR1^.HEAD := SPTR2;
- REPLACEH := SPTR1;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('REPLACEH ')
- END{ OF REPLACEH };
-
- FUNCTION REPLACET(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- BEGIN
- IF TRACE_ON THEN TRACENTER('REPLACET ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR1^.ANATOM ) THEN BEGIN ERROR(6); GOTO 1 END
- ELSE SPTR1^.TAIL := SPTR2;
- REPLACET := SPTR1;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('REPLACET ')
- END{ OF REPLACET };
-
- FUNCTION HEAD(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- BEGIN
- IF TRACE_ON THEN TRACENTER('CAR ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR^.ANATOM ) THEN BEGIN ERROR(7); GOTO 1 END
- ELSE HEAD := SPTR^.HEAD;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('CAR ')
- END{ OF HEAD };
-
- FUNCTION TAIL(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- BEGIN
- IF TRACE_ON THEN TRACENTER('CDR ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR^.ANATOM ) THEN BEGIN ERROR(8); GOTO 1 END
- ELSE TAIL := SPTR^.TAIL;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('CDR ')
- END{ OF TAIL };
-
- FUNCTION CONS(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('CONS ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- TEMP^.ANATOM := FALSE; TEMP^.HEAD := SPTR1;
- TEMP^.TAIL := SPTR2; CONS := TEMP;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('CONS ')
- END{ OF CONS };
-
- FUNCTION COPY(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, NXT: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('COPY ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR^.ANATOM ) THEN BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- NXT := TEMP^.NEXT; TEMP^ := SPTR^;
- TEMP^.NEXT := NXT; COPY := TEMP
- END
- ELSE
- COPY := CONS(COPY(SPTR^.HEAD), COPY(SPTR^.TAIL));
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('COPY ')
- END{ OF COPY };
-
- FUNCTION APPEND(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- BEGIN
- IF TRACE_ON THEN TRACENTER('APPEND ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( SPTR1^.ANATOM ) THEN
- IF ( SPTR1^.NAME<>'NIL ' ) THEN BEGIN ERROR(9); GOTO 1 END
- ELSE APPEND := SPTR2
- ELSE
- APPEND := CONS(COPY(SPTR1^.HEAD), APPEND(SPTR1^.TAIL,SPTR2));
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('APPEND ')
- END{ OF APPEND };
-
- FUNCTION LIST(SPTR1: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR
- NILPTR: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('LIST ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF NOT SPTR1^.ANATOM THEN
- LIST := CONS(EVAL(SPTR1^.HEAD, ALIST), LIST(SPTR1^.TAIL))
- ELSE BEGIN
- IF SPTR1^.NAME <> 'NIL ' THEN BEGIN
- NEW(NILPTR);
- WITH NILPTR^ DO BEGIN
- ANATOM := TRUE; NAME := 'NIL '
- END {WITH};
- LIST := CONS(EVAL(SPTR1, ALIST), NILPTR)
- END
- ELSE LIST := SPTR1
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('LIST ')
- END{ OF LIST };
-
- FUNCTION EQQ(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, NXT: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('EQ ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- NXT := TEMP^.NEXT;
- IF ((SPTR1^.ANATOM) AND (SPTR2^.ANATOM) AND (SPTR1^.NAME=SPTR2^.NAME))
- OR (SPTR1 = SPTR2) THEN TEMP^ := TNODE
- ELSE TEMP^ := NILNODE;
- TEMP^.NEXT := NXT; EQQ := TEMP;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('EQ ')
- END{ OF EQQ };
-
- FUNCTION EQUAL(SPTR1, SPTR2 : SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, NXT : SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('EQUAL ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- NXT := TEMP^.NEXT;
- IF (SPTR1^.ANATOM) THEN BEGIN
- IF (SPTR2^.ANATOM) THEN TEMP := EQQ(SPTR1, SPTR2)
- ELSE TEMP^ := NILNODE
- END
- ELSE BEGIN
- IF SPTR2^.ANATOM THEN TEMP^ := NILNODE
- ELSE BEGIN
- TEMP := EQUAL(HEAD(SPTR1), HEAD(SPTR2));
- IF ( TEMP^.NAME = 'T ' ) THEN
- TEMP := EQUAL(TAIL(SPTR1), TAIL(SPTR2))
- ELSE BEGIN
- TEMP^ := NILNODE
- END
- END
- END;
- TEMP^.NEXT := NXT;
- EQUAL := TEMP
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('EQUAL ')
- END{ OF EQUAL };
-
- FUNCTION NULL(SPTR : SYMBEXPPTR) : SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, NXT : SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('NULL ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- NXT := TEMP^.NEXT; TEMP^ := NILNODE; TEMP^.NEXT := NXT;
- NULL := EQQ(SPTR, TEMP)
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('NULL ')
- END{ OF NULL };
-
- FUNCTION ET(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('AND ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF (SPTR^.ANATOM) AND (SPTR^.NAME = 'NIL ') THEN
- ET := MKATOM('T ')
- ELSE BEGIN
- TEMP := EVAL(HEAD(SPTR), ALIST);
- IF (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL ') THEN ET := TEMP
- ELSE ET := ET(TAIL(SPTR))
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('AND ')
- END{ OF ET };
-
- FUNCTION OU(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('OR ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF (SPTR^.ANATOM) AND (SPTR^.NAME = 'NIL ') THEN OU := SPTR
- ELSE BEGIN
- TEMP := EVAL(HEAD(SPTR), ALIST);
- IF (TEMP^.ANATOM) AND (TEMP^.NAME <> 'NIL ') THEN
- OU := MKATOM('T ')
- ELSE OU := OU(TAIL(SPTR))
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('OR ')
- END{ OF OU };
-
- FUNCTION ATOM(SPTR : SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP, NXT: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('ATOM ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- POP(TEMP);
- IF END_FREELIST THEN GOTO 1;
- NXT := TEMP^.NEXT;
- IF ( SPTR^.ANATOM ) THEN
- TEMP^ := TNODE
- ELSE
- TEMP^ := NILNODE;
- TEMP^.NEXT := NXT; ATOM := TEMP;
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('ATOM ')
- END{ OF ATOM };
-
- FUNCTION LAST(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('LAST ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF (SPTR^.ANATOM) THEN LAST := SPTR ELSE
- BEGIN
- TEMP := TAIL(SPTR);
- IF (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL ') THEN
- LAST := HEAD(SPTR) ELSE LAST := LAST(TEMP)
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('LAST ')
- END{ OF LAST };
-
- FUNCTION REVERSE(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('REVERSE ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP := NULL(SPTR);
- IF (TEMP^.NAME = 'T ') THEN REVERSE := SPTR ELSE
- REVERSE := APPEND(REVERSE(TAIL(SPTR)),
- CONS(HEAD(SPTR), MKATOM('NIL ')))
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('REVERSE ')
- END{ OF REVERSE };
-
- FUNCTION LENGTH(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- IDENTIFIER: ALFA;
- J: INTEGER;
- BEGIN
- IF TRACE_ON THEN TRACENTER('LENGTH ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- J := 0;
- TEMP := SPTR;
- IF (TEMP^.ANATOM) THEN BEGIN
- IF (TEMP^.NAME = 'NIL ') THEN J := 0 ELSE BEGIN
- ERROR(12); GOTO 1 END
- END
- ELSE REPEAT
- J := J + 1;
- TEMP := TAIL(TEMP)
- UNTIL (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL ');
- IDENTIFIER := ' ';
- IDENTIFIER[1] := CHR( (J DIV 100) + 48); {LIMIT FOR J IS 999}
- IDENTIFIER[2] := CHR((J - ((J DIV 100)*100)) DIV 10 + 48);
- IDENTIFIER[3] :=
- CHR( J - ((J DIV 100)*100) - ((J DIV 10)*10) + 48);
- LENGTH := MKATOM(IDENTIFIER)
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('LENGTH ')
- END{ OF LENGTH };
-
- FUNCTION LOOKUP(KEY, ALIST: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR
- TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('LOOKUP ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP := EQQ( HEAD( HEAD(ALIST)), KEY);
- IF ( TEMP^.NAME='T ' ) THEN
- LOOKUP := TAIL(HEAD(ALIST))
- ELSE
- LOOKUP := LOOKUP(KEY, TAIL(ALIST))
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('LOOKUP ')
- END{ OF LOOKUP };
-
- FUNCTION BINDARGS(NAMES, VALUES, ENV: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR
- TEMP, TEMP2: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('BINDARGS ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( NAMES^.ANATOM ) AND (NAMES^.NAME='NIL ') THEN
- BINDARGS := ENV
- ELSE BEGIN
- TEMP := CONS( HEAD(NAMES), EVAL(HEAD(VALUES), ENV) );
- TEMP2 := BINDARGS(TAIL(NAMES), TAIL(VALUES), ENV);
- BINDARGS := CONS(TEMP, TEMP2)
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('BINDARGS ')
- END{ OF BINDARGS };
-
- FUNCTION BINDARG1(NAMES, VALUES, ENV: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR
- TEMP, TEMP2: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('BINDARG1 ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( NAMES^.ANATOM ) AND ( NAMES^.NAME='NIL ') THEN
- BINDARG1 := ENV
- ELSE BEGIN
- TEMP := CONS( HEAD(NAMES), HEAD(VALUES) );
- TEMP2 := BINDARG1( TAIL(NAMES), TAIL(VALUES), ENV);
- BINDARG1 := CONS(TEMP, TEMP2)
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('BINDARG1 ')
- END{ OF BINDARG1 };
-
- FUNCTION EVCON(CONDPAIRS: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR
- TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('EVCON ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP := EVAL( HEAD(HEAD(CONDPAIRS)),ALIST );
- IF ( TEMP^.ANATOM ) AND (TEMP^.NAME='NIL ') THEN
- EVCON := EVCON( TAIL(CONDPAIRS) )
- ELSE
- EVCON := EVAL( HEAD(TAIL(HEAD(CONDPAIRS))),ALIST )
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('EVCON ')
- END{ OF EVCON };
-
- FUNCTION MKFUNARG(SPTR : SYMBEXPPTR) : SYMBEXPPTR;
- VAR
- TEMP : SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('MKFUNARG ');
- IF (SPTR^.ANATOM) AND (NOT SPTR^.ISARESERVEDWORD) THEN
- TEMP := CONS(MKATOM('FUNARG '), CONS(EVAL(SPTR, ALIST), ALIST))
- ELSE
- TEMP := CONS(MKATOM('FUNARG '), CONS(SPTR, ALIST));
- MKFUNARG := TEMP;
- IF TRACE_ON THEN TRACEXIT('MKFUNARG ')
- END{ OF MKFUNARG };
-
- FUNCTION ASSOC(KEY, S_TABLE : SYMBEXPPTR) : SYMBEXPPTR;
- LABEL 1;
- VAR
- TEMP1, TEMP2 : SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('ASSOC ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP1 := EQQ(HEAD(HEAD(S_TABLE)), KEY);
- IF (TEMP1^.NAME = 'T ') THEN
- ASSOC := HEAD(S_TABLE)
- ELSE
- BEGIN
- TEMP2 := HEAD(HEAD(TAIL(S_TABLE)));
- IF NOT (TEMP2^.ANATOM) OR (TEMP2^.NAME <> 'NIL ') THEN
- ASSOC := ASSOC(KEY, TAIL(S_TABLE))
- ELSE
- ASSOC := HEAD(TAIL(S_TABLE))
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('ASSOC ')
- END{OF ASSOC};
-
- PROCEDURE SETT(SPTR1, SPTR2 : SYMBEXPPTR; VAR ALIST : SYMBEXPPTR);
- LABEL 1;
- VAR
- TEMP1, TEMP2, TEMP3, NXT : SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('SETT ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF NOT SPTR1^.ANATOM THEN BEGIN
- ERROR(11);
- GOTO 1
- END;
- TEMP1 := ASSOC(SPTR1, ALIST);
- TEMP2 := HEAD(TEMP1);
- IF (TEMP2^.ANATOM) AND (TEMP2^.NAME = 'NIL ') THEN
- {VARIABLE NOT LOCATED IN THE ALIST}
- BEGIN
- POP(TEMP3);
- IF END_FREELIST THEN GOTO 1;
- TEMP3^.ANATOM := FALSE; TEMP3^.STATUS := UNMARKED;
- TEMP3^.TAIL := ALIST; ALIST := TEMP3;
- POP(ALIST^.HEAD);
- IF END_FREELIST THEN GOTO 1;
- WITH ALIST^.HEAD^ DO BEGIN
- ANATOM := FALSE; STATUS := UNMARKED;
- HEAD := COPY(SPTR1);
- TAIL := COPY(SPTR2)
- END
- END
- ELSE {VARIABLE LOCATED IN THE ALIST}
- TEMP1^.TAIL := COPY(SPTR2)
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('SETT ')
- END{OF SETT};
-
- PROCEDURE REMOB(KEY: SYMBEXPPTR; VAR S_TABLE: SYMBEXPPTR);
- LABEL 1;
- VAR TEMP1, TEMP2, TEMP3: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('REMOB ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP1 := EQQ(HEAD(HEAD(S_TABLE)), KEY);
- IF (TEMP1^.NAME = 'T ') THEN S_TABLE := TAIL(S_TABLE)
- ELSE BEGIN
- TEMP2 := HEAD(TAIL(S_TABLE));
- IF NOT (TEMP2^.ANATOM) OR (TEMP2^.NAME <> 'NIL ') THEN
- BEGIN TEMP3 := TAIL(S_TABLE); REMOB(KEY, TEMP3) END;
- S_TABLE := CONS(HEAD(S_TABLE), TEMP3)
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('REMOB ')
- END{ OF REMOB };
-
- FUNCTION PROG(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP1, TEMP2, TEMP3, AUX: SYMBEXPPTR;
- BEGIN
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF TRACE_ON THEN TRACENTER('PROG ');
- IF SPTR^.ANATOM THEN BEGIN ERROR(13); GOTO 1 END ELSE
- BEGIN
- {ZEROING THE LIST OF VARIABLES}
- AUX:= HEAD(SPTR);
- WHILE NOT (AUX^.ANATOM) OR (AUX^.NAME <> 'NIL ') DO BEGIN
- SETT(HEAD(AUX), MKATOM('NIL '), ALIST);
- AUX := TAIL(AUX)
- END {WHILE};
- {CARRYING OUT THE PROGRAM}
- TEMP3 := TAIL(SPTR);
- REPEAT
- TEMP1 := HEAD(TEMP3);
- {SKIP ATOMS}
- IF TEMP1^.ANATOM THEN TEMP1 := HEAD(TAIL(TEMP3));
- TEMP2 := EVAL(TEMP1, ALIST);
- IF NOT TEMP2^.ANATOM THEN BEGIN
-
- TEMP := HEAD(TEMP2);
- IF TEMP^.ANATOM THEN BEGIN
- IF TEMP^.NAME = 'RETURN ' THEN BEGIN
- PROG := MKATOM('NIL '); GOTO 1 END ELSE BEGIN
- IF TEMP^.NAME = 'GO ' THEN BEGIN
- {GO TO THE TOP OF THE LIST}
- AUX := TAIL(SPTR);
- {LOOK FOR THE TAG}
- TEMP1 := HEAD(AUX);
- TEMP := HEAD(TAIL(TEMP2));
- WHILE NOT (TEMP1^.ANATOM) OR
- (TEMP1^.NAME <> TEMP^.NAME) DO BEGIN
- AUX := TAIL(AUX);
- IF (AUX^.ANATOM) AND (AUX^.NAME = 'NIL ') THEN
- BEGIN ERROR(14); GOTO 1 END;
- TEMP1 := HEAD(AUX)
- END {WHILE};
- TEMP3 := AUX
- END
- END
- END
-
- END;
- TEMP3 := TAIL(TEMP3)
- UNTIL (TEMP3^.ANATOM) AND (TEMP3^.NAME = 'NIL ');
- PROG := TEMP2
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('PROG ')
- END{ OF PROG };
-
- FUNCTION PROG2(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('PROG2 ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- TEMP := EVAL(SPTR1, ALIST);
- TEMP := EVAL(SPTR2, ALIST);
- PROG2 := TEMP
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('PROG2 ')
- END{ OF PROG2 };
-
- FUNCTION PROGN(SPTR: SYMBEXPPTR): SYMBEXPPTR;
- LABEL 1;
- VAR TEMP1, TEMP2, TEMP3: SYMBEXPPTR;
- BEGIN
- IF TRACE_ON THEN TRACENTER('PROGN ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF (SPTR^.ANATOM) THEN PROGN := EVAL(SPTR, ALIST) ELSE
- BEGIN
- TEMP3 := SPTR;
- REPEAT
- TEMP1 := HEAD(TEMP3);
- TEMP2 := EVAL(TEMP1, ALIST);
- TEMP3 := TAIL(TEMP3)
- UNTIL (TEMP3^.ANATOM) AND (TEMP3^.NAME = 'NIL ');
- PROGN := TEMP2
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('PROGN ')
- END{ OF PROGN };
-
- BEGIN { * E V A L * }
- IF TRACE_ON THEN TRACENTER('EVAL ');
- IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
- BEGIN
- IF ( E^.ANATOM ) THEN EVAL := LOOKUP(E, ALIST)
- ELSE
- BEGIN
- CAROFE := HEAD(E);
- IF ( CAROFE^.ANATOM ) THEN
- IF NOT ( CAROFE^.ISARESERVEDWORD ) THEN
- EVAL := EVAL( CONS(LOOKUP(CAROFE,ALIST),TAIL(E)), ALIST )
- ELSE
- CASE CAROFE^.RESSYM OF
-
- LABELSYM, LAMBDASYM, FUNARGSYM, FLAMBDASYM:
- BEGIN ERROR(3); GOTO 1 END;
-
- TRACESYM : BEGIN TRACE_ON := TRUE;
- EVAL := MKATOM('NIL ')
- END;
-
- UNTRACESYM : BEGIN TRACE_ON := FALSE;
- EVAL := MKATOM('NIL ')
- END;
-
- QUOTESYM : EVAL := HEAD(TAIL(E));
-
- ATOMSYM : EVAL := ATOM(EVAL(HEAD(TAIL(E)),ALIST));
-
- EQSYM : EVAL := EQQ(EVAL(HEAD(TAIL(E)),ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- EQUALSYM : EVAL := EQUAL(EVAL(HEAD(TAIL(E)), ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- HEADSYM : EVAL := HEAD(EVAL(HEAD(TAIL(E)),ALIST));
-
- TAILSYM : EVAL := TAIL(EVAL(HEAD(TAIL(E)),ALIST));
-
- CONSSYM : EVAL := CONS(EVAL(HEAD(TAIL(E)),ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- CONDSYM : EVAL := EVCON(TAIL(E));
-
- LISTSYM : EVAL := LIST(TAIL(E));
-
- ANDSYM : EVAL := ET(TAIL(E));
-
- ORSYM : EVAL := OU(TAIL(E));
-
- NULLSYM, NOTSYM :
- EVAL := NULL(EVAL(HEAD(TAIL(E)), ALIST));
-
- EVALSYM : EVAL := EVAL(EVAL(HEAD(TAIL(E)), ALIST), ALIST);
-
- APPENDSYM : EVAL := APPEND(EVAL(HEAD(TAIL(E)),ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- RELACEHSYM : EVAL := REPLACEH(EVAL(HEAD(TAIL(E)),ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- RELACETSYM : EVAL := REPLACET(EVAL(HEAD(TAIL(E)),ALIST),
- EVAL(HEAD(TAIL(TAIL(E))), ALIST));
-
- LASTSYM : EVAL := LAST(EVAL(HEAD(TAIL(E)), ALIST));
-
- LENGTHSYM : EVAL := LENGTH(EVAL(HEAD(TAIL(E)), ALIST));
-
- REVERSESYM : EVAL := REVERSE(EVAL(HEAD(TAIL(E)), ALIST));
-
- FUNCTSYM : EVAL := MKFUNARG(HEAD(TAIL(E)));
-
- SETSYM :
- BEGIN
- TEMP := EVAL(HEAD(TAIL(TAIL(E))), ALIST);
- SETT(EVAL(HEAD(TAIL(E)), ALIST), TEMP, ALIST);
- EVAL := TEMP
- END;
- SETQSYM :
- BEGIN
- TEMP := EVAL(HEAD(TAIL(TAIL(E))), ALIST);
- SETT(HEAD(TAIL(E)), TEMP, ALIST);
- EVAL := TEMP
- END;
- DEFEXPSYM :
- BEGIN
- TEMP := HEAD(TAIL(E));
- SETT(TEMP,
- CONS(MKATOM('LAMBDA '), TAIL(TAIL(E))),
- ALIST);
- EVAL := TEMP
- END;
- DEFFEXPSYM :
- BEGIN
- TEMP := HEAD(TAIL(E));
- SETT(TEMP,
- CONS(MKATOM('FLAMBDA '), TAIL(TAIL(E))),
- ALIST);
- EVAL := TEMP
- END;
- REMOBSYM :
- BEGIN
- REMOB(HEAD(TAIL(E)), ALIST);
- EVAL := MKATOM('NIL ')
- END;
- GOSYM : EVAL := CONS(MKATOM('GO '), TAIL(E));
- RETURNSYM: EVAL := CONS(MKATOM('RETURN '),
- MKATOM('NIL '));
- PROGSYM : EVAL := PROG(TAIL(E));
- PROG2SYM : EVAL := PROG2(HEAD(TAIL(E)),
- HEAD(TAIL(TAIL(E))));
-
- PROGNSYM : EVAL := PROGN(TAIL(E));
-
- END{CASE}
- ELSE
- BEGIN
- CAAROFE := HEAD(CAROFE);
- IF ( CAAROFE^.ANATOM ) AND ( CAAROFE^.ISARESERVEDWORD ) THEN
- IF NOT (CAAROFE^.RESSYM IN [LABELSYM, LAMBDASYM, FUNARGSYM,
- FLAMBDASYM]) THEN BEGIN ERROR(10); GOTO 1 END
- ELSE
- CASE CAAROFE^.RESSYM OF
- LABELSYM:
- BEGIN
- TEMP := CONS( CONS(HEAD(TAIL(CAROFE)),
- HEAD(TAIL(TAIL(CAROFE)))), ALIST);
- EVAL := EVAL(CONS(HEAD(TAIL(TAIL(CAROFE))),
- TAIL(E)),TEMP)
- END;
- LAMBDASYM:
- BEGIN
- TEMP := BINDARGS(HEAD(TAIL(CAROFE)), TAIL(E),
- ALIST);
- EVAL := EVAL( HEAD( TAIL( TAIL(CAROFE))), TEMP)
- END;
- FUNARGSYM:
- BEGIN
- TEMP := TAIL(TAIL(CAROFE));
- EVAL := EVAL(CONS(HEAD(TAIL(CAROFE)), TAIL(E)),
- TEMP)
- END;
- FLAMBDASYM:
- BEGIN
- TEMP := BINDARG1(HEAD(TAIL(CAROFE)), TAIL(E),
- ALIST);
- EVAL := EVAL( HEAD( TAIL( TAIL(CAROFE))), TEMP)
- END;
- END{ CASE }
- ELSE
- EVAL := EVAL(CONS(EVAL(CAROFE, ALIST), TAIL(E)), ALIST)
- END
- END
- END;
- 1:
- IF TRACE_ON THEN TRACEXIT('EVAL ')
- END{ OF EVAL };
-
- PROCEDURE INITIALIZE;
- VAR I: INTEGER;
- TEMP, NXT: SYMBEXPPTR;
- BEGIN
- END_FREELIST := FALSE;
- ERR_COND := FALSE;
- TRACE_ON := FALSE;
- NESTCOUNT := 0;
- ALREADYPEEKED := FALSE;
- NUMBEROFGCS := 0;
- FREENODES := MAXNODE;
- WITH NILNODE DO BEGIN
- ANATOM := TRUE; NEXT := NIL; NAME := 'NIL ';
- STATUS := UNMARKED; ISARESERVEDWORD := FALSE
- END;
-
- WITH TNODE DO BEGIN
- ANATOM := TRUE; NEXT := NIL; NAME := 'T ';
- STATUS := UNMARKED; ISARESERVEDWORD := FALSE
- END;
- {
- ALLOCATE STORAGE AND MARK IT FREE
- }
- FREELIST := NIL;
- FOR I:=1 TO MAXNODE DO BEGIN
- NEW(NODELIST); NODELIST^.NEXT := FREELIST;
- NODELIST^.HEAD := FREELIST; NODELIST^.STATUS := UNMARKED;
- FREELIST := NODELIST
- END;
- {
- INITIALIZE RESERVED WORD TABLE
- }
- RESWORDS[ ANDSYM ] := 'AND ';
- RESWORDS[ APPENDSYM ] := 'APPEND ';
- RESWORDS[ ATOMSYM ] := 'ATOM ';
- RESWORDS[ HEADSYM ] := 'CAR ';
- RESWORDS[ TAILSYM ] := 'CDR ';
- RESWORDS[ CONDSYM ] := 'COND ';
- RESWORDS[ CONSSYM ] := 'CONS ';
- RESWORDS[ COPYSYM ] := 'COPY ';
- RESWORDS[ DEFEXPSYM ] := 'DEFEXP ';
- RESWORDS[ DEFFEXPSYM ] := 'DEFFEXP ';
- RESWORDS[ DEFMACSYM ] := 'DEFMACRO ';
- RESWORDS[ EQSYM ] := 'EQ ';
- RESWORDS[ EQUALSYM ] := 'EQUAL ';
- RESWORDS[ EVALSYM ] := 'EVAL ';
- RESWORDS[ FLAMBDASYM ] := 'FLAMBDA ';
- RESWORDS[ FUNARGSYM ] := 'FUNARG ';
- RESWORDS[ FUNCTSYM ] := 'FUNCTION ';
- RESWORDS[ GOSYM ] := 'GO ';
- RESWORDS[ LABELSYM ] := 'LABEL ';
- RESWORDS[ LAMBDASYM ] := 'LAMBDA ';
- RESWORDS[ LASTSYM ] := 'LAST ';
- RESWORDS[ LENGTHSYM ] := 'LENGTH ';
- RESWORDS[ LISTSYM ] := 'LIST ';
- RESWORDS[ NOTSYM ] := 'NOT ';
- RESWORDS[ NULLSYM ] := 'NULL ';
- RESWORDS[ ORSYM ] := 'OR ';
- RESWORDS[ PROGSYM ] := 'PROG ';
- RESWORDS[ PROG2SYM ] := 'PROG2 ';
- RESWORDS[ PROGNSYM ] := 'PROGN ';
- RESWORDS[ QUOTESYM ] := 'QUOTE ';
- RESWORDS[ RELACEHSYM ] := 'REPLACEH ';
- RESWORDS[ RELACETSYM ] := 'REPLACET ';
- RESWORDS[ REMOBSYM ] := 'REMOB ';
- RESWORDS[ RETURNSYM ] := 'RETURN ';
- RESWORDS[ REVERSESYM ] := 'REVERSE ';
- RESWORDS[ SETSYM ] := 'SET ';
- RESWORDS[ SETQSYM ] := 'SETQ ';
- RESWORDS[ TRACESYM ] := 'TRACE ';
- RESWORDS[ UNTRACESYM ] := 'UNTRACE ';
- {
- INITIALIZE THE A-LIST WITH T AND NIL
- }
- POP(ALIST);
- ALIST^.ANATOM := FALSE;
- ALIST^.STATUS := UNMARKED;
- POP(ALIST^.TAIL);
- NXT := ALIST^.TAIL^.NEXT;
- ALIST^.TAIL^ := NILNODE;
- ALIST^.TAIL^.NEXT := NXT;
- POP(ALIST^.HEAD);
- {
- BIND NIL TO THE ATOM NIL
- }
- WITH ALIST^.HEAD^ DO BEGIN
- ANATOM := FALSE; STATUS := UNMARKED; POP(HEAD);
- NXT := HEAD^.NEXT; HEAD^ := NILNODE; HEAD^.NEXT := NXT;
- POP(TAIL); NXT := TAIL^.NEXT; TAIL^ := NILNODE;
- TAIL^.NEXT := NXT
- END;
- POP(TEMP);
- TEMP^.ANATOM := FALSE;
- TEMP^.STATUS := UNMARKED;
- TEMP^.TAIL := ALIST;
- ALIST := TEMP;
- POP(ALIST^.HEAD);
- {
- BIND T TO THE ATOM T
- }
- WITH ALIST^.HEAD^ DO BEGIN
- ANATOM := FALSE; STATUS := UNMARKED; POP(HEAD);
- NXT := HEAD^.NEXT; HEAD^ := TNODE; HEAD^.NEXT := NXT;
- POP(TAIL); NXT := TAIL^.NEXT; TAIL^ := TNODE;
- TAIL^.NEXT := NXT
- END;
- RESET('INITLISP', INFILE);
- READ(INFILE, CH);
- NEXTSYM1;
- READEXP1(PTR);
- WHILE NOT ( PTR^.ANATOM ) OR ( PTR^.NAME<>'FIN ' ) DO BEGIN
- TEMP := EVAL(PTR, ALIST);
- NEXTSYM1;
- READEXP1(PTR);
- {CALL THE} GARBAGEMAN
- END;
- WRITELN;
- WRITELN(' R E A D Y');
- WRITELN;
- READ(CH);
- END{ OF INITIALIZE };
-
-
-
- BEGIN{+ LISP MAIN PROGRAM +}
- INITIALIZE;
- NEXTSYM;
- READEXPR(PTR);
- WHILE NOT ( PTR^.ANATOM ) OR ( PTR^.NAME<>'FIN ' ) DO BEGIN
- IF NOT TRACE_ON THEN WRITE(' ');
- PRINTEXPR( EVAL(PTR, ALIST) );
- { NESTCOUNT := 0; }
- IF END_FREELIST THEN GOTO 2;
- 1: ERR_COND := FALSE;
- IF ( EOF(INPUT) ) THEN BEGIN
- WRITELN('END OF FILE ENCOUNTERED BEFORE A "FIN" CARD.');
- GOTO 2
- END;
- PTR := NIL;
- WRITELN; WRITELN;
- { CALL THE } GARBAGEMAN;
- NEXTSYM;
- READEXPR(PTR);
- IF ERR_COND THEN GOTO 1;
- IF END_FREELIST THEN GOTO 2;
- END;
- 2:WRITELN; WRITELN;
- WRITELN(' TOTAL NUMBER OF GARBAGE COLLECTIONS = ', NUMBEROFGCS:1,'.');
- WRITELN;
- WRITELN(' FREE NODES LEFT UPON EXIT = ', FREENODES:1, '.');
- WRITELN
- END { OF LISP }.
-