にゃははー

はへらー

lispの勉強がてら・・・

common lispの勉強の為にGrassのインタプリタ(未完)を作っている。
Grassの詳細な仕様などは適当にググってください。

とりあえずパーサとかは作ってないけど、中間コードで書いてみた。
中間コードは

wWWwwwWwwvwWWWwvWw

ってのがあったとしたら

(def 1 `(2 3) `(1 2))
(def 1 `(3 1))
(app 1 1)

って感じ

以下ソース。そのまま処理系に渡すと Hello, world ってでてくる。

(defun out (prim)
  (let ((chr (first prim)))
    (format t "~c" (first chr))
    chr))

(defun succ (prim)
  (let ((chr (first prim)))
    (setf (first chr) (code-char (mod (1+ (char-code (first chr))) 256)))
    chr))

(defun in (prim)
  (let ((rc (first prim))
        (c (read-char)))
    (unless (null c) (setf rc `(,c 0 `())))
    rc))

(defun true (prim) (first prim))
(defun false (prim) (second prim))

(defun stack-trace (stream &optional (prim *prim*))
  (dotimes (i (length *prim*))
    (format stream "~&~d: ~a~%" (1+ i) (first (nth i prim)))))

(defun app (func arg &optional (prim *prim*))
  (let ((func (copy-list (nth (1- func) prim)))
        (arg (copy-list (nth (1- arg) prim))))
    (if (= (second func) 0)
        `(,(if (eql (first func) (first arg)) #'true #'false) 2 (copy-list prim))
        (progn (push arg (third func))
               (if (= (decf (second func)) 0)
                   (funcall (first func) (third func))
                   func)))))

(defun def (arg &rest apps)
  (let ((applist (copy-list apps)))
    (setf func #'(lambda (prim)
                   (dolist (appelem applist)
                     (push (app (first appelem) (second appelem) prim) prim))
                   (first prim)))
    (push `(,func ,arg ,(copy-list *prim*)) *prim*)))

(defvar *prim* `(,`(,#'out 1 `()) ,`(,#'succ 1 `()) ,`(#\w 0 `()) ,`(,#'in 1 `())))

; print w
; wWWwwww
;(def 1 `(2 4))

; print x
; wWWWwwwwWWWw
;(def 1 `(3 4) `(3 1))

; print w (infinite)
;   !!WARNING!!
;   Always stack overflow occurs.
; wWWwwwwWWWW
;(def 1 `(2 4) `(2 2))

; print answer of '1+1' in number of w
; wwWWwvwwwwWWWwwWwwWWWWWWwwwwWwwvwWWwwwWwwwwWwwwwwwWwwwwwwwww
;(def 2 `(2 1))
;(def 4 `(3 2) `(1 2) `(6 4) `(1 2))
;(def 1 `(2 3) `(1 4) `(1 6) `(1 9))

; hello world
(def 2)
(def 3 `(3 2) `(1 2) `(4 1))
(def 1 `(2 3) `(1 2))
(def 1 `(1 3) `(1 2))
(def 1 `(2 1) `(5 1))
(def 1 `(3 4) `(4 1) `(4 1) `(6 1) `(7 1) `(7 1) `(8 1) `(1 8))
(def 1 `(3 5) `(5 1) `(5 1) `(7 1) `(8 1) `(9 1) `(1 7))
(def 1 `(4 6) `(6 1) `(6 1) `(7 1) `(9 1) `(9 1) `(1 7))
(def 1 `(5 7) `(7 1) `(8 1) `(8 1) `(10 1) `(10 1) `(1 7))
(def 1 `(7 8) `(8 1) `(9 1) `(9 1) `(11 1) `(1 6))
(def 1 `(8 9) `(8 1) `(9 1) `(11 1) `(11 1) `(13 1) `(1 7))
(def 1 `(8 10) `(9 1) `(10 1) `(11 1) `(13 1) `(1 6))
(def 1 `(10 11) `(10 1) `(11 1) `(13 1) `(1 5))
(def 1 `(10 12) `(12 1) `(13 1) `(14 1) `(14 1) `(16 1) `(1 7))
(def 1 `(10 17) `(1 19) `(3 19) `(1 2) `(20 1))
(def 1 `(2 4) `(3 10) `(4 10) `(5 13) `(6 7) `(7 11) `(8 22))
(def 1 `(16 7) `(1 2))
(def 1 `(4 7) `(5 3) `(6 7) `(7 8) `(8 14) `(9 14))
(def 1 `(2 1) `(5 1))

; build-in application
(push (app 1 1) *prim*)
;(stack-trace t)

真のlisperからするとかなり汚いコードだろうが結構勉強になった。
次は中間コードではなくパーサーも組み込みたい。