На этом шаге мы рассмотрим работу со стеком.
Функция PUSH помещает S-выражение в стек:
    (PUSH S-выражение Стек)
Вызов PUSH добавляет в начало списка, являющегося значением атома Стек, S-выражение, обновляя значение атома Стек.
Функция POP выталкивает элемент из стека. Ее синтаксис:
    (POP Стек)
$ (SETQ Y (4 5)) (4 5) $ (PUSH (3) Y) ((3) 4 5) $ (POP Y) (3) $ Y (4 5)
   (DEFUN PUSH (LAMBDA (A STACK)
      (SETQ STACK (CONS A (EVAL STACK)))
   ))
   (DEFUN MKTOWER (LAMBDA (NUM ALPHABET TOWER)
      (LOOP
         ( (ZEROP NUM) (REVERSE TOWER) )
         (PUSH (POP ALPHABET) TOWER)
         (SETQ NUM (- NUM 1))
      )
   ))
   (DEFUN PRNSTR (LAMBDA (LST)
      (LOOP
         ( (NULL LST) )
         (PRIN1 (POP LST))
      )
   ))
   (SETQ GENSYM 0)
   (DEFUN GENSYM (LAMBDA (NUM LST)
      (SETQ NUM (- 4 (LENGTH GENSYM)))
      (LOOP
         ( (ZEROP NUM) )
         ( PUSH 0 LST )
         ( SETQ NUM (- NUM 1)) )
      (PROG1
         (PACK (NCONC (CONS (QUOTE G) LST) (LIST GENSYM)))
         (SETQ GENSYM (+ GENSYM 1)) )
   ))
Y = A LST = ((A B) A (C (A (A D)))),
   (DEFUN MAIN (LAMBDA (Y LST)
      (SETQ W (COPY LST LST Y))
      (COPY1 W W)
   ))
   ; ---------------------------- ;
   (DEFUN COPY (LAMBDA (LST LST1 Y)
   ; Построение списка, конгруэнтного списку LST и    ;
   ; содержащего различные (!) атомы вида G*** вместо ;
   ; вхождений атома Y                                ;
      (COND ( (NULL LST) NIL )
            ( (AND (ATOM LST) (EQ LST Y))  (GENSYM) )
            ( (AND (ATOM LST) (NOT (EQ LST Y))) LST )
            (  T  (CONS (COPY (CAR LST) LST1 Y)
                        (COPY (CDR LST) LST1 Y)
                  )
            )
      )
   ))
   ; --------------------------- ;
   (DEFUN COPY1 (LAMBDA (LST LST1)
   ; Построение списка, конгруэнтного списку LST и со-   ;
   ; держащего "глубины погружения" атомов G*** в список ;
   ; LST вместо них самих                                ;
       (COND ( (NULL LST) NIL )
             ( (AND (ATOM LST)
                    (EQ (CAR (UNPACK LST)) G))
                  (POISK LST LST1) )
             ( (AND (ATOM LST)
                    (NOT (EQ (CAR (UNPACK LST)) G)))
                  LST )
             (  T  (CONS (COPY1 (CAR LST) LST1)
                         (COPY1 (CDR LST) LST1)) )
       )
   ))
   ; ----------- ;
   (SETQ GENSYM 0)
   (DEFUN GENSYM (LAMBDA (NUM LST)
   ; Формирование новых атомов ;
      (SETQ NUM (- 4 (LENGTH GENSYM)))
      (LOOP
          ( (ZEROP NUM) )
          ( PUSH 0 LST )
          ( SETQ NUM (- NUM 1)) )
      (PROG1
          (PACK (NCONC (CONS (QUOTE G) LST) (LIST GENSYM)))
          (SETQ GENSYM (+ GENSYM 1))
      )
   ))
   ; ------------------------ ;
   (DEFUN POISK (LAMBDA (X LST)
   ; Нахождение "глубины погружения" X в список LST ;
      (COND ( (MEMBER X LST) 1 )
            ( (MEMBER2 X (CAR LST))
                        (+ 1 (POISK X (CAR LST))) )
            (   T   (POISK X (CDR LST)) )
      )
   ))
   ; -------------------------- ;
   (DEFUN MEMBER2 (LAMBDA (X LST)
   ; Предикат MEMBER2 устанавливает вхождение элемента X ;
   ; в многоуровневый список LST                         ;
      (COND ( (NULL LST) NIL)
            (  T  (OR (COND ( (ATOM (CAR LST))
                                  (EQ X (CAR LST)) )
                            (  T  (MEMBER2 X (CAR LST)) )
                      )
                      (MEMBER2 X (CDR LST))) )
      )
   ))
Функция (POP SYMBOL) возвращает "верхушку" (CAR) стека (списка), который называется SYMBOL, и заменяет значение SYMBOL на оставшуюся часть (CDR) стека. Например:
$ (SETQ STACK-LIST '(A B C D E F)) (A B C D E F) $ (POP STACK-LIST) A $ (POP STACK-LIST) B $ (POP STACK-LIST) C $ STACK-LIST (D E F)
Если SYMBOL не является символом, то возникает прерывание по ошибке "Несимвольный аргумент".
Если значение SYMBOL - не точечная пара, то функция POP возвращает NIL.
Данная специальная функция - это LISP-аналог выражения на машинном языке, предназначенного для выборки информации из "верхушки" стека.
Приведем реализацию функции в виде макроса:
   (DEFMACRO POP (SYM)
      (LIST 'PROG1
            (LIST 'CAR SYM)
            (LIST 'SETQ SYM (LIST 'CDR SYM)))
   )
Функция (PUSH FORM SYMBOL) оценивает FORM, "проталкивает" результат в стек (в SYMBOL) и заменяет значение SYMBOL на увеличенный стек. Функция PUSH возвращает увеличенный стек (список). Например:
$ (SETQ STACK-LIST NIL) NIL $ (PUSH 'A STACK-LIST) (A) $ (PUSH 'B STACK-LIST) (B A) $ (PUSH 'C STACK-LIST) (C B A) $ STACK-LIST (C B A)
Если SYMBOL не является символом, то возникает прерывание по ошибке "Несимвольный аргумент".
Данная функция - это LISP-аналог выражения на машинном языке, предназначенного для размещения информации в "верхушке" стека.
Приведем реализацию функции в виде макроса:
   (DEFMACRO PUSH (OBJ SYM)
      (LIST 'SETQ SYM
           (LIST 'CONS OBJ SYM))
   )
Со следующего шага мы начнем рассматривать работу с файлами.