match

まだまだ機能が足りないが match を書いている。パターンマッチも(最適化と汎用性を気にしなければ)難しくはない。

(def-secd-machine secd-1 "secd machine"
  ;; initial state -> transformed state
  ( s e (:NIL . c) d                         -> (nil . s) e c d )
  ( s e (:LDC x . c) d                       -> (x . s) e c d )
  ( s e (:LD (m . n) . c) d                  -> (x . s) e c d where x = (locate m n e) )
  ( s e (:LDF |c'| . c) d                    -> ((|c'| . e) . s) e c d )
  ( (x . s) e (:SEL cT cF . c) d             -> s e cX (c . d) where cX = (if x cT cF) )
  ( s e (:JOIN . c) (cr . d)                 -> s e cr d )
  ( ((|c'| . |e'|) v . s) e (:AP . c) d      -> nil (v . |e'|) |c'| (s e c . d) )
  ( (a b . s) e (:CONS . c) d                -> ((a . b) . s) e c d )
  ( ((a . b) . s) e (:CAR . c) d             -> (a . s) e c d )
  ( ((a . b) . s) e (:CDR . c) d             -> (b . s) e c d )
  ( (x . z) |e'| (:RTN . |c'|) (s e c . d)   -> (x . s) e c d )
  ( (a b . s) e (:+ . c) d                   -> (x . s) e c d where x = (+ a b) )
  ( (a b . s) e (:- . c) d                   -> (x . s) e c d where x = (- a b) )
  ( (a b . s) e (:* . c) d                   -> (x . s) e c d where x = (* a b) )
  ( (a b . s) e (:= . c) d                   -> (x . s) e c d where x = (= a b) )
  ( (a b . s) e (:> . c) d                   -> (x . s) e c d where x = (> a b) )
  ( (a b . s) e (:< . c) d                   -> (x . s) e c d where x = (< a b) )
  )
(defmacro def-secd-machine (name doc &rest body)
  (let ((s (gensym "S ")) (e (gensym "E ")) (c (gensym "C ")) (d (gensym "D ")))
    `(progn
       (defun ,name (,s ,e ,c ,d)
         ,doc
         (tagbody
          :loop
            (format t ";; ~s~%" (list ,s ,e ,c ,d))
            (match (list ,s ,e ,c ,d)
              ,@(loop :for rule :in body
                   :collect
                   (match rule
                     ((s0 e0 c0 d0 :_ s1 e1 c1 d1 'where var '= init-form)
                      `((,s0 ,e0 ,c0 ,d0)
                        (let ((,var ,init-form))
                          (psetq ,s ,(pattern->cons s1)
                                 ,e ,(pattern->cons e1)
                                 ,c ,c1
                                 ,d ,(pattern->cons d1))
                          (go :loop))))
                     ((s0 e0 c0 d0 :_ s1 e1 c1 d1)
                      `((,s0 ,e0 ,c0 ,d0)
                        (psetq ,s ,(pattern->cons s1)
                               ,e ,(pattern->cons e1)
                               ,c ,c1
                               ,d ,(pattern->cons d1))
                        (go :loop))))))
            (values 'stop ,s))))))