Stack in Common Lisp (Vector ver.)
スタックを Common Lisp で書いてみたものの、思い直して組み込み vector-push, vector-pop を使うことにした。
vector は一次元配列のこと。
(defclass vm () ;; stack machine ((codes :accessor codes :initform nil) (stack :accessor stack :initform (make-array *max-stack* :initial-element nil :fill-pointer 0)) (pc :accessor pc :initform 0) (fp :accessor fp :initform 0) )) (defmethod vm-push ((vm vm) n) (with-slots (stack) vm (vector-push n stack))) (defmethod vm-pop ((vm vm)) (with-slots (stack) vm (vector-pop stack))) (defmethod vm-top ((vm vm)) (with-slots (stack) vm (aref stack (1- (fill-pointer stack)))))
Common Lisp の fill-pointer というのが実質 stack pointer になる。
以下は要素3の配列 v を作って、スタックとして操作してみたもの。
vector-pop を使っても、aref によって直接参照すると値(ここでは'c)が残っている。
そういうものか、と思って HyperSpec を調べたらまさに定義どおりの動作なのだった。
(http://www.lisp.org/HyperSpec/Body/fun_vector-pop.html)
さらに, fill-pointer が指定されている vector は、そこまでしか印字されない、ともちゃんと規定されていた(http://www.lisp.org/HyperSpec/Body/sec_22-1-3-7.html)。
st-machine(15): (setq v (make-array 3 :initial-element 0 :fill-pointer 0)) #() st-machine(16): (vector-push 'a v) 0 st-machine(17): (vector-push 'b v) 1 st-machine(18): (vector-push 'c v) 2 st-machine(19): v #(a b c) st-machine(20): (vector-push 'd v) nil st-machine(21): v #(a b c) st-machine(22): (fill-pointer v) 3 st-machine(23): (vector-pop v) c st-machine(24): (fill-pointer v) 2 st-machine(25): v #(a b) st-machine(26): (aref v 2) c
よく参考にさせてもらっている http://www.geocities.jp/m_hiroi/xyzzy_lisp/abclisp05.html が詳しい。