home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol148 / lisp.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  35.9 KB  |  1,383 lines

  1. {+        PASCAL/Z COMPILER OPTIONS        +}
  2. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  3. {$C- <<< CONTROL-C KEYPRESS CHECKING OFF >>>         }    
  4. {$F- <<< FLOATING POINT ERROR CHECKING OFF >>>         }
  5. {$M- <<< INTEGER MULT & DIVD ERROR CHECKING OFF >>>      }
  6. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  7. PROGRAM LISP {VERSION 1.7};
  8. {
  9. +  PROGRAM TITLE:    THE ESSENCE OF A LISP INTERPRETER.
  10. +  WRITTEN BY:        W. TAYLOR AND L. COX
  11. +
  12. +  WRITTEN FOR:        US DEPT OF ENERGY
  13. +            CONTRACT # W-7405-ENG-48
  14. +
  15. +    FIRST DATA STARTED : 10/29/76
  16. +    LAST DATE MODIFIED : 12/10/76
  17. +
  18. + ENTERED BY RAY PENLEY 8 DEC 80.
  19. + -SOME IDENTIFIERS HAVE BEEN SLIGHTLY MODIFIED BECAUSE OF THE
  20. +  LIMITATION ON IDENTIFIER LENGTH OF 8 CHARACTERS.
  21. +
  22. + MODIFIED BY LANFRANCO EMILIANI IN THE PERIOD MARS-MAY 1983 :
  23. +    - TO REMOVE THE TWO JUMPS OUT OF PROCEDURES PRESENT IN THE
  24. +      ZUG VOL # 14 VERSION;
  25. +    - TO REMOVE TWO BUGS PRESENT IN THAT VERSION;
  26. +    - TO PROVIDE ADDITIONAL FEATURES.
  27. +
  28. + REFER TO LISP.DOC FOR A DESCRIPTION OF THE MAIN FEATURES OF THE
  29. + INTERPRETER AND HOW TO OPERATE IT.
  30. + REFER TO THE COMMENTS IN THE ZUG VOL # 14 VERSION FOR SPECIFIC
  31. + EXPLANATORY NOTES CONCERNING THE MOST SIGNIFICANT PROCEDURES OR
  32. + FUNCTIONS.
  33. +
  34. }
  35. LABEL
  36.   1,    { USED TO RECOVER AFTER AN ERROR BY THE USER }
  37.   2;    { IN CASE THE END OF FILE IS REACHED BEFORE A FIN CARD }
  38.  
  39. CONST
  40.   MAXNODE = 1000;
  41. {}INPUT = 0;    { Pascal/Z = console as input }
  42. {}IDLENGTH = 10;
  43.  
  44. TYPE
  45. {}ALFA = ARRAY [1..IDLENGTH] OF CHAR;
  46.   INPUTSYMBOL = (ATOM, PERIOD, LPAREN, RPAREN);
  47.   RESERVEWORDS = (    ANDSYM,
  48.             APPENDSYM,
  49.             ATOMSYM,
  50.             HEADSYM,
  51.             TAILSYM,
  52.             CONDSYM,
  53.             CONSSYM,
  54.             COPYSYM,
  55.             DEFEXPSYM,
  56.             DEFFEXPSYM,
  57.             DEFMACSYM,
  58.             EQSYM,
  59.             EQUALSYM,
  60.             EVALSYM,
  61.             FLAMBDASYM,
  62.             FUNARGSYM,
  63.             FUNCTSYM,
  64.             GOSYM,
  65.             LABELSYM,
  66.             LAMBDASYM,
  67.             LASTSYM,
  68.             LENGTHSYM,
  69.             LISTSYM,
  70.             NOTSYM,
  71.             NULLSYM,
  72.             ORSYM,
  73.             PROGSYM,
  74.             PROG2SYM,
  75.             PROGNSYM,
  76.             QUOTESYM,
  77.             RELACEHSYM,
  78.             RELACETSYM,
  79.             REMOBSYM,
  80.             RETURNSYM,
  81.             REVERSESYM,
  82.             SETSYM,
  83.             SETQSYM,
  84.             TRACESYM,
  85.             UNTRACESYM    );
  86.   STATUSTYPE = (UNMARKED, LEFT, RIGHT, MARKED);
  87.   SYMBEXPPTR = ^SYMBOLICEXPRESSION;
  88.   SYMBOLICEXPRESSION = RECORD
  89.              STATUS : STATUSTYPE;
  90.              NEXT   : SYMBEXPPTR;
  91.              CASE ANATOM: BOOLEAN OF
  92.                TRUE: (NAME: ALFA;
  93.                   CASE ISARESERVEDWORD: BOOLEAN OF
  94.                     TRUE: (RESSYM: RESERVEWORDS));
  95.                FALSE: (HEAD, TAIL: SYMBEXPPTR)
  96.             END;
  97.  
  98. VAR
  99.   END_FREELIST  : BOOLEAN;
  100.   ERR_COND    : BOOLEAN;
  101.   TRACE_ON      : BOOLEAN;
  102.   NESTCOUNT     : INTEGER;
  103.  
  104. { VARIABLES WHICH PASS INFORMATION FROM THE SCANNER TO THE READ ROUTINE }
  105.  
  106.   LOOKAHEADSYM,            { USED TO SAVE A SYMBOL WHEN WE BACK UP }
  107.   SYM        : INPUTSYMBOL;    { THE SYMBOL THAT WAS LAST SCANNED }
  108.   ID        : ALFA;        { NAME OF THE ATOM THAT WAS LAST READ }
  109.   ALREADYPEEKED    : BOOLEAN;    { TELLS 'NEXTSYM' WHETHER WE HAVE PEEKED }
  110.   CH        : CHAR;        { THE LAST CHAR READ FROM INPUT }
  111.   PTR        : SYMBEXPPTR;    { POINTER TO THE EXPRESSION BEING EVALUATED }
  112.   TEMP        : SYMBEXPPTR;
  113.  
  114.     { THE GLOBAL LISTS OF LISP NODES }
  115.  
  116.   FREELIST,    { POINTER TO THE LINEAR LIST OF FREE NODES }
  117.   NODELIST,     { POINTER USED TO MAKE A LINEAR SCAN OF ALL}
  118.         { THE NODES DURING GARBAGE COLLECTION.       }
  119.   ALIST    : SYMBEXPPTR;{ POINTER TO THE ASSOCIATION LIST }
  120.  
  121.     { TWO NODES WHICH HAVE CONSTANT VALUES }
  122.  
  123.   NILNODE,
  124.   TNODE    : SYMBOLICEXPRESSION;
  125.  
  126.     { VARIABLES USED TO IDENTIFY ATOMS WITH PRE-DEFINED MEANINGS }
  127.  
  128.   RESWORD    : RESERVEWORDS;
  129.   RESERVED    : BOOLEAN;
  130.   RESWORDS    : ARRAY [RESERVEWORDS] OF ALFA;
  131.   FREENODES    : INTEGER; { NUMBER OF CURRENTLY FREE NODES KNOWN }
  132.   NUMBEROFGCS    : INTEGER; { # OF GARBAGE COLLECTIONS MADE }
  133.  
  134.   INFILE        : TEXT;
  135.  
  136.  
  137. PROCEDURE GARBAGEMAN;
  138.  
  139.   PROCEDURE MARK(LIST: SYMBEXPPTR);
  140.   VAR
  141.     FATHER, SON, CURRENT: SYMBEXPPTR;
  142.   BEGIN
  143.     FATHER := NIL;
  144.     CURRENT := LIST;
  145.     SON := CURRENT;
  146.     WHILE ( CURRENT<>NIL ) DO
  147.       WITH CURRENT^ DO
  148.     CASE STATUS OF
  149.       UNMARKED:
  150.         IF ( ANATOM ) THEN
  151.           STATUS := MARKED
  152.         ELSE
  153.           IF (HEAD^.STATUS <> UNMARKED) OR (HEAD = CURRENT) THEN
  154.         IF (TAIL^.STATUS <> UNMARKED) OR (TAIL = CURRENT) THEN
  155.            STATUS := MARKED
  156.         ELSE BEGIN
  157.           STATUS := RIGHT; SON := TAIL; TAIL := FATHER;
  158.           FATHER := CURRENT; CURRENT := SON
  159.         END
  160.           ELSE BEGIN
  161.         STATUS := LEFT; SON := HEAD; HEAD := FATHER;
  162.         FATHER := CURRENT; CURRENT := SON
  163.           END;
  164.       LEFT:
  165.         IF ( TAIL^.STATUS <> UNMARKED ) THEN BEGIN
  166.           STATUS := MARKED; FATHER := HEAD; HEAD := SON;
  167.           SON := CURRENT
  168.         END
  169.         ELSE BEGIN
  170.           STATUS := RIGHT; CURRENT := TAIL; TAIL := HEAD;
  171.           HEAD := SON; SON := CURRENT
  172.         END;
  173.       RIGHT:
  174.         BEGIN
  175.         STATUS := MARKED; FATHER := TAIL; TAIL := SON;
  176.         SON := CURRENT
  177.         END;
  178.       MARKED: CURRENT := FATHER
  179.     END { OF CASE }
  180.   END { OF MARK };
  181.  
  182.   PROCEDURE COLLECTFREENODES;
  183.   VAR
  184.     TEMP: SYMBEXPPTR;
  185.   BEGIN
  186. {
  187.     WRITELN(' NUMBER OF FREE NODES BEFORE COLLECTION = ', FREENODES:1, '.');
  188. }
  189.     FREELIST := NIL; FREENODES := 0; TEMP := NODELIST;
  190.     WHILE ( TEMP <> NIL ) DO BEGIN
  191.     IF ( TEMP^.STATUS <> UNMARKED ) THEN
  192.       TEMP^.STATUS := UNMARKED
  193.     ELSE BEGIN
  194.       FREENODES := FREENODES + 1; TEMP^.HEAD := FREELIST;
  195.       FREELIST := TEMP
  196.     END;
  197.     TEMP := TEMP^.NEXT;
  198.     END {WHILE};
  199. {
  200.     WRITELN(' NUMBER OF FREE NODES AFTER COLLECTION = ', FREENODES:1,'.');
  201. }
  202.   END { OF COLLECTFREENODES };
  203.  
  204. BEGIN{ GARBAGEMAN }
  205.   NUMBEROFGCS := NUMBEROFGCS + 1;
  206. { WRITELN; WRITELN(' GARBAGE COLLECTION. '); WRITELN; }
  207.   MARK(ALIST);
  208.   IF ( PTR <> NIL ) THEN MARK(PTR);
  209.   COLLECTFREENODES
  210. END{ OF GARBAGEMAN };
  211.  
  212. PROCEDURE POP(VAR SPTR: SYMBEXPPTR);
  213. LABEL 1;
  214. BEGIN
  215.   IF ( FREELIST = NIL ) THEN BEGIN
  216.     WRITELN(' NOT ENOUGH SPACE TO EVALUATE THE EXPRESSION.');
  217.     END_FREELIST := TRUE;
  218.     GOTO 1;
  219.   END;
  220.   FREENODES := FREENODES - 1;
  221.   SPTR := FREELIST;
  222.   FREELIST := FREELIST^.HEAD;
  223. 1:
  224. END{ OF POP };
  225.  
  226.  
  227. PROCEDURE ERROR(NUMBER: INTEGER);
  228. BEGIN
  229.   WRITELN; WRITE('  ERROR   ', NUMBER:1, ', ');
  230.   CASE NUMBER OF
  231.     1: WRITELN('ATOM OR LPAREN EXPECTED IN THE S-EXPR.');
  232.     2: WRITELN('ATOM, LPAREN, OR RPAREN EXPECTED IN THE S-EXPR.');
  233.     3: WRITELN('LABEL, LAMBDA, FLAMBDA, ETC. ARE NOT FUNCTIONS NAMES.');
  234.     4: WRITELN('RPAREN EXPECTED IN THE S-EXPR.');
  235.     5: WRITELN('1ST ARGUMENT OF REPLACEH IS AN ATOM.');
  236.     6: WRITELN('1ST ARGUMENT OF REPLACET IS AN ATOM.');
  237.     7: WRITELN('ARGUMENT HEAD IS AN ATOM.');
  238.     8: WRITELN('ARGUMENT TAIL IS AN ATOM.');
  239.     9: WRITELN('1ST ARGUMENT OF APPEND IS NOT A LIST.');
  240.    10: WRITELN('LABEL OR LAMBDA OR FLAMBDA ETC. EXPECTED.');
  241.    11: WRITELN('NAME OF VARIABLE IS NOT AN ATOM.');
  242.    12: WRITELN('ARGUMENT OF LENGTH IS NOT A LIST.');
  243.    13: WRITELN('ARGUMENT OF PROG IS NOT A LIST.');
  244.    14: WRITELN('LOOP IDENTIFIER NOT FOUND.');
  245.   END{CASE};
  246.   ERR_COND := TRUE
  247. END { OF ERROR };
  248.  
  249. PROCEDURE BACKUPINPUT;
  250. BEGIN
  251.   ALREADYPEEKED := TRUE; LOOKAHEADSYM := SYM; SYM := LPAREN
  252. END{ OF BACKUPINPUT };
  253.  
  254. PROCEDURE NEXTSYM1;
  255. VAR    I: INTEGER;
  256. BEGIN
  257.   IF ( ALREADYPEEKED ) THEN BEGIN
  258.       SYM := LOOKAHEADSYM; ALREADYPEEKED := FALSE
  259.   END
  260.   ELSE
  261.     BEGIN
  262.       WHILE ( CH=' ' ) DO BEGIN
  263.     IF ( EOLN(INFILE) ) THEN READLN(INFILE);
  264.         READ(INFILE, CH);
  265.       END{WHILE};
  266.       IF ( CH IN ['(','.',')'] ) THEN BEGIN
  267.     CASE CH OF
  268.       '(': SYM := LPAREN;
  269.       '.': SYM := PERIOD;
  270.       ')': SYM := RPAREN
  271.     END{CASE};
  272.     IF ( EOLN(INFILE) ) THEN READLN(INFILE);
  273.         READ(INFILE, CH);
  274.       END
  275.       ELSE BEGIN
  276.     SYM := ATOM; ID := '          ';
  277.     I := 0;
  278.     REPEAT
  279.       I := I + 1;
  280.       IF ( I < (IDLENGTH+1) ) THEN ID[I] := CH;
  281.       IF ( EOLN(INFILE) ) THEN READLN(INFILE);
  282.           READ(INFILE, CH);
  283.     UNTIL ( CH IN [' ','(','.',')'] );
  284.     RESWORD := ANDSYM;
  285.     WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> UNTRACESYM) DO
  286.       RESWORD := SUCC(RESWORD);
  287.     RESERVED := ( ID=RESWORDS[RESWORD] )
  288.       END
  289.     END  
  290. END{ OF NEXTSYM1 };
  291.  
  292. PROCEDURE READEXP1(VAR SPTR: SYMBEXPPTR);
  293. LABEL 1;
  294. VAR    NXT: SYMBEXPPTR;
  295. BEGIN
  296. IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  297.   BEGIN
  298.   POP(SPTR);
  299.   IF END_FREELIST THEN GOTO 1;
  300.   NXT := SPTR^.NEXT;
  301.   CASE SYM OF
  302.     RPAREN, PERIOD: BEGIN ERROR(1); GOTO 1 END;
  303.     ATOM:
  304.     WITH SPTR^ DO BEGIN {  <ATOM>  }
  305.       ANATOM := TRUE; NAME := ID; ISARESERVEDWORD := RESERVED;
  306.       IF ( RESERVED ) THEN RESSYM := RESWORD
  307.     END;
  308.     LPAREN:
  309.     WITH SPTR^ DO BEGIN
  310.           NEXTSYM1;
  311.       IF ( SYM=PERIOD ) THEN BEGIN ERROR(2); GOTO 1 END
  312.       ELSE
  313.         IF ( SYM=RPAREN ) THEN SPTR^ := NILNODE {   () = NIL   }
  314.         ELSE BEGIN
  315.         ANATOM := FALSE; READEXP1(HEAD); NEXTSYM1;
  316.         IF ( SYM=PERIOD ) THEN BEGIN {   ( <S-EXPR> . <S-EXPR> )   }
  317.            NEXTSYM1; READEXP1(TAIL); NEXTSYM1;
  318.            IF (SYM<>RPAREN) THEN BEGIN ERROR(4); GOTO 1 END
  319.         END
  320.         ELSE BEGIN {   ( <S-EXPR> <S-EXPR> ... <S-EXPR> )   }
  321.           BACKUPINPUT; READEXP1(TAIL)
  322.         END
  323.         END
  324.     END{WITH}
  325.   END{CASE};
  326.   SPTR^.NEXT := NXT;
  327.   END;
  328. 1:
  329. END{ OF READEXP1 };
  330.  
  331. PROCEDURE NEXTSYM;
  332. VAR    I: INTEGER;
  333. BEGIN
  334.   IF ( ALREADYPEEKED ) THEN BEGIN
  335.       SYM := LOOKAHEADSYM; ALREADYPEEKED := FALSE
  336.   END
  337.   ELSE
  338.     BEGIN
  339.       WHILE ( CH=' ' ) DO BEGIN
  340.     IF ( EOLN(INPUT) ) THEN READLN;
  341.     READ(CH);
  342.       END{WHILE};
  343.       IF ( CH IN ['(','.',')'] ) THEN BEGIN
  344.     CASE CH OF
  345.       '(': SYM := LPAREN;
  346.       '.': SYM := PERIOD;
  347.       ')': SYM := RPAREN
  348.     END{CASE};
  349.     IF ( EOLN(INPUT) ) THEN READLN;
  350.     READ(CH);
  351.       END
  352.       ELSE BEGIN
  353.     SYM := ATOM; ID := '          ';
  354.     I := 0;
  355.     REPEAT
  356.       I := I + 1;
  357.       IF ( I < (IDLENGTH+1) ) THEN ID[I] := CH;
  358.       IF (EOLN (INPUT) ) THEN READLN;
  359.       READ(CH);
  360.     UNTIL ( CH IN [' ','(','.',')'] );
  361.     RESWORD := ANDSYM;
  362.     WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> UNTRACESYM) DO
  363.       RESWORD := SUCC(RESWORD);
  364.     RESERVED := ( ID=RESWORDS[RESWORD] )
  365.       END
  366.     END  
  367. END{ OF NEXTSYM };
  368.  
  369. PROCEDURE READEXPR(VAR SPTR: SYMBEXPPTR);
  370. LABEL 1;
  371. VAR    NXT: SYMBEXPPTR;
  372. BEGIN
  373. IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  374.   BEGIN
  375.   POP(SPTR);
  376.   IF END_FREELIST THEN GOTO 1;
  377.   NXT := SPTR^.NEXT;
  378.   CASE SYM OF
  379.     RPAREN, PERIOD: BEGIN ERROR(1); GOTO 1 END;
  380.     ATOM:
  381.     WITH SPTR^ DO BEGIN {  <ATOM>  }
  382.       ANATOM := TRUE; NAME := ID; ISARESERVEDWORD := RESERVED;
  383.       IF ( RESERVED ) THEN RESSYM := RESWORD
  384.     END;
  385.     LPAREN:
  386.     WITH SPTR^ DO BEGIN
  387.       NEXTSYM;
  388.       IF ( SYM=PERIOD ) THEN BEGIN ERROR(2); GOTO 1 END
  389.       ELSE
  390.         IF ( SYM=RPAREN ) THEN SPTR^ := NILNODE {   () = NIL   }
  391.         ELSE BEGIN
  392.         ANATOM := FALSE; READEXPR(HEAD); NEXTSYM;
  393.         IF ( SYM=PERIOD ) THEN BEGIN {   ( <S-EXPR> . <S-EXPR> )   }
  394.            NEXTSYM;  READEXPR(TAIL); NEXTSYM;
  395.            IF (SYM<>RPAREN) THEN BEGIN ERROR(4); GOTO 1 END
  396.         END
  397.         ELSE BEGIN {   ( <S-EXPR> <S-EXPR> ... <S-EXPR> )   }
  398.           BACKUPINPUT; READEXPR(TAIL)
  399.         END
  400.         END
  401.     END{WITH}
  402.   END{CASE};
  403.   SPTR^.NEXT := NXT;
  404.   END;
  405. 1:
  406. END{ OF READEXPR };
  407.  
  408. PROCEDURE PRINTNAME(NAME: ALFA);
  409. VAR    I: INTEGER;
  410. BEGIN
  411.   I := 0;
  412.   REPEAT
  413.     I := I + 1;
  414.     WRITE(NAME[I])
  415.   UNTIL (NAME[I]=' ') OR ( I=IDLENGTH );
  416.   IF ( I=IDLENGTH ) THEN WRITE(' ')
  417. END{ OF PRINTNAME };
  418.  
  419. PROCEDURE PRINTEXPR(SPTR : SYMBEXPPTR);
  420. LABEL 1, 2;
  421. BEGIN
  422. IF (ERR_COND) OR (END_FREELIST) THEN GOTO 2 ELSE
  423.  BEGIN
  424.   IF ( SPTR^.ANATOM ) THEN
  425.     PRINTNAME(SPTR^.NAME)
  426.   ELSE BEGIN
  427.     WRITE('(');
  428.  1: PRINTEXPR(SPTR^.HEAD);
  429.     IF ( SPTR^.TAIL^.ANATOM ) AND ( SPTR^.TAIL^.NAME='NIL       ') THEN
  430.       WRITE(')')
  431.     ELSE IF ( SPTR^.TAIL^.ANATOM ) THEN BEGIN
  432.       WRITE('.'); PRINTEXPR(SPTR^.TAIL); WRITE(')')
  433.     END
  434.     ELSE BEGIN
  435.       SPTR := SPTR^.TAIL;
  436.       GOTO 1
  437.     END
  438.   END
  439.  END;
  440. 2:
  441. END{ OF PRINTEXPR };
  442.  
  443.  
  444. PROCEDURE TRACENTER(ID : ALFA);
  445. VAR     J : INTEGER;
  446. BEGIN
  447. NESTCOUNT := NESTCOUNT + 1;
  448. FOR J := 0 TO NESTCOUNT DO WRITE('  ');
  449. WRITE('ENTERING : ');
  450. FOR J := 1 TO IDLENGTH DO WRITE(ID[J]);
  451. WRITELN
  452. END{ OF TRACENTER };
  453.  
  454. PROCEDURE TRACEXIT(ID : ALFA);
  455. VAR     J : INTEGER;
  456. BEGIN
  457. FOR J := 0 TO NESTCOUNT DO WRITE('  ');
  458. WRITE('EXITING  : ');
  459. FOR J := 1 TO IDLENGTH DO WRITE(ID[J]);
  460. WRITELN;
  461. NESTCOUNT := NESTCOUNT - 1
  462. END{ OF TRACEXIT };
  463.  
  464. FUNCTION EVAL( E : SYMBEXPPTR; VAR ALIST : SYMBEXPPTR ): SYMBEXPPTR;
  465. LABEL 1;
  466. VAR    TEMP, CAROFE, CAAROFE: SYMBEXPPTR;
  467.  
  468.   FUNCTION MKATOM(ID : ALFA): SYMBEXPPTR;
  469.   LABEL 1;
  470.   VAR    TEMP: SYMBEXPPTR;
  471.   BEGIN
  472.     IF TRACE_ON THEN TRACENTER('MKATOM    ');
  473.     POP(TEMP);
  474.     IF END_FREELIST THEN GOTO 1;
  475.     RESWORD := APPENDSYM;
  476.     WHILE (ID <> RESWORDS[RESWORD]) AND (RESWORD <> SETQSYM) DO
  477.       RESWORD := SUCC(RESWORD);
  478.     RESERVED := ( ID = RESWORDS[RESWORD] );
  479.     WITH TEMP^ DO BEGIN
  480.       ANATOM := TRUE;
  481.       NAME := ID;
  482.       ISARESERVEDWORD := RESERVED;
  483.       IF (RESERVED) THEN RESSYM := RESWORD
  484.     END;
  485.     MKATOM := TEMP;
  486.   1:
  487.   IF TRACE_ON THEN TRACEXIT('MKATOM    ')
  488.   END{ OF MKATOM };
  489.  
  490.   FUNCTION REPLACEH(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  491.   LABEL 1;
  492.   BEGIN
  493.   IF TRACE_ON THEN TRACENTER('REPLACEH  ');
  494.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  495.     BEGIN
  496.     IF ( SPTR1^.ANATOM ) THEN BEGIN ERROR(5); GOTO 1 END
  497.     ELSE SPTR1^.HEAD := SPTR2;
  498.     REPLACEH := SPTR1;
  499.     END;
  500.   1:
  501.   IF TRACE_ON THEN TRACEXIT('REPLACEH  ')
  502.   END{ OF REPLACEH };
  503.  
  504.   FUNCTION REPLACET(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  505.   LABEL 1;
  506.   BEGIN
  507.   IF TRACE_ON THEN TRACENTER('REPLACET  ');
  508.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  509.     BEGIN
  510.     IF ( SPTR1^.ANATOM ) THEN BEGIN ERROR(6); GOTO 1 END
  511.     ELSE SPTR1^.TAIL := SPTR2;
  512.     REPLACET := SPTR1;
  513.     END;
  514.   1:
  515.   IF TRACE_ON THEN TRACEXIT('REPLACET  ')
  516.   END{ OF REPLACET };
  517.  
  518.   FUNCTION HEAD(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  519.   LABEL 1;
  520.   BEGIN
  521.   IF TRACE_ON THEN TRACENTER('CAR       ');
  522.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  523.     BEGIN
  524.     IF ( SPTR^.ANATOM ) THEN BEGIN ERROR(7); GOTO 1 END
  525.     ELSE HEAD := SPTR^.HEAD;
  526.     END;
  527.   1:
  528.   IF TRACE_ON THEN TRACEXIT('CAR       ')
  529.   END{ OF HEAD };
  530.  
  531.   FUNCTION TAIL(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  532.   LABEL 1;
  533.   BEGIN
  534.   IF TRACE_ON THEN TRACENTER('CDR       ');
  535.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  536.     BEGIN
  537.     IF ( SPTR^.ANATOM ) THEN BEGIN ERROR(8); GOTO 1 END
  538.     ELSE TAIL := SPTR^.TAIL;
  539.     END;
  540.   1:
  541.   IF TRACE_ON THEN TRACEXIT('CDR       ')
  542.   END{ OF TAIL };
  543.  
  544.   FUNCTION CONS(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  545.   LABEL 1;
  546.   VAR    TEMP: SYMBEXPPTR;
  547.   BEGIN
  548.   IF TRACE_ON THEN TRACENTER('CONS      ');
  549.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  550.     BEGIN
  551.     POP(TEMP);
  552.     IF END_FREELIST THEN GOTO 1;
  553.     TEMP^.ANATOM := FALSE; TEMP^.HEAD := SPTR1;
  554.     TEMP^.TAIL := SPTR2; CONS := TEMP;
  555.     END;
  556.   1:
  557.   IF TRACE_ON THEN TRACEXIT('CONS      ')
  558.   END{ OF CONS };
  559.  
  560.   FUNCTION COPY(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  561.   LABEL 1;
  562.   VAR    TEMP, NXT: SYMBEXPPTR;
  563.   BEGIN
  564.   IF TRACE_ON THEN TRACENTER('COPY      ');
  565.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  566.     BEGIN
  567.     IF ( SPTR^.ANATOM ) THEN BEGIN
  568.     POP(TEMP);
  569.     IF END_FREELIST THEN GOTO 1;
  570.     NXT := TEMP^.NEXT; TEMP^ := SPTR^;
  571.      TEMP^.NEXT := NXT; COPY := TEMP
  572.     END
  573.     ELSE
  574.     COPY := CONS(COPY(SPTR^.HEAD), COPY(SPTR^.TAIL));
  575.     END;
  576.   1:
  577.   IF TRACE_ON THEN TRACEXIT('COPY      ')
  578.   END{ OF COPY };
  579.  
  580.   FUNCTION APPEND(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  581.   LABEL 1;
  582.   BEGIN
  583.   IF TRACE_ON THEN TRACENTER('APPEND    ');
  584.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  585.     BEGIN
  586.     IF ( SPTR1^.ANATOM ) THEN
  587.       IF ( SPTR1^.NAME<>'NIL       ' ) THEN BEGIN ERROR(9); GOTO 1 END
  588.       ELSE APPEND := SPTR2
  589.     ELSE
  590.       APPEND := CONS(COPY(SPTR1^.HEAD), APPEND(SPTR1^.TAIL,SPTR2));
  591.     END;
  592.   1:
  593.   IF TRACE_ON THEN TRACEXIT('APPEND    ')
  594.   END{ OF APPEND };
  595.  
  596.   FUNCTION LIST(SPTR1: SYMBEXPPTR): SYMBEXPPTR;
  597.   LABEL 1;
  598.   VAR
  599.     NILPTR: SYMBEXPPTR;
  600.   BEGIN
  601.   IF TRACE_ON THEN TRACENTER('LIST      ');
  602.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  603.     BEGIN
  604.     IF NOT SPTR1^.ANATOM THEN 
  605.       LIST := CONS(EVAL(SPTR1^.HEAD, ALIST), LIST(SPTR1^.TAIL))
  606.     ELSE BEGIN
  607.       IF SPTR1^.NAME <> 'NIL       ' THEN BEGIN
  608.         NEW(NILPTR);
  609.         WITH NILPTR^ DO BEGIN
  610.       ANATOM := TRUE; NAME := 'NIL       '
  611.       END {WITH};
  612.     LIST := CONS(EVAL(SPTR1, ALIST), NILPTR)
  613.     END
  614.       ELSE LIST := SPTR1
  615.       END
  616.     END;
  617.   1:
  618.   IF TRACE_ON THEN TRACEXIT('LIST      ')
  619.   END{ OF LIST };
  620.  
  621.   FUNCTION EQQ(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  622.   LABEL 1;
  623.   VAR    TEMP, NXT: SYMBEXPPTR;
  624.   BEGIN
  625.   IF TRACE_ON THEN TRACENTER('EQ        ');
  626.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  627.     BEGIN
  628.     POP(TEMP);
  629.     IF END_FREELIST THEN GOTO 1;
  630.     NXT := TEMP^.NEXT;
  631.     IF ((SPTR1^.ANATOM) AND (SPTR2^.ANATOM) AND (SPTR1^.NAME=SPTR2^.NAME))
  632.        OR (SPTR1 = SPTR2) THEN TEMP^ := TNODE
  633.     ELSE TEMP^ := NILNODE;
  634.     TEMP^.NEXT := NXT; EQQ := TEMP;
  635.     END;
  636.   1:
  637.   IF TRACE_ON THEN TRACEXIT('EQ        ')
  638.   END{ OF EQQ };
  639.  
  640.   FUNCTION EQUAL(SPTR1, SPTR2 : SYMBEXPPTR): SYMBEXPPTR;
  641.   LABEL 1;
  642.   VAR   TEMP, NXT : SYMBEXPPTR;
  643.   BEGIN
  644.   IF TRACE_ON THEN TRACENTER('EQUAL     ');
  645.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  646.     BEGIN
  647.     POP(TEMP);
  648.     IF END_FREELIST THEN GOTO 1;
  649.     NXT := TEMP^.NEXT;
  650.     IF (SPTR1^.ANATOM) THEN BEGIN
  651.     IF (SPTR2^.ANATOM) THEN TEMP := EQQ(SPTR1, SPTR2)
  652.     ELSE TEMP^ := NILNODE
  653.     END
  654.     ELSE BEGIN
  655.     IF SPTR2^.ANATOM THEN TEMP^ := NILNODE
  656.     ELSE BEGIN
  657.         TEMP := EQUAL(HEAD(SPTR1), HEAD(SPTR2));
  658.         IF ( TEMP^.NAME = 'T         ' ) THEN
  659.         TEMP := EQUAL(TAIL(SPTR1), TAIL(SPTR2))
  660.         ELSE BEGIN
  661.         TEMP^ := NILNODE
  662.         END
  663.     END
  664.     END;
  665.     TEMP^.NEXT := NXT;
  666.     EQUAL := TEMP
  667.     END;
  668.   1:
  669.   IF TRACE_ON THEN TRACEXIT('EQUAL     ')
  670.   END{ OF EQUAL };
  671.  
  672.   FUNCTION NULL(SPTR : SYMBEXPPTR) : SYMBEXPPTR;
  673.   LABEL 1;
  674.   VAR   TEMP, NXT : SYMBEXPPTR;
  675.   BEGIN
  676.   IF TRACE_ON THEN TRACENTER('NULL      ');
  677.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  678.     BEGIN
  679.     POP(TEMP);
  680.     IF END_FREELIST THEN GOTO 1;
  681.     NXT := TEMP^.NEXT; TEMP^ := NILNODE; TEMP^.NEXT := NXT;
  682.     NULL := EQQ(SPTR, TEMP)
  683.     END;
  684.   1:
  685.   IF TRACE_ON THEN TRACEXIT('NULL      ')
  686.   END{ OF NULL };
  687.  
  688.   FUNCTION ET(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  689.   LABEL 1;
  690.   VAR    TEMP: SYMBEXPPTR;
  691.   BEGIN
  692.   IF TRACE_ON THEN TRACENTER('AND       ');
  693.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  694.     BEGIN
  695.     IF (SPTR^.ANATOM) AND (SPTR^.NAME = 'NIL       ') THEN 
  696.     ET := MKATOM('T         ')
  697.     ELSE BEGIN
  698.       TEMP := EVAL(HEAD(SPTR), ALIST);
  699.       IF (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL       ') THEN ET := TEMP
  700.       ELSE ET := ET(TAIL(SPTR))
  701.       END
  702.     END;
  703.   1:
  704.   IF TRACE_ON THEN TRACEXIT('AND       ')
  705.   END{ OF ET };
  706.  
  707.   FUNCTION OU(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  708.   LABEL 1;
  709.   VAR    TEMP: SYMBEXPPTR;
  710.   BEGIN
  711.   IF TRACE_ON THEN TRACENTER('OR        ');
  712.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  713.     BEGIN
  714.     IF (SPTR^.ANATOM) AND (SPTR^.NAME = 'NIL       ') THEN OU := SPTR
  715.     ELSE BEGIN
  716.       TEMP := EVAL(HEAD(SPTR), ALIST);
  717.       IF (TEMP^.ANATOM) AND (TEMP^.NAME <> 'NIL       ') THEN
  718.       OU := MKATOM('T         ')
  719.       ELSE OU := OU(TAIL(SPTR))
  720.       END
  721.     END;
  722.   1:
  723.   IF TRACE_ON THEN TRACEXIT('OR        ')
  724.   END{ OF OU };
  725.  
  726.   FUNCTION ATOM(SPTR : SYMBEXPPTR): SYMBEXPPTR;
  727.   LABEL 1;
  728.   VAR    TEMP, NXT: SYMBEXPPTR;
  729.   BEGIN
  730.   IF TRACE_ON THEN TRACENTER('ATOM      ');
  731.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  732.     BEGIN
  733.     POP(TEMP);
  734.     IF END_FREELIST THEN GOTO 1;
  735.     NXT := TEMP^.NEXT;
  736.     IF ( SPTR^.ANATOM ) THEN
  737.       TEMP^ := TNODE
  738.     ELSE
  739.       TEMP^ := NILNODE;
  740.     TEMP^.NEXT := NXT; ATOM := TEMP;
  741.     END;
  742.   1:
  743.   IF TRACE_ON THEN TRACEXIT('ATOM      ')
  744.   END{ OF ATOM };
  745.  
  746.   FUNCTION LAST(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  747.   LABEL 1;
  748.   VAR     TEMP: SYMBEXPPTR;
  749.   BEGIN
  750.   IF TRACE_ON THEN TRACENTER('LAST      ');
  751.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  752.     BEGIN
  753.     IF (SPTR^.ANATOM) THEN LAST := SPTR ELSE
  754.       BEGIN
  755.       TEMP := TAIL(SPTR);
  756.       IF (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL       ') THEN
  757.         LAST := HEAD(SPTR) ELSE LAST := LAST(TEMP)
  758.       END
  759.     END;
  760.   1:
  761.   IF TRACE_ON THEN TRACEXIT('LAST      ')
  762.   END{ OF LAST };
  763.  
  764.   FUNCTION REVERSE(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  765.   LABEL 1;
  766.   VAR    TEMP: SYMBEXPPTR;
  767.   BEGIN
  768.   IF TRACE_ON THEN TRACENTER('REVERSE   ');
  769.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  770.     BEGIN
  771.     TEMP := NULL(SPTR);
  772.     IF (TEMP^.NAME = 'T         ') THEN REVERSE := SPTR ELSE
  773.     REVERSE := APPEND(REVERSE(TAIL(SPTR)), 
  774.            CONS(HEAD(SPTR), MKATOM('NIL       ')))
  775.     END;
  776.   1:
  777.   IF TRACE_ON THEN TRACEXIT('REVERSE   ')
  778.   END{ OF REVERSE };
  779.  
  780.   FUNCTION LENGTH(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  781.   LABEL 1;
  782.   VAR    TEMP: SYMBEXPPTR;
  783.     IDENTIFIER: ALFA;
  784.     J: INTEGER;
  785.   BEGIN
  786.   IF TRACE_ON THEN TRACENTER('LENGTH    ');
  787.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  788.     BEGIN
  789.     J := 0;
  790.     TEMP := SPTR;
  791.     IF (TEMP^.ANATOM) THEN BEGIN
  792.       IF (TEMP^.NAME = 'NIL       ') THEN J := 0 ELSE BEGIN
  793.          ERROR(12); GOTO 1 END
  794.       END
  795.     ELSE REPEAT
  796.       J := J + 1;
  797.       TEMP := TAIL(TEMP)
  798.       UNTIL (TEMP^.ANATOM) AND (TEMP^.NAME = 'NIL       ');
  799.     IDENTIFIER := '          ';
  800.     IDENTIFIER[1] := CHR( (J DIV 100) + 48); {LIMIT FOR J IS 999}
  801.     IDENTIFIER[2] := CHR((J - ((J DIV 100)*100)) DIV 10 + 48);
  802.     IDENTIFIER[3] :=
  803.       CHR( J - ((J DIV 100)*100) - ((J DIV 10)*10) +  48);
  804.     LENGTH := MKATOM(IDENTIFIER)
  805.     END;
  806.   1:
  807.   IF TRACE_ON THEN TRACEXIT('LENGTH    ')
  808.   END{ OF LENGTH };
  809.  
  810.   FUNCTION LOOKUP(KEY, ALIST: SYMBEXPPTR): SYMBEXPPTR;
  811.   LABEL 1;
  812.   VAR
  813.     TEMP: SYMBEXPPTR;
  814.   BEGIN
  815.   IF TRACE_ON THEN TRACENTER('LOOKUP    ');
  816.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  817.     BEGIN
  818.     TEMP := EQQ( HEAD( HEAD(ALIST)), KEY);
  819.     IF ( TEMP^.NAME='T         ' ) THEN
  820.       LOOKUP := TAIL(HEAD(ALIST))
  821.     ELSE
  822.       LOOKUP := LOOKUP(KEY, TAIL(ALIST))
  823.     END;
  824.   1:
  825.   IF TRACE_ON THEN TRACEXIT('LOOKUP    ')
  826.   END{ OF LOOKUP };
  827.  
  828.   FUNCTION BINDARGS(NAMES, VALUES, ENV: SYMBEXPPTR): SYMBEXPPTR;
  829.   LABEL 1;
  830.   VAR
  831.     TEMP, TEMP2: SYMBEXPPTR;
  832.   BEGIN
  833.   IF TRACE_ON THEN TRACENTER('BINDARGS  ');
  834.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  835.     BEGIN
  836.     IF ( NAMES^.ANATOM ) AND (NAMES^.NAME='NIL       ') THEN
  837.       BINDARGS := ENV
  838.     ELSE BEGIN
  839.         TEMP := CONS( HEAD(NAMES), EVAL(HEAD(VALUES), ENV) );
  840.     TEMP2 := BINDARGS(TAIL(NAMES), TAIL(VALUES), ENV);
  841.     BINDARGS := CONS(TEMP, TEMP2)
  842.     END
  843.     END;
  844.   1:
  845.   IF TRACE_ON THEN TRACEXIT('BINDARGS  ')
  846.   END{ OF BINDARGS };
  847.  
  848.   FUNCTION BINDARG1(NAMES, VALUES, ENV: SYMBEXPPTR): SYMBEXPPTR;
  849.   LABEL 1;
  850.   VAR
  851.     TEMP, TEMP2: SYMBEXPPTR;
  852.   BEGIN
  853.   IF TRACE_ON THEN TRACENTER('BINDARG1  ');
  854.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  855.     BEGIN
  856.     IF ( NAMES^.ANATOM ) AND ( NAMES^.NAME='NIL       ') THEN
  857.       BINDARG1 := ENV
  858.     ELSE BEGIN
  859.     TEMP := CONS( HEAD(NAMES), HEAD(VALUES) );
  860.     TEMP2 := BINDARG1( TAIL(NAMES), TAIL(VALUES), ENV);
  861.         BINDARG1 := CONS(TEMP, TEMP2)
  862.     END
  863.     END;
  864.   1:
  865.   IF TRACE_ON THEN TRACEXIT('BINDARG1  ')
  866.   END{ OF BINDARG1 };
  867.  
  868.   FUNCTION EVCON(CONDPAIRS: SYMBEXPPTR): SYMBEXPPTR;
  869.   LABEL 1;
  870.   VAR
  871.     TEMP: SYMBEXPPTR;
  872.   BEGIN
  873.   IF TRACE_ON THEN TRACENTER('EVCON     ');
  874.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  875.     BEGIN
  876.     TEMP := EVAL( HEAD(HEAD(CONDPAIRS)),ALIST );
  877.     IF ( TEMP^.ANATOM ) AND (TEMP^.NAME='NIL       ') THEN
  878.       EVCON := EVCON( TAIL(CONDPAIRS) )
  879.     ELSE
  880.       EVCON := EVAL( HEAD(TAIL(HEAD(CONDPAIRS))),ALIST )
  881.     END;
  882.   1:
  883.   IF TRACE_ON THEN TRACEXIT('EVCON     ')
  884.   END{ OF EVCON };
  885.  
  886.   FUNCTION MKFUNARG(SPTR : SYMBEXPPTR) : SYMBEXPPTR;
  887.   VAR
  888.     TEMP : SYMBEXPPTR;
  889.   BEGIN
  890.   IF TRACE_ON THEN TRACENTER('MKFUNARG  ');
  891.   IF (SPTR^.ANATOM) AND (NOT SPTR^.ISARESERVEDWORD) THEN
  892.     TEMP := CONS(MKATOM('FUNARG    '), CONS(EVAL(SPTR, ALIST), ALIST))
  893.   ELSE
  894.     TEMP := CONS(MKATOM('FUNARG    '), CONS(SPTR, ALIST));
  895.   MKFUNARG := TEMP;
  896.   IF TRACE_ON THEN TRACEXIT('MKFUNARG  ')
  897.   END{ OF MKFUNARG };
  898.  
  899.   FUNCTION ASSOC(KEY, S_TABLE : SYMBEXPPTR) : SYMBEXPPTR;
  900.   LABEL 1;
  901.   VAR
  902.     TEMP1, TEMP2 : SYMBEXPPTR;
  903.   BEGIN
  904.   IF TRACE_ON THEN TRACENTER('ASSOC     ');
  905.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  906.     BEGIN
  907.     TEMP1 := EQQ(HEAD(HEAD(S_TABLE)), KEY);
  908.     IF (TEMP1^.NAME = 'T         ') THEN
  909.       ASSOC := HEAD(S_TABLE)
  910.     ELSE
  911.       BEGIN
  912.       TEMP2 := HEAD(HEAD(TAIL(S_TABLE)));
  913.       IF NOT (TEMP2^.ANATOM) OR (TEMP2^.NAME <> 'NIL       ') THEN
  914.       ASSOC := ASSOC(KEY, TAIL(S_TABLE))
  915.       ELSE
  916.       ASSOC := HEAD(TAIL(S_TABLE))
  917.       END
  918.     END;
  919.   1:
  920.   IF TRACE_ON THEN TRACEXIT('ASSOC     ')
  921.   END{OF ASSOC};
  922.  
  923.   PROCEDURE SETT(SPTR1, SPTR2 : SYMBEXPPTR; VAR ALIST : SYMBEXPPTR);
  924.   LABEL 1;
  925.   VAR
  926.     TEMP1, TEMP2, TEMP3, NXT : SYMBEXPPTR;
  927.   BEGIN
  928.   IF TRACE_ON THEN TRACENTER('SETT      ');
  929.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  930.     BEGIN
  931.     IF NOT SPTR1^.ANATOM THEN BEGIN
  932.       ERROR(11);
  933.       GOTO 1
  934.       END;
  935.     TEMP1 := ASSOC(SPTR1, ALIST);
  936.     TEMP2 := HEAD(TEMP1);
  937.     IF (TEMP2^.ANATOM) AND (TEMP2^.NAME = 'NIL       ') THEN
  938.     {VARIABLE NOT LOCATED IN THE ALIST}
  939.       BEGIN
  940.       POP(TEMP3);
  941.       IF END_FREELIST THEN GOTO 1;
  942.       TEMP3^.ANATOM := FALSE; TEMP3^.STATUS := UNMARKED;
  943.       TEMP3^.TAIL := ALIST; ALIST := TEMP3;
  944.       POP(ALIST^.HEAD);
  945.       IF END_FREELIST THEN GOTO 1;
  946.       WITH ALIST^.HEAD^ DO BEGIN
  947.         ANATOM := FALSE; STATUS := UNMARKED;
  948.         HEAD := COPY(SPTR1);
  949.         TAIL := COPY(SPTR2)
  950.     END
  951.       END
  952.     ELSE  {VARIABLE LOCATED IN THE ALIST}
  953.       TEMP1^.TAIL := COPY(SPTR2)
  954.     END;
  955.   1:
  956.   IF TRACE_ON THEN TRACEXIT('SETT      ')
  957.   END{OF SETT};
  958.  
  959.   PROCEDURE REMOB(KEY: SYMBEXPPTR; VAR S_TABLE: SYMBEXPPTR);
  960.   LABEL 1;
  961.   VAR    TEMP1, TEMP2, TEMP3: SYMBEXPPTR;
  962.   BEGIN
  963.   IF TRACE_ON THEN TRACENTER('REMOB     ');
  964.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO  1 ELSE
  965.     BEGIN
  966.     TEMP1 := EQQ(HEAD(HEAD(S_TABLE)), KEY);
  967.     IF (TEMP1^.NAME = 'T         ') THEN S_TABLE := TAIL(S_TABLE)
  968.     ELSE BEGIN
  969.       TEMP2 := HEAD(TAIL(S_TABLE));
  970.       IF NOT (TEMP2^.ANATOM) OR (TEMP2^.NAME <> 'NIL       ') THEN
  971.       BEGIN TEMP3 := TAIL(S_TABLE); REMOB(KEY, TEMP3) END;
  972.       S_TABLE := CONS(HEAD(S_TABLE), TEMP3)
  973.       END
  974.     END;
  975.   1:
  976.   IF TRACE_ON THEN TRACEXIT('REMOB     ')
  977.   END{ OF REMOB };
  978.  
  979.   FUNCTION PROG(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  980.   LABEL 1;
  981.   VAR    TEMP1, TEMP2, TEMP3, AUX: SYMBEXPPTR;
  982.   BEGIN
  983.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  984.     BEGIN
  985.     IF TRACE_ON THEN TRACENTER('PROG      ');
  986.     IF SPTR^.ANATOM THEN BEGIN ERROR(13); GOTO 1 END ELSE
  987.       BEGIN
  988.       {ZEROING THE LIST OF VARIABLES}
  989.       AUX:= HEAD(SPTR);
  990.       WHILE NOT (AUX^.ANATOM) OR (AUX^.NAME <> 'NIL       ') DO BEGIN
  991.     SETT(HEAD(AUX), MKATOM('NIL       '), ALIST);
  992.     AUX := TAIL(AUX)
  993.     END {WHILE};
  994.       {CARRYING OUT THE PROGRAM}
  995.       TEMP3 := TAIL(SPTR);
  996.       REPEAT
  997.     TEMP1 := HEAD(TEMP3);
  998.     {SKIP ATOMS}
  999.     IF TEMP1^.ANATOM THEN TEMP1 := HEAD(TAIL(TEMP3));
  1000.     TEMP2 := EVAL(TEMP1, ALIST);
  1001.     IF NOT TEMP2^.ANATOM THEN BEGIN
  1002.  
  1003.         TEMP := HEAD(TEMP2);
  1004.         IF TEMP^.ANATOM THEN BEGIN
  1005.       IF TEMP^.NAME = 'RETURN    ' THEN BEGIN
  1006.         PROG := MKATOM('NIL       '); GOTO 1 END ELSE BEGIN
  1007.         IF TEMP^.NAME = 'GO        ' THEN BEGIN
  1008.           {GO TO THE TOP OF THE LIST}
  1009.               AUX := TAIL(SPTR);
  1010.               {LOOK FOR THE TAG}
  1011.           TEMP1 := HEAD(AUX);
  1012.           TEMP := HEAD(TAIL(TEMP2));
  1013.           WHILE NOT (TEMP1^.ANATOM) OR
  1014.         (TEMP1^.NAME <> TEMP^.NAME) DO BEGIN
  1015.           AUX := TAIL(AUX);
  1016.           IF (AUX^.ANATOM) AND (AUX^.NAME = 'NIL       ') THEN
  1017.             BEGIN ERROR(14); GOTO 1 END;
  1018.           TEMP1 := HEAD(AUX)
  1019.         END {WHILE};
  1020.           TEMP3 := AUX
  1021.         END
  1022.       END
  1023.     END
  1024.  
  1025.         END;
  1026.         TEMP3 := TAIL(TEMP3)
  1027.         UNTIL (TEMP3^.ANATOM) AND (TEMP3^.NAME = 'NIL       ');
  1028.       PROG := TEMP2
  1029.       END
  1030.     END;
  1031.   1:
  1032.   IF TRACE_ON THEN TRACEXIT('PROG      ')
  1033.   END{ OF PROG };
  1034.  
  1035.   FUNCTION PROG2(SPTR1, SPTR2: SYMBEXPPTR): SYMBEXPPTR;
  1036.   LABEL 1;
  1037.   VAR    TEMP: SYMBEXPPTR;
  1038.   BEGIN
  1039.   IF TRACE_ON THEN TRACENTER('PROG2     ');
  1040.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  1041.     BEGIN
  1042.     TEMP := EVAL(SPTR1, ALIST);
  1043.     TEMP := EVAL(SPTR2, ALIST);
  1044.     PROG2 := TEMP
  1045.     END;
  1046.   1:
  1047.   IF TRACE_ON THEN TRACEXIT('PROG2     ')
  1048.   END{ OF PROG2 };
  1049.  
  1050.   FUNCTION PROGN(SPTR: SYMBEXPPTR): SYMBEXPPTR;
  1051.   LABEL 1;
  1052.   VAR    TEMP1, TEMP2, TEMP3: SYMBEXPPTR;
  1053.   BEGIN
  1054.   IF TRACE_ON THEN TRACENTER('PROGN     ');
  1055.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  1056.     BEGIN
  1057.     IF (SPTR^.ANATOM) THEN PROGN := EVAL(SPTR, ALIST) ELSE
  1058.       BEGIN
  1059.       TEMP3 := SPTR;
  1060.     REPEAT
  1061.     TEMP1 := HEAD(TEMP3);
  1062.     TEMP2 := EVAL(TEMP1, ALIST);
  1063.     TEMP3 := TAIL(TEMP3)
  1064.     UNTIL (TEMP3^.ANATOM) AND (TEMP3^.NAME = 'NIL       ');
  1065.       PROGN := TEMP2
  1066.       END
  1067.     END;
  1068.   1:
  1069.   IF TRACE_ON THEN TRACEXIT('PROGN     ')
  1070.   END{ OF PROGN };
  1071.  
  1072.   BEGIN    {   * E V A L *   }
  1073.   IF TRACE_ON THEN TRACENTER('EVAL      ');
  1074.   IF (ERR_COND) OR (END_FREELIST) THEN GOTO 1 ELSE
  1075.     BEGIN
  1076.     IF ( E^.ANATOM ) THEN EVAL := LOOKUP(E, ALIST)
  1077.     ELSE
  1078.       BEGIN
  1079.     CAROFE := HEAD(E);
  1080.     IF ( CAROFE^.ANATOM ) THEN
  1081.        IF NOT ( CAROFE^.ISARESERVEDWORD ) THEN
  1082.          EVAL := EVAL( CONS(LOOKUP(CAROFE,ALIST),TAIL(E)), ALIST )
  1083.        ELSE
  1084.          CASE CAROFE^.RESSYM OF
  1085.  
  1086.            LABELSYM, LAMBDASYM, FUNARGSYM, FLAMBDASYM:
  1087.               BEGIN ERROR(3); GOTO 1 END;
  1088.  
  1089.            TRACESYM : BEGIN TRACE_ON := TRUE;
  1090.                 EVAL := MKATOM('NIL       ')
  1091.                 END;
  1092.  
  1093.            UNTRACESYM : BEGIN TRACE_ON := FALSE;
  1094.                   EVAL := MKATOM('NIL       ')
  1095.                   END;
  1096.  
  1097.            QUOTESYM    : EVAL := HEAD(TAIL(E));
  1098.  
  1099.            ATOMSYM    : EVAL := ATOM(EVAL(HEAD(TAIL(E)),ALIST));
  1100.  
  1101.            EQSYM    : EVAL := EQQ(EVAL(HEAD(TAIL(E)),ALIST),
  1102.                       EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1103.  
  1104.                EQUALSYM : EVAL := EQUAL(EVAL(HEAD(TAIL(E)), ALIST),
  1105.                     EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1106.  
  1107.            HEADSYM    : EVAL := HEAD(EVAL(HEAD(TAIL(E)),ALIST));
  1108.  
  1109.            TAILSYM    : EVAL := TAIL(EVAL(HEAD(TAIL(E)),ALIST));
  1110.  
  1111.            CONSSYM    : EVAL := CONS(EVAL(HEAD(TAIL(E)),ALIST),
  1112.                        EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1113.  
  1114.            CONDSYM    : EVAL := EVCON(TAIL(E));
  1115.  
  1116.            LISTSYM  : EVAL := LIST(TAIL(E));
  1117.  
  1118.            ANDSYM   : EVAL := ET(TAIL(E));
  1119.  
  1120.              ORSYM    : EVAL := OU(TAIL(E));
  1121.  
  1122.            NULLSYM, NOTSYM :
  1123.               EVAL := NULL(EVAL(HEAD(TAIL(E)), ALIST));
  1124.  
  1125.            EVALSYM  : EVAL := EVAL(EVAL(HEAD(TAIL(E)), ALIST), ALIST);
  1126.  
  1127.            APPENDSYM : EVAL := APPEND(EVAL(HEAD(TAIL(E)),ALIST),
  1128.                       EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1129.  
  1130.            RELACEHSYM : EVAL := REPLACEH(EVAL(HEAD(TAIL(E)),ALIST),
  1131.                        EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1132.  
  1133.            RELACETSYM : EVAL := REPLACET(EVAL(HEAD(TAIL(E)),ALIST),
  1134.                        EVAL(HEAD(TAIL(TAIL(E))), ALIST));
  1135.  
  1136.            LASTSYM  : EVAL := LAST(EVAL(HEAD(TAIL(E)), ALIST));
  1137.  
  1138.            LENGTHSYM : EVAL := LENGTH(EVAL(HEAD(TAIL(E)), ALIST));
  1139.  
  1140.            REVERSESYM : EVAL := REVERSE(EVAL(HEAD(TAIL(E)), ALIST));
  1141.  
  1142.            FUNCTSYM : EVAL := MKFUNARG(HEAD(TAIL(E)));
  1143.  
  1144.            SETSYM :
  1145.                   BEGIN
  1146.             TEMP := EVAL(HEAD(TAIL(TAIL(E))), ALIST);
  1147.             SETT(EVAL(HEAD(TAIL(E)), ALIST), TEMP, ALIST);
  1148.             EVAL := TEMP
  1149.                   END;
  1150.            SETQSYM :
  1151.           BEGIN
  1152.             TEMP := EVAL(HEAD(TAIL(TAIL(E))), ALIST);
  1153.             SETT(HEAD(TAIL(E)), TEMP, ALIST);
  1154.             EVAL := TEMP
  1155.           END;
  1156.            DEFEXPSYM :
  1157.                   BEGIN
  1158.                     TEMP := HEAD(TAIL(E));
  1159.             SETT(TEMP,
  1160.             CONS(MKATOM('LAMBDA    '), TAIL(TAIL(E))),
  1161.             ALIST);
  1162.             EVAL := TEMP
  1163.           END;
  1164.            DEFFEXPSYM :
  1165.           BEGIN
  1166.             TEMP := HEAD(TAIL(E));
  1167.             SETT(TEMP,
  1168.             CONS(MKATOM('FLAMBDA   '), TAIL(TAIL(E))),
  1169.             ALIST);
  1170.             EVAL := TEMP
  1171.           END;
  1172.            REMOBSYM :
  1173.           BEGIN
  1174.             REMOB(HEAD(TAIL(E)), ALIST);
  1175.             EVAL := MKATOM('NIL       ')
  1176.                   END;
  1177.            GOSYM    : EVAL := CONS(MKATOM('GO        '), TAIL(E));
  1178.            RETURNSYM: EVAL := CONS(MKATOM('RETURN    '),
  1179.                        MKATOM('NIL       '));
  1180.            PROGSYM  : EVAL := PROG(TAIL(E));
  1181.            PROG2SYM : EVAL := PROG2(HEAD(TAIL(E)),
  1182.                     HEAD(TAIL(TAIL(E))));
  1183.  
  1184.            PROGNSYM : EVAL := PROGN(TAIL(E));
  1185.  
  1186.          END{CASE}
  1187.          ELSE
  1188.        BEGIN
  1189.          CAAROFE := HEAD(CAROFE);
  1190.          IF ( CAAROFE^.ANATOM ) AND ( CAAROFE^.ISARESERVEDWORD ) THEN
  1191.            IF NOT (CAAROFE^.RESSYM IN [LABELSYM, LAMBDASYM, FUNARGSYM,
  1192.          FLAMBDASYM]) THEN BEGIN ERROR(10); GOTO 1 END
  1193.            ELSE
  1194.          CASE CAAROFE^.RESSYM OF
  1195.            LABELSYM:
  1196.               BEGIN
  1197.             TEMP := CONS( CONS(HEAD(TAIL(CAROFE)),
  1198.                          HEAD(TAIL(TAIL(CAROFE)))), ALIST);
  1199.             EVAL := EVAL(CONS(HEAD(TAIL(TAIL(CAROFE))),
  1200.                        TAIL(E)),TEMP)
  1201.               END;
  1202.            LAMBDASYM:
  1203.               BEGIN
  1204.             TEMP := BINDARGS(HEAD(TAIL(CAROFE)), TAIL(E),
  1205.                 ALIST);
  1206.             EVAL := EVAL( HEAD( TAIL( TAIL(CAROFE))), TEMP)
  1207.               END;
  1208.            FUNARGSYM:
  1209.               BEGIN
  1210.             TEMP := TAIL(TAIL(CAROFE));
  1211.             EVAL := EVAL(CONS(HEAD(TAIL(CAROFE)), TAIL(E)),
  1212.                 TEMP)
  1213.               END;
  1214.                    FLAMBDASYM:
  1215.               BEGIN
  1216.             TEMP := BINDARG1(HEAD(TAIL(CAROFE)), TAIL(E),
  1217.                 ALIST);
  1218.                 EVAL := EVAL( HEAD( TAIL( TAIL(CAROFE))), TEMP)
  1219.               END;
  1220.          END{ CASE }
  1221.          ELSE
  1222.            EVAL := EVAL(CONS(EVAL(CAROFE, ALIST), TAIL(E)), ALIST)
  1223.           END   
  1224.       END
  1225.   END;
  1226. 1:
  1227. IF TRACE_ON THEN TRACEXIT('EVAL      ')
  1228. END{ OF EVAL };
  1229.  
  1230. PROCEDURE INITIALIZE;
  1231. VAR    I: INTEGER;
  1232.     TEMP, NXT: SYMBEXPPTR;
  1233. BEGIN
  1234.   END_FREELIST := FALSE;
  1235.   ERR_COND := FALSE;
  1236.   TRACE_ON := FALSE;
  1237.   NESTCOUNT := 0;
  1238.   ALREADYPEEKED := FALSE;
  1239.   NUMBEROFGCS := 0;
  1240.   FREENODES := MAXNODE;
  1241.   WITH NILNODE DO BEGIN
  1242.     ANATOM := TRUE; NEXT := NIL; NAME := 'NIL       ';
  1243.     STATUS := UNMARKED; ISARESERVEDWORD := FALSE
  1244.   END;
  1245.  
  1246.   WITH TNODE DO BEGIN
  1247.     ANATOM := TRUE; NEXT := NIL; NAME := 'T         ';
  1248.     STATUS := UNMARKED; ISARESERVEDWORD := FALSE
  1249.   END;
  1250. {
  1251.     ALLOCATE STORAGE AND MARK IT FREE
  1252. }
  1253.   FREELIST := NIL;
  1254.   FOR I:=1 TO MAXNODE DO BEGIN
  1255.     NEW(NODELIST); NODELIST^.NEXT := FREELIST;
  1256.     NODELIST^.HEAD := FREELIST; NODELIST^.STATUS := UNMARKED;
  1257.     FREELIST := NODELIST
  1258.   END;
  1259. {
  1260.     INITIALIZE RESERVED WORD TABLE
  1261. }
  1262.   RESWORDS[ ANDSYM      ] := 'AND       ';
  1263.   RESWORDS[ APPENDSYM   ] := 'APPEND    ';
  1264.   RESWORDS[ ATOMSYM     ] := 'ATOM      ';
  1265.   RESWORDS[ HEADSYM     ] := 'CAR       ';
  1266.   RESWORDS[ TAILSYM     ] := 'CDR       ';
  1267.   RESWORDS[ CONDSYM     ] := 'COND      ';
  1268.   RESWORDS[ CONSSYM     ] := 'CONS      ';
  1269.   RESWORDS[ COPYSYM     ] := 'COPY      ';
  1270.   RESWORDS[ DEFEXPSYM   ] := 'DEFEXP    ';
  1271.   RESWORDS[ DEFFEXPSYM  ] := 'DEFFEXP   ';
  1272.   RESWORDS[ DEFMACSYM   ] := 'DEFMACRO  ';
  1273.   RESWORDS[ EQSYM       ] := 'EQ        ';
  1274.   RESWORDS[ EQUALSYM    ] := 'EQUAL     ';
  1275.   RESWORDS[ EVALSYM     ] := 'EVAL      ';
  1276.   RESWORDS[ FLAMBDASYM  ] := 'FLAMBDA   ';
  1277.   RESWORDS[ FUNARGSYM   ] := 'FUNARG    ';
  1278.   RESWORDS[ FUNCTSYM    ] := 'FUNCTION  ';
  1279.   RESWORDS[ GOSYM       ] := 'GO        ';
  1280.   RESWORDS[ LABELSYM    ] := 'LABEL     ';
  1281.   RESWORDS[ LAMBDASYM   ] := 'LAMBDA    ';
  1282.   RESWORDS[ LASTSYM     ] := 'LAST      ';
  1283.   RESWORDS[ LENGTHSYM   ] := 'LENGTH    ';
  1284.   RESWORDS[ LISTSYM     ] := 'LIST      ';
  1285.   RESWORDS[ NOTSYM      ] := 'NOT       ';
  1286.   RESWORDS[ NULLSYM     ] := 'NULL      ';
  1287.   RESWORDS[ ORSYM       ] := 'OR        ';
  1288.   RESWORDS[ PROGSYM     ] := 'PROG      ';
  1289.   RESWORDS[ PROG2SYM    ] := 'PROG2     ';
  1290.   RESWORDS[ PROGNSYM    ] := 'PROGN     ';
  1291.   RESWORDS[ QUOTESYM    ] := 'QUOTE     ';
  1292.   RESWORDS[ RELACEHSYM  ] := 'REPLACEH  ';
  1293.   RESWORDS[ RELACETSYM  ] := 'REPLACET  ';
  1294.   RESWORDS[ REMOBSYM    ] := 'REMOB     ';
  1295.   RESWORDS[ RETURNSYM   ] := 'RETURN    ';
  1296.   RESWORDS[ REVERSESYM  ] := 'REVERSE   ';
  1297.   RESWORDS[ SETSYM      ] := 'SET       ';
  1298.   RESWORDS[ SETQSYM     ] := 'SETQ      ';
  1299.   RESWORDS[ TRACESYM    ] := 'TRACE     ';
  1300.   RESWORDS[ UNTRACESYM  ] := 'UNTRACE   ';
  1301. {
  1302.     INITIALIZE THE A-LIST WITH  T  AND  NIL
  1303. }
  1304.   POP(ALIST);
  1305.   ALIST^.ANATOM := FALSE;
  1306.   ALIST^.STATUS := UNMARKED;
  1307.   POP(ALIST^.TAIL);
  1308.   NXT := ALIST^.TAIL^.NEXT;
  1309.   ALIST^.TAIL^ := NILNODE;
  1310.   ALIST^.TAIL^.NEXT := NXT;
  1311.   POP(ALIST^.HEAD);
  1312. {
  1313.     BIND NIL TO THE ATOM NIL
  1314. }
  1315.   WITH ALIST^.HEAD^ DO BEGIN
  1316.     ANATOM := FALSE; STATUS := UNMARKED; POP(HEAD);
  1317.     NXT := HEAD^.NEXT; HEAD^ := NILNODE; HEAD^.NEXT := NXT;
  1318.     POP(TAIL); NXT := TAIL^.NEXT; TAIL^ := NILNODE;
  1319.     TAIL^.NEXT := NXT
  1320.   END;
  1321.   POP(TEMP);
  1322.   TEMP^.ANATOM := FALSE;
  1323.   TEMP^.STATUS := UNMARKED;
  1324.   TEMP^.TAIL := ALIST;
  1325.   ALIST := TEMP;
  1326.   POP(ALIST^.HEAD);
  1327. {
  1328.     BIND  T  TO THE ATOM  T
  1329. }
  1330.   WITH ALIST^.HEAD^ DO BEGIN
  1331.     ANATOM := FALSE;  STATUS := UNMARKED; POP(HEAD);
  1332.     NXT := HEAD^.NEXT; HEAD^ := TNODE; HEAD^.NEXT := NXT;
  1333.     POP(TAIL); NXT := TAIL^.NEXT; TAIL^ := TNODE;
  1334.     TAIL^.NEXT := NXT
  1335.   END;
  1336.   RESET('INITLISP', INFILE);
  1337.   READ(INFILE, CH);
  1338.   NEXTSYM1;
  1339.   READEXP1(PTR);
  1340.   WHILE NOT ( PTR^.ANATOM ) OR ( PTR^.NAME<>'FIN       ' ) DO BEGIN
  1341.     TEMP := EVAL(PTR, ALIST);
  1342.     NEXTSYM1;
  1343.     READEXP1(PTR);
  1344.     {CALL THE} GARBAGEMAN
  1345.     END;
  1346.   WRITELN;
  1347.   WRITELN('                                  R E A D Y');
  1348.   WRITELN;
  1349.   READ(CH);
  1350. END{ OF INITIALIZE };
  1351.  
  1352.  
  1353.  
  1354. BEGIN{+        LISP MAIN PROGRAM        +}
  1355.   INITIALIZE;
  1356.   NEXTSYM;
  1357.   READEXPR(PTR);
  1358.   WHILE NOT ( PTR^.ANATOM ) OR ( PTR^.NAME<>'FIN       ' ) DO BEGIN
  1359.     IF NOT TRACE_ON THEN WRITE('  ');
  1360.     PRINTEXPR( EVAL(PTR, ALIST) );
  1361. {   NESTCOUNT := 0;  }
  1362.     IF END_FREELIST THEN GOTO 2;
  1363. 1:  ERR_COND := FALSE;
  1364.     IF ( EOF(INPUT) ) THEN BEGIN
  1365.     WRITELN('END OF FILE ENCOUNTERED BEFORE A "FIN" CARD.');
  1366.     GOTO 2
  1367.     END;
  1368.     PTR := NIL;
  1369.     WRITELN; WRITELN;
  1370.     { CALL THE } GARBAGEMAN;
  1371.     NEXTSYM;
  1372.     READEXPR(PTR);
  1373.     IF ERR_COND THEN GOTO 1;
  1374.     IF END_FREELIST THEN GOTO 2;
  1375.   END;
  1376. 2:WRITELN; WRITELN;
  1377.   WRITELN(' TOTAL NUMBER OF GARBAGE COLLECTIONS = ', NUMBEROFGCS:1,'.');
  1378.   WRITELN;
  1379.   WRITELN(' FREE NODES LEFT UPON EXIT = ', FREENODES:1, '.');
  1380.   WRITELN
  1381. END { OF LISP }.
  1382.