"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.
ruby
Features 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
But, 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.
Also 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
Other Module # module_eval
, Object # instance_eval
that in the
The movements of their habit. This area is more
Chapter 17, and the dynamic evaluation述べよう.
eval.c
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_dvar_
,
rb_mod_
, rb_obj_
, 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.
Finally, 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 | rb_eval () centered on the core part of the evaluator | ||
exception | exceptions occur and generate trace back | ||
method | implementation method calls | ||
iterator | block functions related to the implementation | ||
load | external file and load rating | ||
Proc | Proc implementation | ||
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 | ||
exception | this chapter | ||
method | Chapter 15, the method | ||
iterator | Chapter 16, the block | ||
Proc | Chapter 16, the block |
main
DP ruby_run
via rb_eval
go
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 main.c
of
That function to bring it back.
Return the call, and is written, main.c
and ruby.c
is a rather
ruby
implementation and command files to opt out. eval.c
is ruby
and is Commands
Put a little distance, evaluating the implementation of the instrument itself. In other words eval.c
is ruby.c
to
Even used to stand, eval.c
and 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 ruby.c
to
It should be.
Why does PUSH_TAG ()
and extern
function and the public and what not.
Actually 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 ruby
interpreter
If you only use the built-command to make, and do not use the library expansion,
Function. 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 rb_
and ruby_
two kinds? Look
But do not know the difference between a difference, so I asked why it directly, " ruby
Ko
Mando is a subsidiary of ruby_
official interface rb_
"What DASO
U.
Then eval.c
internal use only ruby_scope
Why are ruby_
today? To
TSUKKO shortly see, this is just a偶然らしい. ruby_scope
are
Originally the_
, but it was called, in the midst of all 1.3 interface
A change is a prefix. When the "-ish sort of internal"
Variable 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
Interface. It.
main ()
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.
Also __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 cc
.
HP-UX is 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_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.
Wax. Specifically, 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_options ()
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_eval_tree
set
By.
ruby_options ()
steady code is an abbreviation of fun too.
ruby_run ()
Finally 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
For example 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)
ruby_eval_tree
a rb_eval ()
call. ruby_eval_tree_begin
it is
BEGIN
registered in the statement to the store. , But this has not really matter.
Also 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 ()
Now 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).
Figure 1: rb_eval
image
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
Split. 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.
Always CHECK_INTS
to make sure we pass through. This macro is a thread
Relationship, so when I ignored them.
And finally, local variables result
and node
to
volatile
to the GC's measures.
NODE_IF
, if
sentence for example rb_eval ()
evaluation process to look at concrete.
Here, 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, elsif
and 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.
And Ruby's 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 → goto
conversion."
NODE_NEWLINE
if
ceremony at the NODE_NEWLINE
There was, let us also take a look at the handling code.
This node 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
It alone
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 ( tracer.rb
),
Profiler ( profile.rb
),
irb
(interactive ruby
command) are using this feature.
set_trace_func
to call a function, style and method for tracing Proc
of
Projects can be registered but the Proc
objects
trace_func
on. trace_func
0 is not, that is
Qfalse
not, it Proc
objects and alert mechanism to see
( Call_trace_func ()
) run.
This 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)
self
is 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
break
and 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
Wrapper. 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 / ) )
First 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
There may if
side. This is child1 ()
is called.
Then child2 ()
control is shifted to longjmp
to call it, the argument buf
to
setjmp
of
Can suddenly at the top. So in this case parent ()
- setjmp
and
Time back. longjmp
, when the setjmp ()
return value longjmp
second
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?
Figure 2: setjmp ()
longjmp ()
image
Now, setjmp ()
of preparation for this month. eval.c
, 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. jmp_buf
is
Where are gone.
Actually ruby
, jmp_buf
is struct tag
wrapped in a structure.
Let's see.
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
do
in while
separation of the two macro. Using the C preprocessor
But it's a very brutal way into the category might be. Clearly
PUSH
/ 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.
Incidentally 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, setjmp
and longjmp
respectively EXEC_TAG ()
and JUMP_TAG ()
to
Under wraps. 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.
And break
and next
have JUMP_TAG ()
a ( longjmp
).
Then while
loop, but the starting point to get back (Fig. 5).
Figure 5: jump-tag while
implementation
This is break
, for example, but not implemented can not jump break
.
Not only. while
is only next
and 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 TAG_MASK
is 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
, 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. * /
First PUSH_TAG ()
and POP_TAG ()
a mechanism of the above must be sure to pair
. Also EXEC_TAG ()
must be from within or outside. And now laden with
Just jmp_buf
and 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
( Default
).
Jump, it will also look at the code might be easy to understand.
The following 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 NODE_WHILE
of
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
Explains. Said 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 do
in while
and while
until a
Hardened to handle. node-> nd_state
0 when do
in while
, 1 and
Normal KIGA 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 next
and 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
Are you parse.y
- value_expr ()
.
while
estimate of
Long 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 result
of
Value 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
NODE_WHILE
- EXEC_TAG ()
and NODE_BREAK
- JUMP_TAG ()
up
Between different 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
So NODE_BREAK
, JUMP_TAG ()
when struct tag
is NODE_WHILE
,
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
As before.
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.
raise
while
, setjmp ()
side, so I have seen at this time for a change
longjmp ()
we go from side to it. raise
entity 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).
The TAG_RAISE
SURURASHII jump, but I'll keep an eye on.
And 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
LE variable $!
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
PASAREBERU in rescue
and 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
To 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
I think.
That is also protected from the body you want NODE_ENSURE
and NODE_RESCUE
is coming on,
Just EXEC_TAG ()
only raise
to stop. Than to say, I can do it
Syntax木上mentioned in the above, he said it is correct.
ensure
ensure
nodes 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)
This 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 expr0
value
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, ensure
Clause
Rewritten to avoid accidentally running to take shelter local variables (B-1).
And 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.
rescue
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.
The prototype
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
For 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.