概要
引数
- CODE 処理を待っているgrassのコード
- ENV 現時点の環境リスト 値のスタック
- DUMP 現時点の中断して再開を待っている計算 リターン先を覚えておくスタック
実装
(defun grass-eval-machine (code env dump)
(cond
((eq (caar code) 'app)
- CODEの先頭要素の1番目の要素が 'app 関数適用だったら
- 以下ルールを適用する
- (App(m, n) :: C, E, D) → (Cm, (Cn, En) :: Em, (C, E) :: D) where E = (C1, E1) :: (C2, E2) :: … :: (Ci, Ei) :: E' (i = m, n)
(let ((m (cadr (car code)))
(n (nth 2 (car code)))
(c (cdr code)))
- App(m, n) :: C
- 適用する関数の "関数定義の位置を示す部分" を ローカル変数 m に束縛
- 適用する関数の "引数の位置を示す部分" を ローカル変数 n に束縛
- CODEの2番目以降を ローカル変数 c に束縛
(if (grass-primitive-p (nth (1- m) env))
;; Em is a primitive
(list c
(cons (funcall
(grass-primitive-func (nth (1- m) env)) (nth (1- n) env))
env)
dump)
;; Em is a list
(list (car (nth (1- m) env))
(cons (nth (1- n) env) (cdr (nth (1- m) env)))
(cons (cons c env) dump)))))
- 適用する関数が primitive関数 ではない場合
- (
- 環境ENVの m 番目の要素の "関数定義の位置を示す部分"
- ( 環境ENVの n 番目の要素 . 環境ENVの m 番目の "引数の位置を示す部分" )
- ( CODEリストの2番目以降 . 環境ENV )
- ) というリストを作る(戻り値になる)
((eq (caar code) 'abs)
- 先頭のリストの1番目の要素が 'abs 関数定義だったら
(let ((n (cadr (car code)))
(cc (nth 2 (car code)))
(c (cdr code)))
- 関数定義の "引数" を ローカル変数 n に束縛
- 関数定義の "本体" を ローカル変数 cc に束縛
- CODEの2番目以降を ローカル変数 c に束縛
(if (eq n 1)
- 引数 n が 1 だったら
- 以下ルールを適用する
- (Abs(n, C') :: C, E, D) → (C, (C', E) :: E, D) if n = 1
(list c
(cons (cons cc env) env)
dump)
- (
- CODEの2番目以降
- ( ( 関数本体 cc . 環境ENV) . 環境ENV)
- 実行待ちDUMP
- ) というリストを作る(戻り値になる)
- 引数 n が 1 より大きかったら
- 以下ルールを適用する
- (Abs(n, C') :: C, E, D) → (C, (Abs(n - 1, C')::・, E) :: E, D) if n > 1
(list c
(cons (cons (list (list 'abs (1- n) cc)) env) env)
dump))))
- (
- CODEの2番目以降
- ((( 'abs "引数 n - 1" "関数本体 cc" ) . 環境ENV) . 環境ENV)
- 実行待ちDUMP
- ) というリストを作る(戻り値になる)
((null code)
;; (・, f :: E, (C', E') :: D) → (C', f :: E', D)
(and dump
(list (caar dump)
(cons (car env) (cdar dump))
(cdr dump))))
- (
- 実行待ちの計算DUMPの先頭リストの先頭要素
- ( 環境の先頭要素 . 実行待ちDUMPの先頭要素の第二要素 )
- 実行待ちDUMPの第2要素
- ) とういうリストを作る(戻り値になる)
(t
(error "grass-eval: runtime error"))))
呼出元
履歴
コメント
最終更新:2009年01月16日 07:59