Ruby1.9/$で始まるローカル変数
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#n9c102fb]
Rubyでは$で始まる変数はグローバル変数です。しかし、[[リフ...
:$&|ローカルスコープ
:$SAFE|スレッドローカルスコープ
と書かれています。今回の読解対象はこれがどのようなカラク...
なお、今回対象としたバージョンは
ruby 1.9.0 (2008-06-14 revision 16363)
です。
*グローバル変数の実装 [#gf84ef59]
グローバル変数実装の概要は[[RHG>http://i.loveruby.net/ja/...
-グローバル変数にはglobal_variable構造体が対応している
-グローバル変数が参照されるときはglobal_variable構造体のg...
ということになります。
Rubyではこの仕組みを利用して実体のないグローバル変数を定...
ruby.c
ruby_prog_init(void)
{
rb_define_virtual_variable("$-W", opt_W_getter, 0);
opt_W_getter(VALUE val, ID id)
{
if (ruby_verbose == Qnil)
return INT2FIX(0);
if (ruby_verbose == Qfalse)
return INT2FIX(1);
if (ruby_verbose == Qtrue)
return INT2FIX(2);
return Qnil; /* not reached */
}
というようなことが可能です。((書いた数日後に$-Wはvirtual ...
青木さんはグローバル変数のところを投げ遣り度85%で進行して...
*$で始まるスレッドローカル変数 [#aba710b2]
スレッドローカルなグローバル変数の例として$SAFEを見てみま...
eval.c
Init_eval(void)
{
rb_define_virtual_variable("$SAFE", safe_getter, saf...
eval_safe.c
safe_getter(void)
{
return INT2NUM(rb_safe_level());
}
rb_safe_level(void)
{
return GET_THREAD()->safe_level;
}
というわけでgetterの関数が呼ばれた場合、現在実行している...
余談ですがスレッド構造体なんてなかったRuby1.8まではsafe_l...
*$で始まるローカル変数 [#ned85b09]
ローカル変数の方はもう少し複雑です。例として$&を使います。
re.c
Init_Regexp(void)
{
rb_define_virtual_variable("$&", last_match_getter, ...
last_match_getter(void)
{
return rb_reg_last_match(rb_backref_get());
}
vm.c
rb_backref_get(void)
{
return vm_svar_get(1);
}
svarという単語が出てきました。svar用の領域はスレッドスタ...
|Qnil # for n
|Qnil # for pi
|Qnil # for svar
dfp,lfp→|GC_GUARDED_PTR(0)
では先に進みます。
vm.c
vm_svar_get(VALUE key)
{
rb_thread_t *th = GET_THREAD();
return vm_cfp_svar_get(th, th->cfp, key);
}
vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp...
{
cfp = vm_normal_frame(th, cfp);
return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
}
vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
{
while (cfp->pc == 0) {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, c...
return 0;
}
}
return cfp;
}
vm_insnhelper.c
lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
{
NODE *svar = lfp_svar_place(th, lfp);
switch (key) {
case 0:
return svar->u1.value;
case 1:
return svar->u2.value;
default: {
const VALUE hash = svar->u3.value;
if (hash == Qnil) {
return Qnil;
}
else {
return rb_hash_lookup(hash, key);
}
}
}
}
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
{
VALUE *svar;
if (lfp && th->local_lfp != lfp) {
svar = &lfp[-1];
}
else {
svar = &th->local_svar;
}
if (NIL_P(*svar)) {
*svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
}
return (NODE *)*svar;
}
場合分けされてますが先ほどのsvar用に確保された領域を使う...
とこんな感じなのですが実は$&参照時には上記のパスは通りま...
insns.def
DEFINE_INSN
getspecial
(VALUE key, rb_num_t type)
()
(VALUE val)
{
val = vm_getspecial(th, GET_LFP(), key, type);
}
vm_insnhelper.c
vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb...
{
VALUE val;
if (type == 0) {
VALUE k = key;
if (FIXNUM_P(key)) {
k = FIX2INT(key);
}
val = lfp_svar_get(th, lfp, k);
}
else {
VALUE backref = lfp_svar_get(th, lfp, 1);
と、lfp_svar_get関数まで処理がバイパスされています。
*おわりに [#p1510ac1]
今回はグローバル変数に見えるローカル変数の実装を見てきま...
-グローバル変数はgetterを呼び出して値を取得するいう仕組み...
-ローカル変数領域に特殊変数領域がありそこに格納されている
それではみなさんもよいコードリーディングを。
終了行:
#contents
*はじめに [#n9c102fb]
Rubyでは$で始まる変数はグローバル変数です。しかし、[[リフ...
:$&|ローカルスコープ
:$SAFE|スレッドローカルスコープ
と書かれています。今回の読解対象はこれがどのようなカラク...
なお、今回対象としたバージョンは
ruby 1.9.0 (2008-06-14 revision 16363)
です。
*グローバル変数の実装 [#gf84ef59]
グローバル変数実装の概要は[[RHG>http://i.loveruby.net/ja/...
-グローバル変数にはglobal_variable構造体が対応している
-グローバル変数が参照されるときはglobal_variable構造体のg...
ということになります。
Rubyではこの仕組みを利用して実体のないグローバル変数を定...
ruby.c
ruby_prog_init(void)
{
rb_define_virtual_variable("$-W", opt_W_getter, 0);
opt_W_getter(VALUE val, ID id)
{
if (ruby_verbose == Qnil)
return INT2FIX(0);
if (ruby_verbose == Qfalse)
return INT2FIX(1);
if (ruby_verbose == Qtrue)
return INT2FIX(2);
return Qnil; /* not reached */
}
というようなことが可能です。((書いた数日後に$-Wはvirtual ...
青木さんはグローバル変数のところを投げ遣り度85%で進行して...
*$で始まるスレッドローカル変数 [#aba710b2]
スレッドローカルなグローバル変数の例として$SAFEを見てみま...
eval.c
Init_eval(void)
{
rb_define_virtual_variable("$SAFE", safe_getter, saf...
eval_safe.c
safe_getter(void)
{
return INT2NUM(rb_safe_level());
}
rb_safe_level(void)
{
return GET_THREAD()->safe_level;
}
というわけでgetterの関数が呼ばれた場合、現在実行している...
余談ですがスレッド構造体なんてなかったRuby1.8まではsafe_l...
*$で始まるローカル変数 [#ned85b09]
ローカル変数の方はもう少し複雑です。例として$&を使います。
re.c
Init_Regexp(void)
{
rb_define_virtual_variable("$&", last_match_getter, ...
last_match_getter(void)
{
return rb_reg_last_match(rb_backref_get());
}
vm.c
rb_backref_get(void)
{
return vm_svar_get(1);
}
svarという単語が出てきました。svar用の領域はスレッドスタ...
|Qnil # for n
|Qnil # for pi
|Qnil # for svar
dfp,lfp→|GC_GUARDED_PTR(0)
では先に進みます。
vm.c
vm_svar_get(VALUE key)
{
rb_thread_t *th = GET_THREAD();
return vm_cfp_svar_get(th, th->cfp, key);
}
vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp...
{
cfp = vm_normal_frame(th, cfp);
return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
}
vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
{
while (cfp->pc == 0) {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, c...
return 0;
}
}
return cfp;
}
vm_insnhelper.c
lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
{
NODE *svar = lfp_svar_place(th, lfp);
switch (key) {
case 0:
return svar->u1.value;
case 1:
return svar->u2.value;
default: {
const VALUE hash = svar->u3.value;
if (hash == Qnil) {
return Qnil;
}
else {
return rb_hash_lookup(hash, key);
}
}
}
}
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
{
VALUE *svar;
if (lfp && th->local_lfp != lfp) {
svar = &lfp[-1];
}
else {
svar = &th->local_svar;
}
if (NIL_P(*svar)) {
*svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
}
return (NODE *)*svar;
}
場合分けされてますが先ほどのsvar用に確保された領域を使う...
とこんな感じなのですが実は$&参照時には上記のパスは通りま...
insns.def
DEFINE_INSN
getspecial
(VALUE key, rb_num_t type)
()
(VALUE val)
{
val = vm_getspecial(th, GET_LFP(), key, type);
}
vm_insnhelper.c
vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb...
{
VALUE val;
if (type == 0) {
VALUE k = key;
if (FIXNUM_P(key)) {
k = FIX2INT(key);
}
val = lfp_svar_get(th, lfp, k);
}
else {
VALUE backref = lfp_svar_get(th, lfp, 1);
と、lfp_svar_get関数まで処理がバイパスされています。
*おわりに [#p1510ac1]
今回はグローバル変数に見えるローカル変数の実装を見てきま...
-グローバル変数はgetterを呼び出して値を取得するいう仕組み...
-ローカル変数領域に特殊変数領域がありそこに格納されている
それではみなさんもよいコードリーディングを。
ページ名: