Created
June 30, 2017 20:16
-
-
Save fogus/1592ccfc85fac7f11c79b58e144246ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{+ 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 }. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment