Chapter 15: Method

Blue Chapter -- Machine Translation

In this chapter we will talk about methods and start exploring.

search method

term

This chapter is a method call and talk to both the method of defining one's relationships, Such a variety of "argument" will come out. So, so ambiguously Term to decide exactly where it can get to it.

 
m (a) # a "typical argument" 
m (* list) # list is "an array of arguments" 
m (& block) # block the "block argument" 

def m (a) # a "normal parameters" 
def m (a = nil) # a "parameter options", nil, "the default value" 
def m (* rest) # rest is "rest parameters" 
def m (& block) # block the "block parameters" 

YOUSURUNI to pass all the "arguments", it will receive all the "parameters" Each type of adjectives one, they say.

However, I just mentioned. "Block argument" and "block parameters" Next, in the case of the block will be dealing with.

survey

▼ source program

 
obj.method (7,8) 

▼ corresponding syntax tree

 
NODE_CALL 
nd_mid = 9049 (method) 
nd_recv: 
     NODE_VCALL 
     nd_mid = 9617 (obj) 
nd_args: 
     NODE_ARRAY [ 
     0: 
         NODE_LIT 
         nd_lit = 7: Fixnum 
     1: 
         NODE_LIT 
         nd_lit = 8: Fixnum 
     ] 

Node is a method call NODE_CALL . nd_args in NODE_ARRAY is a list of arguments that are stored.

In addition to this method is called as a node NODE_FCALL and NODE_VCALL Correction UNO. NODE_FCALL is " method (args) " format, NODE_VCALL is local The same variables " method " in the form of response to the call. It is not really FCALL and VCALL is one that can be put together, VCALL when the argument to prepare No need for a code that the memory and only in order to save time That distinction.

, rb_eval () , NODE_CALL handlers to look at.

rb_eval () - NODE_CALL

 
2745 case NODE_CALL: 
(2746 
2747 VALUE recv; 
2748 int argc; VALUE * argv; / * used in SETUP_ARGS * / 
2749 TMP_PROTECT; 
2750 
2751 BEGIN_CALLARGS; 
2752 recv = rb_eval (self, node-> nd_recv); 
2753 SETUP_ARGS (node-> nd_args); 
2754 END_CALLARGS; 
2755 
2756 SET_CURRENT_SOURCE (); 
2757 result = rb_call (CLASS_OF (recv), recv, node-> nd_mid, argc, argv, 0); 
2758) 
2759 break; 

(eval.c) 

There are three macro issues, BEGIN_CALLARGS SETUP_ARGS () END_CALLARGS . rb_eval () receiver evaluation rb_call () 起動らしいhad a method, the three Macro assessment of the argument that it's tough, and you can imagine the sort of Is actually what you are doing? BEGIN_CALLARGS and END_CALLARGS is Iterator to talk to them and not hard to understand, the next chapter in the block, Once explained. This is SETUP_ARGS () with the investigation only.

SETUP_ARGS ()

SETUP_ARGS () is a method to assess the macro part of the argument. This macro , The original program as the comments, argc and argv a variable So it must be defined in advance. Also TMP_ALLOC () since they use TMP_PROTECT should have been using. So the following is formulaic.

 
int argc; VALUE * argv; / * used in SETUP_ARGS * / 
TMP_PROTECT; 

SETUP_ARGS (args_node); 

args_node is the method of argument (to represent node), which evaluated The array of different values, argv stored. Let's not look at.

SETUP_ARGS ()

 
1780 # define SETUP_ARGS (anode) do (\ 
1781 NODE * n = anode; \ 
1782 if (! N) (\ no argument 
1783 argc = 0; \ 
1784 argv = 0; \ 
1785) \ 
1786 else if (nd_type (n) == NODE_ARRAY) (\ usually only argument 
1787 argc = n-> nd_alen; \ 
1788 if (argc> 0) (\ arguments in 
1789 int i; \ 
1790 n = anode; \ 
1791 argv = TMP_ALLOC (argc); \ 
1792 for (i = 0; i  nd_head); \ 
1794 n = n-> nd_next; \ 
1795) \ 
1796) \ 
1797 else (\ no argument 
1798 argc = 0; \ 
1799 argv = 0; \ 
1800) \ 
1801) \ 
1802 else (\ array of arguments and 
1803 VALUE args = rb_eval (self, n); \ argument for the block 
1804 if (TYPE (args)! = T_ARRAY) \ 
1805 args = rb_ary_to_ary (args); \ 
1806 argc = RARRAY (args) -> len; \ 
1807 argv = ALLOCA_N (VALUE, argc); \ 
1808 MEMCPY (argv, RARRAY (args) -> ptr, VALUE, argc); \ 
1809) \ 
1810) while (0) 

(eval.c) 

Rather lengthy, and three branches to the sea because TAISHITE actually does harm. Each branch is the meaning of the comments earlier in the street.

None of the arguments does not matter as the rest of the two branches have a similar thing Do you have. I can roughly say that the three phases,

  1. argument into space
  2. formula to evaluate the argument
  3. value to the variable region copy

. I try writing the code. (Incidentally format and a little earlier).

 
/***** Else if clause, argc! = 0 *****/ 
int i; 
n = anode; 
argv = TMP_ALLOC (argc); / * 1 * / 
for (i = 0; i  nd_head); / * 2,3 * / 
     n = n-> nd_next; 
) 

/***** Else clause *****/ 
VALUE args = rb_eval (self, n); / * 2 * / 
if (TYPE (args)! = T_ARRAY) 
     args = rb_ary_to_ary (args); 
argc = RARRAY (args) -> len; 
argv = ALLOCA_N (VALUE, argc); / * 1 * / 
MEMCPY (argv, RARRAY (args) -> ptr, VALUE, argc); / * 3 * / 

else if side, it is TMP_ALLOC () , but with else side, ALLOCA_N () , that is normal alloca () Why are you using? C_ALLOCA environment is alloca () is malloc () equal to it, is dangerous and No?

This is " else side of the argument value is args it is," It is Points. If the figure as shown in Figure 1.

(anchor)
Figure 1: Even if you do not heap

It is also one of VALUE on the stack if there through the chain marked. Such VALUE other VALUE stack to stop the Spanish beard anchor (anchor) like Role, namely "anchor VALUE " said. else side, it is args to anchor VALUE .

Incidentally anchor VALUE is not a term coined made.

rb_call ()

SETUP_ARGS () If anything is wrong way. From here you can go back to the main topic. Method To start the function rb_call () . If you are a real exception to the above見付からなかった You look at the code, but omit all by example.

rb_call () (condensed version)

 
static VALUE 
rb_call (klass, recv, mid, argc, argv, scope) 
     VALUE klass, recv; 
     ID mid; 
     int argc; 
     const VALUE * argv; 
     int scope; 
( 
     NODE * body; 
     int noex; 
     ID id = mid; 
     struct cache_entry * ent; 

     / * * Method cache / 
     ent = cache + EXPR1 (klass, mid); 
     if (ent-> mid == mid & & ent-> klass == klass) ( 
         / * * Cache hit / 
         klass = ent-> origin; 
         id = ent-> mid0; 
         noex = ent-> noex; 
         body = ent-> method; 
     ) 
     else ( 
         / * Miss cache. Execute search * / 
         body = rb_get_method_body (& klass, & id, & noex); 
     ) 

     / *…… Check the visibility…… * / 

     return rb_call0 (klass, recv, mid, id, 
                     argc, argv, body, noex & NOEX_UNDEF); 
) 

The basic method is exploring how the object, in Chapter 2. Super TADORI class while m_tbl You can search. Is to do it search_method () .

That's right, the principle is, however, but to actually run the stage and method calls How many times each time searching for the hash to pull his speed is too late. To break Good for ruby , once called the method is similar to the cache . The method is called just once, and we can often invoked, that Experience on the facts as known, and the cache hit rate is high.

The cache, which is索い rb_call () the first half. This

 
ent = cache + EXPR1 (klass, mid); 

Only one line has been cached. The mechanism is more to look after.

When the cache is out of the next rb_get_method_body () class tree in an honest way Search the results of the cache TSUIDENI keep it that. Search the entire flow chart should look like Figure 2.

(msearch)
Figure 2: The search method

method cache

Then method of cash, let's take a closer look at the structure.

▼ method cache

 
  180 # define CACHE_SIZE 0x800 
  181 # define CACHE_MASK 0x7ff 
  182 # define EXPR1 (c, m) ((((c)>> 3) ^ (m)) & CACHE_MASK) 
  183 
  184 struct cache_entry (/ * method hash table. * / 
  185 ID mid; / * method's id * / 
  186 ID mid0; / * method's original id * / 
  187 VALUE klass; / * receiver's class * / 
  188 VALUE origin; / * where method defined * / 
  189 NODE * method; 
  190 int noex; 
  191); 
  192 
  193 static struct cache_entry cache [CACHE_SIZE]; 

(eval.c) 

In a nutshell mechanisms to hash tables. And the principle of the hash table YOUSURUNI table an array of search indexing convert it. Resona The time required to be at least three. An array of data, key, and hash Function.

This is the first array is struct cache_entry array. Kula and methods Su and uniquely determined by the method name only from the two key calculation of the hash Be. After the cache from an array of key index ( 0x000 in 0x7ff ) live Sung to make a hash function. That's EXPR1 () . Arguments c of the class Projects in, m is the method name ( ID ) (see Figure 3).

(mhash)
Figure 3: Cash method

However EXPR1 () hash function is completely different because of what method is really a coincidence To generate the same index that can result possible. However, this is just an interesting SHU collision because it is not the problem. But work is only a little slower.

method cache effect

By the way, the method is actually how much cash is the effect? "…… It is known that" they are also unconvinced. Measuring your own.

types program hit rate
LALR (1) generated parser racc ruby.y 99.9%
generated MERUSUREDDO certain mailers 99.1%
document generation rd2html rubyrefm.rd 97.8%

What the experiment in all three cases hit a record rate of 95% or more. This is Great. Apparently, "…… it is known that" the effect of Outstanding.

start

rb_call0 ()

Now the method for many reasons, but where to start with Tasoritsuku this rb_call0 () is And big. It is more than 200 lines on the page will be five or six pages? Anyway, the viewer, at once lay out the paper and it would be disastrous split in detail While we go to it. From the first snap.

rb_call0 () (primary)

 
4482 static VALUE 
4483 rb_call0 (klass, recv, id, oid, argc, argv, body, nosuper) 
4484 VALUE klass, recv; 
4485 ID id; 
4486 ID oid; 
4487 int argc; / * OK * / 
4488 VALUE * argv; / * OK * / 
4489 NODE * body; / * OK * / 
4490 int nosuper; 
(4491 
4492 NODE * b2; / * OK * / 
4493 volatile VALUE result = Qnil; 
4494 int itr; 
4495 static int tick; 
4496 TMP_PROTECT; 
4497 
4498 switch (ruby_iter-> iter) ( 
4499 case ITER_PRE: 
4500 itr = ITER_CUR; 
4501 break; 
4502 case ITER_CUR: 
4503 default: 
4504 itr = ITER_NOT; 
4505 break; 
4506) 
4507 
4508 if ((+ + tick & 0xff) == 0) ( 
4509 CHECK_INTS; / * better than nothing * / 
4510 stack_check (); 
4511) 
4512 PUSH_ITER (itr); 
4513 PUSH_FRAME (); 
4514 
4515 ruby_frame-> last_func = id; 
4516 ruby_frame-> orig_func = oid; 
4517 ruby_frame-> last_class = nosuper? 0: klass; 
4518 ruby_frame-> self = recv; 
4519 ruby_frame-> argc = argc; 
4520 ruby_frame-> argv = argv; 
4521 
4522 switch (nd_type (body)) ( 
               / *…… This treatment…… * / 
4698 
4699 default: 
4700 rb_bug ( "unknown node type% d", nd_type (body)); 
4701 break; 
4702) 
4703 POP_FRAME (); 
4704 POP_ITER (); 
4705 return result; 
4706) 

(eval.c) 

First ITER putting in iterator whether this method is ultimately determined. Resona After PUSH_FRAME () , whose value is immediately used to PUSH_ITER () in front of the But you have to. PUSH_FRAME () on the heels of.

And at "…… this treatment……" and I talk about here is Following each node is divided into different startup process.

NODE_CFUNC C defined by the method
NODE_IVAR attr_reader
NODE_ATTRSET attr_writer
NODE_SUPER super
NODE_ZSUPER no arguments super
NODE_DMETHOD UnboundMethod start
NODE_BMETHOD Method start
NODE_SCOPE Ruby method defined by

This document will not have to explain, but none is so important with scant disregard them . It is important NODE_CFUNC and NODE_SCOPE , and NODE_ZSUPER only.

PUSH_FRAME ()

PUSH_FRAME () POP_FRAME ()

 
  536 # define PUSH_FRAME () do (\ 
  537 struct FRAME _frame; \ 
  538 _frame.prev = ruby_frame; \ 
  539 _frame.tmp = 0; \ 
  540 _frame.node = ruby_current_node; \ 
  541 _frame.iter = ruby_iter-> iter; \ 
  542 _frame.cbase = ruby_frame-> cbase; \ 
  543 _frame.argc = 0; \ 
  544 _frame.argv = 0; \ 
  545 _frame.flags = FRAME_ALLOCA; \ 
  546 ruby_frame = & _frame 

  548 # define POP_FRAME () \ 
  549 ruby_current_node = _frame.node; \ 
  550 ruby_frame = _frame.prev; \ 
  551) while (0) 

(eval.c) 

First FRAME solid place to ensure that the stack you want to see. This is module_setup () same. The rest is basically normal and only initialization.

If you add one thing, FRAME_ALLOCA Flags FRAME of It shows how the assignment, much? FRAME_ALLOCA and Of course, "on a stack" shows.

rb_call0 () - NODE_CFUNC

Here's a look at the real number is a lot of writing, but most of trace_func substantive relationship because it is the end of the line.

rb_call0 () - NODE_CFUNC (condensed version)

 
case NODE_CFUNC: 
   result = call_cfunc (body-> nd_cfnc, recv, len, argc, argv); 
   break; 

, call_cfunc () is said……

call_cfunc () (condensed version)

 
4394 static VALUE 
4395 call_cfunc (func, recv, len, argc, argv) 
4396 VALUE (* func) (); 
4397 VALUE recv; 
4398 int len, argc; 
4399 VALUE * argv; 
(4400 
4401 if (len> = 0 & & argc! = Len) ( 
4402 rb_raise (rb_eArgError, "wrong number of arguments (% d for% d)", 
4403 argc, len); 
4404) 
4405 
4406 switch (len) ( 
4407 case -2: 
4408 return (* func) (recv, rb_ary_new4 (argc, argv)); 
4409 break; 
4410 case -1: 
4411 return (* func) (argc, argv, recv); 
4412 break; 
4413 case 0: 
4414 return (* func) (recv); 
4415 break; 
4416 case 1: 
4417 return (* func) (recv, argv [0]); 
4418 break; 
4419 case 2: 
4420 return (* func) (recv, argv [0], argv [1]); 
4421 break; 
                 : 
                 : 
4475 default: 
4476 rb_raise (rb_eArgError, "too many arguments (% d)", len); 
4477 break; 
4478) 
4479 return Qnil; / * not reached * / 
4480) 

(eval.c) 

Thus, the argument based on the number of branches. By the way, the argument that the maximum number is 15.

One of them is aware, NODE_CFUNC when the SCOPE and VARS not on board . The method is C If it is defined in Ruby, so do not use local variables There is good reason to put it. But at the same time C from the "current" local variables To access the previous one and FRAME local variables that will see it Mean that. And it actually doing both. For example rb_svar ( eval.c ).

rb_call0 () - NODE_SCOPE

NODE_SCOPE Ruby That is defined by the start of the method. The underlying part of Ruby.

rb_call0 () - NODE_SCOPE (primary)

 
4568 case NODE_SCOPE: 
(4558 
4570 int state; 
4571 VALUE * local_vars; / * OK * / 
4572 NODE * saved_cref = 0; 
4573 
4574 PUSH_SCOPE (); 
4575 
             / * (A) CREF transfer * / 
4576 if (body-> nd_rval) ( 
4577 saved_cref = ruby_cref; 
4578 ruby_cref = (NODE *) body-> nd_rval; 
4579 ruby_frame-> cbase = body-> nd_rval; 
4580) 
             / * (B) ruby_scope-> local_vars initialization * / 
4581 if (body-> nd_tbl) ( 
4582 local_vars = TMP_ALLOC (body-> nd_tbl [0] +1); 
4583 * local_vars + + = (VALUE) body; 
4584 rb_mem_clear (local_vars, body-> nd_tbl [0]); 
4585 ruby_scope-> local_tbl = body-> nd_tbl; 
4586 ruby_scope-> local_vars = local_vars; 
4587) 
4588 else ( 
4589 local_vars = ruby_scope-> local_vars = 0; 
4590 ruby_scope-> local_tbl = 0; 
4591) 
4592 b2 = body = body-> nd_next; 
4593 
4594 PUSH_VARS (); 
4595 PUSH_TAG (PROT_FUNC); 
4596 
4597 if ((state = EXEC_TAG ()) == 0) ( 
4598 NODE * node = 0; 
4599 int i; 

                 / *…… (C) local variable arguments…… * / 

4666 if (trace_func) ( 
4667 call_trace_func ( "call", b2, recv, id, klass); 
4668) 
4669 ruby_last_node = b2; 
                 / * (D) method bodies * / 
4670 result = rb_eval (recv, body); 
4671) 
4672 else if (state == TAG_RETURN) (/ * return to return * / 
4673 result = prot_tag-> retval; 
4674 state = 0; 
4675) 
4676 POP_TAG (); 
4677 POP_VARS (); 
4678 POP_SCOPE (); 
4679 ruby_cref = saved_cref; 
4680 if (trace_func) ( 
4681 call_trace_func ( "return", ruby_last_node, recv, id, klass); 
4682) 
4683 switch (state) ( 
4684 case 0: 
4685 break; 
4686 
4687 case TAG_RETRY: 
4688 if (rb_block_given_p ()) ( 
4689 JUMP_TAG (state); 
4690) 
4691 / * fall through * / 
4692 default: 
4693 jump_tag_but_local_jump (state); 
4694 break; 
4695) 
4696) 
4697 break; 

(eval.c) 

(A) Back at the constant talk CREF transmission. That is the method of entry FRAME in cbase transplant.

(B) is here module_setup () , did exactly the same. SCOPE - local_vars array assigned to it. In PUSH_SCOPE () , PUSH_VARS () generated in the scope of local variables is complete. This is after Exactly the same methods and internal environment rb_eval () can be.

(C) received a method's arguments set the parameters variable. YOUSURUNI local variables and parameters of the same variable. Argument The number of NODE_ARGS specified in the same honest way I set SHITEYARE. Further explanation of this immediately. And,

(D) method to run the body. Naturally receiver ( recv ) to self said. In other words rb_eval () the first argument. This method is fully launched.

arguments set

SUTTOBA part of the argument, set a detailed look at the The method of construction before the first trees to see me again.

 
% Ruby-rnodedump-e 'def m (a) nil end' 
NODE_SCOPE 
nd_rval = (null) 
nd_tbl = 3 [_ ~ a] 
nd_next: 
     NODE_BLOCK 
     nd_head: 
         NODE_ARGS 
         nd_cnt = 1 
         nd_rest = -1 
         nd_opt = (null) 
     nd_next: 
         NODE_BLOCK 
         nd_head: 
             NODE_NEWLINE 
             nd_file = "-e" 
             nd_nth = 1 
             nd_next: 
                 NODE_NIL 
         nd_next = (null) 

NODE_ARGS method is to specify the parameters of nodes. まくっtried to dump some of its members are as follows: Being used.

nd_cnt usual number of parameters.
nd_rest rest variable parameters ID . rest parameters unless -1 .
nd_opt default option syntax tree to represent the value in it. NODE_BLOCK list.

With so much information you need to respond to each parameter variable ID is unique to the local variables Determined. First one is always 0 $_ and $~. The next two from the normal parameters The number of line up. The parameters are lining up to the next option. PERTH options The number of parameter NODE_BLOCK can see in length. The parameters of the rest came after Be.

For example, following the definition,

 
def m (a, b, c = nil, * rest) 
   lvar1 = nil 
end 

Local variables are as follows ID allocated.

 
0 1 2 3 4 5 6 
$ _ $ ~ A b c rest lvar1 

I? Based on this, a look at the code.

rb_call0 () - NODE_SCOPE - assignment argument

 
4601 if (nd_type (body) == NODE_ARGS) (/ * * No body / 
4602 node = body; / * NODE_ARGS * / 
4603 body = 0; / * * method bodies / 
4604) 
4605 else if (nd_type (body) == NODE_BLOCK) (/ * body * / 
4606 node = body-> nd_head; / * NODE_ARGS * / 
4607 body = body-> nd_next; / * * method bodies / 
4608) 
4609 if (node) (/ * * some parameters / 
4610 if (nd_type (node)! = NODE_ARGS) ( 
4611 rb_bug ( "no argument-node"); 
4612) 
4613 
4614 i = node-> nd_cnt; 
4615 if (i> argc) ( 
4616 rb_raise (rb_eArgError, "wrong number of arguments (% d for% d)", 
4617 argc, i); 
4618) 
4619 if (node-> nd_rest == -1) (/ * rest parameters * / 
               / * * Count the number of parameters / 
4620 int opt = i; / * number of parameters (i is nd_cnt) * / 
4621 NODE * optnode = node-> nd_opt; 
4622 
4623 while (optnode) ( 
4624 opt + +; 
4625 optnode = optnode-> nd_next; 
4626) 
4627 if (opt  argc = opt; 
4632 ruby_frame-> argv = local_vars +2; 
4633) 
4634 
4635 if (local_vars) (/ * * parameters / 
4636 if (i> 0) (/ * * normal parameters / 
4637 / __ * $ $ to the region in order to dodge +2 * / 
4638 MEMCPY (local_vars +2, argv, VALUE, i); 
4639) 
4640 argv + = i; argc -= i; 
4641 if (node-> nd_opt) (/ * * options parameters / 
4642 NODE * opt = node-> nd_opt; 
4643 
4644 while (opt & & argc) ( 
4645 assign (recv, opt-> nd_head, * argv, 1); 
4646 argv + +; argc -; 
4647 opt = opt-> nd_next; 
4648) 
4649 if (opt) ( 
4650 rb_eval (recv, opt); 
4651) 
4652) 
4653 local_vars = ruby_scope-> local_vars; 
4654 if (node-> nd_rest> = 0) (/ * rest parameters * / 
4655 VALUE v; 
4656 
                   / * Exactly zero of the array of arguments to the variable * / 
4657 if (argc> 0) 
4658 v = rb_ary_new4 (argc, argv); 
4659 else 
4660 v = rb_ary_new2 (0); 
4661 ruby_scope-> local_vars [node-> nd_rest] = v; 
4662) 
4663) 
4664) 

(eval.c) 

Comments from a generous amount ever in looking at and we've been a steady pursuit of ERE if they are doing it.

I was the one ruby_frame - argc and argv to be. rest parameters Not only update the like, but why not the rest parameters Need to do?

This is argc and argv useful to think of things. This is actually a member The argument super for a man. This means following form.

 
super 

This super is currently running as a method parameter hand over work KIGA. At that time you can give to ruby_frame-> argv arguments to keep it Beast.

Write back to the original story, rest when you have the parameters super , the original argument Limited It is convenient to pass the sort of strike is likely to feel it. Not when the Op Applications will be assigned after the parameters of what it is I do not think so.

 
def m (a, b, * rest) 
   Perhaps super # 5, 6, 7, 8 to be passed 
end 
m (5, 6, 7, 8) 

def m (a, b = 6) 
   Perhaps super # 5, 6 to be passed 
end 
m (5) 

This is "I must be" rather than as either good or specifications, The problem. If you have any method parameters rest of the superclass But the parameters are also believed to rest, compiled after a pass value Inconveniences may become very expensive.

Now, many methods are said to start this story is all over. After the closing of this chapter is now the subject of super , looking at implementation Especially.

super

super to respond to the NODE_SUPER and NODE_ZSUPER . NODE_SUPER is a simple super , NODE_ZSUPER None of the arguments super .

rb_eval () - NODE_SUPER

 
2780 case NODE_SUPER: 
2781 case NODE_ZSUPER: 
(2782 
2783 int argc; VALUE * argv; / * used in SETUP_ARGS * / 
2784 TMP_PROTECT; 
2785 
                   / * (A) super if you are prohibited * / 
2786 if (ruby_frame-> last_class == 0) ( 
2787 if (ruby_frame-> orig_func) ( 
2788 rb_name_error (ruby_frame-> last_func, 
2789 "superclass method`% s' disabled ", 
2790 rb_id2name (ruby_frame-> orig_func)); 
2791) 
2792 else ( 
2793 rb_raise (rb_eNoMethodError, 
                                    "super called outside of method"); 
2794) 
2795) 
                   / * (B) or prepare arguments rating * / 
2796 if (nd_type (node) == NODE_ZSUPER) ( 
2797 argc = ruby_frame-> argc; 
2798 argv = ruby_frame-> argv; 
2799) 
2800 else ( 
2801 BEGIN_CALLARGS; 
2802 SETUP_ARGS (node-> nd_args); 
2803 END_CALLARGS; 
2804) 
2805 
                   / * (C) still a mystery PUSH_ITER () * / 
2806 PUSH_ITER (ruby_iter-> iter? ITER_PRE: ITER_NOT); 
2807 SET_CURRENT_SOURCE (); 
2808 result = rb_call (RCLASS (ruby_frame-> last_class) -> super, 
2809 ruby_frame-> self, ruby_frame-> orig_func, 
2810 argc, argv, 3); 
2811 POP_ITER (); 
2812) 
2813 break; 

(eval.c) 

None of the arguments super , ruby_frame-> argv as the argument Said, but (B) as it emerged.

(C) rb_call () call just before PUSH_ITER () . This theory is also more It is not clear, and thus keep the current method was passed along to block Leave again the following method (that is now called super-class method) Delegates.

And finally (A) ruby_frame-> last_class is 0 when super of Calling the ban. Error messages are " Must be enabled by rb_enable_super () " The film is, rb_enable_super () to call to get the word NARURASHII. Why?

First of all last_class 0 is what you get when you examine it, I was real C, defined in the method ( NODE_CFUNC ) and I said to be running. In addition to such methods alias or replaced or when the same.

So far, but found that the source code, but insist that read more Do not know. Since no choice but do not know ruby log mailing list " Rb_enable_super " discovered in the search. The Mail said the following KOTORASHII.

For example String.new method. Of course, to generate a string method DE. String.new is T_STRING to make the structure. Therefore String of The receiver is always an instance method T_STRING is expected to be written.

Now, String.new - super is Object.new . Object.new is T_OBJECT to make the structure. , String.new to replace the definition super and What will become of those.

 
def String.new 
   super 
end 

As a result of the structure is T_OBJECT But class is String , the object is . But String methods T_STRING hope that the structure of the writing Deserves fall.

How to avoid it, or do I say that a different structure in the hope that the media Method is described as like I do. But the method is "expected structure" I have no information, no class. For example String class T_STRING how to get in if he could check before calling, but I think that Is not possible at this time. So as the second best "C from the method defined super is prohibited, "they have. Then, C-level hierarchical method Let's lock down, you can make it not. And "absolute It's okay to super I hope that "if the rb_enable_super () to You should call super there will be.

YOUSURUNI root of the problem is the structure of the mismatch. AROKESHONFUREMUWAKU occurred in the same issue.

That solution is what should I do or say, the root of the problem, "Kula Is not an instance of the structure not know "to resolve that I do. But it But there is a new API from the need to be more thorough about it compatible with Lose. So right now it is not the final solution is not always .


The original work is Copyright © 2002 - 2004 Minero AOKI.
Translations,  additions,  and graphics by C.E. Thornton
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike2.5 License.