"Evaluator" What a strange word. In the face of an evaluator "Evaluation" An "instrument" is KEDOMO sure, we evaluate what it is ?
"Evaluation" to evaluate the definitive translation of the programming language talk about the assumption that the GIMI misinterpretation. Japanese rating, meanwhile, say that "good bad" meaning that contains Them out.
HRS evaluate the program in language that is completely regardless of the "Absolute" Or "running" close to meaning. evaluate the origin of the Latin ex + value + ate, the literal translation do "value". This is most easily understood? May. From the text represented value for the ceremony, he said.
Well, speaking only to put it YOUSURUNI rating formula is written in the running to the conclusion Get the results mean. Why say no and run it and run only Reviews are not.
For example, common programming language, "3" and writing to be treated as an integer 3. This
But when "
" 3 " was 3 of the assessment results" and saying. Expression is constant running
It is hard to say, but also the rating. "3" to face
6 rating when treated as a whole (the rating) even though the language is a separate structure
I do not.
挙げようanother example. Combined with a constant expression, compiled during the calculation It can have a (constant folding). This is normal "run" and calculate that Not to tell. Speaking of the binary run made while running from the point of work. But when the program tried to calculate the final estimate will not change.
In other words, "evaluation" and is usually run a program that is equal to it, Is fundamentally different from the run and evaluation. Let's just remember this point.
rubyFeatures Rating System
ruby evaluator of the biggest feature is the true interpreter, but overall, C level
(Extended library) and Ruby code-level expression of the difference is small. Ordinary
Processing system, the extended use interpreter from the library's function is considerably restricted in
ruby scarier, less restrictions. Class definitions, methods to define, limit
Protection method call, it is natural and around the exceptions, iterators, and end
To allow for the thread.
But the convenience is something to pay the price. Implementation is very strange Or very large overhead, a similar thing for Ruby and C - The second part of the implementation of the considerable.
ruby is a dynamic language, so when you run the setup program as a string
It can also be evaluated.
eval That method is a function wind.
Of course, is to evaluate the corner. I use it can be.
lvar = 1 answer = eval ( "lvar + lvar") # 2 The answer is
Module # module_eval ,
Object # instance_eval that in the
The movements of their habit. This area is more
Chapter 17, and the dynamic evaluation述べよう.
The instrument rating
eval.c has been implemented. However, the
eval.c is huge and very, very
200 K bytes 9000 line, the function of the number of 309 enemy fire. This has come about
And looked at from head to the degree that will not make any structural TSUKAMENAI.
Then how? First, if I see a huge file, and no type It is unthinkable not injured. This means more small unit inside the module LE has been a wonder. So I find it to be considered first. How do you find the module will be better. Listed several methods to try.
First of all functions defined in the list of the prefix of output.
rb_thread_ functions such as a prefix ZURAZURA
Along with that. This is clearly a function of the same kind of unity.
The number of class libraries, which is known,
ruby code, is
Init_xxxx () is always placed at the end of the block. So
Init_xxxx () should happen
It also break.
And of course the name is important.
eval () and
rb_eval () and
eval_node () is
Close to each other if there is a deep relationship, and I think it is only natural.
ruby source code and variables to define the type and prototype declarationはさまっ
That is often break.
This awareness around and look at it,
eval.c is primarily attributable to the following modules
He could split.
|Chapter 7, and illustrated the security|
|entry manipulation method||entities for use of search methods and to remove|
|evaluator core|| |
|exception||exceptions occur and generate trace back|
|method||implementation method calls|
|iterator||block functions related to the implementation|
|load||external file and load rating|
| || |
|thread||Ruby thread implementations|
Among them was originally part of the load and thread
eval.c is not supposed to be part of.
eval.c there is simply because of the constraints of the C language. A little more and say,
PUSH_TAG () ,
eval.c internally defined in the macro need to use
There. So these two areas off the third and fourth division to handle it.
Safe levels are also described in Part I so good.
Shaving more than three of the six remaining items are subject to the third part of the explanation. And the correspondence, as the following table.
|entry method of operation||context, the following chapter|
|evaluator core||the third part of all chapters|
|method||Chapter 15, the method|
|iterator||Chapter 16, the block|
| ||Chapter 16, the block|
The core is a true evaluator
rb_eval () , which is a function of the
This section is
main () from the
rb_eval () to follow the road to the film industry.
The following is the
rb_eval () Call rough around the graph.
main .... main.c ruby_init .... eval.c ruby_prog_init .... ruby.c ruby_options .... eval.c ruby_process_options .... ruby.c ruby_run .... eval.c eval_node rb_eval * ruby_stop
The file was moved to the right place to put it in the file name.
ジッlook at this and realize the first,
eval.c function from
That function to bring it back.
Return the call, and is written,
ruby.c is a rather
ruby implementation and command files to opt out.
ruby and is Commands
Put a little distance, evaluating the implementation of the instrument itself. In other words
Even used to stand,
ruby.c called those functions
eval.c independence down.
Why does this have? The main reason is that the C language constraints.
ruby_prog_init () and
ruby_process_options () , the world's API using Ruby
Since starting, an exception may occur. However, an exception to stop Ruby
In order to
eval.c can only be used in
PUSH_TAG () to use the macro
Be. That is primarily a
ruby_init () and
ruby_run () it is
It should be.
PUSH_TAG () and
extern function and the public and what not.
PUSH_TAG () is as follows
POP_TAG () counterpart to not be used.
PUSH_TAG (); / * All * / POP_TAG ();
Implementation of reasons, these two are the same macro function should not be inserted. I'll separate function and therefore can be divided into as it can be implemented, Then, very slowly, so it is not.
Then the notice,
main () and
ruby_xxxx () called a continuous function, called
The meaning is very likely that that. This is overtly
Symmetrical shape if anything to do with it is not funny.
These three functions are actually closely linked. In short, they say, this is three
Any "built-Ruby interface". In other words
If you only use the built-command to make, and do not use the library expansion,
ruby command is built on the theory itself is a kind of program and Ruby koh
The arrangement of this nature is to use interface.
ruby_ What is a prefix.
ruby This is a function of everything
rb_ . Why
ruby_ two kinds? Look
But do not know the difference between a difference, so I asked why it directly, "
Mando is a subsidiary of
ruby_ official interface
rb_ "What DASO
eval.c internal use only
ruby_scope Why are
ruby_ today? To
TSUKKO shortly see, this is just a偶然らしい.
the_ , but it was called, in the midst of all 1.3 interface
A change is a prefix. When the "-ish sort of internal"
ruby_ gave it a likely.
That is the only conclusion and say,
ruby_ that does not have
ruby auxiliary command
Private or internal variables.
rb_ that does not have
ruby official interpreter
The first is fairly straightforward for
main () look at it from you.
This is a very quick buckets and survive.
36 int 37 main (argc, argv, envp) 38 int argc; 39 char ** argv, ** envp; 40 ( 41 # if defined (NT) 42 NtInitialize (& argc, & argv); 43 # endif 44 # if defined (__MACOS__) & & defined (__MWERKS__) 45 argc = ccommand (& argv); 46 # endif 47 48 ruby_init (); 49 ruby_options (argc, argv); 50 ruby_run (); 51 return 0; 52) (main.c)
# ifdef NT of course Windows NT, NT. However, I do not know why but Win9x
NT is defined. That is the meaning of Win32 environment.
NtInitialize () for the Win32
argc argv and socket system
(WinSock) to initialize. This function is initialized so that only
The trail, too insipid not omitted.
__MACOS__ "KOSU will" not the Mac OS. Earlier this case Mac OS 9
That, Mac OS X is free. I
# ifdef is remaining is the first written by
And the current version of Mac OS 9 and earlier work. When I was working in the afterglow
There is. Thus the number of Northern Ireland.
By the way, readers familiar with the C language know if you think it is under-bar work
Identifier of the system libraries and OS reserved for that. The most reserved
It can be used in error or that there is no First,
Henrik kind of
cc has also become an error. For example, the HP-UX
HP of doing things UNIX. Henrik is not HP-UX,
A loud voice the opinion of the rejection.
Well, what are the user applications such identifier is not defined With the promise.
Rubyさらっinterface, and built the live commentary.
ruby_init () Ruby interpreter is to initialize. Ruby interpreter was present
The process can not be only one argument and return value is required. This point is
In general, is "lack of features," believed to be.
Is just one interpreter is at a loss for what is said and done around Ruby development environment.
irb , or RubyWin, RDE application said.
Rewriting the program to load classes are also supposed to be left out. Li
API-driven FUREKUSHON can probably deal with it is quite difficult.
But Matsumoto, who has apparently been intentionally interpreted to limit the number of one of the . "Initialization is not complete" is理由らしい. For example, low - DE have been extended to remove the library can not be cited as example In the book.
ruby_init () look at the code is meaningless because it stands for.
Ruby interpreter for the command line to Perth
ruby_options () . Of course, the command will use it.
This function in
-r (Library Road) and
-e (from the command line program to pass) process is being conducted.
And the argument passed to the Ruby file is a program for Perth goes here.
ruby command file is then given a choice, given
stdin in the main reading program. Then he introduced the second part of
rb_compile_string () and
rb_compile_file () text with the syntax tree
Compile. As a result of global variables
ruby_options () steady code is an abbreviation of fun too.
ruby_run () ,
ruby_eval_tree set the syntax tree
To begin the evaluation. You do not even call this function.
ruby_run () except in the
rb_eval_string () string with a function to evaluate the strategies.
1257 void 1258 ruby_run () (1259 1260 int state; 1261 static int ex; 1262 volatile NODE * tmp; 1263 1264 if (ruby_nerrs> 0) exit (ruby_nerrs); 1265 1266 Init_stack ((void *) & tmp); 1267 PUSH_TAG (PROT_NONE); 1268 PUSH_ITER (ITER_NOT); 1269 if ((state = EXEC_TAG ()) == 0) ( 1270 eval_node (ruby_top_self, ruby_eval_tree); 1271) 1272 POP_ITER (); 1273 POP_TAG (); 1274 1275 if (state & &! Ex) ex = state; 1276 ruby_stop (ex); 1277) (eval.c)
PUSH_xxxx () to see the macro, just ignore them. Oh this
It is when one or more explanation is right. This is the important thing is
eval_node () only. The contents of the said,
1112 static VALUE 1113 eval_node (self, node) 1114 VALUE self; 1115 NODE * node; (1116 1117 NODE * beg_tree = ruby_eval_tree_begin; 1118 1119 ruby_eval_tree_begin = 0; 1120 if (beg_tree) ( 1121 rb_eval (self, beg_tree); 1122) 1123 1124 if (! Node) return Qnil; 1125 return rb_eval (self, node); 1126) (eval.c)
rb_eval () call.
ruby_eval_tree_begin it is
BEGIN registered in the statement to the store. , But this has not really matter.
ruby_run () in
ruby_stop () , close them all the threads,
All objects to finalize an exception to check the final
exit () call. Also how can I not watch it.
rb_eval () . This function is
ruby nuclear true.
rb_eval () is calling once
NODE to handle one of the recursion
木全body while processing the syntax (see Figure 1).
rb_eval () and
yylex () as well as huge
switch statement, and its
Each node has a branch. First, let's look at the snap.
2221 static VALUE 2222 rb_eval (self, n) 2223 VALUE self; 2224 NODE * n; (2225 2226 NODE * nodesave = ruby_current_node; 2227 NODE * volatile node = n; 2228 int state; 2229 volatile VALUE result = Qnil; 2230 2231 # define RETURN (v) do (\ 2232 result = (v); \ 2233 goto finish; \ 2234) while (0) 2235 2236 again: 2237 if (! Node) RETURN (Qnil); 2238 2239 ruby_last_node = ruby_current_node = node; 2240 switch (nd_type (node)) ( case NODE_BLOCK: ..... case NODE_POSTEXE: ..... case NODE_BEGIN: : (The case of mass statement) : 3415 default: 3416 rb_bug ( "unknown node type% d", nd_type (node)); 3417) 3418 finish: 3419 CHECK_INTS; 3420 ruby_current_node = nodesave; 3421 return result; 3422) (eval.c)
Back at the entire process node ZURA there, along with the code.
Looked at each node of the branch to do so. Code to少なけれ
rb_eval () of only processed by them, along with many functions
eval.c most of the functions that's how they were able.
rb_eval () when I return from the value of
return well as macro
RETURN () to use.
CHECK_INTS to make sure we pass through. This macro is a thread
Relationship, so when I ignored them.
And finally, local variables
volatile to the GC's measures.
if sentence for example
rb_eval () evaluation process to look at concrete.
rb_eval () description covers
rb_eval ()in the process code node
At the beginning of the three listed would be read.
if true 'true expr' else 'false expr' end
NODE_NEWLINE nd_file = "if" nd_nth = 1 nd_next: NODE_IF nd_cond: NODE_TRUE nd_body: NODE_NEWLINE nd_file = "if" nd_nth = 2 nd_next: NODE_STR nd_lit = "true expr": String nd_else: NODE_NEWLINE nd_file = "if" nd_nth = 4 nd_next: NODE_STR nd_lit = "false expr": String
The second part of what you see,
unless is designed to be a fitting way
NODE_IF organized by a single species, so there is no need for a special treat.
2324 case NODE_IF: 2325 if (trace_func) ( 2326 call_trace_func ( "line", node, self, 2327 ruby_frame-> last_func, 2328 ruby_frame-> last_class); 2329) 2330 if (RTEST (rb_eval (self, node-> nd_cond))) ( 2331 node = node-> nd_body; 2332) 2333 else ( 2334 node = node-> nd_else; 2335) 2336 goto again; (eval.c)
The important thing for the last
if statement only.
Without changing the meaning of this statement, he will be re-written.
if (RTEST (rb_eval (self, node-> nd_cond))) ((A) RETURN (rb_eval (self, node-> nd_body)); (B) ) else ( RETURN (rb_eval (self, node-> nd_else)); (C) )
First (A), Ruby's condition formula (node) to assess the value of
RTEST () tested.
RTEST () is
VALUE Ruby is the true test of whether the macro.
That is true (B) in
then to assess the side sections,
If you fake (C),
else to evaluate the side sections.
if ceremony was also having a value of the value and not return it.
if value is
then side or
else side, it runs the value of the clause because,
RETURN () returning it to the macro.
The original list
rb_eval () without a recursion
goto done, and
Back in the construction of the building, but the appearance of a tree "at the end of reflexive →
if ceremony at the
NODE_NEWLINE There was, let us also take a look at the handling code.
stmt header by the piece looks like a bandwagon.
rb_eval () , running programs, files on the position of
Successive be used together.
3404 case NODE_NEWLINE: 3405 ruby_sourcefile = node-> nd_file; 3406 ruby_sourceline = node-> nd_nth; 3407 if (trace_func) ( 3408 call_trace_func ( "line", node, self, 3409 ruby_frame-> last_func, 3410 ruby_frame-> last_class); 3411) 3412 node = node-> nd_next; 3413 goto again; (eval.c)
It is not particularly difficult.
call_trace_func () is
NODE_IF also emerged. And this is what
Let's just easy to explain. This is Ruby Ruby level of the program to trace SU
Because of the feature. Debugger (
debug.rb ) and tracer (
ruby command) are using this feature.
set_trace_func to call a function, style and method for tracing
Projects can be registered but the
trace_func 0 is not, that is
Qfalse not, it
Proc objects and alert mechanism to see
Call_trace_func () ) run.
call_trace_func () and the trail was as if they have no relationship, a very interesting
This document is not to ignore the future. Those who are interested in the block, a Chapter 16
I want to give it a read.
NODE_IF syntax tree, in terms of the clause was part of the sun.
Let's just see part of the leaf.
2312 case NODE_SELF: 2313 RETURN (self); 2314 2315 case NODE_NIL: 2316 RETURN (Qnil); 2317 2318 case NODE_TRUE: 2319 RETURN (Qtrue); 2320 2321 case NODE_FALSE: 2322 RETURN (Qfalse); (eval.c)
rb_eval () argument. Go back and check the kind you want.
Others are better.
The following is
while corresponding node
NODE_WHILE I want to explain it,
Translate TextOriginal text: Translation: Japanese »English
next to implement a function of recursion is difficult.
ruby syntax of these tags to jump to that achieved by using so
First the story.
Tag and jump to say a word, C-language library function
setjmp () and
longjmp () of
setjmp () I know it's going to be?
This function is
gc.c also emerged, how are you going to use quite a wrong way.
setjmp () jump over the normal function is to use.
The following describes the code as an example. Entry point is
parent () .
jmp_buf buf; void child2 (void) ( longjmp (buf, 34); / * parent to return at once. setjmp return value is 34 * / puts ( "This message is not absolute power"); ) void child1 (void) ( child2 (); puts ( "This message is not absolute power"); ) void parent (void) ( int result; if ((result = setjmp (buf)) == 0) ( / * Setjmp returned to normal * / child1 (); ) Else ( / * Child2, came back from longjmp * / printf ( "% d \ n", result); / * 34 * displayed and / ) )
parent () ,
setjmp () and a controversial arguments
buf when the state is run record
By. A little direct say, address and the end of the stack machine
The CPU was recorded in the register.
setjmp () , I would return its value is 0
setjmp () ?
They returned to normal, so that, normally I write more code. Resona
if side. This is
child1 () is called.
child2 () control is shifted to
longjmp to call it, the argument
Can suddenly at the top. So in this case
parent () -
longjmp , when the
setjmp () return value
Argument would be
else side will be executed. Incidentally
longjmp 0 and passing
To force a different value in it will be wasted.
Examples of the state machine to stack the figure as in Figure 2.
Normal function once the call only once per return. But
setjmp () will return to the times.
fork () kind of thing that I put a little
The image is ascertained?
longjmp () image
setjmp () of preparation for this month.
EXEC_TAG () is
setjmp () ,
JUMP_TAG () is
longjmp () , each worth (see Figure 3).
Figure 3: image tag jump
This shows that
EXEC_TAG () there are no arguments.
Where are gone.
struct tag wrapped in a structure.
783 struct tag ( 784 jmp_buf buf; 785 struct FRAME * frame; / * PUSH_TAG when FRAME * / 786 struct iter * iter; / * PUSH_TAG of the ITER * / 787 ID tag; / * * types of tags / 788 VALUE retval; / * jump due to return value * / 789 struct SCOPE * scope; / * PUSH_TAG of the SCOPE * / 790 int dst; / * jump at ID * / 791 struct tag * prev; 792); (eval.c)
prev is a member, so
struct tag stack is used to link list
Structure would be predictable. Also try looking round and round
PUSH_TAG () and
POP_TAG () the macro, because there are stacks間違いなdo not think so.
793 static struct tag * prot_tag; / * end of the stack pointer * / 795 # define PUSH_TAG (ptag) do (\ 796 struct tag _tag; \ 797 _tag.retval = Qnil; \ 798 _tag.frame = ruby_frame; \ 799 _tag.iter = ruby_iter; \ 800 _tag.prev = prot_tag; \ 801 _tag.scope = ruby_scope; \ 802 _tag.tag = ptag; \ 803 _tag.dst = 0; \ 804 prot_tag = & _tag 818 # define POP_TAG () \ 819 if (_tag.prev) \ 820 _tag.prev-> retval = _tag.retval; \ 821 prot_tag = _tag.prev; \ 822) while (0) (eval.c)
唖然here, and I hope it is, what a tag as a local entity BETTER
NSUTAKKU solid place to ensure that seem (Fig. 4). And
while separation of the two macro. Using the C preprocessor
But it's a very brutal way into the category might be. Clearly
POP macro groups and to expand this.
do ( struct tag _tag; _tag.prev = prot_tag; / * * to save the previous tag / prot_tag = & _tag; / * new tag stack * / / * All * / prot_tag = _tag.prev; / * Previous restituit tag * / ) While (0);
This way, and nor is it a function call overhead costs memory allocation
With no equal. This technique is most
ruby assessment instrument
rb_eval () made recursion
Because the technique can be.
Figure 4: tag stack stack is embedded in the machine
Since this implementation
PUSH_TAG () and
POP_TAG () is a function of the pair
And not put the bad. Also inadvertently used outside evaluator, which I can not
Can not be published.
EXEC_TAG () and
JUMP_TAG () , let us also take a look at.
810 # define EXEC_TAG () setjmp (prot_tag-> buf) 812 # define JUMP_TAG (st) do (\ 813 ruby_frame = prot_tag-> frame; \ 814 ruby_iter = prot_tag-> iter; \ 815 longjmp (prot_tag-> buf, (st)); \ 816) while (0) (eval.c)
In this way,
EXEC_TAG () and
JUMP_TAG () to
EXEC_TAG () and a face only a moment of
longjmp () of
The rapper, but look, this is
setjmp () execution.
Based on more than
while mechanism to explain. First
while at the beginning
EXEC_TAG () a (
setjmp ). Then
rb_eval () to the body to perform a recurrence.
JUMP_TAG () a (
while loop, but the starting point to get back (Fig. 5).
Figure 5: jump-tag
break , for example, but not implemented can not jump
while is only
redo . Also from the method
return and exceptions in
rb_eval () 越えなけれmust be a wall. And
A different tag for each stack is inconvenient to use because, in one way or anotherスタッ
QUEUE MATOMETAI a book.
This is achieved in the "What this jump for jump?" Information
I TSUKERE. The right to
longjmp () arguments to pass
setjmp () return
Resona was able to specify a value, it makes it looks good. The following types of
As shown in the flag.
828 # define TAG_RETURN 0x1 / * return * / 829 # define TAG_BREAK 0x2 / * break * / 830 # define TAG_NEXT 0x3 / * next * / 831 # define TAG_RETRY 0x4 / * retry * / 832 # define TAG_REDO 0x5 / * redo * / 833 # define TAG_RAISE 0x6 / * * General exception / 834 # define TAG_THROW 0x7 / * throw (in this document扱わない) * / 835 # define TAG_FATAL 0x8 / * Supplementary impossible exception fatal * / 836 # define TAG_MASK 0xf (eval.c)
Meaning to comment on Friday. Last
setjmp () return to these values
To remove the flag bit mask.
setjmp () return value is "Ja
Lamp types "of information other than put them there.
NODE_WHILE code actually spent確かめようtags.
while true 'true_expr' end
NODE_WHILE nd_state = 1 (while) nd_cond: NODE_TRUE nd_body: NODE_STR nd_lit = "true_expr": String
2418 case NODE_WHILE: 2419 PUSH_TAG (PROT_NONE); 2420 result = Qnil; 2421 switch (state = EXEC_TAG ()) ( 2422 case 0: 2423 if (node-> nd_state & &! RTEST (rb_eval (self, node-> nd_cond))) 2424 goto while_out; 2425 do ( 2426 while_redo: 2427 rb_eval (self, node-> nd_body); 2428 while_next: 2429; 2430) while (RTEST (rb_eval (self, node-> nd_cond))); 2431 break; 2432 2433 case TAG_REDO: 2434 state = 0; 2435 goto while_redo; 2436 case TAG_NEXT: 2437 state = 0; 2438 goto while_next; 2439 case TAG_BREAK: 2440 state = 0; 2441 result = prot_tag-> retval; 2442 default: 2443 break; 2444) 2445 while_out: 2446 POP_TAG (); 2447 if (state) JUMP_TAG (state); 2448 RETURN (result); (eval.c)
There are what appear again and again came to the idiom.
PUSH_TAG (PROT_NONE); switch (state = EXEC_TAG ()) ( case 0: / * Normal operation * / break; case TAG_a: state = 0; / * I was waiting to jump from state to clear * / / * TAG_a, which has been flying in Operation when * / break; case TAG_b: state = 0; / * I was waiting to jump from state to clear * / / * TAG_b, which has been flying in Operation when * / break; default break; / * I was waiting to jump is not. Then…… * / ) POP_TAG (); if (state) JUMP_TAG (state); / *…… re-jump here. * /
PUSH_TAG () and
POP_TAG () a mechanism of the above must be sure to pair
EXEC_TAG () must be from within or outside. And now laden with
EXEC_TAG () . In other words
setjmp () . The return value is 0
setjmp () just returned from a normal to do so (usually
rb_eval () included).
EXEC_TAG () if the return value is zero
longjmp () to come back
So that only one is necessary jump
case chinois, while the rest will be through
Jump, it will also look at the code might be easy to understand.
redo node handler.
2560 case NODE_REDO: 2561 CHECK_INTS; 2562 JUMP_TAG (TAG_REDO); 2563 break; (eval.c)
JUMP_TAG () fly, the one before the
EXEC_TAG () page.
When the return value is the argument
TAG_REDO . That's what while
Have a look at the code, make sure to go through what route they would like.
Idiom is not as good,
NODE_WHILE code, a little more detail
case 0: in this process because there is only取りだし,
Incidentally, read labels to make it easier to shift some of that also.
if (node-> nd_state & &! RTEST (rb_eval (self, node-> nd_cond))) goto while_out; do ( rb_eval (self, node-> nd_body); ) While (RTEST (rb_eval (self, node-> nd_cond))); while_out:
Conditional expression equivalent to
node-> nd_cond in two places
rb_eval () that. The first
The only condition is determined by the separation. This is
while until a
Hardened to handle.
node-> nd_state 0 when
while , 1 and
while . The rest is an honest way so we can follow it. ICHII
Clubbing is not explained.
By the way, if the conditions during the ceremony
redo should happen easily
Infinite loop and feel like one. Of course, this sense of
Write code because it is a bad thing, but a little worrisome.
So I really do.
% Ruby-e 'while next do nil end' - e: 1: void value expression
It's plain elephant in Perth at the time. Safety, but,
The result is not interesting. By the way out of this error
value_expr () .
while , but did not have a value,
ruby 1.7 from
break value in return
To happen. Now is the flow estimate to try to pay attention. Local variables
rb_eval () return value to be put to his head to look at.
result = Qnil; switch (state = EXEC_TAG ()) ( case 0: / * This * / case TAG_REDO: case TAG_NEXT: / * Each jump * / case TAG_BREAK: state = 0; result = prot_tag-> retval; (A) default: break; ) RETURN (result);
Particularly noteworthy is (A) only. The return value is jumping
prot_tag-> retval In other words
struct tag to have passed through.
This is the way it pass.
2219 # define return_value (v) prot_tag-> retval = (v) 2539 case NODE_BREAK: 2540 if (node-> nd_stts) ( 2541 return_value (avalue_to_svalue (rb_eval (self, node-> nd_stts))); 2542) 2543 else ( 2544 return_value (Qnil); 2545) 2546 JUMP_TAG (TAG_BREAK); 2547 break; (eval.c)
In this way
return_value () tag stack tip of the macro structure
Value in it.
This basic trend is a good thing, but is actually
EXEC_TAG () and
JUMP_TAG () up
EXEC_TAG that it would be possible. For example, exception handling
rescue is on the way to
It may be entered.
while cond # NODE_WHILE in EXEC_TAG () Here begin # In order to rescue EXEC_TAG () break 1 rescue end end
JUMP_TAG () when
struct tag is
I do not know if laden with tags. If this is
POP_TAG () in the following
retval to the propagation, particularly in nothing but think about the following values travelled tag and return
818 # define POP_TAG () \ 819 if (_tag.prev) \ 820 _tag.prev-> retval = _tag.retval; \ 821 prot_tag = _tag.prev; \ 822) while (0) (eval.c)
If the figure would be in Figure 6.
Figure 6: Return propagation
Tag jump on using the example of a second look at the handling of exceptions.
setjmp () side, so I have seen at this time for a change
longjmp () we go from side to it.
rb_exc_raise () .
3645 void 3646 rb_exc_raise (mesg) 3647 VALUE mesg; (: 3648 3649 rb_longjmp (TAG_RAISE, mesg); 3650) (eval.c)
mesg is an exception object (
Exception following classes instance).
TAG_RAISE SURURASHII jump, but I'll keep an eye on.
rb_longjmp () 思いきりeasily to anything below.
static void rb_longjmp (tag, mesg) int tag; VALUE mesg; ( if (NIL_P (mesg)) mesg = ruby_errinfo; set_backtrace (mesg, get_backtrace (mesg)); ruby_errinfo = mesg; JUMP_TAG (tag); )
Speaking Well of course it is only natural, normal
JUMP_TAG () jump on it.
ruby_errinfo What? Some
grep told me that this variable is the Ruby Glover
$! and the entities. This variable is currently developing an exception and shows
To be the entity
ruby_errinfo rightly should have the same meaning.
begin raise ( 'exception raised') rescue 'rescue clause' ensure 'ensure clause' end
NODE_BEGIN nd_body: NODE_ENSURE nd_head: NODE_RESCUE nd_head: NODE_FCALL nd_mid = 3857 (raise) nd_args: NODE_ARRAY [ 0: NODE_STR nd_lit = "exception raised": String ] nd_resq: NODE_RESBODY nd_args = (null) nd_body: NODE_STR nd_lit = "rescue clause": String nd_head = (null) nd_else = (null) nd_ensr: NODE_STR nd_lit = "ensure clause": String
ensure is determined by the order, as the syntax of wood
Also strict order at all. Always
NODE_ENSURE is the most "in" the next
NODE_RESCUE , the last unit (
raise There's) is coming.
NODE_BEGIN nodes because it does nothing, but it is
NODE_ENSURE is at the top
That is also protected from the body you want
NODE_RESCUE is coming on,
EXEC_TAG () only
raise to stop. Than to say, I can do it
Syntax木上mentioned in the above, he said it is correct.
NODE_ENSURE look at the handler.
2634 case NODE_ENSURE: 2635 PUSH_TAG (PROT_NONE); 2636 if ((state = EXEC_TAG ()) == 0) ( 2637 result = rb_eval (self, node-> nd_head); (A-1) 2638) 2639 POP_TAG (); 2640 if (node-> nd_ensr) ( 2641 VALUE retval = prot_tag-> retval; (B-1) 2642 VALUE errinfo = ruby_errinfo; 2643 2644 rb_eval (self, node-> nd_ensr); (A-2) 2645 return_value (retval); (B-2) 2646 ruby_errinfo = errinfo; 2647) 2648 if (state) JUMP_TAG (state); (B-3) 2649 break; (eval.c)
if tags are used to treat second branch idioms.
EXEC_TAG () to jump to stop them,
ensure clause (
node-> nd_ensr ) to
Evaluation, said. No problem about the process.
The estimate that I think about it. Check the specifications,
begin expr0 ensure expr1 end
If the sentence,
begin overall value of
ensure without regardless of
Is. That is reflected in the (A-1, 2) at,
ensure estimate that the clause
無碍has been abandoned.
And (B-1, 3), console jump occurs when dealing with the estimate.
If the value is
prot_tag-> retval in that it was,
Rewritten to avoid accidentally running to take shelter local variables (B-1).
ensure clause evaluation is finished
return_value () Undo (B-2).
If the jump itself, even if you have not occurred, that is
state == 0 But
When the first place
prot_tag-> retval not used to not matter.
So little time is available again
rescue syntax, let us look at the trees.
begin raise () rescue ArgumentError, TypeError 'error raised' end
NODE_BEGIN nd_body: NODE_RESCUE nd_head: NODE_FCALL nd_mid = 3857 (raise) nd_args = (null) nd_resq: NODE_RESBODY nd_args: NODE_ARRAY [ 0: NODE_CONST nd_vid = 4733 (ArgumentError) 1: NODE_CONST nd_vid = 4725 (TypeError) ] nd_body: NODE_STR nd_lit = "error raised": String nd_head = (null) nd_else = (null)
rescue statement you want to target (for use)
NODE_RESCUE "inferior" to be
I want to confirm.
2590 case NODE_RESCUE: 2591 retry_entry: (2592 2593 volatile VALUE e_info = ruby_errinfo; 2594 2595 PUSH_TAG (PROT_NONE); 2596 if ((state = EXEC_TAG ()) == 0) ( 2597 result = rb_eval (self, node-> nd_head); / * * rating body / 2598) 2599 POP_TAG (); 2600 if (state == TAG_RAISE) (/ * * exception occurs in the body / 2601 NODE * volatile resq = node-> nd_resq; 2602 2603 while (resq) (/ * rescue clause in order to handle * / 2604 ruby_current_node = resq; 2605 if (handle_rescue (self, resq)) (/ * * If you deal with this section / 2606 state = 0; 2607 PUSH_TAG (PROT_NONE); 2608 if ((state = EXEC_TAG ()) == 0) ( 2609 result = rb_eval (self, resq-> nd_body); 2610) / * rescue clause to evaluate * / 2611 POP_TAG (); 2612 if (state == TAG_RETRY) (/ * retry occurred because * / 2613 state = 0; 2614 ruby_errinfo = Qnil; / * * The exception is a stop / 2615 goto retry_entry; / * goto converted * / 2616) 2617 if (state! = TAG_RAISE) (/ * return, and even * / 2618 ruby_errinfo = e_info; / * exception will stop * / 2619) 2620 break; 2621) 2622 resq = resq-> nd_head; / * * forward to the next section of the rescue / 2623) 2624) 2625 else if (node-> nd_else) (/ * else clause, * / 2626 if (! State) (/ * only exception is when you evaluate起きなかった* / 2627 result = rb_eval (self, node-> nd_else); 2628) 2629) 2630 if (state) JUMP_TAG (state); / * not waiting for the jump * / 2631) 2632 break; (eval.c)
Although there are some code size of the node to handle only honest way to make an honest
Is not difficult.
handle_rescue () is the first appearance, but this function is
Not just because I can not see. It only describes the effect.
static int handle_rescue (VALUE self, NODE * resq)
, During the current exception (
ruby_errinfo ) is
resq represented by the class (for example
TypeError ) of the lower class
Whether the decision.
self passing of the function in
resq to evaluate
rb_eval () need to call.
The original work is Copyright © 2002 - 2004 Minero AOKI.
Translations,  additions,  and graphics by C.E. Thornton
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike2.5 License.