3imp 読んでみる (5)

送別会は酒が出ず、早々に終了したので帰宅後、作業再開。
recur の define-syntax を検討。まず rec のソレから検証か。ええと

(rec var exp)

(let ([var '()])
  (set! var exp))

と等価とある。例示されている

(rec count
     (lambda (x)
       (if (null? x)
	   0
	   (+ (count (cdr x)) 1))))

(let ([count '()])
  (set! count (lambda (x)
		(if (null? x)
		    0
		    (+ (count (cdr x)) 1)))))

define-syntax 的にはこう書けば良いのでしょうか。

(define-syntax rec
  (syntax-rules ()
    ((_ a b) (let ([a '()])
	       (set! a b)))))

試験。

gosh> (define-syntax rec
  (syntax-rules ()
    ((_ a b) (let ([a '()])
	       (set! a b)))))

#<undef>
gosh> ((rec count (lambda (x) (if (null? x) 0 (+ (count (cdr x)) 1)))) '(1 2 3))
3
gosh> 

次は recur ですが

(recur f ([var init ...) exp ...))

((rec f (lambda (var ...) exp ...))
 init ...)

と等価との事。こうすれば良いのかな

(define-syntax recur
  (syntax-rules ()
    ((_ f ([v i] ...) e ...)
     ((rec f (lambda (v ...) e ...)) 
      i))))

REPL に吸わせてみた。

gosh> (define-syntax recur
  (syntax-rules ()
    ((_ f ([v i] ...) e ...)
     ((rec f (lambda (v ...) e ...))
      i))))

*** ERROR: Compile Error: recur: Pattern variable i is used in wrong level: ((rec f (lambda (v |...|) e |...|)) i)
"(stdin)":10:(define-syntax recur (syntax-rules ( ...

Stack Trace:
_______________________________________
gosh> 

むが。こうか。

(define-syntax recur
  (syntax-rules ()
    ((_ f ([v i] ...) e ...)
     ((rec f (lambda (v ...) e ...)) 
      i ...))))

REPL に吸わせたら

gosh> (define-syntax recur
  (syntax-rules ()
    ((_ f ([v i] ...) e ...)
     ((rec f (lambda (v ...) e ...)) 
      i ...))))

#<undef>
gosh> (recur count ([x '(a b c d e)]) (if (null? x) 0 (+ (count (cdr x)) 1)))
5
gosh> 

ええのかなぁ。とりあえず元に戻ろう。

Assembly Code

そういえば _sets next expression x_ なソレですが x を next expression にセット、という意味で OK かなぁ。VM 見てると record-case というのもあるな。28p に定義が記述されている。

(record-case exp1
   [key vars exp2 ...]
   .
   .
   .
   [else exp3 ...])

(let ([r exp1])
  (cond
   [(eq? (car r) 'key)
    (record vars (cdr r) exp2 ...)]
   .
   .
   .
   [else exp3 ...]))

になるそうな。ちょっとこれ define-syntax 方面に行ってしまうとハマるので別途で。

  • (test then else) : accumulator を test し accumulator が nonnull だったら next expression に then をセット、そうでなければ else を next expression にセット
  • (assign var x) : current environment に束縛されている var に accumulator の値をセットして next expression に x をセット
  • (conti x) : current stack から継続を生成し accumulator に置いて next expression に x をセット。
  • (nuate s var) : s を current stack に、var の値を current environment から探して accumulator に、next expression に (return) をセット
  • (frame x ret) : current environment、current rib と next expression が ret な新しいフレームを生成。このフレームに current stack を追加して current rib は空リストをセットし、next expression を x に。(微妙
  • (argument x) : accumulator の値を current rib に追加して x を next expression にセット (VM のコードを見るに current rib はリストになっている模様
  • (apply) : accumulator にあるクロージャを apply (current rib は引数??) する。ここ、ちょっと長いので VM の定義を見てみると以下
[apply ()
  (record a (body e vars)
    (VM a body (extend e vars r) '() s))]

record の定義は 27p にある。apply しとります。

(redord (var ...) val exp ...)

(apply (lambda (var ...) exp ...) val)

だそうな。サンプルとしては

(lambda (x) (record (a b c) x (list c b a)))

みたいなソレ。こんなカンジが

((lambda (x) (record (a b c) x (list c b a))) '(1 2 3))

こんな感じで評価されるはず

(apply (lambda (a b c) (list c b a)) '(1 2 3))

これは define-syntax なナニは簡単そげな気がしますがスルーで別途。と言いつつ record-case もチェック

(record-case exp1
  [key vars exp2 ...]
  .
  .
  .
  [else exp3 ...])

は以下と等価

(let ([r exp1])
  (cond
   [(eq? (car r) 'key)
    (record vars (cdr r) exp2 ...)]
   .
   .
   .
   [else exp3 ...]))

これはツライ。VM のコードは別途じっくりってコトで元に戻ります。って英語は英語で微妙なんだけどなぁ。