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 方面に戻ります。