ref とか

直前エントリで lambda な式を ref に渡しても slot が戻る事を知った。
そりゃそうか、と言いつつ以下。

gosh> (d (lambda (obj selector) (ref obj selector)))
#<closure #f> is an instance of class <procedure>
slots:
  required  : 2
  optional  : #f
  locked    : #f
  info      : #f
  setter    : #f
gosh>

引数二つ。あるいは以下だと

gosh> (d (lambda (obj selector . more) (apply @ (ref obj selector) more)))
#<closure #f> is an instance of class <procedure>
slots:
  required  : 2
  optional  : #t
  locked    : #f
  info      : #f
  setter    : #f
gosh> 

optional が #t になってます。今度は disasm してみる。

gosh> (disasm (lambda () (ref (lambda (obj selector) (ref obj selector)) 'required)))
main_code (name=#f, code=0x80f6de0, size=8, const=3, stack=5):
args: #f
     0 CLOSURE #<lambda 0>      ; (lambda (obj selector) (ref obj selector ...
     2 PUSH 
     3 CONST-PUSH required
     5 GREF-TAIL-CALL(2) #<identifier user#ref>; (ref (lambda (obj selector) (ref obj sel ...
     7 RET 
internal_closure_0 (name=#f, code=0x80d6770, size=4, const=1 stack=5):
args: #f
     0 LREF1-PUSH               ; obj
     1 LREF0-PUSH-GREF-TAIL-CALL(2) #<identifier user#ref>; (ref obj selector)
     3 RET 
#<undef>
gosh>

CLOSURE な instruction にて手続きオブジェクトになっているんでしょうか。

            CASE(SCM_VM_CLOSURE) {
                ScmObj body;
                FETCH_OPERAND(body);
                INCR_PC;

                /* preserve environment */
                VAL0 = Scm_MakeClosure(body, get_env(vm));
                NEXT1;
            }

1 に何があるのか、凄く気になる。compile してみれば良いのか。

gosh> (with-module gauche.internal (compile-p2 (compile-p1 '(lambda (obj selector) (ref obj selector)))))
($lambda[#f;0] (obj[1;0] selector[1;0])
  ($call ($gref ref)
    ($lref obj[1;0])
    ($lref selector[1;0])))
($const #<undef>)
#<undef>
gosh>

うーん ...

gosh> (with-module gauche.internal (compile-p2 (compile-p1 '(ref (lambda (obj selector) (ref obj selector)) 'optional))))
($call ($gref ref)
  ($lambda[#f;0] (obj[1;0] selector[1;0])
    ($call ($gref ref)
      ($lref obj[1;0])
      ($lref selector[1;0])))
  ($const optional))
($const #<undef>)
#<undef>
gosh> 

むむむ。だんだん何がしたいのかワケワカらんぞ。

とりあえず

vm.c な実装を見るに、手続きオブジェクトが生成されるのは compile 時ではなくて VM instruction の評価時?
なんか割り込み多くて gdgd 気味。
とは言え、

gosh> (disasm (lambda () (ref (lambda (obj selector) (ref obj selector)) 'required)))
main_code (name=#f, code=0x80f6de0, size=8, const=3, stack=5):
args: #f
     0 CLOSURE #<lambda 0>      ; (lambda (obj selector) (ref obj selector ...
     2 PUSH 

の 1 なナニがとても気になる。とりあえず gencomp 方面に戻ります。