Haskell で SECD マシン

どこかにバグがあるけど何とか関数適用まで動くようになったので貼付けておく。

  • 「:.」は「.」のつもりのデータ構築子。
-- SECD Machine
data SECD = SECD LispVal LispVal LispVal LispVal
            deriving (Eq, Show)

step (SECD s e (LDC x :. c) d) = SECD (x :. s) e c d
step (SECD s e (NIL :. c) d) = SECD (Nil :. s) e c d

-- (+ a b) => LDC b LDC a Op +
step (SECD (a :. b :. s) e (Op "+" :. c) d) = SECD (binOp (+) a b :. s) e c d
-- (- a b) => LDC b LDC a Op -
step (SECD (a :. b :. s) e (Op "-" :. c) d) = SECD (binOp (-) a b :. s) e c d
step (SECD (a :. b :. s) e (Op "*" :. c) d) = SECD (binOp (*) a b :. s) e c d
step (SECD (a :. b :. s) e (Op ">" :. c) d) = SECD (fn a b :. s) e c d
    where fn (Number a) (Number b) = Bool (a > b)
step (SECD (a :. b :. s) e (Op "<" :. c) d) = SECD (fn a b :. s) e c d
    where fn (Number a) (Number b) = Bool (a < b)
step (SECD (x :. s) e (SEL :. ct :. cf :. c) d) = SECD s e c' (c :. d)
    where c' = if x == Bool True
               then
                   ct
               else
                   cf
step (SECD s e (JOIN :. c) (cr :. d)) = SECD s e cr d
step (SECD s e (LDF f :. c) d) = SECD ((f :. e) :. s) e c d
-- (cons a b) => ldc b ldc a cons, stack = a b . s
step (SECD (a :. b :. s) e (CONS :. c) d) = SECD ((a :. b) :. s) e c d
step (SECD ((f :. e') :. v :. s) e (AP :. c) d) = SECD Nil (v :. e') f (s :. e :. c :. d)
step (SECD (x :. z) e' (RTN :. q) (s :. e :. c :. d)) = SECD (x :. s) e c d
step (SECD s e (LD (i, j) :. c) d) = SECD ((locate (i,j) e) :. s) e c d
    where
      locate (i,j) e = (lispNth j (lispNth i e))
step (SECD s e c d) = SECD s e c d

runSecd = fixpoint step
readAndRun str = runSecd (SECD (Atom "s") (Atom "e") (comp (readExpr str)) (Atom "d"))
readAndRun' str = showLispVal $ car s
    where
      SECD s e c d = readAndRun str