第17章 動的評価

概略


evalModule#module_evalObject#instance_eval

eval


eval

eval使
p eval("1 + 1")   # 2

eval
lvar = 5
@ivar = 6
p eval("lvar + @ivar")   # 11

eval


def a
  eval('class C;  def test() puts("ok") end   end')
end

a()          # クラスCとC#testを定義する
C.new.test   # okと表示される

Proc
def new_env
  n = 5
  Proc.new { nil }   # このメソッドの環境をオブジェクトにして返す
end

p eval('n * 3', new_env())   # 15

module_evalinstance_eval


Procevalmodule_eval instance_eval module_eval
lvar = "toplevel lvar"   # スコープ確認用のローカル変数

module M
end
M.module_eval(<<'EOS')   # こういうときこそヒアドキュメント
    p lvar   # 参照できる
    p self   # Mと表示される
    def ok   # M#okを定義する
      puts 'ok'
    end
EOS

instance_evalself
lvar = "toplevel lvar"   # スコープ確認用のローカル変数

obj = Object.new
obj.instance_eval(<<'EOS')
    p lvar   # 参照できる
    p self   # #<Object:0x40274f5c>と表示される
    def ok   # obj.okを定義する
      puts 'ok'
    end
EOS

module_evalinstance_eval使
obj = Object.new
p obj                 # #<Object:0x40274fac>
obj.instance_eval {
    p self            # #<Object:0x40274fac>
}



使使 a binstance_evala abinstance_eval b

eval

eval()


Rubyeval
eval(prog_string, some_block)

rb_f_eval() eval() eval()
static VALUE
eval(VALUE self, VALUE src, VALUE scope, char *file, int line);

scopeProcfilelineeval

eval()
4984  static VALUE
4985  eval(self, src, scope, file, line)
4986      VALUE self, src, scope;
4987      char *file;
4988      int line;
4989  {
4990      struct BLOCK *data = NULL;
4991      volatile VALUE result = Qnil;
4992      struct SCOPE * volatile old_scope;
4993      struct BLOCK * volatile old_block;
4994      struct RVarmap * volatile old_dyna_vars;
4995      VALUE volatile old_cref;
4996      int volatile old_vmode;
4997      volatile VALUE old_wrapper;
4998      struct FRAME frame;
4999      NODE *nodesave = ruby_current_node;
5000      volatile int iter = ruby_frame->iter;
5001      int state;
5002
5003      if (!NIL_P(scope)) {  /* 今は常に真 */
5009          Data_Get_Struct(scope, struct BLOCK, data);
5010          /* dataからBLOCKを積む */
5011          frame = data->frame;
5012          frame.tmp = ruby_frame; /* GCよけ */
5013          ruby_frame = &(frame);
5014          old_scope = ruby_scope;
5015          ruby_scope = data->scope;
5016          old_block = ruby_block;
5017          ruby_block = data->prev;
5018          old_dyna_vars = ruby_dyna_vars;
5019          ruby_dyna_vars = data->dyna_vars;
5020          old_vmode = scope_vmode;
5021          scope_vmode = data->vmode;
5022          old_cref = (VALUE)ruby_cref;
5023          ruby_cref = (NODE*)ruby_frame->cbase;
5024          old_wrapper = ruby_wrapper;
5025          ruby_wrapper = data->wrapper;
5032          self = data->self;
5033          ruby_frame->iter = data->iter;
5034      }
5045      PUSH_CLASS();
5046      ruby_class = ruby_cbase;  /* == ruby_frame->cbase */
5047
5048      ruby_in_eval++;
5049      if (TYPE(ruby_class) == T_ICLASS) {
5050          ruby_class = RBASIC(ruby_class)->klass;
5051      }
5052      PUSH_TAG(PROT_NONE);
5053      if ((state = EXEC_TAG()) == 0) {
5054          NODE *node;
5055
5056          result = ruby_errinfo;
5057          ruby_errinfo = Qnil;
5058          node = compile(src, file, line);
5059          if (ruby_nerrs > 0) {
5060              compile_error(0);
5061          }
5062          if (!NIL_P(result)) ruby_errinfo = result;
5063          result = eval_node(self, node);
5064      }
5065      POP_TAG();
5066      POP_CLASS();
5067      ruby_in_eval--;
5068      if (!NIL_P(scope)) {  /* 今は常に真 */
5069          int dont_recycle = ruby_scope->flags & SCOPE_DONT_RECYCLE;
5070
5071          ruby_wrapper = old_wrapper;
5072          ruby_cref  = (NODE*)old_cref;
5073          ruby_frame = frame.tmp;
5074          ruby_scope = old_scope;
5075          ruby_block = old_block;
5076          ruby_dyna_vars = old_dyna_vars;
5077          data->vmode = scope_vmode; /* 可視性スコープの変更を保存 */
5078          scope_vmode = old_vmode;
5079          if (dont_recycle) {
                  /* ……SCOPE・BLOCK・VARSをコピーする…… */
5097          }
5098      }
5104      if (state) {
5105          if (state == TAG_RAISE) {
                  /* ……例外オブジェクトを準備…… */
5121              rb_exc_raise(ruby_errinfo);
5122          }
5123          JUMP_TAG(state);
5124      }
5125
5126      return result;
5127  }

(eval.c)

eval.c 退


FRAME

ruby_crefruby_frame->cbase

scope_vmodedata


compile()eval_node() eval_node()node ruby_run()使

compile()

compile()
4968  static NODE*
4969  compile(src, file, line)
4970      VALUE src;
4971      char *file;
4972      int line;
4973  {
4974      NODE *node;
4975
4976      ruby_nerrs = 0;
4977      Check_Type(src, T_STRING);
4978      node = rb_compile_string(file, src, line);
4979
4980      if (ruby_nerrs == 0) return node;
4981      return 0;
4982  }

(eval.c)

ruby_nerrsyyerror() rb_compile_string()Ruby

12 lvtbl使 SCOPEVARS eval() parse.y

top_local


struct local_vars使 local_push() local_pop() parse.y top_local_init()top_local_setup()

top_local_init()
program :   { top_local_init(); }
          compstmt
            { top_local_setup(); }



top_local_init()
5273  static void
5274  top_local_init()
5275  {
5276      local_push(1);
5277      lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
5278      if (lvtbl->cnt > 0) {
5279          lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
5280          MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
5281      }
5282      else {
5283          lvtbl->tbl = 0;
5284      }
5285      if (ruby_dyna_vars)
5286          lvtbl->dlev = 1;
5287      else
5288          lvtbl->dlev = 0;
5289  }

(parse.y)

ruby_scopelvtbllocal_tbl top_local_setup()

top_local_setup()
5291  static void
5292  top_local_setup()
5293  {
5294      int len = lvtbl->cnt;  /* パース後のローカル変数の数 */
5295      int i;                 /* パース前のローカル変数の数 */
5296
5297      if (len > 0) {
5298          i = ruby_scope->local_tbl ? ruby_scope->local_tbl[0] : 0;
5299
5300          if (i < len) {
5301              if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
5302                  VALUE *vars = ALLOC_N(VALUE, len+1);
5303                  if (ruby_scope->local_vars) {
5304                      *vars++ = ruby_scope->local_vars[-1];
5305                      MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
5306                      rb_mem_clear(vars+i, len-i);
5307                  }
5308                  else {
5309                      *vars++ = 0;
5310                      rb_mem_clear(vars, len);
5311                  }
5312                  ruby_scope->local_vars = vars;
5313                  ruby_scope->flags |= SCOPE_MALLOC;
5314              }
5315              else {
5316                  VALUE *vars = ruby_scope->local_vars-1;
5317                  REALLOC_N(vars, VALUE, len+1);
5318                  ruby_scope->local_vars = vars+1;
5319                  rb_mem_clear(ruby_scope->local_vars+i, len-i);
5320              }
5321              if (ruby_scope->local_tbl &&
                      ruby_scope->local_vars[-1] == 0) {
5322                  free(ruby_scope->local_tbl);
5323              }
5324              ruby_scope->local_vars[-1] = 0;  /* NODEはもういらない */
5325              ruby_scope->local_tbl = local_tbl();
5326          }
5327      }
5328      local_pop();
5329  }

(parse.y)

local_vars ruby_scopelocal_tbllocal_vars SCOPE_MALLOClocal_varsmalloc() alloca()使malloc()


yycompile()

ruby_dyna_vars退
static NODE*
yycompile(f, line)
{
    struct RVarmap *vars = ruby_dyna_vars;
         :
    n = yyparse();
         :
    ruby_dyna_vars = vars;
}

退ruby_dyna_vars RVarmap

ruby_dyna_vars id=0RVarmap

top_local_init()local_push(1)1 local_push()ruby_dyna_vars 1eval
(dynavars)
1: evalruby_dyna_vars

ruby_dyna_vars

yycompile()ruby_dyna_vars
2386      vp = ruby_dyna_vars;
2387      ruby_dyna_vars = vars;
2388      lex_strterm = 0;
2389      while (vp && vp != vars) {
2390          struct RVarmap *tmp = vp;
2391          vp = vp->next;
2392          rb_gc_force_recycle((VALUE)tmp);
2393      }

(parse.y)

vars

instance_eval


Module#module_evalrb_mod_module_eval() Object#instance_evalrb_obj_instance_eval()

rb_mod_module_eval() rb_obj_instance_eval()
5316  VALUE
5317  rb_mod_module_eval(argc, argv, mod)
5318      int argc;
5319      VALUE *argv;
5320      VALUE mod;
5321  {
5322      return specific_eval(argc, argv, mod, mod);
5323  }

5298  VALUE
5299  rb_obj_instance_eval(argc, argv, self)
5300      int argc;
5301      VALUE *argv;
5302      VALUE self;
5303  {
5304      VALUE klass;
5305
5306      if (rb_special_const_p(self)) {
5307          klass = Qnil;
5308      }
5309      else {
5310          klass = rb_singleton_class(self);
5311      }
5312
5313      return specific_eval(argc, argv, klass, self);
5314  }

(eval.c)

selfclass specific_eval() 2

(speceval)
2: 

instance_evalmodule_eval evalyield exec_under()

 2\times 2=4 


(一)instance_eval

(二)


rb_obj_instance_eval()




specific_eval()instance_evaleval
static VALUE
instance_eval_string(self, src, file, line)
    VALUE self, src;
    const char *file;
    int line;
{
    VALUE sclass;
    VALUE result;
    int state;
    int mode;

    sclass = rb_singleton_class(self);

    PUSH_CLASS();
    ruby_class = sclass;
    PUSH_FRAME();
    ruby_frame->self       = ruby_frame->prev->self;
    ruby_frame->last_func  = ruby_frame->prev->last_func;
    ruby_frame->last_class = ruby_frame->prev->last_class;
    ruby_frame->argc       = ruby_frame->prev->argc;
    ruby_frame->argv       = ruby_frame->prev->argv;
    if (ruby_frame->cbase != sclass) {
        ruby_frame->cbase = rb_node_newnode(NODE_CREF, sclass, 0,
                                            ruby_frame->cbase);
    }
    PUSH_CREF(sclass);

    mode = scope_vmode;
    SCOPE_SET(SCOPE_PUBLIC);
    PUSH_TAG(PROT_NONE);
    if ((state = EXEC_TAG()) == 0) {
        result = eval(self, src, Qnil, file, line);
    }
    POP_TAG();
    SCOPE_SET(mode);

    POP_CREF();
    POP_FRAME();
    POP_CLASS();
    if (state) JUMP_TAG(state);

    return result;
}

CLASSCREFruby_frame->cbase eval() FRAME




specific_eval()Ruby

specific_eval()
5258  static VALUE
5259  specific_eval(argc, argv, klass, self)
5260      int argc;
5261      VALUE *argv;
5262      VALUE klass, self;
5263  {
5264      if (rb_block_given_p()) {

5268          return yield_under(klass, self);
5269      }
5270      else {

5294          return eval_under(klass, self, argv[0], file, line);
5295      }
5296  }

(eval.c)



yield_under()fileline yield

eval_under()eval_under_i()

eval_under()
5222  static VALUE
5223  eval_under(under, self, src, file, line)
5224      VALUE under, self, src;
5225      const char *file;
5226      int line;
5227  {
5228      VALUE args[4];
5229
5230      if (ruby_safe_level >= 4) {
5231          StringValue(src);
5232      }
5233      else {
5234          SafeStringValue(src);
5235      }
5236      args[0] = self;
5237      args[1] = src;
5238      args[2] = (VALUE)file;
5239      args[3] = (VALUE)line;
5240      return exec_under(eval_under_i, under, under, args);
5241  }

5214  static VALUE
5215  eval_under_i(args)
5216      VALUE *args;
5217  {
5218      return eval(args[0], args[1], Qnil, (char*)args[2], (int)args[3]);
5219  }

(eval.c)

args argseval_under()eval_under_i() exec_under()args

fileline

exec_under()under exec_under()under exec_under()CLASSCREF CLASSCREF使
VALUE sclass = .....;
VALUE cbase = sclass;

sclass











ruby


 <aamine@loveruby.net>

Ruby  ()

Copyright (c) 2002-2004 Minero Aoki, All rights reserved.