複数call/ccに対応
GitHub - sodeyama/slisp: lisp interpreter
sLispの以下の点を改善しました。
- コメントを可能にしました
- call/ccで生成するラムダ式で使う変数名をgensymで作るようにしました(変数名の衝突を防ぐ目的)
- call/ccを複数書けるようにしました。(ただし、トップレベルの各S式中に1つのみ)
- slisp-mode(emacsメジャーモード)。ファイル開いてC-c nで評価
各々の対応するコードは以下
コメント
(defun slisp-get-src-string (filename) (let ((pre-buffer (current-buffer)) (ret "")) (find-file filename) (setq str (buffer-substring-no-properties (point-min) (point-max))) (let ((lines (split-string str "\n"))) (dolist (line lines) (if (not (string-match "^;" line)) (setq ret (concat ret line))))) (switch-to-buffer pre-buffer) ret))
ファイルを開いたバッファからslisp-get-tokensに渡す文字列を生成する段階でコメント行を排除。
call/ccで生成するラムダ式で使う変数名をgensymで生成
(defmacro with-gensyms (syms &rest body) (declare (indent 1)) `(let ,(mapcar (lambda (sym) `(,sym (gensym))) syms) ,@body))
Common Lispでよく使われるwith-gensymsをelispのmacroで再現してます。
(with-gensyms (a b c) body)
のようなコードは
(let ((a (gensym)) (b (gensym)) (c (gensym))) body)
に展開されます。gensymは一意なシンボルを生成するelispのmacro。
call/ccを複数書けるように
(defun slisp-callcc-parse (exp env) (dolist (seed (cdr exp)) (with-gensyms (variable) (let* ((ret (slisp-callcc-getcc seed variable env)) (find (slisp-get-findcallcc ret)) (cc (slisp-get-callcc ret))) (if find (progn (let ((sexp (list "lambda" (list variable) (list "throw" cc)))) (slisp-callcc-fifo-set sexp))))))))
slisp-callcc-fifoをcall/ccで生成された継続を保存するfifoデータとしslisp-callcc-fifo-set, slisp-callcc-fifo-getでセット、ゲットしただけ。