From 89dc9f574795ce7a991cc9ab1ee9aa4f555b60b8 Mon Sep 17 00:00:00 2001 From: John Bohn Date: Fri, 16 Aug 2013 10:24:01 -0500 Subject: [PATCH 001/121] Typo --- class.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class.textile b/class.textile index 4bfe5e3..e55e9e2 100644 --- a/class.textile +++ b/class.textile @@ -895,7 +895,7 @@ Let's first start our reading with its caller, `rb_define_class_id()`. `rb_class_new()` was a function that creates a class with `super` as its superclass. `rb_name_class()`'s name means it names a class, but -for the moment we do note care about names so we'll skip it. After +for the moment we do not care about names so we'll skip it. After that there's the `rb_make_metaclass()` in question. I'm concerned by the fact that when called from `rb_singleton_class()`, the parameters were different. Last time was like this: From f36d9f47a370a039897e501fdcc0c541d54bc96e Mon Sep 17 00:00:00 2001 From: John Bohn Date: Fri, 16 Aug 2013 12:13:30 -0500 Subject: [PATCH 002/121] Fix translation --- class.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class.textile b/class.textile index e55e9e2..6eee2c8 100644 --- a/class.textile +++ b/class.textile @@ -1000,7 +1000,7 @@ h3. Class of a class of a class You've understood the working of class methods inheritance, but by doing that, in the opposite some questions have appeared. What is the class of a class's singleton class? To do this we can try -debugging. I've made the figure 7 from the results of this +debugging. I've made figure 7 from the results of this investigation. !images/ch_class_mmm.png(Class of a class's singleton class)! From 5973ea6226a76523ed6063a3389efc045bf0d962 Mon Sep 17 00:00:00 2001 From: John Bohn Date: Fri, 16 Aug 2013 13:54:24 -0500 Subject: [PATCH 003/121] Escape (C) subsections so they don't show up as copyright symbol --- class.textile | 8 ++++---- evaluator.textile | 4 ++-- gc.textile | 4 ++-- load.textile | 6 +++--- module.textile | 4 ++-- object.textile | 2 +- parser.textile | 10 +++++----- preface.textile | 20 ++++++++++---------- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/class.textile b/class.textile index 6eee2c8..f1c952a 100644 --- a/class.textile +++ b/class.textile @@ -1144,7 +1144,7 @@ the class can be found from the constant. 193 rb_autoload_load(id); 194 } 195 if (rb_const_defined(rb_cObject, id)) { /* (B) rb_const_defined */ - 196 klass = rb_const_get(rb_cObject, id); /* (C) rb_const_get */ + 196 klass = rb_const_get(rb_cObject, id); /* ==(C)== rb_const_get */ 197 if (TYPE(klass) != T_CLASS) { 198 rb_raise(rb_eTypeError, "%s is not a class", name); 199 } /* (D) rb_class_real */ @@ -1177,7 +1177,7 @@ libraries when some constants are accessed. This is done in the (B) We determine whether the `name` constant has been defined or not in `Object`. -(C) Get the value of the `name` constant. This will be explained in +==(C)== Get the value of the `name` constant. This will be explained in detail in chapter 6. (D) We've seen `rb_class_real()` some time ago. If the class `c` is a @@ -1523,7 +1523,7 @@ h3. `include_class_new()` 331 } 332 klass->iv_tbl = RCLASS(module)->iv_tbl; /* (B) */ 333 klass->m_tbl = RCLASS(module)->m_tbl; - 334 klass->super = super; /* (C) */ + 334 klass->super = super; /* ==(C)== */ 335 if (TYPE(module) == T_ICLASS) { /* (D) */ 336 RBASIC(klass)->klass = RBASIC(module)->klass; /* (D-1) */ 337 } @@ -1546,7 +1546,7 @@ We're lucky there's nothing we do not know. (B) Transplant `module`'s instance variable and method tables into this class. -(C) Make the including class's superclass (`super`) the super class of +==(C)== Make the including class's superclass (`super`) the super class of this new class. In other words, this function creates an include class for the diff --git a/evaluator.textile b/evaluator.textile index cd11b98..fc2ba21 100644 --- a/evaluator.textile +++ b/evaluator.textile @@ -623,7 +623,7 @@ 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) + RETURN(rb_eval(self, node->nd_else)); ==(C)== } @@ -633,7 +633,7 @@ testing its value with @RTEST()@ . I've mentioned that @RTEST()@ is a macro to test whether or not a @VALUE@ is true of Ruby. If that was true, evaluating the @then@ side clause at (B). -If false, evaluating the @else@ side clause at (C). +If false, evaluating the @else@ side clause at ==(C)==. In addition, I've mentioned that @if@ statement of Ruby also has its own value, diff --git a/gc.textile b/gc.textile index b07079c..eaafc59 100644 --- a/gc.textile +++ b/gc.textile @@ -1493,7 +1493,7 @@ This hook is called "finalizer". 890 } 891 n++; 892 } - 893 (C) else if (RBASIC(p)->flags == FL_MARK) { + 893 ==(C)== else if (RBASIC(p)->flags == FL_MARK) { 894 /* the objects that need to finalize */ 895 /* are left untouched */ 896 } @@ -1565,7 +1565,7 @@ It means that while executing the finalizers, one cannot use the hooked objects. The `for` in the last half is the main finalizing procedure. The `if` in the first half is the case when the execution could not be moved to the Ruby program for various reasons. -The objects whose finalization is deferred will be appear in the route (C) of +The objects whose finalization is deferred will be appear in the route ==(C)== of the previous list. diff --git a/load.textile b/load.textile index 70e4a22..3fc6509 100644 --- a/load.textile +++ b/load.textile @@ -591,7 +591,7 @@ load_file(fname, /* script=0 */) fclose(fp); } f = rb_file_open(fname, "r"); (B) - rb_compile_file(fname, f, 1); (C) + rb_compile_file(fname, f, 1); ==(C)== rb_io_close(f); } @@ -609,7 +609,7 @@ loading error, but getting the errors related to `open`, for example `Errno::ENOENT`, `Errno::EACCESS`..., would be problematic. We are in `ruby.c` so we cannot stop a tag jump. -(C) Using the parser interface `rb_compile_file()`, the program is +==(C)== Using the parser interface `rb_compile_file()`, the program is read from an `IO` object, and compiled in a syntax tree. The syntax tree is added to `ruby_eval_tree` so there is no need to get the result. @@ -942,7 +942,7 @@ First, let's start with the API code for the `dlopen` series. 1324 dlclose(handle); 1325 goto failed; 1326 } -1327 /* (C)Init_xxxx()を呼ぶ */ +1327 /* ==(C)==Init_xxxx()を呼ぶ */ 1328 (*init_fct)(); 1329 1330 return handle; diff --git a/module.textile b/module.textile index f76e766..bea210d 100644 --- a/module.textile +++ b/module.textile @@ -1330,7 +1330,7 @@ The method @initialize@ to initialize an object will unquestionably become @priv My feeling is that there're few cases @protected@ is required in Ruby. -(C) This is a bug. I found this just before the submission of this book, +==(C)== This is a bug. I found this just before the submission of this book, so I couldn't fix this beforehand. In the latest code this part is probably already removed. The original intention is to enforce the methods defined at top level to be @private@ . @@ -2035,7 +2035,7 @@ Fig.9. assign when corresponded array and assign it into (the left-hand side expressed by) the @node->nd_args@ . -(C) if there are remainders on the left-hand side, assign @nil@ to all of them. +==(C)== if there are remainders on the left-hand side, assign @nil@ to all of them. diff --git a/object.textile b/object.textile index 66149b5..7a32ddd 100644 --- a/object.textile +++ b/object.textile @@ -815,7 +815,7 @@ how to get them. 976 return generic_ivar_get(obj, id); 977 break; 978 } - /* (C) */ + /* ==(C)== */ 979 rb_warning("instance variable %s not initialized", rb_id2name(id)); 980 981 return Qnil; diff --git a/parser.textile b/parser.textile index dda825a..dfc9565 100644 --- a/parser.textile +++ b/parser.textile @@ -1834,7 +1834,7 @@ h4. ヒアドキュメント 2982 lex_strterm = rb_node_newnode(NODE_HEREDOC, 2983 rb_str_new(tok(), toklen()), /* nd_lit */ 2984 len, /* nd_nth */ -2985 /*(C)*/ lex_lastline); /* nd_orig */ +2985 /*==(C)==*/ lex_lastline); /* nd_orig */ 2986 2987 return term == '`' ? tXSTRING_BEG : tSTRING_BEG; 2988 } @@ -1853,7 +1853,7 @@ h4. ヒアドキュメント (B)そしていきなり`lex_p`を行の末尾まで飛ばす。 ということは、読み込み中の行のうち開始記号の後が読み捨てられて しまっている。この残りの部分はいつパースするのだろう。 -その謎の答えは(C)で`lex_lastline`(読み込み中の行)と +その謎の答えは==(C)==で`lex_lastline`(読み込み中の行)と `len`(既に読んだ長さ)を保存しているところにヒントがある。 では`heredoc_identifier()`前後の動的コールグラフを以下に簡単に示す。 @@ -1885,7 +1885,7 @@ here_document(NODE *here) line = lex_lastline; /*(A)*/ rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len); lex_p = lex_pend; /*(B)*/ - if (nextc() == -1) { /*(C)*/ + if (nextc() == -1) { /*==(C)==*/ goto error; } } while (読み込み中の行が終了記号と等しくない); @@ -1903,11 +1903,11 @@ here_document(NODE *here) `rb_str_cat()`はRubyの文字列の末尾に`char*`を連結する関数だ。 つまり(A)では現在読み込み中の行`lex_lastline`を`str`に連結している。 連結したらもう今の行は用済みだ。(B)で`lex_p`をいきなり行末に -飛ばす。そして(C)が問題で、ここでは終了チェックをしているように +飛ばす。そして==(C)==が問題で、ここでは終了チェックをしているように 見せかけつつ実は次の「行」を読み込んでいるのだ。思い出してほしいの だが、`nextc()`は行が読み終わっていると勝手に次の行を読み込むという 仕様だった。だから(B)で強制的に行を終わらせているので -(C)で`lex_p`は次の行に移ることになる。 +==(C)==で`lex_p`は次の行に移ることになる。 そして最後に`do`〜`while`ループを抜けて`heredoc_restore()`だ。 diff --git a/preface.textile b/preface.textile index fe71337..c5e6bdc 100644 --- a/preface.textile +++ b/preface.textile @@ -105,34 +105,34 @@ Part 4: Peripheral around the evaluator Supplementary chapters are included at the beginning of each part when necessary. These provide a basic introduction for those who are not familiar -with Ruby and the general mechanism of a language processing system. +with Ruby and the general mechanism of a language processing system. Now, we are going through the overview of the four main parts. The symbol in -parentheses after the explanation indicates the difficulty gauge. They are (C), +parentheses after the explanation indicates the difficulty gauge. They are ==(C)==, (B), (A) in order of easy to hard, (S) being the highest. h4. Part 1: Object -Chapter 1: Focuses the basics of Ruby to get ready to accomplish Part 1. (C) -Chapter 2: Gives concrete inner structure of Ruby objects. (C) -Chapter 3: States about hash table. (C) +Chapter 1: Focuses the basics of Ruby to get ready to accomplish Part 1. ==(C)== +Chapter 2: Gives concrete inner structure of Ruby objects. ==(C)== +Chapter 3: States about hash table. ==(C)== Chapter 4: Writes about Ruby class system. You may read through this chapter quickly at first, because it tells plenty of abstract stories. (A) Chapter 5: Shows the garbage collector which is responsible for generating and releasing objects. The first story in low-level series. (B) -Chapter 6: Describes the implementation of global variables, class variables, and constants. (C) -Chapter 7: Outline of the security features of Ruby. (C) +Chapter 6: Describes the implementation of global variables, class variables, and constants. ==(C)== +Chapter 7: Outline of the security features of Ruby. ==(C)== h4. Part 2: Syntactic analysis -Chapter 8: Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. (C) +Chapter 8: Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. ==(C)== Chapter 9: Introduction to @yacc@ required to read the syntax file at least. (B) Chapter 10: Look through the rules and physical structure of the parser. (A) Chapter 11: Explore around the peripherals of @lex_state@, which is the most difficult part of the parser. The most difficult part of this book. (S) -Chapter 12: Finalization of Part 2 and connection to Part 3. (C) +Chapter 12: Finalization of Part 2 and connection to Part 3. ==(C)== h4. Part 3: Evaluator -Chapter 13: Describe the basic mechanism of the evaluator. (C) +Chapter 13: Describe the basic mechanism of the evaluator. ==(C)== Chapter 14: Reads the evaluation stack that creates the main context of Ruby. (A) Chapter 15: Talks about search and initialization of methods. (B) Chapter 16: Defies the implementation of the iterator, the most characteristic feature of Ruby. (A) From a0d13f6860079d4ae8d66ad7c06da610f2fd97d2 Mon Sep 17 00:00:00 2001 From: John Bohn Date: Fri, 16 Aug 2013 10:24:06 -0500 Subject: [PATCH 004/121] Whitespace --- class.textile | 2 +- load.textile | 6 ++--- parser.textile | 2 +- preface.textile | 70 ++++++++++++++++++++++++------------------------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/class.textile b/class.textile index f1c952a..6ae1162 100644 --- a/class.textile +++ b/class.textile @@ -171,7 +171,7 @@ end h3. Singleton methods definition -We can define methods that are specific to a single object instance. +We can define methods that are specific to a single object instance. They are called singleton methods. As I used `File.unlink` as an example in chapter 1 "Ruby language minimum", I first wanted to show it here, but for a particular reason we'll look at `File.link` diff --git a/load.textile b/load.textile index 3fc6509..6f6b430 100644 --- a/load.textile +++ b/load.textile @@ -638,7 +638,7 @@ can be open, but in fact during the loading process other functions like for example `rb_find_file_ext()` also do checks using `open`. How many times is `open()` called in the whole process? -If you're wondering that, it's just a matter of having the right program available to count and see. You can easily find out using a system call tracer. On Linux, the tool to use would be `strace`; on Solaris, `truss`; or on BSD, `ktrace` or `truss`. +If you're wondering that, it's just a matter of having the right program available to count and see. You can easily find out using a system call tracer. On Linux, the tool to use would be `strace`; on Solaris, `truss`; or on BSD, `ktrace` or `truss`. というように OSによって名前がてんでバラバラなのだが、Googleで検索すればすぐ見付かる @@ -796,9 +796,9 @@ By the way, what is `gcc` actually doing here? Usually we just say is "compiles" h3. 真にダイナミックなリンク -And finally we get into our main topic. The "dynamic" in "dynamic linking" naturally means it "occurs at execution time", but what people usually refer to as "dynamic linking" is pretty much decided already at compile time. For example, the names of the needed functions, and which library they can be found in, are already known. For instance, if you need `cos()`, you know it's in `libm`, so you use `gcc -lm`. If you didn't specify the correct library at compile time, you'd get a link error. +And finally we get into our main topic. The "dynamic" in "dynamic linking" naturally means it "occurs at execution time", but what people usually refer to as "dynamic linking" is pretty much decided already at compile time. For example, the names of the needed functions, and which library they can be found in, are already known. For instance, if you need `cos()`, you know it's in `libm`, so you use `gcc -lm`. If you didn't specify the correct library at compile time, you'd get a link error. -But extension libraries are different. Neither the names of the needed functions, or the name of the library which defines them are known at compile time. +But extension libraries are different. Neither the names of the needed functions, or the name of the library which defines them are known at compile time. 文字列をプログラムの実 行中に組み立ててロード・リンクしなければいけないのである。つまり先程の 言葉で言う「論理結合」すらも全て実行時に行わなければならない。そのため diff --git a/parser.textile b/parser.textile index dfc9565..d188e55 100644 --- a/parser.textile +++ b/parser.textile @@ -345,7 +345,7 @@ Syntax OK Strange, it worked! What actually happens is this: consecutive newlines are simply discarded by the scanner, which returns only the first newline in a series. -By the way, although we said that `program` is the same as `compstmt`, if that was really true, you would question why `compstmt` exists at all. Actually, the distinction is there only for execution of semantic actions. `program` exists to execute any semantic actions which should be done once in the processing of an entire program. If it was only a question of parsing, `program` could be omitted with no problems at all. +By the way, although we said that `program` is the same as `compstmt`, if that was really true, you would question why `compstmt` exists at all. Actually, the distinction is there only for execution of semantic actions. `program` exists to execute any semantic actions which should be done once in the processing of an entire program. If it was only a question of parsing, `program` could be omitted with no problems at all. To generalize this point, the grammar rules can be divided into 2 groups: those which are needed for parsing the program structure, and those which are needed for execution of semantic actions. The `none` rule which was mentioned earlier when talking about `stmts` is another one which exists for executing actions -- it's used to return a `NULL` pointer for an empty list of type `NODE*`. diff --git a/preface.textile b/preface.textile index c5e6bdc..40a8022 100644 --- a/preface.textile +++ b/preface.textile @@ -33,7 +33,7 @@ included to help understand the topics. The main themes of this book are the first and the second point above. Though, what I want to emphasize the most is the third one: To acquire skill in reading source code. I dare to say it's a "hidden" theme. I will explain why we need -this. +this. It is often said "To be a skilled programmer, you should read source code @@ -56,14 +56,14 @@ source code. When I started writing this book, I had some experience with the Ruby language, but I did not fully understand the inner structure of the @ruby@ implementation. In other words, this book begins exploring @ruby@ from the same starting place as the reader. This book is the summary of the process and -results of my code analysis from that point. +results of my code analysis from that point. I asked Yukihiro Matsumoto, the author of @ruby@, for supervision. But I thought the spirit of this book would be lost if each analysis was monitored by the author of the language himself. Therefore I limited his review to the final stage of writing. In this way, I tried to assure the correctness of the -contents, keeping the goal of reading code alive at the same time. +contents, keeping the goal of reading code alive at the same time. To be honest, this book is not easy. In the very least, it is limited in its simplicity by the inherent complexity of its aim. However, this complexity may @@ -73,24 +73,24 @@ that you know the answer to in a heartbeat? How about a suspense novel whose criminal you can guess halfway through? If you really want to come to new knowledge, you need to solve a problem engaging all your capacities. This is the book that lets you practice such idealism exhaustively. "I think, -therefore it's fun!" Everybody who finds it fun gives pleasure to the author. +therefore it's fun!" Everybody who finds it fun gives pleasure to the author. h2. Target audience Firstly, knowledge about the Ruby language isn't required. However, since the knowledge of the Ruby language is absolutely necessary to understand certain explanations of its structure, supplementary explanations of the language are -inserted here and there. +inserted here and there. Knowledge about the C language is required, to some extent. I assume you have experience calling @malloc()@ to assign a list or stack, and have used function -pointer at least a few times. +pointer at least a few times. This book doesn't provide a proper introduction to an object-oriented language. You will have a difficult time if you don't know the basics of at least one -object-oriented language. Furthermore, some examples are given in Java and C++. +object-oriented language. Furthermore, some examples are given in Java and C++. h2. Structure of this book @@ -157,7 +157,7 @@ for confirmation of compiling and testing the basic operation. The details of this build test are given in @ doc/buildtest.html@ in the attached CD-ROM. However, it doesn't necessarily assume the probability of the execution even under the same environment listed in the table. The author doesn't guarantee -in any form the execution of @ruby@. +in any form the execution of @ruby@. BeOS 5 Personal Edition/i386 @@ -192,9 +192,9 @@ Windows XP (Visual C++.NET, MinGW+Cygwin) These numerous tests aren't of a lone effort by the author. Those test build couldn't be achieved without magnificent cooperations by the people listed -below. +below. -I'd like to extend warmest thanks from my heart. +I'd like to extend warmest thanks from my heart. Tietew @@ -222,7 +222,7 @@ please be advised to contact the author by e-mail: @aamine@loveruby.net@. h2. Web site -The web site for this book is @http://i.loveruby.net/ja/rhg/@. +The web site for this book is @http://i.loveruby.net/ja/rhg/@. I will add information about related programs and additional documentation, as well as errata. In addition, I'm going to publisize the first few chapters of this book at the same time of the release. I will look for a certain @@ -237,57 +237,57 @@ willingly approved me to publish a book about analyzing @ruby@, but also he agreed to supervise the content of it. In addition, he helped my stay in Florida with simultaneous translation. There are plenty of things beyond enumeration I have to say thanks to him. Instead of writing all the things, I -give this book to him. +give this book to him. Next, I would like to thank arton, who proposed me to publish this book. The words of arton always moves me. One of the things I'm currently struggled due -to his words is that I have no reason I don't get a .NET machine. +to his words is that I have no reason I don't get a .NET machine. Koji Arai, the 'captain' of documentation in the Ruby society, conducted a scrutiny review as if he became the official editor of this book while I was -not told so. I thank all his review. +not told so. I thank all his review. Also I'd like to mention those who gave me comments, pointed out mistakes and submitted proposals about the construction of the book throughout all my work. -Tietew, -Yuya, -Kawaji, -Gotoken, -Tamura, -Funaba, -Morikyu, -Ishizuka, -Shimomura, -Kubo, -Sukeda, -Nishiyama, -Fujimoto, -Yanagawa, -(I'm sorry if there's any people missing), -I thank all those people contributed. +Tietew, +Yuya, +Kawaji, +Gotoken, +Tamura, +Funaba, +Morikyu, +Ishizuka, +Shimomura, +Kubo, +Sukeda, +Nishiyama, +Fujimoto, +Yanagawa, +(I'm sorry if there's any people missing), +I thank all those people contributed. As a final note, I thank Otsuka , Haruta, and Kanemitsu who you for arranging everything despite my broke deadline as much as four times, and that the -manuscript exceeded 200 pages than originally planned. +manuscript exceeded 200 pages than originally planned. I cannot expand the full list here to mention the name of all people contributed to this book, but I say that I couldn't successfully publish this book without such assistance. Let me take this place to express my -appreciation. Thank you very much. +appreciation. Thank you very much. -p(=right). +p(=right). If you want to send remarks, suggestions and reports of typographcal errors, -please address to " ":mailto:aamine@loveruby.net. +please address to " ":mailto:aamine@loveruby.net. ""Rubyソースコード完全解説" can be reserved/ordered at ImpressDirect. ":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721"(Jump to the introduction page)":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721 -Copyright (c) 2002-2004 Minero Aoki, All rights reserved. +Copyright (c) 2002-2004 Minero Aoki, All rights reserved. From 1b3e6336c2aafa0da978a6c919d023d56ba29818 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 18 Aug 2013 07:54:31 +0900 Subject: [PATCH 005/121] fix script/publish --- script/publish | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/script/publish b/script/publish index 760b1b6..8ea6758 100755 --- a/script/publish +++ b/script/publish @@ -7,18 +7,19 @@ # Usage is simple: # # gem install eeepub -# ruby ./epub.rb +# ./script/publish require 'eeepub' require 'date' require 'fileutils' today = Date.today -system("../jekyll build") +system("jekyll build") GUIDE_DIR = File.expand_path("../..", __FILE__) ORIGINAL_DIR = "#{GUIDE_DIR}/_site" TEMP_DIR = "epub_tmp" +EBOOK_DIR = File.join GUIDE_DIR, "ebooks" FileUtils.mkdir_p("#{TEMP_DIR}/images") FileUtils.cp(Dir["#{ORIGINAL_DIR}/images/*"], "#{TEMP_DIR}/images") @@ -101,6 +102,8 @@ epub = EeePub.make do nav navigation end + +FileUtils.mkdir_p EBOOK_DIR sha = `git rev-parse HEAD`[0..5] -epub.save("#{GUIDE_DIR}/ebooks/rgh-#{today}_#{sha}.epub") +epub.save("#{EBOOK_DIR}/rgh-#{today}_#{sha}.epub") FileUtils.rm_rf("#{TEMP_DIR}") From 01b5e06a6cbbc423556de389075c015539f84567 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 18 Aug 2013 08:10:50 +0900 Subject: [PATCH 006/121] specify the directories to exclude --- _config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/_config.yml b/_config.yml index b852a84..b37e81f 100644 --- a/_config.yml +++ b/_config.yml @@ -1,2 +1,3 @@ redcloth: hard_breaks: false +exclude: ["ebooks", "script", "original_repo"] From 6936c628eca42a51f540d1682c4370bb97015557 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 18 Aug 2013 08:57:01 +0900 Subject: [PATCH 007/121] let GitHub pages use ./htmls as the source directory --- README.md | 4 ++-- _config.htmls.yml | 4 ++++ _config.local.yml | 3 +++ _config.yml | 3 ++- script/publish | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 _config.htmls.yml create mode 100644 _config.local.yml diff --git a/README.md b/README.md index 8111490..b1696c9 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Running the site locally $ git clone https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com $ gem install jekyll $ gem install RedCloth -$ jekyll serve # this compiles files and starts a server on localhost:4000. +$ jekyll serve --config _config.local.yml # this compiles files and starts a server on localhost:4000. ``` @@ -33,7 +33,7 @@ For Bundler users ```sh $ git clone https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com $ bundle install -$ jekyll serve # this compiles files and starts a server on localhost:4000. +$ jekyll serve --config _config.local.yml # this compiles files and starts a server on localhost:4000. ``` diff --git a/_config.htmls.yml b/_config.htmls.yml new file mode 100644 index 0000000..ff58ad1 --- /dev/null +++ b/_config.htmls.yml @@ -0,0 +1,4 @@ +redcloth: + hard_breaks: false +exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] +destination: htmls diff --git a/_config.local.yml b/_config.local.yml new file mode 100644 index 0000000..b4d19e5 --- /dev/null +++ b/_config.local.yml @@ -0,0 +1,3 @@ +redcloth: + hard_breaks: false +exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] diff --git a/_config.yml b/_config.yml index b37e81f..6acff37 100644 --- a/_config.yml +++ b/_config.yml @@ -1,3 +1,4 @@ redcloth: hard_breaks: false -exclude: ["ebooks", "script", "original_repo"] +exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] +source: htmls diff --git a/script/publish b/script/publish index 8ea6758..a1ed71a 100755 --- a/script/publish +++ b/script/publish @@ -14,7 +14,7 @@ require 'date' require 'fileutils' today = Date.today -system("jekyll build") +system("jekyll build --config _config.local.yml") GUIDE_DIR = File.expand_path("../..", __FILE__) ORIGINAL_DIR = "#{GUIDE_DIR}/_site" From 4470694b1ab7e5190b7e503e69403a19fd47bf2b Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 18 Aug 2013 09:10:19 +0900 Subject: [PATCH 008/121] commit the generated htmls for Github Pages --- htmls/anyeval.html | 675 ++++++++++++++ htmls/class.html | 1422 +++++++++++++++++++++++++++++ htmls/contextual.html | 1755 +++++++++++++++++++++++++++++++++++ htmls/css/styles.css | 173 ++++ htmls/evaluator.html | 1236 +++++++++++++++++++++++++ htmls/fin.html | 364 ++++++++ htmls/gc.html | 1652 +++++++++++++++++++++++++++++++++ htmls/index.html | 129 +++ htmls/intro.html | 1021 +++++++++++++++++++++ htmls/iterator.html | 1094 ++++++++++++++++++++++ htmls/load.html | 906 ++++++++++++++++++ htmls/method.html | 921 +++++++++++++++++++ htmls/minimum.html | 1251 +++++++++++++++++++++++++ htmls/module.html | 1560 +++++++++++++++++++++++++++++++ htmls/name.html | 591 ++++++++++++ htmls/object.html | 1011 +++++++++++++++++++++ htmls/parser.html | 2014 +++++++++++++++++++++++++++++++++++++++++ htmls/preface.html | 247 +++++ htmls/security.html | 208 +++++ htmls/spec.html | 1675 ++++++++++++++++++++++++++++++++++ htmls/syntree.html | 1615 +++++++++++++++++++++++++++++++++ htmls/thread.html | 1153 +++++++++++++++++++++++ htmls/variable.html | 589 ++++++++++++ htmls/yacc.html | 1013 +++++++++++++++++++++ 24 files changed, 24275 insertions(+) create mode 100644 htmls/anyeval.html create mode 100644 htmls/class.html create mode 100644 htmls/contextual.html create mode 100644 htmls/css/styles.css create mode 100644 htmls/evaluator.html create mode 100644 htmls/fin.html create mode 100644 htmls/gc.html create mode 100644 htmls/index.html create mode 100644 htmls/intro.html create mode 100644 htmls/iterator.html create mode 100644 htmls/load.html create mode 100644 htmls/method.html create mode 100644 htmls/minimum.html create mode 100644 htmls/module.html create mode 100644 htmls/name.html create mode 100644 htmls/object.html create mode 100644 htmls/parser.html create mode 100644 htmls/preface.html create mode 100644 htmls/security.html create mode 100644 htmls/spec.html create mode 100644 htmls/syntree.html create mode 100644 htmls/thread.html create mode 100644 htmls/variable.html create mode 100644 htmls/yacc.html diff --git a/htmls/anyeval.html b/htmls/anyeval.html new file mode 100644 index 0000000..e7998da --- /dev/null +++ b/htmls/anyeval.html @@ -0,0 +1,675 @@ + + + + + Chapter 17: Dynamic evaluation | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 17: Dynamic evaluation

+

Overview

+

I have already finished to describe about the mechanism of the evaluator by the +previous chapter. +In this chapter, by including the parser in addition to it, +let’s examine the big picture as “the evaluator in a broad sense”. +There are three targets: eval, Module#module_eval and +Object#instance_eval.

+

eval

+

I’ve already described about eval, +but I’ll introduce more tiny things about it here.

+

By using eval, you can compile and evaluate a string at runtime in the place. +Its return value is the value of the last expression of the program.

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

You can also refer to a variable in its scope from inside of a string to eval.

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

Readers who have been reading until here cannot simply read and pass over the +word “its scope”. For instance, you are curious about how is its “scope” of +constants, aren’t you? I am. To put the bottom line first, basically you +can think it directly inherits the environment of outside of eval.

+

And you can also define methods and define classes.

+
+def a
+  eval('class C;  def test() puts("ok") end   end')
+end
+
+a()          # define class C and C#test
+C.new.test   # shows ok
+
+

Moreover, as mentioned a little in the previous chapter, +when you pass a Proc as the second argument, the string can be evaluated in +its environment.

+
+def new_env
+  n = 5
+  Proc.new { nil }   # turn the environment of this method into an object and return it
+end
+
+p eval('n * 3', new_env())   # 15
+
+

module_eval and instance_eval

+

When a Proc is passed as the second argument of eval, the evaluations can be +done in its environment. module_eval and instance_eval is its limited (or +shortcut) version. With module_eval, you can evaluate in an environment that +is as if in a module statement or a class statement.

+
+lvar = "toplevel lvar"   # a local variable to confirm this scope
+
+module M
+end
+M.module_eval(<<'EOS')   # a suitable situation to use here-document
+    p lvar   # referable
+    p self   # shows M
+    def ok   # define M#ok
+      puts 'ok'
+    end
+EOS
+
+

With instance_eval, you can evaluate in an environment whose self of the +singleton class statement is the object.

+
+lvar = "toplevel lvar"   # a local variable to confirm this scope
+
+obj = Object.new
+obj.instance_eval(<<'EOS')
+    p lvar   # referable
+    p self   # shows #<Object:0x40274f5c>
+    def ok   # define obj.ok
+      puts 'ok'
+    end
+EOS
+
+

Additionally, these module_eval and instance_eval can also be used as +iterators, a block is evaluated in each environment in that case. +For instance,

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

Like this.

+

However, between the case when using a string and the case when using a block, +the behavior around local variables is different each other. +For example, when creating a block in the a method then doing instance_eval +it in the b method, the block would refer to the local variables of a. +When creating a string in the a method then doing instance_eval it in the +b method, from inside of the string, it would refer to the local variables of b. +The scope of local variables is decided “at compile time”, +the consequence differs because a string is compiled every time but a block is +compiled when loading files.

+

eval

+

eval()

+

The eval of Ruby branches many times based on the presence and absence of the +parameters. Let’s assume the form of call is limited to the below:

+
+eval(prog_string, some_block)
+
+

Then, since this makes the actual interface function rb_f_eval() almost +meaningless, we’ll start with the function eval() which is one step lower. +The function prototype of eval() is:

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

scope is the Proc of the second parameter. +file and line is the file name and line number of where a string to eval +is supposed to be located. Then, let’s see the content:

+

eval() (simplified)

+ +
+4984  static VALUE
+4985  eval(self, src, scope, file, line)
+4986      VALUE self, src, scope;
+4987      char *file;
+4988      int line;
+4989  {
+4990      struct BLOCK *data = NULL;
+4991      volatile VALUE result = Qnil;
+4992      struct SCOPE * volatile old_scope;
+4993      struct BLOCK * volatile old_block;
+4994      struct RVarmap * volatile old_dyna_vars;
+4995      VALUE volatile old_cref;
+4996      int volatile old_vmode;
+4997      volatile VALUE old_wrapper;
+4998      struct FRAME frame;
+4999      NODE *nodesave = ruby_current_node;
+5000      volatile int iter = ruby_frame->iter;
+5001      int state;
+5002
+5003      if (!NIL_P(scope)) {  /* always true now */
+5009          Data_Get_Struct(scope, struct BLOCK, data);
+5010          /* push BLOCK from data */
+5011          frame = data->frame;
+5012          frame.tmp = ruby_frame; /* to prevent from GC */
+5013          ruby_frame = &(frame);
+5014          old_scope = ruby_scope;
+5015          ruby_scope = data->scope;
+5016          old_block = ruby_block;
+5017          ruby_block = data->prev;
+5018          old_dyna_vars = ruby_dyna_vars;
+5019          ruby_dyna_vars = data->dyna_vars;
+5020          old_vmode = scope_vmode;
+5021          scope_vmode = data->vmode;
+5022          old_cref = (VALUE)ruby_cref;
+5023          ruby_cref = (NODE*)ruby_frame->cbase;
+5024          old_wrapper = ruby_wrapper;
+5025          ruby_wrapper = data->wrapper;
+5032          self = data->self;
+5033          ruby_frame->iter = data->iter;
+5034      }
+5045      PUSH_CLASS();
+5046      ruby_class = ruby_cbase;  /* == ruby_frame->cbase */
+5047
+5048      ruby_in_eval++;
+5049      if (TYPE(ruby_class) == T_ICLASS) {
+5050          ruby_class = RBASIC(ruby_class)->klass;
+5051      }
+5052      PUSH_TAG(PROT_NONE);
+5053      if ((state = EXEC_TAG()) == 0) {
+5054          NODE *node;
+5055
+5056          result = ruby_errinfo;
+5057          ruby_errinfo = Qnil;
+5058          node = compile(src, file, line);
+5059          if (ruby_nerrs > 0) {
+5060              compile_error(0);
+5061          }
+5062          if (!NIL_P(result)) ruby_errinfo = result;
+5063          result = eval_node(self, node);
+5064      }
+5065      POP_TAG();
+5066      POP_CLASS();
+5067      ruby_in_eval--;
+5068      if (!NIL_P(scope)) {  /* always true now */
+5069          int dont_recycle = ruby_scope->flags & SCOPE_DONT_RECYCLE;
+5070
+5071          ruby_wrapper = old_wrapper;
+5072          ruby_cref  = (NODE*)old_cref;
+5073          ruby_frame = frame.tmp;
+5074          ruby_scope = old_scope;
+5075          ruby_block = old_block;
+5076          ruby_dyna_vars = old_dyna_vars;
+5077          data->vmode = scope_vmode; /* save the modification of the visibility scope */
+5078          scope_vmode = old_vmode;
+5079          if (dont_recycle) {
+                  /* ……copy SCOPE BLOCK VARS…… */
+5097          }
+5098      }
+5104      if (state) {
+5105          if (state == TAG_RAISE) {
+                  /* ……prepare an exception object…… */
+5121              rb_exc_raise(ruby_errinfo);
+5122          }
+5123          JUMP_TAG(state);
+5124      }
+5125
+5126      return result;
+5127  }
+
+(eval.c)
+
+

If this function is shown without any preamble, you probably feel “oww!”. +But we’ve defeated many functions of eval.c until here, +so this is not enough to be an enemy of us. +This function is just continuously saving/restoring the stacks. +The points we need to care about are only the below three:

+
    +
  • unusually FRAME is also replaced (not copied and pushed)
  • +
  • ruby_cref is substituted (?) by ruby_frame->cbase
  • +
  • only scope_vmode is not simply restored but influences data.
  • +
+

And the main parts are the compile() and eval_node() located around the +middle. Though it’s possible that eval_node() has already been forgotten, +it is the function to start the evaluation of the parameter node. +It was also used in ruby_run().

+

Here is compile().

+

compile()

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

ruby_nerrs is the variable incremented in yyerror(). +In other words, if this variable is non-zero, it indicates more than one parse +error happened. And, rb_compile_string() was already discussed in Part 2. +It was a function to compile a Ruby string into a syntax tree.

+

One thing becomes a problem here is local variable. +As we’ve seen in Chapter 12: Syntax tree construction, +local variables are managed by using lvtbl. +However, since a SCOPE (and possibly also VARS) already exists, +we need to parse in the way of writing over and adding to it. +This is in fact the heart of eval(), +and is the worst difficult part. +Let’s go back to parse.y again and complete this investigation.

+

top_local

+

I’ve mentioned that the functions named local_push() local_pop() are used +when pushing struct local_vars, which is the management table of local +variables, +but actually there’s one more pair of functions to push the management table. +It is the pair of top_local_init() and top_local_setup(). +They are called in this sort of way.

+

▼ How top_local_init() is called

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

Of course, in actuality various other things are also done, +but all of them are cut here because it’s not important. +And this is the content of it:

+

top_local_init()

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

This means that local_tbl is copied from ruby_scope to lvtbl. +As for block local variables, since it’s better to see them all at once later, +we’ll focus on ordinary local variables for the time being. +Next, here is top_local_setup().

+

top_local_setup()

+ +
+5291  static void
+5292  top_local_setup()
+5293  {
+5294      int len = lvtbl->cnt;  /* the number of local variables after parsing */
+5295      int i;                 /* the number of local varaibles before parsing */
+5296
+5297      if (len > 0) {
+5298          i = ruby_scope->local_tbl ? ruby_scope->local_tbl[0] : 0;
+5299
+5300          if (i < len) {
+5301              if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
+5302                  VALUE *vars = ALLOC_N(VALUE, len+1);
+5303                  if (ruby_scope->local_vars) {
+5304                      *vars++ = ruby_scope->local_vars[-1];
+5305                      MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
+5306                      rb_mem_clear(vars+i, len-i);
+5307                  }
+5308                  else {
+5309                      *vars++ = 0;
+5310                      rb_mem_clear(vars, len);
+5311                  }
+5312                  ruby_scope->local_vars = vars;
+5313                  ruby_scope->flags |= SCOPE_MALLOC;
+5314              }
+5315              else {
+5316                  VALUE *vars = ruby_scope->local_vars-1;
+5317                  REALLOC_N(vars, VALUE, len+1);
+5318                  ruby_scope->local_vars = vars+1;
+5319                  rb_mem_clear(ruby_scope->local_vars+i, len-i);
+5320              }
+5321              if (ruby_scope->local_tbl &&
+                      ruby_scope->local_vars[-1] == 0) {
+5322                  free(ruby_scope->local_tbl);
+5323              }
+5324              ruby_scope->local_vars[-1] = 0;  /* NODE is not necessary anymore */
+5325              ruby_scope->local_tbl = local_tbl();
+5326          }
+5327      }
+5328      local_pop();
+5329  }
+
+(parse.y)
+
+

Since local_vars can be either in the stack or in the heap, it makes the code +complex to some extent. However, this is just updating local_tbl and +local_vars of ruby_scope. (When SCOPE_MALLOC was set, local_vars was +allocated by malloc()). And here, because there’s no meaning of using alloca(), +it is forced to change its allocation method to malloc.

+

Block Local Variable

+

By the way, how about block local variables? +To think about this, we have to go back to the entry point of the parser first, +it is yycompile().

+

▼ setting ruby_dyna_vars aside

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

This looks like a mere save-restore, but the point is that this does not clear +the ruby_dyna_vars. This means that also in the parser it directly adds +elements to the link of RVarmap created in the evaluator.

+

However, according to the previous description, the structure of +ruby_dyna_vars differs between the parser and the evalutor. +How does it deal with the difference in the way of attaching the header +(RVarmap whose id=0)?

+

What is helpful here is the “1” of local_push(1) in top_local_init(). +When the argument of local_push() becomes true, +it does not attach the first header of ruby_dyna_vars. +It means, it would look like Figure 1. Now, it is assured that +we can refer to the block local variables of the outside scope +from inside of a string to eval.

+
+

(dynavars)
+Figure 1: ruby_dyna_vars inside eval

+
    +
  • パーサで追加 added in the parser
  • +
  • 評価機で作成 created in the evaluator +
+ +

Well, it’s sure we can refer to, +but didn’t you say that ruby_dyna_vars is entirely freed in the parser? +What can we do if the link created at the evaluator will be freed? +… +I’d like the readers who noticed this to be relieved by reading the next part.

+

yycompile() − freeing ruby_dyna_vars

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

It is designed so that the loop would stop +when it reaches the link created at the evaluator (vars).

+

instance_eval

+

The Whole Picture

+

The substance of Module#module_eval is rb_mod_module_eval(), +and the substance of Object#instance_eval is rb_obj_instance_eval().

+

rb_mod_module_eval() rb_obj_instance_eval()

+ +
+5316  VALUE
+5317  rb_mod_module_eval(argc, argv, mod)
+5318      int argc;
+5319      VALUE *argv;
+5320      VALUE mod;
+5321  {
+5322      return specific_eval(argc, argv, mod, mod);
+5323  }
+
+5298  VALUE
+5299  rb_obj_instance_eval(argc, argv, self)
+5300      int argc;
+5301      VALUE *argv;
+5302      VALUE self;
+5303  {
+5304      VALUE klass;
+5305
+5306      if (rb_special_const_p(self)) {
+5307          klass = Qnil;
+5308      }
+5309      else {
+5310          klass = rb_singleton_class(self);
+5311      }
+5312
+5313      return specific_eval(argc, argv, klass, self);
+5314  }
+
+(eval.c)
+
+

These two methods have a common part as “a method to replace self with class”, +that part is defined as specific_eval(). +Figure 2 shows it and also what will be described. +What with parentheses are calls by function pointers.

+

+

(speceval)
+Figure 2: Call Graph

+

+

Whichever instance_eval or module_eval, +it can accept both a block and a string, +thus it branches for each particular process to yield and eval respectively. +However, most of them are also common again, +this part is extracted as exec_under().

+

But for those who reading, one have to simultaneously face at 2 times 2 = 4 ways, +it is not a good plan. Therefore, here we assume only the case when

+
    +
  1. it is an instance_eval
  2. +
  3. which takes a string as its argument
  4. +
+

. And extracting all functions under rb_obj_instance_eval() in-line, +folding constants, we’ll read the result.

+

After Absorbed

+

After all, +it becomes very comprehensible in comparison to the one before being absorbed.

+

specific_eval()instance_eval, eval, string

+ +
+static VALUE
+instance_eval_string(self, src, file, line)
+    VALUE self, src;
+    const char *file;
+    int line;
+{
+    VALUE sclass;
+    VALUE result;
+    int state;
+    int mode;
+
+    sclass = rb_singleton_class(self);
+
+    PUSH_CLASS();
+    ruby_class = sclass;
+    PUSH_FRAME();
+    ruby_frame->self       = ruby_frame->prev->self;
+    ruby_frame->last_func  = ruby_frame->prev->last_func;
+    ruby_frame->last_class = ruby_frame->prev->last_class;
+    ruby_frame->argc       = ruby_frame->prev->argc;
+    ruby_frame->argv       = ruby_frame->prev->argv;
+    if (ruby_frame->cbase != sclass) {
+        ruby_frame->cbase = rb_node_newnode(NODE_CREF, sclass, 0,
+                                            ruby_frame->cbase);
+    }
+    PUSH_CREF(sclass);
+
+    mode = scope_vmode;
+    SCOPE_SET(SCOPE_PUBLIC);
+    PUSH_TAG(PROT_NONE);
+    if ((state = EXEC_TAG()) == 0) {
+        result = eval(self, src, Qnil, file, line);
+    }
+    POP_TAG();
+    SCOPE_SET(mode);
+
+    POP_CREF();
+    POP_FRAME();
+    POP_CLASS();
+    if (state) JUMP_TAG(state);
+
+    return result;
+}
+
+

It seems that this pushes the singleton class of the object to CLASS and +CREF and ruby_frame->cbase. +The main process is one-shot of eval(). +It is unusual that things such as initializing FRAME by a struct-copy are +missing, but this is also not create so much difference.

+

Before being absorbed

+

Though the author said it becomes more friendly to read, +it’s possible it has been already simple since it was not absorbed, +let’s check where is simplified in comparison to the before-absorbed one.

+

The first one is specific_eval(). Since this function is to share the code of +the interface to Ruby, almost all parts of it is to parse the parameters. +Here is the result of cutting them all.

+

specific_eval() (simplified)

+ +
+5258  static VALUE
+5259  specific_eval(argc, argv, klass, self)
+5260      int argc;
+5261      VALUE *argv;
+5262      VALUE klass, self;
+5263  {
+5264      if (rb_block_given_p()) {
+
+5268          return yield_under(klass, self);
+5269      }
+5270      else {
+
+5294          return eval_under(klass, self, argv[0], file, line);
+5295      }
+5296  }
+
+(eval.c)
+
+

As you can see, this is perfectly branches in two ways based on whether there’s +a block or not, and each route would never influence the other. +Therefore, when reading, we should read one by one. +To begin with, the absorbed version is enhanced in this point.

+

And file and line are irrelevant when reading yield_under(), +thus in the case when the route of yield is absorbed by the main body, +it might become obvious that we don’t have to think about the parse of these +parameters at all.

+

Next, we’ll look at eval_under() and eval_under_i().

+

eval_under()

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

In this function, in order to make its arguments single, +it stores them into the args array and passes it. +We can imagine that this args exists as a temporary container to pass from +eval_under() to eval_under_i(), +but not sure that it is truly so. +It’s possible that args is modified inside evec_under().

+

As a way to share a code, this is a very right way to do. +But for those who read it, this kind of indirect passing is incomprehensible. +Particularly, because there are extra castings for file and line to fool +the compiler, it is hard to imagine what were their actual types. +The parts around this entirely disappeared in the absorbed version, +so you don’t have to worry about getting lost.

+

However, it’s too much to say that absorbing and extracting always makes things +easier to understand. +For example, when calling exec_under(), under is passed as both the second +and third arguments, but is it all right if the exec_under() side extracts +the both parameter variables into under? +That is to say, the second and third arguments of exec_under() are, in fact, +indicating CLASS and CREF that should be pushed. +CLASS and CREF are “different things”, +it might be better to use different variables. +Also in the previous absorbed version, for only this point,

+
+VALUE sclass = .....;
+VALUE cbase = sclass;
+
+

I thought that I would write this way, +but also thought it could give the strange impression +if abruptly only these variables are left, +thus it was extracted as sclass. +It means that this is only because of the flow of the texts.

+

By now, so many times, I’ve extracted arguments and functions, +and for each time I repeatedly explained the reason to extract. +They are

+
    +
  • there are only a few possible patterns
  • +
  • the behavior can slightly change
  • +
+

Definitely, I’m not saying +“In whatever ways extracting various things always makes things simpler”.

+

In whatever case, what of the first priority is the comprehensibility for +ourself and not keep complying the methodology. +When extracting makes things simpler, extract it. +When we feel that not extracting or conversely bundling as a procedure makes +things easier to understand, let us do it. +As for ruby, I often extracted them because the original is written properly, +but if a source code was written by a poor programmer, +aggressively bundling to functions should often become a good choice.

+ + + +
+ + diff --git a/htmls/class.html b/htmls/class.html new file mode 100644 index 0000000..14f0036 --- /dev/null +++ b/htmls/class.html @@ -0,0 +1,1422 @@ + + + + + Classes and modules | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Vincent ISAMBART

+

Chapter 4: Classes and modules

+

In this chapter, we’ll see the details of the data structures created +for classes and modules.

+

Classes and methods definition

+

First, I’d like to have a look at how Ruby classes are defined at the +C level. This chapter investigates almost only particular +cases, so I’d like you to know first the way used most often.

+

The main API to define classes and modules consists of the following 6 +functions:

+
    +
  • rb_define_class()
  • +
  • rb_define_class_under()
  • +
  • rb_define_module()
  • +
  • rb_define_module_under()
  • +
  • rb_define_method()
  • +
  • rb_define_singleton_method()
  • +
+

There are a few other versions of these functions, but the extension +libraries and even most of the core library is defined using just this +API. I’ll introduce to you these functions one by one.

+

Class definition

+

rb_define_class() defines a class at the top-level. Let’s take the +Ruby array class, Array, as an example.

+

Array class definition +

+  19  VALUE rb_cArray;

+

1809 void +1810 Init_Array() +1811 { +1812 rb_cArray = rb_define_class(“Array”, rb_cObject);

+

(array.c) +

+

rb_cObject and rb_cArray correspond respectively to Object and +Array at the Ruby level. The added prefix rb shows that it belongs +to ruby and the c that it is a class object. These naming rules +are used everywhere in ruby.

+

This call to rb_define_class() defines a class called Array, which +inherits from Object. At the same time as rb_define_class() creates +the class object, it also defines the constant. That means that after this +you can already access Array from a Ruby program. It corresponds to +the following Ruby program:

+
+class Array < Object
+
+

I’d like you to note the fact that there is no end. It was +written like this on purpose. It is because with rb_define_class() +the body of the class has not been executed.

+

Nested class definition

+

After that, there’s rb_define_class_under(). This function defines a +class nested in an other class or module. This time the example is +what is returned by stat(2), File::Stat.

+

▼ Definition of File::Stat +

+  78  VALUE rb_cFile;
+  80  static VALUE rb_cStat;

+

2581 rb_cFile = rb_define_class(“File”, rb_cIO); +2674 rb_cStat = rb_define_class_under(rb_cFile, “Stat”, rb_cObject);

+

(file.c) +

+

This code corresponds to the following Ruby program;

+
+class File < IO
+  class Stat < Object
+
+

This time again I omitted the end on purpose.

+

Module definition

+

rb_define_module() is simple so let’s end this quickly.

+

▼ Definition of Enumerable +

+  17  VALUE rb_mEnumerable;

+492 rb_mEnumerable = rb_define_module(“Enumerable”); +

(enum.c) +

+

The m in the beginning of rb_mEnumerable is similar to the c for +classes: it shows that it is a module. The corresponding Ruby program +is:

+
+module Enumerable
+
+

rb_define_module_under() is not used much so we’ll skip it.

+

Method definition

+

This time the function is the one for defining methods, +rb_define_method(). It’s used very often. We’ll take once again an +example from Array.

+

▼ Definition of Array#to_s +

+1818  rb_define_method(rb_cArray, “to_s”, rb_ary_to_s, 0);

+

(array.c) +

+

With this the to_s method is defined in Array. The method body is +given by a function pointer (rb_ary_to_s). The fourth parameter is +the number of parameters taken by the method. As to_s does not take +any parameters, it’s 0. If we write the corresponding Ruby program, +we’ll have this:

+
+class Array < Object
+  def to_s
+    # content of rb_ary_to_s()
+  end
+end
+
+

Of course the class part is not included in rb_define_method() and +only the def part is accurate. But if there is no class part, it +will look like the method is defined like a function, so I also wrote +the enclosing class part.

+

One more example, this time taking a parameter:

+

▼ Definition of Array#concat +

+1835  rb_define_method(rb_cArray, “concat”, rb_ary_concat, 1);

+

(array.c) +

+

The class for the definition is rb_cArray +(Array), the method name is concat, its body +is rb_ary_concat() and the number of parameters is 1. It +corresponds to writing the corresponding Ruby program:

+
+class Array < Object
+  def concat( str )
+    # content of rb_ary_concat()
+  end
+end
+
+

Singleton methods definition

+

We can define methods that are specific to a single object instance. +They are called singleton methods. As I used File.unlink as +an example in chapter 1 “Ruby language minimum”, I first wanted to +show it here, but for a particular reason we’ll look at File.link +instead.

+

▼ Definition of File.link +

+2624  rb_define_singleton_method(rb_cFile, “link”, rb_file_s_link, 2);

+

(file.c) +

+

It’s used like rb_define_method(). The only difference is that here +the first parameter is just the object where the method is +defined. In this case, it’s defined in rb_cFile.

+

Entry point

+

Being able to make definitions like before is great, but where +are these functions called from, and by what means are they executed? +These definitions are grouped in functions named Init_xxxx(). For +instance, for Array a function Init_Array() like this has been +made:

+

Init_Array +

+1809  void
+1810  Init_Array()
+1811  {
+1812      rb_cArray  = rb_define_class(“Array”, rb_cObject);
+1813      rb_include_module(rb_cArray, rb_mEnumerable);
+1814
+1815      rb_define_singleton_method(rb_cArray, “allocate”,
+                                     rb_ary_s_alloc, 0);
+1816      rb_define_singleton_method(rb_cArray, “[]”, rb_ary_s_create, -1);
+1817      rb_define_method(rb_cArray, “initialize”, rb_ary_initialize, -1);
+1818      rb_define_method(rb_cArray, “to_s”, rb_ary_to_s, 0);
+1819      rb_define_method(rb_cArray, “inspect”, rb_ary_inspect, 0);
+1820      rb_define_method(rb_cArray, “to_a”, rb_ary_to_a, 0);
+1821      rb_define_method(rb_cArray, “to_ary”, rb_ary_to_a, 0);
+1822      rb_define_method(rb_cArray, “frozen?”,  rb_ary_frozen_p, 0);

+

(array.c) +

+

The Init for the built-in functions are explicitly called during +the startup of ruby. This is done in inits.c.

+

rb_call_inits() +

+  47  void
+  48  rb_call_inits()
+  49  {
+  50      Init_sym();
+  51      Init_var_tables();
+  52      Init_Object();
+  53      Init_Comparable();
+  54      Init_Enumerable();
+  55      Init_Precision();
+  56      Init_eval();
+  57      Init_String();
+  58      Init_Exception();
+  59      Init_Thread();
+  60      Init_Numeric();
+  61      Init_Bignum();
+  62      Init_Array();

+

(inits.c) +

+

This way, Init_Array() is called properly.

+

That explains it for the built-in libraries, but what about extension +libraries? In fact, for extension libraries the convention is the +same. Take the following code:

+
+require "myextension"
+
+

With this, if the loaded extension library is myextension.so, at +load time, the (extern) function named Init_myextension() is +called. How they are called is beyond the scope of this chapter. For +that, you should read chapter 18, “Load”. Here we’ll just end this +with an example of Init.

+

The following example is from stringio, an extension library +provided with ruby, that is to say not from a built-in library.

+

Init_stringio() (beginning) +

+ 895  void
+ 896  Init_stringio()
+ 897  {
+ 898      VALUE StringIO = rb_define_class(“StringIO”, rb_cData);
+ 899      rb_define_singleton_method(StringIO, “allocate”,
+                                     strio_s_allocate, 0);
+ 900      rb_define_singleton_method(StringIO, “open”, strio_s_open, -1);
+ 901      rb_define_method(StringIO, “initialize”, strio_initialize, -1);
+ 902      rb_enable_super(StringIO, “initialize”);
+ 903      rb_define_method(StringIO, “become”, strio_become, 1);
+ 904      rb_define_method(StringIO, “reopen”, strio_reopen, -1);

+

(ext/stringio/stringio.c) +

+

Singleton classes

+

rb_define_singleton_method()

+

You should now be able to more or less understand how normal methods are +defined. Somehow making the body of the method, then registering it +in m_tbl will do. But what about singleton methods? We’ll now look +into the way singleton methods are defined.

+

rb_define_singleton_method() +

+ 721  void
+ 722  rb_define_singleton_method(obj, name, func, argc)
+ 723      VALUE obj;
+ 724      const char name;
+ 725      VALUE (func)();
+ 726      int argc;
+ 727  {
+ 728      rb_define_method(rb_singleton_class(obj), name, func, argc);
+ 729  }

+

(class.c) +

+

As I explained, rb_define_method() is a function used to define +normal methods, so the difference from normal methods is only +rb_singleton_class(). But what on earth are singleton classes?

+

In brief, singleton classes are virtual classes that are only used +to execute singleton methods. Singleton methods are functions defined +in singleton classes. Classes themselves are in the first place (in a +way) the “implementation” to link objects and methods, but singleton +classes are even more on the implementation side. In the Ruby language +way, they are not formally included, and don’t appear much at the Ruby +level.

+

rb_singleton_class()

+

Well, let’s confirm what the singleton classes are made of. It’s too +simple to just show you the code of a function each time so this time +I’ll use a new weapon, a call graph.

+
+rb_define_singleton_method
+    rb_define_method
+    rb_singleton_class
+        SPECIAL_SINGLETON
+        rb_make_metaclass
+            rb_class_boot
+            rb_singleton_class_attached
+
+

Call graphs are graphs showing calling relationships among functions +(or more generally procedures). The call graphs showing all the calls +written in the source code are called static call graphs. The ones +expressing only the calls done during an execution are called dynamic +call graphs.

+

This diagram is a static call graph and the indentation expresses +which function calls which one. For instance, +rb_define_singleton_method() calls rb_define_method() and +rb_singleton_class(). And this rb_singleton_class() itself calls +SPECIAL_SINGLETON() and rb_make_metaclass().

+

Let’s go back to the code. When looking at the call graph, you can see +that the calls made by rb_singleton_class() go very deep. Until now +all call levels were shallow, so we could simply look at the functions +without getting too lost. But at this depth, I easily forget +what is going on in the code. That’s why in those situations I check +the call graph to have a better understanding. This time, we’ll decode +in parallel what the procedures below rb_singleton_class() do. The +two points to look out for are the following ones:

+
    +
  • What exactly are singleton classes?
  • +
  • What is the purpose of singleton classes?
  • +
+

Normal classes and singleton classes

+

Singleton classes are special classes: they’re basically the same as +normal classes, but there are a few differences. We can say that +finding these differences is explaining concretely singleton classes.

+

What should we do to find them? We should find the differences between +the function creating normal classes and the one creating singleton +classes. For this, we have to find the function for creating normal +classes. That is as normal classes can be defined by +rb_define_class(), it must call in a way or another a function to +create normal classes. For the moment, we’ll not look at the content +of rb_define_class() itself. I have some reasons to be interested in +something that’s deeper. That’s why we will first look at the call +graph of rb_define_class().

+
+rb_define_class
+    rb_class_inherited
+    rb_define_class_id
+        rb_class_new
+            rb_class_boot
+        rb_make_metaclass
+            rb_class_boot
+            rb_singleton_class_attached
+
+

I’m interested by rb_class_new(). Doesn’t this name means it creates +a new class? Let’s confirm that.

+

rb_class_new() +

+  37  VALUE
+  38  rb_class_new(super)
+  39      VALUE super;
+  40  {
+  41      Check_Type(super, T_CLASS);
+  42      if (super == rb_cClass) {
+  43          rb_raise(rb_eTypeError, “can’t make subclass of Class”);
+  44      }
+  45      if (FL_TEST(super, FL_SINGLETON)) {
+  46          rb_raise(rb_eTypeError, “can’t make subclass of virtual class”);
+  47      }
+  48      return rb_class_boot(super);
+  49  }

+

(class.c) +

+

Check_Type() is checks the type of object structure, so we can +ignore it. rb_raise() is error handling so we can ignore it. Only +rb_class_boot() remains. So let’s look at it.

+

rb_class_boot() +

+  21  VALUE
+  22  rb_class_boot(super)
+  23      VALUE super;
+  24  {
+  25      NEWOBJ;        /* allocates struct RClass /
+  26      OBJSETUP; / initialization of the RBasic part /
+  27
+  28      klass→super = super;       / (A) */
+  29      klass→iv_tbl = 0;
+  30      klass→m_tbl = 0;
+  31      klass→m_tbl = st_init_numtable();
+  32
+  33      OBJ_INFECT(klass, super);
+  34      return (VALUE)klass;
+  35  }

+

(class.c) +

+

NEWOBJ() and OBJSETUP() are fixed expressions used when creating +Ruby objects that possess one of the internal structure types (`struct +Rxxxx). They are both macros. In NEWOBJ, the struct RBasic member of the RClass (and thus +basic.klass and basic.flags) is initialized.

+

OBJ_INFECT() is a macro related to security. From now on, we’ll +ignore it.

+

At (A), the super member of klassis set to the super +parameter. It looks like rb_class_boot() is a function that creates +a class inheriting from super.

+

So, as rb_class_boot() is a function that creates a class, +what does rb_class_new() is very similar.

+

Then, let’s once more look at rb_singleton_class()’s call graph:

+
+rb_singleton_class
+    SPECIAL_SINGLETON
+    rb_make_metaclass
+        rb_class_boot
+        rb_singleton_class_attached
+
+

Here also rb_class_boot() is called. So up to that point, it’s the +same as in normal classes. What’s going on after is what’s different +between normal classes and singleton classes, in other words the +characteristics of singleton classes. If everything’s clear so +far, we just need to read rb_singleton_class() and +rb_make_metaclass().

+

Compressed rb_singleton_class()

+

rb_singleton_class() is a little long so we’ll first remove its +non-essential parts.

+

rb_singleton_class() +

+ 678  #define SPECIAL_SINGLETON(x,c) do {\
+ 679      if (obj == (x)) {\
+ 680          return c;\
+ 681      }\
+ 682  } while (0)

+684 VALUE +685 rb_singleton_class(obj) +686 VALUE obj; +687 { +688 VALUE klass; +689 +690 if (FIXNUM_P(obj) || SYMBOL_P(obj)) { +691 rb_raise(rb_eTypeError, “can’t define singleton”); +692 } +693 if (rb_special_const_p(obj)) { +694 SPECIAL_SINGLETON(Qnil, rb_cNilClass); +695 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); +696 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); +697 rb_bug(“unknown immediate %ld”, obj); +698 } +699 +700 DEFER_INTS; +701 if (FL_TEST(RBASIC→klass, FL_SINGLETON) && +702 (BUILTIN_TYPE(obj) == T_CLASS || +703 rb_iv_get(RBASIC→klass, “attached”) == obj)) { +704 klass = RBASIC→klass; +705 } +706 else { +707 klass = rb_make_metaclass(obj, RBASIC→klass); +708 } +709 if (OBJ_TAINTED(obj)) { +710 OBJ_TAINT(klass); +711 } +712 else { +713 FL_UNSET(klass, FL_TAINT); +714 } +715 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); +716 ALLOW_INTS; +717 +718 return klass; +719 } +

(class.c) +

+

The first and the second half are separated by a blank line. The first +half handles a special case and the second half handles the general +case. In other words, the second half is the trunk of the +function. That’s why we’ll keep it for later and talk about the first +half.

+

Everything that is handled in the first half are non-pointer VALUEs, +in other words objects without an existing C structure. First, +Fixnum and Symbol are explicitly picked. Then, +rb_special_const_p() is a function that returns true for non-pointer +VALUEs, so there only Qtrue, Qfalse and Qnil should get +caught. Other than that, there are no valid non-pointer value so a bug +is reported with rb_bug().

+

DEFER_INTS() and ALLOW_INTS() both end with the same INTS so you +should see a pair in them. That’s the case, and they are macros +related to signals. Because they are defined in rubysig.h, you can +guess that INTS is the abbreviation of interrupts. You can ignore +them.

+

Compressed rb_make_metaclass()

+

rb_make_metaclass() +

+ 142  VALUE
+ 143  rb_make_metaclass(obj, super)
+ 144      VALUE obj, super;
+ 145  {
+ 146      VALUE klass = rb_class_boot(super);
+ 147      FL_SET(klass, FL_SINGLETON);
+ 148      RBASIC→klass = klass;
+ 149      rb_singleton_class_attached(klass, obj);
+ 150      if (BUILTIN_TYPE(obj) == T_CLASS) {
+ 151          RBASIC→klass = klass;
+ 152          if (FL_TEST(obj, FL_SINGLETON)) {
+ 153              RCLASS→super =
+                          RBASIC→super))→klass;
+ 154          }
+ 155      }
+ 156
+ 157      return klass;
+ 158  }

+

(class.c) +

+

We already saw rb_class_boot(). It creates a (normal) class using +the super parameter as its superclass. After that, the +FL_SINGLETON of this class is set. This is clearly suspicious. The +name of the function makes us think that it is not the indication of +a singleton class.

+

What are singleton classes?

+

Continuing the simplification process, furthermore as parameters, +return values, local variables are all VALUE, we can throw away the +declarations. That makes us able to compress to the following:

+

rb_singleton_class() rb_make_metaclass() (after compression) +

+rb_singleton_class(obj)
+{
+    if (FL_TEST(RBASIC→klass, FL_SINGLETON) &&
+        (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) &&
+        rb_iv_get(RBASIC→klass, “attached”) == obj) {
+        klass = RBASIC→klass;
+    }
+    else {
+        klass = rb_make_metaclass(obj, RBASIC→klass);
+    }
+    return klass;
+}

+

rb_make_metaclass(obj, super) +{ + klass = create a class with super as superclass; + FL_SET(klass, FL_SINGLETON); + RBASIC→klass = klass; + rb_singleton_class_attached(klass, obj); + if (BUILTIN_TYPE(obj) == T_CLASS) { + RBASIC→klass = klass; + if (FL_TEST(obj, FL_SINGLETON)) { + RCLASS→super = + RBASIC→super))→klass; + } + }

+return klass; +

} +

+

The condition of the if statement of rb_singleton_class() seems +quite complicated. However, this condition is not connected to the +mainstream of rb_make_metaclass() so we’ll see it later. Let’s first +think about what happens on the false branch of the if.

+

The BUILTIN_TYPE() of rb_make_metaclass() is similar to TYPE() +as it is a macro to get the structure type flag (T_xxxx). That means +this check in rb_make_metaclass means “if obj is a class”. For the +moment it’s better not to limit ourselves to obj being a class, so +we’ll remove it.

+

With these simplifications, we get the the following:

+

rb_singleton_class() rb_make_metaclass() (after recompression) +

+rb_singleton_class(obj)
+{
+    klass = create a class with RBASIC→klass as superclass;
+    FL_SET(klass, FL_SINGLETON);
+    RBASIC→klass = klass;
+    return klass;
+}
+

+

But there is still a quite hard to understand side to it. That’s +because klass is used too often. So let’s rename the klass +variable to sclass.

+

rb_singleton_class() rb_make_metaclass() (variable substitution) +

+rb_singleton_class(obj)
+{
+    sclass = create a class with RBASIC→klass as superclass;
+    FL_SET(sclass, FL_SINGLETON);
+    RBASIC→klass = sclass;
+    return sclass;
+}
+

+

Now it should be very easy to understand. To make it even simpler, +I’ve represented what is done with a diagram (figure 1). In the +horizontal direction is the “instance – class” relation, and in the +vertical direction is inheritance (the superclasses are above).

+

+

(addsclass)
+Figure 1: rb_singleton_class

+

+

When comparing the first and last part of this diagram, you can +understand that sclass is inserted without changing the +structure. That’s all there is to singleton classes. In other words +the inheritance is increased one step. If a method is defined in a +singleton class, this construction allows the other instances of +klass to define completely different methods.

+

Singleton classes and instances

+

By the way, you must have seen that during the compression process, +the call to rb_singleton_class_attached() was stealthily +removed. Here:

+
+rb_make_metaclass(obj, super)
+{
+    klass = create a class with super as superclass;
+    FL_SET(klass, FL_SINGLETON);
+    RBASIC(obj)->klass = klass;
+    rb_singleton_class_attached(klass, obj);   /* THIS */
+
+

Let’s have a look at what it does.

+

rb_singleton_class_attached() +

+ 130  void
+ 131  rb_singleton_class_attached(klass, obj)
+ 132      VALUE klass, obj;
+ 133  {
+ 134      if (FL_TEST(klass, FL_SINGLETON)) {
+ 135          if (!RCLASS→iv_tbl) {
+ 136              RCLASS→iv_tbl = st_init_numtable();
+ 137          }
+ 138          st_insert(RCLASS→iv_tbl,
+                        rb_intern(“attached”), obj);
+ 139      }
+ 140  }

+

(class.c) +

+

If the FL_SINGLETON flag of klass is set… in other words if it’s a +singleton class, put the __attached__obj relation in the +instance variable table of klass (iv_tbl). That’s how it looks +like (in our case klass is always a singleton class… in other +words its FL_SINGLETON flag is always set).

+

__attached__ does not have the @ prefix, but it’s stored in the +instance variables table so it’s still an instance variable. Such an +instance variable can never be read at the Ruby level so it can be +used to keep values for the system’s exclusive use.

+

Let’s now think about the relationship between klass and +obj. klass is the singleton class of obj. In other words, this +“invisible” instance variable allows the singleton class to remember +the instance it was created from. Its value is used when the singleton +class is changed, notably to call hook methods on the instance +(i.e. obj). For example, when a method is added to a singleton +class, the obj‘s singleton_method_added method is called. There is +no logical necessity to doing it, it was done because that’s how it +was defined in the language.

+

But is it really all right? Storing the instance in __attached__ +will force one singleton class to have only one attached instance. For +example, by getting (in some way or an other) the singleton class and +calling new on it, won’t a singleton class end up having multiple +instances?

+

This cannot be done because the proper checks are done to prevent the +creation of an instance of a singleton class.

+

Singleton classes are in the first place for singleton +methods. Singleton methods are methods existing only on a particular +object. If singleton classes could have multiple instances, there +would the same as normal classes. That’s why they are forced to only +have one instance.

+

Summary

+

We’ve done a lot, maybe made a real mayhem, so let’s finish and put +everything in order with a summary.

+

What are singleton classes? They are classes that have the +FL_SINGLETON flag set and that can only have one instance.

+

What are singleton methods? They are methods defined in the singleton +class of an object.

+

Metaclasses

+

Inheritance of singleton methods

+

Infinite chain of classes

+

Even a class has a class, and it’s Class. And the class of Class +is again Class. We find ourselves in an infinite loop (figure 2).

+

+

(infloop)
+Figure 2: Infinite loop of classes

+

+

Up to here it’s something we’ve already gone through. What’s going +after that is the theme of this chapter. Why do classes have to make a +loop?

+

First, in Ruby all data are objects. And classes are data so in Ruby +they have to be objects.

+

As they are objects, they must answer to methods. And setting the rule +“to answer to methods you must belong to a class” made processing +easier. That’s where comes the need for a class to also have a class.

+

Let’s base ourselves on this and think about the way to implement it. +First, we can try first with the most naïve way, Class‘s class is +ClassClass, ClassClass’s class is ClassClassClass…, chaining +classes of classes one by one. But whichever the way you look at it, +this can’t be implemented effectively. That’s why it’s common in +object oriented languages where classes are objects that Class’s +class is to Class itself, creating an endless virtual instance-class +relationship.

+

I’m repeating myself, but the fact that Class‘s class is Class is +only to make the implementation easier, there’s nothing important in +this logic.

+

“Class is also an object”

+

“Everything is an object” is often used as advertising statement when +speaking about Ruby. And as a part of that, “Classes are also objects!” +also appears. But these expressions often go too far. When thinking +about these sayings, we have to split them in two:

+
    +
  • all data are objects
  • +
  • classes are data
  • +
+

Talking about data or code makes a discussion much harder to +understand. That’s why here we’ll restrict the meaning of “data” to +“what can be put in variables in programs”.

+

Being able to manipulate classes from programs gives programs the +ability to manipulate themselves. This is called reflection. It fits +object oriented languages, and even more Ruby with the classes it has, +to be able to directly manipulate classes.

+

Nevertheless, classes could be made available in a form that is not an +object. For example, classes could be manipulated with function-style +methods (functions defined at the top-level). However, as inside the +interpreter there are data structures to represent the classes, it’s +more natural in object oriented languages to make them available +directly. And Ruby did this choice.

+

Furthermore, an objective in Ruby is for all data to be +objects. That’s why it’s appropriate to make them objects.

+

By the way, there is a reason not linked to reflection why in Ruby +classes had to be made objects. That is to be able to define methods +independently from instances (what is called static methods in Java in +C++).

+

And to implement static methods, another thing was necessary: +singleton methods. By chain reaction, that also makes singleton +classes necessary. Figure 3 shows these dependency relationships.

+

+

(reqlink)
+Figure 3: Requirements dependencies

+

+

Class methods inheritance

+

In Ruby, singleton methods defined in a class are called class +methods. However, their specification is a little strange. Why are +class methods inherited?

+
+class A
+  def A.test    # defines a singleton method in A
+    puts("ok")
+  end
+end
+
+class B < A
+end
+
+B.test()  # calls it
+
+

This can’t occur with singleton methods from objects that are not +classes. In other words, classes are the only ones handled +specially. In the following section we’ll see how class methods are +inherited.

+

Singleton class of a class

+

Assuming that class methods are inherited, where is this operation +done? At class definition (creation)? At singleton method definition? +Then let’s look at the code defining classes.

+

Class definition means of course rb_define_class(). Now +let’s take the call graph of this function.

+
+rb_define_class
+    rb_class_inherited
+    rb_define_class_id
+        rb_class_new
+            rb_class_boot
+        rb_make_metaclass
+            rb_class_boot
+            rb_singleton_class_attached
+
+

If you’re wondering where you’ve seen it before, we looked at it in +the previous section. At that time you did not see it but if you look +closely, why does rb_make_metaclass() appear? As we saw before, this +function introduces a singleton class. This is very suspicious. Why is +this called even if we are not defining a singleton function? +Furthermore, why is the lower level rb_make_metaclass() used instead +of rb_singleton_class()? It looks like we have to check these +surroundings again.

+

rb_define_class_id()

+

Let’s first start our reading with its caller, rb_define_class_id().

+

rb_define_class_id() +

+ 160  VALUE
+ 161  rb_define_class_id(id, super)
+ 162      ID id;
+ 163      VALUE super;
+ 164  {
+ 165      VALUE klass;
+ 166
+ 167      if (!super) super = rb_cObject;
+ 168      klass = rb_class_new(super);
+ 169      rb_name_class(klass, id);
+ 170      rb_make_metaclass(klass, RBASIC→klass);
+ 171
+ 172      return klass;
+ 173  }

+

(class.c) +

+

rb_class_new() was a function that creates a class with super as +its superclass. rb_name_class()‘s name means it names a class, but +for the moment we do note care about names so we’ll skip it. After +that there’s the rb_make_metaclass() in question. I’m concerned by +the fact that when called from rb_singleton_class(), the parameters +were different. Last time was like this:

+
+rb_make_metaclass(obj, RBASIC(obj)->klass);
+
+

But this time is like this:

+
+rb_make_metaclass(klass, RBASIC(super)->klass);
+
+

So as you can see it’s slightly different. How do the results change +depending on that? Let’s have once again a look at a simplified +rb_make_metaclass().

+

rb_make_metaclass (once more)

+

rb_make_metaclass (after first compression) +

+rb_make_metaclass(obj, super)
+{
+    klass = create a class with super as superclass;
+    FL_SET(klass, FL_SINGLETON);
+    RBASIC→klass = klass;
+    rb_singleton_class_attached(klass, obj);
+    if (BUILTIN_TYPE(obj) == T_CLASS) {
+        RBASIC→klass = klass;
+        if (FL_TEST(obj, FL_SINGLETON)) {
+            RCLASS→super =
+                    RBASIC→super))→klass;
+        }
+    }

+return klass; +

} +

+

Last time, the if statement was skillfully skipped, but looking once +again, something is done only for T_CLASS, in other words +classes. This clearly looks important. In rb_define_class_id(), as +it’s called like this:

+
+rb_make_metaclass(klass, RBASIC(super)->klass);
+
+

Let’s expand rb_make_metaclass()’s parameter variables with this +values.

+

rb_make_metaclass (recompression) +

+rb_make_metaclass(klass, super_klass /* == RBASIC→klass */)
+{
+    sclass = create a class with super_class as superclass;
+    RBASIC→klass = sclass;
+    RBASIC→klass = sclass;
+    return sclass;
+}
+

+

Doing this as a diagram gives something like figure 4. In it, the +names between parentheses are singleton classes. This notation is +often used in this book so I’d like you to remember it. This means +that obj‘s singleton class is written as (obj). And (klass) is +the singleton class for klass. It looks like the singleton class is +caught between a class and this class’s superclass’s class.

+

+

(metaclass)
+Figure 4: Introduction of a class’s singleton class

+

+

From this result, and moreover when thinking more deeply, we can think +that the superclass’s class must again be the superclass’s singleton +class. You’ll understand with one more inheritance level (figure 5).

+

+

(multi)
+Figure 5: Hierarchy of multi-level inheritance

+

+

As the relationship between super and klass is the same as the one +between klass and klass2, c must be the singleton class +(super). If you continue like this, finally you’ll arrive at the +conclusion that Object‘s class must be (Object). And that’s the +case in practice. For example, by inheriting like in the following +program :

+
+class A < Object
+end
+class B < A
+end
+
+

internally, a structure like figure 6 is created.

+

+

(metatree)
+Figure 6: Class hierarchy and metaclasses

+

+

As classes and their metaclasses are linked and inherit like this, +class methods are inherited.

+

Class of a class of a class

+

You’ve understood the working of class methods inheritance, but by +doing that, in the opposite some questions have appeared. What is the +class of a class’s singleton class? To do this we can try +debugging. I’ve made the figure 7 from the results of this +investigation.

+

+

(mmm)
+Figure 7: Class of a class’s singleton class

+

+

A class’s singleton class puts itself as its own class. Quite +complicated.

+

The second question: the class of Object must be Class. Didn’t I +properly confirm this in chapter 1: Ruby language minimum?

+
+p(Object.class())   # Class
+
+

Certainly, that’s the case “at the Ruby level”. But “at the C level”, +it’s the singleton class (Object). If (Object) does not appear at +the Ruby level, it’s because Object#class skips the singleton +classes. Let’s look at the body of the method, rb_obj_class() to +confirm that.

+

rb_obj_class() +

+  86  VALUE
+  87  rb_obj_class(obj)
+  88      VALUE obj;
+  89  {
+  90      return rb_class_real(CLASS_OF(obj));
+  91  }

+76 VALUE +77 rb_class_real(cl) +78 VALUE cl; +79 { +80 while (FL_TEST(cl, FL_SINGLETON) || TYPE == T_ICLASS) { +81 cl = RCLASS→super; +82 } +83 return cl; +84 } +

(object.c) +

+

CLASS_OF(obj) returns the basic.klass of obj. While in +rb_class_real(), all singleton classes are skipped (advancing +towards the superclass). In the first place, singleton class are +caught between a class and its superclass, like a proxy. That’s why +when a “real” class is necessary, we have to follow the superclass +chain (figure 8).

+

I_CLASS will appear later when we will talk about include.

+

+

(real)
+Figure 8: Singleton class and real class

+

+

Singleton class and metaclass

+

Well, the singleton classes that were introduced in classes is also +one type of class, it’s a class’s class. So it can be called +metaclass.

+

However, you should be wary of the fact that singleton class are +not metaclasses. It’s the singleton classes introduced in classes that +are metaclasses. The important fact is not that they are singleton +classes, but that they are the classes of classes. I was stuck on this +point when I started learning Ruby. As I may not be the only one, I +would like to make this clear.

+

Thinking about this, the rb_make_metaclass() function name is not +very good. When used in classes, it does indeed create a metaclass, +but not in the other cases, when using objects.

+

Then finally, even if you understood that some class are metaclasses, +it’s not as if there was any concrete gain. I’d like you not to care +too much about it.

+

Bootstrap

+

We have nearly finished our talk about classes and metaclasses. But +there is still one problem left. It’s about the 3 metaobjects +Object, Module and Class. These 3 cannot be created with the +common use API. To make a class, its metaclass must be built, but like +we saw some time ago, the metaclass’s superclass is Class. However, +as Class has not been created yet, the metaclass cannot be build. So +in ruby, only these 3 classes’s creation is handled specially.

+

Then let’s look at the code:

+

Object, Module and Class creation +

+1243  rb_cObject = boot_defclass(“Object”, 0);
+1244  rb_cModule = boot_defclass(“Module”, rb_cObject);
+1245  rb_cClass =  boot_defclass(“Class”,  rb_cModule);
+1246
+1247  metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
+1248  metaclass = rb_make_metaclass(rb_cModule, metaclass);
+1249  metaclass = rb_make_metaclass(rb_cClass, metaclass);

+

(object.c) +

+

First, in the first half, boot_defclass() is similar to +rb_class_boot(), it just creates a class with its given superclass +set. These links give us something like the left part of figure 9.

+

And in the three lines of the second half, (Object), (Module) and +(Class) are created and set (right figure 9). (Object) and +(Module)‘s classes… that is themselves… is already set in +rb_make_metaclass() so there is no problem. With this, the +metaobjects’ bootstrap is finished.

+

+

(boot1)
+Figure 9: Metaobjects creation

+

+

After taking everything into account, it gives us a the final shape +like figure 10.

+

+

(metaobj)
+Figure 10: Ruby metaobjects

+

+

Class names

+

In this section, we will analyse how’s formed the reciprocal +conversion between class and class names, in other words +constants. Concretely, we will target rb_define_class() and +rb_define_class_under().

+

Name → class

+

First we’ll read rb_defined_class(). After the end of this function, +the class can be found from the constant.

+

rb_define_class() +

+ 183  VALUE
+ 184  rb_define_class(name, super)
+ 185      const char name;
+ 186      VALUE super;
+ 187  {
+ 188      VALUE klass;
+ 189      ID id;
+ 190
+ 191      id = rb_intern(name);
+ 192      if (rb_autoload_defined(id)) {             / (A) autoload /
+ 193          rb_autoload_load(id);
+ 194      }
+ 195      if (rb_const_defined(rb_cObject, id)) {    / (B) rb_const_defined /
+ 196          klass = rb_const_get(rb_cObject, id);  / © rb_const_get /
+ 197          if (TYPE != T_CLASS) {
+ 198              rb_raise(rb_eTypeError, “%s is not a class”, name);
+ 199          }                                      / (D) rb_class_real */
+ 200          if (rb_class_real(RCLASS→super) != super) {
+ 201              rb_name_error(id, “%s is already defined”, name);
+ 202          }
+ 203          return klass;
+ 204      }
+ 205      if (!super) {
+ 206          rb_warn(“no super class for ‘%s’, Object assumed”, name);
+ 207      }
+ 208      klass = rb_define_class_id(id, super);
+ 209      rb_class_inherited(super, klass);
+ 210      st_add_direct(rb_class_tbl, id, klass);
+ 211
+ 212      return klass;
+ 213  }

+

(class.c) +

+

Many things can be understood with what’s before and after +rb_define_class_id()… Before we acquire or create the class. After +we set the constant. We will look at it in more detail below.

+

(A) In Ruby, there is an autoload function that automatically loads +libraries when some constants are accessed. This is done in the +rb_autoload_xxxx() function. You can ignore it without any problem.

+

(B) We determine whether the name constant has been defined or not +in Object.

+

© Get the value of the name constant. This will be explained in +detail in chapter 6.

+

(D) We’ve seen rb_class_real() some time ago. If the class c is a +singleton class or an ICLASS, it climbs the super hierarchy up to +a class that is not and returns it. In short, this function skips the +virtual classes that should not appear at the Ruby level.

+

That’s what we can read nearby.

+

As around constants are involved, it is very troublesome. However, we +will talk about class definition in the constants chapter so for the +moment we will content ourselves with a partial description.

+

After rb_define_class_id, we can find the following:

+
+st_add_direct(rb_class_tbl, id, klass);
+
+

This part assigns the class to the constant. However, whichever +way you look at it you do not see that. In fact, top-level classes are +separated from the other constants and regrouped in +rb_class_tbl(). The split is slightly related to the GC. It’s not +essential.

+

Class → name

+

We understood how the class can be obtained from the class name, but +how to do the opposite? By doing things like calling p or +Class#name, we can get the name of the class, but how is it +implemented?

+

In fact this was already done a long time ago by +rb_name_class(). The call is around the following:

+
+rb_define_class
+    rb_define_class_id
+        rb_name_class
+
+

Let’s look at its content:

+

rb_name_class() +

+ 269  void
+ 270  rb_name_class(klass, id)
+ 271      VALUE klass;
+ 272      ID id;
+ 273  {
+ 274      rb_iv_set(klass, “classid”, ID2SYM);
+ 275  }

+

(variable.c) +

+

__classid__ is another instance variable that can’t be seen from +Ruby. As only VALUEs can be put in the instance variable table, the +ID is converted to Symbol using ID2SYM().

+

That’s how we are able to find the constant name from the class.

+

Nested classes

+

So, in the case of classes defined at the top-level, we know how works +the reciprocal link between name and class. What’s left is the case of +classes defined in modules or other classes, and for that it’s a +little more complicated. The function to define these nested classes +is rb_define_class_under().

+

rb_define_class_under() +

+ 215  VALUE
+ 216  rb_define_class_under(outer, name, super)
+ 217      VALUE outer;
+ 218      const char *name;
+ 219      VALUE super;
+ 220  {
+ 221      VALUE klass;
+ 222      ID id;
+ 223
+ 224      id = rb_intern(name);
+ 225      if (rb_const_defined_at(outer, id)) {
+ 226          klass = rb_const_get(outer, id);
+ 227          if (TYPE != T_CLASS) {
+ 228              rb_raise(rb_eTypeError, “%s is not a class”, name);
+ 229          }
+ 230          if (rb_class_real(RCLASS→super) != super) {
+ 231              rb_name_error(id, “%s is already defined”, name);
+ 232          }
+ 233          return klass;
+ 234      }
+ 235      if (!super) {
+ 236          rb_warn(“no super class for ‘%s::%s’, Object assumed”,
+ 237                  rb_class2name(outer), name);
+ 238      }
+ 239      klass = rb_define_class_id(id, super);
+ 240      rb_set_class_path(klass, outer, name);
+ 241      rb_class_inherited(super, klass);
+ 242      rb_const_set(outer, id, klass);
+ 243
+ 244      return klass;
+ 245  }

+

(class.c) +

+

The structure is like the one of rb_define_class(): before the call +to rb_define_class_id() is the redefinition check, after is the +creation of the reciprocal link between constant and class. The first +half is pretty boringly similar to rb_define_class() so we’ll skip +it. In the second half, rb_set_class() is new. We’re going to look +at it.

+

rb_set_class_path()

+

This function gives the name name to the class klass nested in the +class under. “class path” means a name including all the nesting +information starting from top-level, for example +“Net::NetPrivate::Socket”.

+

rb_set_class_path() +

+ 210  void
+ 211  rb_set_class_path(klass, under, name)
+ 212      VALUE klass, under;
+ 213      const char name;
+ 214  {
+ 215      VALUE str;
+ 216
+ 217      if (under == rb_cObject) {
+              / defined at top-level /
+ 218          str = rb_str_new2(name);    / create a Ruby string from name /
+ 219      }
+ 220      else {
+              / nested constant /
+ 221          str = rb_str_dup(rb_class_path(under));  / copy the return value /
+ 222          rb_str_cat2(str, “::”);     / concatenate “::” /
+ 223          rb_str_cat2(str, name);     / concatenate name */
+ 224      }
+ 225      rb_iv_set(klass, “classpath”, str);
+ 226  }

+

(variable.c) +

+

Everything except the last line is the construction of the class path, +and the last line makes the class remember its own +name. __classpath__ is of course another instance variable that +can’t be seen from a Ruby program. In rb_name_class() there was +__classid__, but id is different because it does not include +nesting information (look at the table below).

+
+__classpath__    Net::NetPrivate::Socket
+__classid__                       Socket
+
+

It means classes defined for example in rb_defined_class() all have +__classid__ or __classpath__ defined. So to find under‘s +classpath we can look up in these instance variables. This is done by +rb_class_path(). We’ll omit its content.

+

Nameless classes

+

Contrary to what I have just said, there are in fact cases in which +neither __classpath__ nor __classid__ are set. That is because in +Ruby you can use a method like the following to create a class.

+
+c = Class.new()
+
+

If you create a class like this, we won’t go through +rb_define_class_id() and the classpath won’t be set. In this case, +c does not have any name, which is to say we get an unnamed class.

+

However, if later it’s assigned to a constant, the name of this +constant will be attached to the class.

+
+SomeClass = c   # the class name is SomeClass
+
+

Strictly speaking, the name is attached after the assignment, the +first time it is requested. For instance, when calling p on this +SomeClass class or when calling the Class#name method. When doing +this, a value equal to the class is searched in rb_class_tbl, and a +name has to be chosen. The following case can also happen:

+
+class A
+  class B
+    C = tmp = Class.new()
+    p(tmp)   # here we search for the name
+  end
+end
+
+

so in the worst case we have to search for the whole constant +space. However, generally, there aren’t many constants so searching +all constants does not take too much time.

+

Include

+

We only talked about classes so let’s finish this chapter with +something else and talk about module inclusion.

+

rb_include_module (1)

+

Includes are done by the ordinary method Module#include. Its +corresponding function in C is rb_include_module(). In fact, to be +precise, its body is rb_mod_include(), and there +Module#append_feature is called, and this function’s default +implementation finally calls rb_include_module(). Mixing what’s +happening in Ruby and C gives us the following call graph.

+
+Module#include (rb_mod_include)
+    Module#append_features (rb_mod_append_features)
+        rb_include_module
+
+

All usual includes are done by rb_include_module(). This function is +a little long so we’ll look at it a half at a time.

+

rb_include_module (first half) +

+      /* include module in class */
+ 347  void
+ 348  rb_include_module(klass, module)
+ 349      VALUE klass, module;
+ 350  {
+ 351      VALUE p, c;
+ 352      int changed = 0;
+ 353
+ 354      rb_frozen_class_p(klass);
+ 355      if (!OBJ_TAINTED(klass)) {
+ 356          rb_secure(4);
+ 357      }
+ 358
+ 359      if (NIL_P(module)) return;
+ 360      if (klass == module) return;
+ 361
+ 362      switch (TYPE) {
+ 363        case T_MODULE:
+ 364        case T_CLASS:
+ 365        case T_ICLASS:
+ 366          break;
+ 367        default:
+ 368          Check_Type(module, T_MODULE);
+ 369      }

+

(class.c) +

+

For the moment it’s only security and type checking, therefore we can +ignore it. The process itself is below:

+

rb_include_module (second half) +

+ 371      OBJ_INFECT(klass, module);
+ 372      c = klass;
+ 373      while (module) {
+ 374          int superclass_seen = Qfalse;
+ 375
+ 376          if (RCLASS→m_tbl == RCLASS→m_tbl)
+ 377              rb_raise(rb_eArgError, “cyclic include detected”);
+ 378          /* (A) skip if the superclass already includes module /
+ 379          for (p = RCLASS→super; p; p = RCLASS→super) {
+ 380              switch (BUILTIN_TYPE(p)) {
+ 381                case T_ICLASS:
+ 382                  if (RCLASS→m_tbl == RCLASS→m_tbl) {
+ 383                      if (!superclass_seen) {
+ 384                          c = p;  / move the insertion point */
+ 385                      }
+ 386                      goto skip;
+ 387                  }
+ 388                  break;
+ 389                case T_CLASS:
+ 390                  superclass_seen = Qtrue;
+ 391                  break;
+ 392              }
+ 393          }
+ 394          c = RCLASS→super =
+                          include_class_new(module, RCLASS→super);
+ 395          changed = 1;
+ 396        skip:
+ 397          module = RCLASS→super;
+ 398      }
+ 399      if (changed) rb_clear_cache();
+ 400  }

+

(class.c) +

+

First, what the (A) block does is written in the comment. It seems to +be a special condition so let’s first skip reading it for now. By +extracting the important parts from the rest we get the following:

+
+c = klass;
+while (module) {
+    c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
+    module = RCLASS(module)->super;
+}
+
+

In other words, it’s a repetition of module‘s super. What is in +module’s super must be a module included by module (because our +intuition tells us so). Then the superclass of the class where the +inclusion occurs is replaced with something. We do not understand much +what, but at the moment I saw that I felt “Ah, doesn’t this look the +addition of elements to a list (like LISP’s cons)?” and it suddenly +make the story faster. In other words it’s the following form:

+
+list = new(item, list)
+
+

Thinking about this, it seems we can expect that module is inserted +between c and c->super. If it’s like this, it fits module’s +specification.

+

But to be sure of this we have to look at include_class_new().

+

include_class_new()

+

include_class_new() +

+ 319  static VALUE
+ 320  include_class_new(module, super)
+ 321      VALUE module, super;
+ 322  {
+ 323      NEWOBJ;               /* (A) /
+ 324      OBJSETUP;
+ 325
+ 326      if (BUILTIN_TYPE(module) == T_ICLASS) {
+ 327          module = RBASIC→klass;
+ 328      }
+ 329      if (!RCLASS→iv_tbl) {
+ 330          RCLASS→iv_tbl = st_init_numtable();
+ 331      }
+ 332      klass→iv_tbl = RCLASS→iv_tbl;     / (B) /
+ 333      klass→m_tbl = RCLASS→m_tbl;
+ 334      klass→super = super;                       / © /
+ 335      if (TYPE == T_ICLASS) {             / (D) /
+ 336          RBASIC→klass = RBASIC→klass;   / (D-1) /
+ 337      }
+ 338      else {
+ 339          RBASIC→klass = module;                  / (D-2) */
+ 340      }
+ 341      OBJ_INFECT(klass, module);
+ 342      OBJ_INFECT(klass, super);
+ 343
+ 344      return (VALUE)klass;
+ 345  }

+

(class.c) +

+

We’re lucky there’s nothing we do not know.

+

(A) First create a new class.

+

(B) Transplant module’s instance variable and method tables into +this class.

+

© Make the including class’s superclass (super) the super class of +this new class.

+

In other words, this function creates an include class for the +module. The important point is that at (B) only the pointer is moved +on, without duplicating the table. Later, if a method is added, the +module’s body and the include class will still have exactly the +same methods (figure 11).

+

+

(symbolic)
+Figure 11: Include class

+

+

If you look closely at (A), the structure type flag is set to +T_ICLASS. This seems to be the mark of an include class. This +function’s name is include_class_new() so ICLASS’s I must be +include.

+

And if you think about joining what this function and +rb_include_module() do, we know that our previous expectations were not +wrong. In brief, including is inserting the include class of a +module between a class and its superclass (figure 12).

+

+

(include)
+Figure 12: Include

+

+

At (D-2) the module is stored in the include class’s klass. At +(D-1), the module’s body is taken out… at least that’s what I’d like +to say, but in fact this check does not have any use. The T_ICLASS +check is already done at the beginning of this function, so when +arriving here there can’t still be a T_ICLASS. Modification to +ruby piled up at a fast pace during quite a long period of time so +there are quite a few small overlooks.

+

There is one more thing to consider. Somehow the include class’s +basic.klass is only used to point to the module’s body, so for +example calling a method on the include class would be very bad. So +include classes must not be seen from Ruby programs. And in +practice all methods skip include classes, with no exception.

+

Simulation

+

It was complicated so let’s look at a concrete example. I’d like you +to look at figure 13 (1). We have the c1 class and the m1 module +that includes m2. From there, the changes made to include m1 in +c1 are (2) and (3). ims are of course include classes.

+

+

(simulate)
+Figure 13: Include

+

+

rb_include_module (2)

+

Well, now we can explain the part of rb_include_module() we skipped.

+

rb_include_module (avoiding double inclusion) +

+ 378  /* (A) skip if the superclass already includes module /
+ 379  for (p = RCLASS→super; p; p = RCLASS→super) {
+ 380      switch (BUILTIN_TYPE(p)) {
+ 381        case T_ICLASS:
+ 382          if (RCLASS→m_tbl == RCLASS→m_tbl) {
+ 383              if (!superclass_seen) {
+ 384                  c = p;  / the inserting point is moved */
+ 385              }
+ 386              goto skip;
+ 387          }
+ 388          break;
+ 389        case T_CLASS:
+ 390          superclass_seen = Qtrue;
+ 391          break;
+ 392      }
+ 393  }

+

(class.c) +

+

If one of the T_ICLASSes (include classes) that are in klass‘s +superclasses (p) has the same table as one of the modules we want to +include (module), it’s an include class for module. That’s why we +skip the inclusion to not include the module twice. If this module +includes an other module (module->super), we check this once more.

+

However, when we skip an inclusion, p is a module that has been +included once, so its included modules must already be +included… that’s what I thought for a moment, but we can have the +following context:

+
+module M
+end
+module M2
+end
+class C
+  include M   # M2 is not yet included in M
+end           # therefore M2 is not in C's superclasses
+
+module M
+  include M2  # as there M2 is included in M,
+end
+class C
+  include M   # I would like here to only add M2
+end
+
+

So on the contrary, there are cases for which include does not have +real-time repercussions.

+

For class inheritance, the class’s singleton methods were inherited +but in the case of module there is no such thing. Therefore the +singleton methods of the module are not inherited by the including +class (or module). When you want to also inherit singleton methods, +the usual way is to override Module#append_features.

+ + + +
+ + diff --git a/htmls/contextual.html b/htmls/contextual.html new file mode 100644 index 0000000..58a65ac --- /dev/null +++ b/htmls/contextual.html @@ -0,0 +1,1755 @@ + + + + + Finite-state scanner | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Peter Zotov
+I’m very grateful to my employer Evil Martians , who sponsored +the work, and Nikolay Konovalenko , who put +more effort in this translation than I could ever wish for. Without them, +I would be still figuring out what COND_LEXPOP() actually does.

+

Chapter 11 Finite-state scanner

+

Outline

+

In theory, the scanner and the parser are completely independent of each other +– the scanner is supposed to recognize tokens, while the parser is supposed to +process the resulting series of tokens. It would be nice if things were that +simple, but in reality it rarely is. Depending on the context of the program it +is often necessary to alter the way tokens are recognized or their symbols. In +this chapter we will take a look at the way the scanner and the parser +cooperate.

+

Practical examples

+

In most programming languages, spaces don’t have any specific meaning unless +they are used to separate words. However, Ruby is not an ordinary language and +meanings can change significantly depending on the presence of spaces. +Here is an example

+
+a[i] = 1      # a[i] = (1)
+a [i]         # a([i])
+
+

The former is an example of assigning an index. The latter is an example of +omitting the method call parentheses and passing a member of an array to a +parameter.

+

Here is another example.

+
+a  +  1    # (a) + (1)
+a  +1      # a(+1)
+
+

This seems to be really disliked by some.

+

However, the above examples might give one the impression that only omitting +the method call parentheses can be a source of trouble. Let’s look at a +different example.

+
+`cvs diff parse.y`          # command call string
+obj.`("cvs diff parse.y")   # normal method call
+
+

Here, the former is a method call using a literal. In contrast, the latter is a +normal method call (with ‘’’ being the method name). Depending on the context, +they could be handled quite differently.

+

Below is another example where the functioning changes dramatically

+
+print(<<EOS)   # here-document
+......
+EOS
+
+list = []
+list << nil    # list.push(nil)
+
+

The former is a method call using a here-document. The latter is a method call +using an operator.

+

As demonstrated, Ruby’s grammar contains many parts which are difficult to +implement in practice. I couldn’t realistically give a thorough description of +all in just one chapter, so in this one I will look at the basic principles and +those parts which present the most difficulty.

+

lex_state

+

There is a variable called “lex_state”. “lex”, obviously, stands for “lexer”. +Thus, it is a variable which shows the scanner’s state.

+

What states are there? Let’s look at the definitions.

+

enum lex_state

+
  61  static enum lex_state {
+  62      EXPR_BEG,      /* ignore newline, +/- is a sign. */
+  63      EXPR_END,      /* newline significant, +/- is a operator. */
+  64      EXPR_ARG,      /* newline significant, +/- is a operator. */
+  65      EXPR_CMDARG,   /* newline significant, +/- is a operator. */
+  66      EXPR_ENDARG,   /* newline significant, +/- is a operator. */
+  67      EXPR_MID,      /* newline significant, +/- is a operator. */
+  68      EXPR_FNAME,    /* ignore newline, no reserved words. */
+  69      EXPR_DOT,      /* right after `.' or `::', no reserved words. */
+  70      EXPR_CLASS,    /* immediate after `class', no here document. */
+  71  } lex_state;
+(parse.y)
+

The EXPR prefix stands for “expression”. EXPR_BEG is “Beginning of +expression” and EXPR_DOT is “inside the expression, after the dot”.

+

To elaborate, EXPR_BEG denotes “Located at the head of the expression”. +EXPR_END denotes “Located at the end of the expression”. EXPR_ARG denotes +“Before the method parameter”. EXPR_FNAME denotes “Before the method name +(such as def)”. The ones not covered here will be analyzed in detail below.

+

Incidentally, I am led to believe that lex_state actually denotes “after +parentheses”, “head of statement”, so it shows the state of the parser rather +than the scanner. However, it’s still conventionally referred to as the +scanner’s state and here’s why.

+

The meaning of “state” here is actually subtly different from how it’s usually +understood. The “state” of lex_state is “a state under which the scanner does +x”. For example an accurate description of EXPR_BEG would be “A state under +which the scanner, if run, will react as if this is at the head of the +expression”

+

Technically, this “state” can be described as the state of the scanner if we +look at the scanner as a state machine. However, delving there would be veering +off topic and too tedious. I would refer any interested readers to any textbook +on data structures.

+

Understanding the finite-state scanner

+

The trick to reading a finite-state scanner is to not try to grasp everything +at once. Someone writing a parser would prefer not to use a finite-state +scanner. That is to say, they would prefer not to make it the main part of the +process. Scanner state management often ends up being an extra part attached to +the main part. In other words, there is no such thing as a clean and concise +diagram for state transitions.

+

What one should do is think toward specific goals: “This part is needed to +solve this task” “This code is for overcoming this problem”. Basically, put out +code in accordance with the task at hand. If you start thinking about the +mutual relationship between tasks, you’ll invariably end up stuck. Like I said, +there is simply no such thing.

+

However, there still needs to be an overreaching objective. When reading a +finite-state scanner, that objective would undoubtedly be to understand every +state. For example, what kind of state is EXPR_BEG? It is a state where the +parser is at the head of the expression.

+

The static approach

+

So, how can we understand what a state does? There are three basic approaches

+
    +
  • Look at the name of the state
  • +
+

The simplest and most obvious approach. For example, the name EXPR_BEG +obviously refers to the head (beginning) of something.

+
    +
  • Observe what changes under this state
  • +
+

Look at the way token recognition changes under the state, then test it in +comparison to previous examples.

+
    +
  • Look at the state from which it transitions
  • +
+

Look at which state it transitions from and which token causes it. For example, +if '\n' is always followed by a transition to a HEAD state, it must denote +the head of the line.

+

Let us take EXPR_BEG as an example. +In Ruby, all state transitions are expressed as assignments to lex_state, so +first we need to grep EXPR_BEG assignments to find them. Then we need to +export their location, for example, such as '#' and '*' and '!' of +yylex() Then we need to recall the state prior to the transition and consider +which case suits best (see image 1)

+

+

(transittobeg)
+Figure 1: Transition to EXPR_BEG

+

+

This does indeed look like the head of statement. Especially the '\n' and the +';' The open parentheses and the comma also suggest that it’s the head not +just of the statement, but of the expression as well.

+

The dynamic approach

+

There are other easy methods to observe the functioning. For example, you can +use a debugger to “hook” the yylex() and look at the lex_state

+

Another way is to rewrite the source code to output state transitions. In the +case of lex_state we only have numerical patterns for assignment and +comparison, so the solution would be to treat them as text patterns and rewrite +the code to output state transitions. The CD that comes with this book contains +the rubylex-analyser tool. When necessary, I will refer to it in this text.

+

The overall process looks like this: use a debugger or the aforementioned tool +to observe the functioning of the program. Then look at the source code to +confirm the acquired data and use it.

+

Description of states

+

Here I will give simple descriptions of lex_state states.

+
    +
  • EXPR_BEG
  • +
+

Head of expression. Comes immediately after \n ( { [ ! ? : , or the operator +op= The most general state.

+
    +
  • EXPR_MID
  • +
+

Comes immediately after the reserved words return break next rescue. +Invalidates binary operators such as * or & +Generally similar in function to EXPR_BEG

+
    +
  • EXPR_ARG
  • +
+

Comes immediately after elements which are likely to be the method name in a +method call. +Also comes immediately after '[' +Except for cases where EXPR_CMDARG is used.

+
    +
  • EXPR_CMDARG
  • +
+

Comes before the first parameter of a normal method call. +For more information, see the section “The do conflict”

+
    +
  • EXPR_END
  • +
+

Used when there is a possibility that the statement is terminal. For example, +after a literal or brackets. Except for cases when EXPR_ENDARG is used

+
    +
  • EXPR_ENDARG
  • +
+

Special iteration of EXPR_END Comes immediately after the closing parenthesis +corresponding to tLPAREN_ARG +Refer to the section “First parameter enclosed in parentheses”

+
    +
  • EXPR_FNAME
  • +
+

Comes before the method name, usually after def, alias, undef or the +symbol ':' In an independent position ` is the method name.

+
    +
  • EXPR_DOT
  • +
+

Comes after the dot in a method call. Handled similarly to EXPR_FNAME +Various reserved words are treated as simple identifiers. +In an independent position '`' is the name.

+
    +
  • EXPR_CLASS
  • +
+

Comes after the reserved word class This is a very limited state.

+

The following states can be grouped together

+
    +
  • BEG MID
  • +
  • END ENDARG
  • +
  • ARG CMDARG
  • +
  • FNAME DOT
  • +
+

They all express similar conditions. EXPR_CLASS is a little different, but +only appears in a limited number of places, not warranting any special +attention.

+

Line-break handling

+

The problem

+

In Ruby, a statement does not necessarily require a terminator. In C or Java a +statement must always end with a semicolon, but Ruby has no such requirement. +Statements usually take up only one line, and thus end at the end of the line.

+

On the other hand, when a statement is clearly continued, this happens +automatically. Some conditions for “This statement is clearly continued” are as +follows:

+
    +
  • After a comma
  • +
  • After an infix operator
  • +
  • Parentheses or brackets are not balanced
  • +
  • Immediately after the reserved word if
  • +
+

Etc.

+

Implementation

+

So, what do we need to implement this grammar? Simply having the scanner ignore +line-breaks is not sufficient. In a grammar like Ruby’s, where statements are +delimited by reserved words on both ends, conflicts don’t happen as frequently +as in C languages, but when I tried a simple experiment, I couldn’t get it to +work until I got rid of return +next break and returned the method call parentheses wherever they were +omitted. To retain those features we need some kind of terminal symbol for +statements’ ends. It doesn’t matter whether it’s \n or ';' but it is +necessary.

+

Two solutions exist – parser-based and scanner-based. For the former, you can +just optionally put \n in every place that allows it. For the latter, have +the \n passed to the parser only when it has some meaning (ignoring it +otherwise).

+

Which solution to use is up to your preferences, but usually the scanner-based +one is used. That way produces a more compact code. Moreover, if the rules are +overloaded with meaningless symbols, it defeats the purpose of the +parser-generator.

+

To sum up, in Ruby, line-breaks are best handled using the scanner. When a line +needs to continued, the \n will be ignored, and when it needs to be +terminated, the \n is passed as a token. In the yylex() this is found here:

+

yylex()-'\n' +

+3155        case ‘\n’:
+3156          switch (lex_state) {
+3157            case EXPR_BEG:
+3158            case EXPR_FNAME:
+3159            case EXPR_DOT:
+3160            case EXPR_CLASS:
+3161              goto retry;
+3162            default:
+3163              break;
+3164          }
+3165          command_start = Qtrue;
+3166          lex_state = EXPR_BEG;
+3167          return ‘\n’;

+

(parse.y) +

+

With EXPR_BEG, EXPR_FNAME, EXPR_DOT, EXPR_CLASS it will be goto retry. +That is to say, it’s meaningless and shall be ignored. The label retry is +found in front of the large switch in the yylex()

+

In all other instances, line-breaks are meaningful and shall be passed to the +parser, after which lex_state is restored to EXPR_BEG Basically, whenever a +line-break is meaningful, it will be the end of expr

+

I recommend leaving command_start alone for the time being. To reiterate, +trying to grasp too many things at once will only end in needless confusion.

+

Let us now take a look at some examples using the rubylex-analyser tool.

+
+% rubylex-analyser -e '
+m(a,
+  b, c) unless i
+'
++EXPR_BEG
+EXPR_BEG     C      "\nm"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG           "("  '('                  EXPR_BEG
+                                              0:cond push
+                                              0:cmd push
+EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG           ","  ','                  EXPR_BEG
+EXPR_BEG    S     "\n  b"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ","  ','                  EXPR_BEG
+EXPR_BEG    S         "c"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ")"  ')'                  EXPR_END
+                                              0:cond lexpop
+                                              0:cmd lexpop
+EXPR_END    S    "unless"  kUNLESS_MOD          EXPR_BEG
+EXPR_BEG    S         "i"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG             "\n"  \n                   EXPR_BEG
+EXPR_BEG     C       "\n"  '                    EXPR_BEG
+
+

As you can see, there is a lot of output here, but we only need the left and +middle columns. The left column displays the lex_state before it enters the +yylex() while the middle column displays the tokens and their symbols.

+

The first token m and the second parameter b are preceded by a line-break +but a \n is appended in front of them and it is not treated as a terminal +symbol. That is because the lex_state is EXPR_BEG.

+

However, in the second to last line \n is used as a terminal symbol. +That is because the state is EXPR_ARG

+

And that is how it should be used. Let us have another example.

+
+% rubylex-analyser -e 'class
+C < Object
+end'
++EXPR_BEG
+EXPR_BEG     C    "class"  kCLASS               EXPR_CLASS
+EXPR_CLASS          "\nC"  tCONSTANT            EXPR_END
+EXPR_END    S         "<"  '<'                  EXPR_BEG
++EXPR_BEG
+EXPR_BEG    S    "Object"  tCONSTANT            EXPR_ARG
+EXPR_ARG             "\n"  \n                   EXPR_BEG
+EXPR_BEG     C      "end"  kEND                 EXPR_END
+EXPR_END             "\n"  \n                   EXPR_BEG
+
+

The reserved word class is followed by EXPR_CLASS so the line-break is ignored. +However, the superclass Object is followed by EXPR_ARG, so the \n appears.

+
+% rubylex-analyser -e 'obj.
+class'
++EXPR_BEG
+EXPR_BEG     C      "obj"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG           "."  '.'                  EXPR_DOT
+EXPR_DOT        "\nclass"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG             "\n"  \n                   EXPR_BEG
+
+

'.' is followed by EXPR_DOT so the \n is ignored.

+

Note that class becomes tIDENTIFIER despite being a reserved word. +This is discussed in the next section.

+

Reserved words and identical method names

+

The problem

+

In Ruby, reserved words can used as method names. However, in actuality it’s +not as simple as “it can be used” – there exist three possible contexts:

+
    +
  • Method definition (def xxxx)
  • +
  • Call (obj.xxxx)
  • +
  • Symbol literal (:xxxx)
  • +
+

All three are possible in Ruby. Below we will take a closer look at each.

+

First, the method definition. +It is preceded by the reserved word def so it should work.

+

In case of the method call, omitting the receiver can be a source of difficulty. +However, the scope of use here is even more limited, and omitting the receiver +is actually forbidden. That is, when the method name is a reserved word, the +receiver absolutely cannot be omitted. Perhaps it would be more accurate to say +that it is forbidden in order to guarantee that parsing is always possible.

+

Finally, in case of the symbol, it is preceded by the terminal symbol ':' so +it also should work. However, regardless of reserved words, the ':' here +conflicts with the colon in a?b:c If this is avoided, there should be no +further trouble.

+

For each of these cases, similarly to before, a scanner-based solution and a +parser-based solution exist. For the former use tIDENTIFIER (for example) as +the reserved word that comes after def or . or : For the latter, make +that into a rule. Ruby allows for both solutions to be used in each of the +three cases.

+

Method definition

+

The name part of the method definition. This is handled by the parser.

+

▼ Method definition rule +

+                | kDEF fname
+                  f_arglist
+                  bodystmt
+                  kEND
+                | kDEF singleton dot_or_colon  fname
+                  f_arglist
+                  bodystmt
+                  kEND
+

+

There exist only two rules for method definition – one for normal methods and +one for singleton methods. For both, the name part is fname and it is defined +as follows.

+

fname +

+fname           : tIDENTIFIER
+                | tCONSTANT
+                | tFID
+                | op
+                | reswords
+

+

reswords is a reserved word and op is a binary operator. Both rules consist +of simply all terminal symbols lined up, so I won’t go into detail here. +Finally, for tFID the end contains symbols similarly to gsub! and include?

+

Method call

+

Method calls with names identical to reserved words are handled by the scanner. +The scan code for reserved words is shown below.

+
+Scanning the identifier
+result = (tIDENTIFIER or tCONSTANT)
+
+if (lex_state != EXPR_DOT) {
+    struct kwtable *kw;
+
+    /* See if it is a reserved word.  */
+    kw = rb_reserved_word(tok(), toklen());
+    Reserved word is processed
+}
+
+

EXPR_DOT expresses what comes after the method call dot. Under EXPR_DOT +reserved words are universally not processed. The symbol for reserved words +after the dot becomes either tIDENTIFIER or tCONSTANT.

+

Symbols

+

Reserved word symbols are handled by both the scanner and the parser. +First, the rule.

+

symbol +

+symbol          : tSYMBEG sym

+

sym : fname +                | tIVAR +                | tGVAR +                | tCVAR

+

fname : tIDENTIFIER +                | tCONSTANT +                | tFID +                | op +                | reswords +

+

Reserved words (reswords) are explicitly passed through the parser. This is +only possible because the special terminal symbol tSYMBEG is present at the +start. If the symbol were, for example, ':' it would conflict with the +conditional operator (a?b:c) and stall. Thus, the trick is to recognize +tSYMBEG on the scanner level.

+

But how to cause that recognition? Let’s look at the implementation of the +scanner.

+

yylex-':' +

+3761        case ‘:’:
+3762          c = nextc();
+3763          if (c == ‘:’) {
+3764              if (lex_state == EXPR_BEG ||  lex_state == EXPR_MID ||
+3765                  (IS_ARG() && space_seen)) {
+3766                  lex_state = EXPR_BEG;
+3767                  return tCOLON3;
+3768              }
+3769              lex_state = EXPR_DOT;
+3770              return tCOLON2;
+3771          }
+3772          pushback©;
+3773          if (lex_state == EXPR_END ||
+                  lex_state == EXPR_ENDARG ||
+                  ISSPACE©) {
+3774              lex_state = EXPR_BEG;
+3775              return ‘:’;
+3776          }
+3777          lex_state = EXPR_FNAME;
+3778          return tSYMBEG;

+

(parse.y) +

+

This is a situation when the if in the first half has two consecutive ':' +In this situation, the '::'is scanned in accordance with the leftmost longest +match basic rule.

+

For the next if , the ':' is the aforementioned conditional operator. Both +EXPR_END and EXPR_ENDARG come at the end of the expression, so a parameter +does not appear. That is to say, since there can’t be a symbol, the ':' is a +conditional operator. +Similarly, if the next letter is a space (ISSPACE(c)) , a symbol is unlikely +so it is again a conditional operator.

+

When none of the above applies, it’s all symbols. In that case, a transition to +EXPR_FNAME occurs to prepare for all method names. There is no particular +danger to parsing here, but if this is forgotten, the scanner will not pass +values to reserved words and value calculation will be disrupted.

+

Modifiers

+

The problem

+

For example, for if if there exists a normal notation and one for postfix +modification.

+
+# Normal notation
+if cond then
+  expr
+end
+
+# Postfix
+expr if cond
+
+

This could cause a conflict. The reason can be guessed – again, it’s because +method parentheses have been omitted previously. Observe this example

+
+call if cond then a else b end
+
+

Reading this expression up to the if gives us two possible interpretations.

+
+call((if ....))
+call() if ....
+
+

When unsure, I recommend simply using trial and error and seeing if a conflict +occurs. Let us try to handle it with yacc after changing kIF_MOD to kIF +in the grammar.

+
+% yacc parse.y
+parse.y contains 4 shift/reduce conflicts and 13 reduce/reduce conflicts.
+
+

As expected, conflicts are aplenty. If you are interested, you add the option +-v to yacc and build a log. The nature of the conflicts should be shown +there in great detail.

+

Implementation

+

So, what is there to do? In Ruby, on the symbol level (that is, on the scanner +level) the normal if is distinguished from the postfix if by them being +kIF and kIF_MOD respectively. This also applies to all other postfix +operators. In all, there are five – kUNLESS_MOD kUNTIL_MOD kWHILE_MOD +kRESCUE_MOD and kIF_MOD The distinction is made here:

+

yylex-Reserved word

+
4173                  struct kwtable *kw;
+4174
+4175                  /* See if it is a reserved word.  */
+4176                  kw = rb_reserved_word(tok(), toklen());
+4177                  if (kw) {
+4178                      enum lex_state state = lex_state;
+4179                      lex_state = kw->state;
+4180                      if (state == EXPR_FNAME) {
+4181                          yylval.id = rb_intern(kw->name);
+4182                      }
+4183                      if (kw->id[0] == kDO) {
+4184                          if (COND_P()) return kDO_COND;
+4185                          if (CMDARG_P() && state != EXPR_CMDARG)
+4186                              return kDO_BLOCK;
+4187                          if (state == EXPR_ENDARG)
+4188                              return kDO_BLOCK;
+4189                          return kDO;
+4190                      }
+4191                      if (state == EXPR_BEG)  /*** Here ***/
+4192                          return kw->id[0];
+4193                      else {
+4194                          if (kw->id[0] != kw->id[1])
+4195                              lex_state = EXPR_BEG;
+4196                          return kw->id[1];
+4197                      }
+4198                  }
+(parse.y)
+

This is located at the end of yylex after the identifiers are scanned. +The part that handles modifiers is the last (innermost) ifelse Whether +the return value is altered can be determined by whether or not the state is +EXPR_BEG. This is where a modifier is identified. Basically, the variable kw +is the key and if you look far above you will find that it is struct kwtable

+

I’ve already described in the previous chapter how struct kwtable is a +structure defined in keywords and the hash function rb_reserved_word() is +created by gperf. I’ll show the structure here again.

+

keywordsstruct kwtable

+
   1  struct kwtable {char *name; int id[2]; enum lex_state state;};
+(keywords)
+

I’ve already explained about name and id[0] – they are the reserved word +name and its symbol. Here I will speak about the remaining members.

+

First, id[1] is a symbol to deal with modifiers. For example, in case of if +that would be kIF_MOD. +When a reserved word does not have a modifier equivalent, id[0] and id[1] +contain the same things.

+

Because state is enum lex_state it is the state to which a transition +should occur after the reserved word is read. +Below is a list created in the kwstat.rb tool which I made. The tool can be +found on the CD.

+
+% kwstat.rb ruby/keywords
+---- EXPR_ARG
+defined?  super     yield
+
+---- EXPR_BEG
+and     case    else    ensure  if      module  or      unless  when
+begin   do      elsif   for     in      not     then    until   while
+
+---- EXPR_CLASS
+class
+
+---- EXPR_END
+BEGIN     __FILE__  end       nil       retry     true
+END       __LINE__  false     redo      self
+
+---- EXPR_FNAME
+alias  def    undef
+
+---- EXPR_MID
+break   next    rescue  return
+
+---- modifiers
+if      rescue  unless  until   while
+
+

The do conflict

+

The problem

+

There are two iterator forms – doend and {} Their difference is in +priority – {} has a much higher priority. A higher priority means that as +part of the grammar a unit is “small” which means it can be put into a smaller +rule. For example, it can be put not into stmt but expr or primary. In +the past {} iterators were in primary while doend iterators were +in stmt

+

By the way, there has been a request for an expression like this:

+
+m do .... end + m do .... end
+
+

To allow for this, put the doend iterator in arg or primary. +Incidentally, the condition for while is expr, meaning it contains arg +and primary, so the do will cause a conflict here. Basically, it looks like +this:

+
+while m do
+  ....
+end
+
+

At first glance, the do looks like the do of while. However, a closer +look reveals that it could be a m doend bundling. Something that’s not +obvious even to a person will definitely cause yacc to conflict. Let’s try it +in practice.

+
+/* do conflict experiment */
+%token kWHILE kDO tIDENTIFIER kEND
+%%
+expr: kWHILE expr kDO expr kEND
+    | tIDENTIFIER
+    | tIDENTIFIER kDO expr kEND
+
+

I simplified the example to only include while, variable referencing and +iterators. This rule causes a shift/reduce conflict if the head of the +conditional contains tIDENTIFIER. If tIDENTIFIER is used for variable +referencing and do is appended to while, then it’s reduction. If it’s made +an iterator do, then it’s a shift.

+

Unfortunately, in a shift/reduce conflict the shift is prioritized, so if left +unchecked, do will become an iterator do. That said, even if a reduction +is forced through operator priorities or some other method, do won’t shift at +all, becoming unusable. Thus, to solve the problem without any contradictions, +we need to either deal with on the scanner level or write a rule that allows to +use operators without putting the doend iterator into expr.

+

However, not putting doend into expr is not a realistic goal. That +would require all rules for expr (as well as for arg and primary) to be +repeated. This leaves us only the scanner solution.

+

Rule-level solution

+

Below is a simplified example of a relevant rule.

+

do symbol +

+primary         : kWHILE expr_value do compstmt kEND

+

do : term +                | kDO_COND

+

primary : operation brace_block +                | method_call brace_block

+

brace_block : ‘{’ opt_block_var compstmt ‘}’ +                | kDO opt_block_var compstmt kEND +

+

As you can see, the terminal symbols for the do of while and for the +iterator do are different. For the former it’s kDO_COND while for the +latter it’s kDO Then it’s simply a matter of pointing that distinction out to +the scanner.

+

Symbol-level solution

+

Below is a partial view of the yylex section that processes reserved words. +It’s the only part tasked with processing do so looking at this code should +be enough to understand the criteria for making the distinction.

+

yylex-Identifier-Reserved word

+
4183                      if (kw->id[0] == kDO) {
+4184                          if (COND_P()) return kDO_COND;
+4185                          if (CMDARG_P() && state != EXPR_CMDARG)
+4186                              return kDO_BLOCK;
+4187                          if (state == EXPR_ENDARG)
+4188                              return kDO_BLOCK;
+4189                          return kDO;
+4190                      }
+(parse.y)
+

It’s a little messy, but you only need the part associated with kDO_COND. +That is because only two comparisons are meaningful. +The first is the comparison between kDO_COND and kDO/kDO_BLOCK +The second is the comparison between kDO and kDO_BLOCK. +The rest are meaningless. +Right now we only need to distinguish the conditional do – leave all the +other conditions alone.

+

Basically, COND_P() is the key.

+

COND_P()

+

cond_stack

+

COND_P() is defined close to the head of parse.y

+

cond_stack +

+  75  #ifdef HAVE_LONG_LONG
+  76  typedef unsigned LONG_LONG stack_type;
+  77  #else
+  78  typedef unsigned long stack_type;
+  79  #endif
+  80
+  81  static stack_type cond_stack = 0;
+  82  #define COND_PUSH(n) (cond_stack = (cond_stack<<1)|((n)&1))
+  83  #define COND_POP() (cond_stack >>= 1)
+  84  #define COND_LEXPOP() do {\
+  85      int last = COND_P();\
+  86      cond_stack >>= 1;\
+  87      if (last) cond_stack |= 1;\
+  88  } while (0)
+  89  #define COND_P() (cond_stack&1)

+

(parse.y) +

+

The type stack_type is either long (over 32 bit) or long long (over 64 +bit). cond_stack is initialized by yycompile() at the start of parsing and +after that is handled only through macros. All you need, then, is to understand +those macros.

+

If you look at COND_PUSH/POP you will see that these macros use integers as +stacks consisting of bits.

+
+MSB←   →LSB
+...0000000000         Initial value 0
+...0000000001         COND_PUSH(1)
+...0000000010         COND_PUSH(0)
+...0000000101         COND_PUSH(1)
+...0000000010         COND_POP()
+...0000000100         COND_PUSH(0)
+...0000000010         COND_POP()
+
+

As for COND_P(), since it determines whether or not the least significant bit +(LSB) is a 1, it effectively determines whether the head of the stack is a 1.

+

The remaining COND_LEXPOP() is a little weird. It leaves COND_P() at the +head of the stack and executes a right shift. Basically, it “crushes” the +second bit from the bottom with the lowermost bit.

+
+MSB←   →LSB
+...0000000000         Initial value 0
+...0000000001         COND_PUSH(1)
+...0000000010         COND_PUSH(0)
+...0000000101         COND_PUSH(1)
+...0000000011         COND_LEXPOP()
+...0000000100         COND_PUSH(0)
+...0000000010         COND_LEXPOP()
+
+

Now I will explain what that means.

+

Investigating the function

+

Let us investigate the function of this stack. To do that I will list up all +the parts where COND_PUSH() COND_POP() are used.

+
+        | kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
+--
+        | kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();}
+--
+        | kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
+--
+      case '(':
+                :
+                :
+        COND_PUSH(0);
+        CMDARG_PUSH(0);
+--
+      case '[':
+                :
+                :
+        COND_PUSH(0);
+        CMDARG_PUSH(0);
+--
+      case '{':
+                :
+                :
+        COND_PUSH(0);
+        CMDARG_PUSH(0);
+--
+      case ']':
+      case '}':
+      case ')':
+        COND_LEXPOP();
+        CMDARG_LEXPOP();
+
+

From this we can derive the following general rules

+
    +
  • At the start of a conditional expression PUSH(1)
  • +
  • At opening parenthesis PUSH(0)
  • +
  • At the end of a conditional expression POP()
  • +
  • At closing parenthesisLEXPOP()
  • +
+

With this, you should see how to use it. If you think about it for a minute, +the name cond_stack itself is clearly the name for a macro that determines +whether or not it’s on the same level as the conditional expression (see image 2)

+

+

(condp)
+Figure 2: Changes of COND_P()

+

+

Using this trick should also make situations like the one shown below easy to +deal with.

+
+while (m do .... end)   # do is an iterator do(kDO)
+  ....
+end
+
+

This means that on a 32-bit machine in the absence of long long if +conditional expressions or parentheses are nested at 32 levels, things could +get strange. Of course, in reality you won’t need to nest so deep so there’s no +actual risk.

+

Finally, the definition of COND_LEXPOP() looks a bit strange – that seems to +be a way of dealing with lookahead. However, the rules now do not allow for +lookahead to occur, so there’s no purpose to make the distinction between POP +and LEXPOP. Basically, at this time it would be correct to say that +COND_LEXPOP() has no meaning.

+

tLPAREN_ARG(1)

+

The problem

+

This one is very complicated. It only became workable in in Ruby 1.7 and only +fairly recently. The core of the issue is interpreting this:

+
+call (expr) + 1
+
+

As one of the following

+
+(call(expr)) + 1
+call((expr) + 1)
+
+

In the past, it was always interpreted as the former. That is, the parentheses +were always treated as “Method parameter parentheses”. But since Ruby 1.7 it +became possible to interpret it as the latter – basically, if a space is added, +the parentheses become “Parentheses of expr

+

I will also provide an example to explain why the interpretation changed. +First, I wrote a statement as follows

+
+p m() + 1
+
+

So far so good. But let’s assume the value returned by m is a fraction and +there are too many digits. Then we will have it displayed as an integer.

+
+p m() + 1 .to_i   # ??
+
+

Uh-oh, we need parentheses.

+
+p (m() + 1).to_i
+
+

How to interpret this? Up to 1.6 it will be this

+
+(p(m() + 1)).to_i
+
+

The much-needed to_i is rendered meaningless, which is unacceptable. +To counter that, adding a space between it and the parentheses will cause the +parentheses to be treated specially as expr parentheses.

+

For those eager to test this, this feature was implemented in parse.y +revision 1.100(2001-05-31). Thus, it should be relatively prominent when +looking at the differences between it and 1.99. This is the command to find the +difference.

+
+~/src/ruby % cvs diff -r1.99 -r1.100 parse.y
+
+

Investigation

+

First let us look at how the set-up works in reality. Using the ruby-lexer +tool{ruby-lexer: located in tools/ruby-lexer.tar.gz on the CD} we can look +at the list of symbols corresponding to the program.

+
+% ruby-lexer -e 'm(a)'
+tIDENTIFIER '(' tIDENTIFIER ')' '\n'
+
+

Similarly to Ruby, -e is the option to pass the program directly from the +command line. With this we can try all kinds of things. Let’s start with the +problem at hand – the case where the first parameter is enclosed in parentheses.

+
+% ruby-lexer -e 'm (a)'
+tIDENTIFIER tLPAREN_ARG tIDENTIFIER ')' '\n'
+
+

After adding a space, the symbol of the opening parenthesis became tLPAREN_ARG. +Now let’s look at normal expression parentheses.

+
+% ruby-lexer -e '(a)'
+tLPAREN tIDENTIFIER ')' '\n'
+
+

For normal expression parentheses it seems to be tLPAREN. To sum up:

+ + + + + + + + + + + + + + + + + +
Input Symbol of opening parenthesis
m(a) '('
m (a) tLPAREN_ARG
(a) tLPAREN
+

Thus the focus is distinguishing between the three. For now tLPAREN_ARG is +the most important.

+

The case of one parameter

+

We’ll start by looking at the yylex() section for '('

+

yylex-'(' +

+3841        case ‘(’:
+3842          command_start = Qtrue;
+3843          if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+3844              c = tLPAREN;
+3845          }
+3846          else if (space_seen) {
+3847              if (lex_state == EXPR_CMDARG) {
+3848                  c = tLPAREN_ARG;
+3849              }
+3850              else if (lex_state == EXPR_ARG) {
+3851                  c = tLPAREN_ARG;
+3852                  yylval.id = last_id;
+3853              }
+3854          }
+3855          COND_PUSH(0);
+3856          CMDARG_PUSH(0);
+3857          lex_state = EXPR_BEG;
+3858          return c;

+

(parse.y) +

+

Since the first if is tLPAREN we’re looking at a normal expression +parenthesis. The distinguishing feature is that lex_state is either BEG or +MID – that is, it’s clearly at the beginning of the expression.

+

The following space_seen shows whether the parenthesis is preceded by a space. +If there is a space and lex_state is either ARG or CMDARG, basically if +it’s before the first parameter, the symbol is not '(' but tLPAREN_ARG. +This way, for example, the following situation can be avoided

+
+m(              # Parenthesis not preceded by a space. Method parenthesis ('(')
+m arg, (        # Unless first parameter, expression parenthesis (tLPAREN)
+
+

When it is neither tLPAREN nor tLPAREN_ARG, the input character c is used +as is and becomes '('. This will definitely be a method call parenthesis.

+

If such a clear distinction is made on the symbol level, no conflict should +occur even if rules are written as usual. Simplified, it becomes something like +this:

+
+stmt         : command_call
+
+method_call  : tIDENTIFIER '(' args ')'    /* Normal method */
+
+command_call : tIDENTIFIER command_args    /* Method with parentheses omitted */
+
+command_args : args
+
+args         : arg
+             : args ',' arg
+
+arg          : primary
+
+primary      : tLPAREN compstmt ')'        /* Normal expression parenthesis */
+             | tLPAREN_ARG expr ')'        /* First parameter enclosed in parentheses */
+             | method_call
+
+

Now I need you to focus on method_call and command_call If you leave the +'(' without introducing tLPAREN_ARG, then command_args will produce +args, args will produce arg, arg will produce primary. Then, '(' +will appear from tLPAREN_ARG and conflict with method_call (see image 3)

+

+

(trees)
+Figure 3: method_call and command_call

+

+

The case of two parameters and more

+

One might think that if the parenthesis becomes tLPAREN_ARG all will be well. +That is not so. For example, consider the following

+
+m (a, a, a)
+
+

Before now, expressions like this one were treated as method calls and did not +produce errors. However, if tLPAREN_ARG is introduced, the opening +parenthesis becomes an expr parenthesis, and if two or more parameters are +present, that will cause a parse error. This needs to be resolved for the sake +of compatibility.

+

Unfortunately, rushing ahead and just adding a rule like

+
+command_args : tLPAREN_ARG args ')'
+
+

will just cause a conflict. Let’s look at the bigger picture and think carefully.

+
+stmt         : command_call
+             | expr
+
+expr         : arg
+
+command_call : tIDENTIFIER command_args
+
+command_args : args
+             | tLPAREN_ARG args ')'
+
+args         : arg
+             : args ',' arg
+
+arg          : primary
+
+primary      : tLPAREN compstmt ')'
+             | tLPAREN_ARG expr ')'
+             | method_call
+
+method_call  : tIDENTIFIER '(' args ')'
+
+

Look at the first rule of command_args Here, args produces arg Then arg +produces primary and out of there comes the tLPAREN_ARG rule. And since +expr contains arg and as it is expanded, it becomes like this:

+
+command_args : tLPAREN_ARG arg ')'
+             | tLPAREN_ARG arg ')'
+
+

This is a reduce/reduce conflict, which is very bad.

+

So, how can we deal with only 2+ parameters without causing a conflict? We’ll +have to write to accommodate for that situation specifically. In practice, it’s +solved like this:

+

command_args +

+command_args    : open_args

+

open_args : call_args +                | tLPAREN_ARG ‘)’ +                | tLPAREN_ARG call_args2 ‘)’

+

call_args : command +                | args opt_block_arg +                | args ‘,’ tSTAR arg_value opt_block_arg +                | assocs opt_block_arg +                | assocs ‘,’ tSTAR arg_value opt_block_arg +                | args ‘,’ assocs opt_block_arg +                | args ‘,’ assocs ‘,’ tSTAR arg opt_block_arg +                | tSTAR arg_value opt_block_arg +                | block_arg

+

call_args2 : arg_value ‘,’ args opt_block_arg +                | arg_value ‘,’ block_arg +                | arg_value ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ args ‘,’ tSTAR arg_value opt_block_arg +                | assocs opt_block_arg +                | assocs ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ assocs opt_block_arg +                | arg_value ‘,’ args ‘,’ assocs opt_block_arg +                | arg_value ‘,’ assocs ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ args ‘,’ assocs ‘,’ +                                  tSTAR arg_value opt_block_arg +                | tSTAR arg_value opt_block_arg +                | block_arg

+

primary : literal +                | strings +                | xstring +                       : +                | tLPAREN_ARG expr ‘)’ +

+

Here command_args is followed by another level – open_args which may not be +reflected in the rules without consequence. The key is the second and third +rules of this open_args This form is similar to the recent example, but is +actually subtly different. The difference is that call_args2 has been +introduced. The defining characteristic of this call_args2 is that the number +of parameters is always two or more. This is evidenced by the fact that most +rules contain ',' The only exception is assocs, but since assocs does not +come out of expr it cannot conflict anyway.

+

That wasn’t a very good explanation. To put it simply, in a grammar where this:

+
+command_args    : call_args
+
+

doesn’t work, and only in such a grammar, the next rule is used to make an +addition. Thus, the best way to think here is “In what kind of grammar would +this rule not work?” Furthermore, since a conflict only occurs when the +primary of tLPAREN_ARG appears at the head of call_args, the scope can be +limited further and the best way to think is “In what kind of grammar does this +rule not work when a tIDENTIFIER tLPAREN_ARG line appears?” Below are a few +examples.

+
+m (a, a)
+
+

This is a situation when the tLPAREN_ARG list contains two or more items.

+
+m ()
+
+

Conversely, this is a situation when the tLPAREN_ARG list is empty.

+
+m (*args)
+m (&block)
+m (k => v)
+
+

This is a situation when the tLPAREN_ARG list contains a special expression +(one not present in expr).

+

This should be sufficient for most cases. Now let’s compare the above with a +practical implementation.

+

open_args(1) +

+open_args       : call_args
+                | tLPAREN_ARG   ‘)’
+

+

First, the rule deals with empty lists

+

open_args(2) +

+                | tLPAREN_ARG call_args2  ‘)’

+

call_args2 : arg_value ‘,’ args opt_block_arg +                | arg_value ‘,’ block_arg +                | arg_value ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ args ‘,’ tSTAR arg_value opt_block_arg +                | assocs opt_block_arg +                | assocs ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ assocs opt_block_arg +                | arg_value ‘,’ args ‘,’ assocs opt_block_arg +                | arg_value ‘,’ assocs ‘,’ tSTAR arg_value opt_block_arg +                | arg_value ‘,’ args ‘,’ assocs ‘,’ +                                  tSTAR arg_value opt_block_arg +                | tSTAR arg_value opt_block_arg +                | block_arg +

+

And call_args2 deals with elements containing special types such as assocs, +passing of arrays or passing of blocks. With this, the scope is now +sufficiently broad.

+

tLPAREN_ARG(2)

+

The problem

+

In the previous section I said that the examples provided should be sufficient +for “most” special method call expressions. I said “most” because iterators are +still not covered. For example, the below statement will not work:

+
+m (a) {....}
+m (a) do .... end
+
+

In this section we will once again look at the previously introduced parts with +solving this problem in mind.

+

Rule-level solution

+

Let us start with the rules. The first part here is all familiar rules, +so focus on the do_block part

+

command_call +

+command_call    : command
+                | block_command

+

command : operation command_args

+

command_args : open_args

+

open_args : call_args +                | tLPAREN_ARG ‘)’ +                | tLPAREN_ARG call_args2 ‘)’

+

block_command : block_call

+

block_call : command do_block

+

do_block : kDO_BLOCK opt_block_var compstmt ‘}’ +                | tLBRACE_ARG opt_block_var compstmt ‘}’ +

+

Both do and { are completely new symbols kDO_BLOCK and tLBRACE_ARG. +Why isn’t it kDO or '{' you ask? In this kind of situation the best answer +is an experiment, so we will try replacing kDO_BLOCK with kDO and +tLBRACE_ARG with '{' and processing that with yacc

+
+% yacc parse.y
+conflicts:  2 shift/reduce, 6 reduce/reduce
+
+

It conflicts badly. A further investigation reveals that this statement is the +cause.

+
+m (a), b {....}
+
+

That is because this kind of statement is already supposed to work. b{....} +becomes primary. And now a rule has been added that concatenates the block +with m That results in two possible interpretations:

+
+m((a), b) {....}
+m((a), (b {....}))
+
+

This is the cause of the conflict – namely, a 2 shift/reduce conflict.

+

The other conflict has to do with doend

+
+m((a)) do .... end     # Add do〜end using block_call
+m((a)) do .... end     # Add do〜end using primary
+
+

These two conflict. This is 6 reduce/reduce conflict.

+

{} iterator

+

This is the important part. As shown previously, you can avoid a conflict by +changing the do and '{' symbols.

+

yylex-'{'

+
3884        case '{':
+3885          if (IS_ARG() || lex_state == EXPR_END)
+3886              c = '{';          /* block (primary) */
+3887          else if (lex_state == EXPR_ENDARG)
+3888              c = tLBRACE_ARG;  /* block (expr) */
+3889          else
+3890              c = tLBRACE;      /* hash */
+3891          COND_PUSH(0);
+3892          CMDARG_PUSH(0);
+3893          lex_state = EXPR_BEG;
+3894          return c;
+(parse.y)
+

IS_ARG() is defined as

+

IS_ARG +

+3104  #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)

+

(parse.y) +

+

Thus, when the state is EXPR_ENDARG it will always be false. In other words, +when lex_state is EXPR_ENDARG, it will always become tLBRACE_ARG, so the +key to everything is the transition to EXPR_ENDARG.

+

EXPR_ENDARG

+

Now we need to know how to set EXPR_ENDARG I used grep to find where it is +assigned.

+

▼ Transition toEXPR_ENDARG +

+open_args       : call_args
+                | tLPAREN_ARG  {lex_state = EXPR_ENDARG;} ‘)’
+                | tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ‘)’

+

primary : tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ‘)’ +

+

That’s strange. One would expect the transition to EXPR_ENDARG to occur after +the closing parenthesis corresponding to tLPAREN_ARG, but it’s actually +assigned before ')' I ran grep a few more times thinking there might be +other parts setting the EXPR_ENDARG but found nothing.

+

Maybe there’s some mistake. Maybe lex_state is being changed some other way. +Let’s use rubylex-analyser to visualize the lex_state transition.

+
+% rubylex-analyser -e 'm (a) { nil }'
++EXPR_BEG
+EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG S         "("  tLPAREN_ARG          EXPR_BEG
+                                              0:cond push
+                                              0:cmd push
+                                              1:cmd push-
+EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG           ")"  ')'                  EXPR_END
+                                              0:cond lexpop
+                                              1:cmd lexpop
++EXPR_ENDARG
+EXPR_ENDARG S         "{"  tLBRACE_ARG          EXPR_BEG
+                                              0:cond push
+                                             10:cmd push
+                                              0:cmd resume
+EXPR_BEG    S       "nil"  kNIL                 EXPR_END
+EXPR_END    S         "}"  '}'                  EXPR_END
+                                              0:cond lexpop
+                                              0:cmd lexpop
+EXPR_END             "\n"  \n                   EXPR_BEG
+
+

The three big branching lines show the state transition caused by yylex(). +On the left is the state before yylex() The middle two are the word text and +its symbols. Finally, on the right is the lex_state after yylex()

+

The problem here are parts of single lines that come out as +EXPR_ENDARG. +This indicates a transition occurring during parser action. According to this, +for some reason an action is executed after reading the ')' a transition to +EXPR_ENDARG occurs and '{' is nicely changed into tLBRACE_ARG This is +actually a pretty high-level technique – indiscriminately (ab)using +the LALR up to the (1).

+

Abusing the lookahead

+

ruby -y can bring up a detailed display of the yacc parser engine. +This time we will use it to more closely trace the parser.

+
+% ruby -yce 'm (a) {nil}' 2>&1 | egrep '^Reading|Reducing'
+Reducing via rule 1 (line 303),  -> @1
+Reading a token: Next token is 304 (tIDENTIFIER)
+Reading a token: Next token is 340 (tLPAREN_ARG)
+Reducing via rule 446 (line 2234), tIDENTIFIER  -> operation
+Reducing via rule 233 (line 1222),  -> @6
+Reading a token: Next token is 304 (tIDENTIFIER)
+Reading a token: Next token is 41 (')')
+Reducing via rule 392 (line 1993), tIDENTIFIER  -> variable
+Reducing via rule 403 (line 2006), variable  -> var_ref
+Reducing via rule 256 (line 1305), var_ref  -> primary
+Reducing via rule 198 (line 1062), primary  -> arg
+Reducing via rule 42 (line 593), arg  -> expr
+Reducing via rule 260 (line 1317),  -> @9
+Reducing via rule 261 (line 1317), tLPAREN_ARG expr @9 ')'  -> primary
+Reading a token: Next token is 344 (tLBRACE_ARG)
+                         :
+                         :
+
+

Here we’re using the option -c which stops the process at just compiling and +-e which allows to give a program from the command line. And we’re using +grep to single out token read and reduction reports.

+

Start by looking at the middle of the list. ')' is read. Now look at the end +– the reduction (execution) of embedding action (@9) finally happens. Indeed, +this would allow EXPR_ENDARG to be set after the ')' before the '{' +But is this always the case? Let’s take another look at the part where it’s set.

+
+Rule 1    tLPAREN_ARG  {lex_state = EXPR_ENDARG;} ')'
+Rule 2    tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ')'
+Rule 3    tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ')'
+
+

The embedding action can be substituted with an empty rule. For example, +we can rewrite this using rule 1 with no change in meaning whatsoever.

+
+target  : tLPAREN_ARG tmp ')'
+tmp     :
+            {
+                lex_state = EXPR_ENDARG;
+            }
+
+

Assuming that this is before tmp, it’s possible that one terminal symbol will +be read by lookahead. Thus we can skip the (empty) tmp and read the next. +And if we are certain that lookahead will occur, the assignment to lex_state +is guaranteed to change to EXPR_ENDARG after ')' +But is ')' certain to be read by lookahead in this rule?

+

Ascertaining lookahead

+

This is actually pretty clear. Think about the following input.

+
+m () { nil }        # A
+m (a) { nil }       # B
+m (a,b,c) { nil }   # C
+
+

I also took the opportunity to rewrite the rule to make it easier to understand +(with no actual changes).

+
+rule1: tLPAREN_ARG             e1  ')'
+rule2: tLPAREN_ARG  one_arg    e2  ')'
+rule3: tLPAREN_ARG  more_args  e3  ')'
+
+e1:   /* empty */
+e2:   /* empty */
+e3:   /* empty */
+
+

First, the case of input A. Reading up to

+
+m (         # ... tLPAREN_ARG
+
+

we arrive before the e1. If e1 is reduced here, another rule cannot be +chosen anymore. Thus, a lookahead occurs to confirm whether to reduce e1 and +continue with rule1 to the bitter end or to choose a different rule. +Accordingly, if the input matches rule1 it is certain that ')' will be read +by lookahead.

+

On to input B. First, reading up to here

+
+m (         # ... tLPAREN_ARG
+
+

Here a lookahead occurs for the same reason as described above. +Further reading up to here

+
+m (a        # ... tLPAREN_ARG '(' tIDENTIFIER
+
+

Another lookahead occurs. It occurs because depending on whether what follows +is a ',' or a ')' a decision is made between rule2 and rule3 If what +follows is a ',' then it can only be a comma to separate parameters, thus +rule3 the rule for two or more parameters, is chosen. This is also true if +the input is not a simple a but something like an if or literal. When the +input is complete, a lookahead occurs to choose between rule2 and rule3 - +the rules for one parameter and two or more parameters respectively.

+

The presence of a separate embedding action is present before ')' in every +rule. There’s no going back after an action is executed, so the parser will try +to postpone executing an action until it is as certain as possible. For that +reason, situations when this certainty cannot be gained with a single lookahead +should be excluded when building a parser as it is a conflict.

+

Proceeding to input C.

+
+m (a, b, c
+
+

At this point anything other than rule3 is unlikely so we’re not expecting a +lookahead. And yet, that is wrong. If the following is '(' then it’s a method +call, but if the following is ',' or ')' it needs to be a variable +reference. Basically, this time a lookahead is needed to confirm parameter +elements instead of embedding action reduction.

+

But what about the other inputs? For example, what if the third parameter is a +method call?

+
+m (a, b, c(....)    # ... ',' method_call
+
+

Once again a lookahead is necessary because a choice needs to be made between +shift and reduction depending on whether what follows is ',' or ')'. Thus, +in this rule in all instances the ')' is read before the embedding action is +executed. This is quite complicated and more than a little impressive.

+

But would it be possible to set lex_state using a normal action instead of an +embedding action? For example, like this:

+
+                | tLPAREN_ARG ')' { lex_state = EXPR_ENDARG; }
+
+

This won’t do because another lookahead is likely to occur before the action is +reduced. This time the lookahead works to our disadvantage. With this it should +be clear that abusing the lookahead of a LALR parser is pretty tricky and not +something a novice should be doing.

+

doend iterator

+

So far we’ve dealt with the {} iterator, but we still have doend +left. Since they’re both iterators, one would expect the same solutions to work, +but it isn’t so. The priorities are different. For example,

+
+m a, b {....}          # m(a, (b{....}))
+m a, b do .... end     # m(a, b) do....end
+
+

Thus it’s only appropriate to deal with them differently.

+

That said, in some situations the same solutions do apply. +The example below is one such situation

+
+m (a) {....}
+m (a) do .... end
+
+

In the end, our only option is to look at the real thing. +Since we’re dealing with do here, we should look in the part of yylex() +that handles reserved words.

+

yylex-Identifiers-Reserved words-do +

+4183                      if (kw→id0 == kDO) {
+4184                          if (COND_P()) return kDO_COND;
+4185                          if (CMDARG_P() && state != EXPR_CMDARG)
+4186                              return kDO_BLOCK;
+4187                          if (state == EXPR_ENDARG)
+4188                              return kDO_BLOCK;
+4189                          return kDO;
+4190                      }

+

(parse.y) +

+

This time we only need the part that distinguishes between kDO_BLOCK and kDO. +Ignore kDO_COND Only look at what’s always relevant in a finite-state scanner.

+

The decision-making part using EXPR_ENDARG is the same as tLBRACE_ARG so +priorities shouldn’t be an issue here. Similarly to '{' the right course of +action is probably to make it kDO_BLOCK

+

The problem lies with CMDARG_P() and EXPR_CMDARG. Let’s look at both.

+

CMDARG_P()

+

cmdarg_stack +

+  91  static stack_type cmdarg_stack = 0;
+  92  #define CMDARG_PUSH(n) (cmdarg_stack = (cmdarg_stack<<1)|((n)&1))
+  93  #define CMDARG_POP() (cmdarg_stack >>= 1)
+  94  #define CMDARG_LEXPOP() do {\
+  95      int last = CMDARG_P();\
+  96      cmdarg_stack >>= 1;\
+  97      if (last) cmdarg_stack |= 1;\
+  98  } while (0)
+  99  #define CMDARG_P() (cmdarg_stack&1)

+

(parse.y) +

+

The structure and interface (macro) of cmdarg_stack is completely identical +to cond_stack. It’s a stack of bits. Since it’s the same, we can use the same +means to investigate it. Let’s list up the places which use it. +First, during the action we have this:

+
+command_args    :  {
+                        $<num>$ = cmdarg_stack;
+                        CMDARG_PUSH(1);
+                    }
+                  open_args
+                    {
+                        /* CMDARG_POP() */
+                        cmdarg_stack = $<num>1;
+                        $$ = $2;
+                    }
+
+

$<num>$ represents the left value with a forced casting. In this case it +comes out as the value of the embedding action itself, so it can be produced in +the next action with $<num>1. Basically, it’s a structure where cmdarg_stack +is hidden in $$ before open_args and then restored in the next action.

+

But why use a hide-restore system instead of a simple push-pop? That will be +explained at the end of this section.

+

Searching yylex() for more CMDARG relations, I found this.

+ + + + + + + + + + + + + +
Token Relation
'(' '[' '{' CMDARG_PUSH(0)
')' ']' '}' CMDARG_LEXPOP()
+

Basically, as long as it is enclosed in parentheses, CMDARG_P() is false.

+

Consider both, and it can be said that when command_args , a parameter for a +method call with parentheses omitted, is not enclosed in parentheses +CMDARG_P() is true.

+

EXPR_CMDARG

+

Now let’s take a look at one more condition – EXPR_CMDARG +Like before, let us look for place where a transition to EXPR_CMDARG occurs.

+

yylex-Identifiers-State Transitions +

+4201              if (lex_state == EXPR_BEG ||
+4202                  lex_state == EXPR_MID ||
+4203                  lex_state == EXPR_DOT ||
+4204                  lex_state == EXPR_ARG ||
+4205                  lex_state == EXPR_CMDARG) {
+4206                  if (cmd_state)
+4207                      lex_state = EXPR_CMDARG;
+4208                  else
+4209                      lex_state = EXPR_ARG;
+4210              }
+4211              else {
+4212                  lex_state = EXPR_END;
+4213              }

+

(parse.y) +

+

This is code that handles identifiers inside yylex() +Leaving aside that there are a bunch of lex_state tests in here, let’s look +first at cmd_state +And what is this?

+

cmd_state +

+3106  static int
+3107  yylex()
+3108  {
+3109      static ID last_id = 0;
+3110      register int c;
+3111      int space_seen = 0;
+3112      int cmd_state;
+3113
+3114      if (lex_strterm) {
+              /* ……omitted…… */
+3132      }
+3133      cmd_state = command_start;
+3134      command_start = Qfalse;

+

(parse.y) +

+

Turns out it’s an yylex local variable. Furthermore, an investigation using +grep revealed that here is the only place where its value is altered. This +means it’s just a temporary variable for storing command_start during a +single run of yylex

+

When does command_start become true, then?

+

command_start +

+2327  static int command_start = Qtrue;

+

2334 static NODE* +2335 yycompile(f, line) +2336 char *f; +2337 int line; +2338 { +                   : +2380 command_start = 1;

+

      static int +      yylex() +      { +                   : +            case ‘\n’: +              /* ……omitted…… */ +3165 command_start = Qtrue; +3166 lex_state = EXPR_BEG; +3167 return ‘\n’;

+

3821 case ‘;’: +3822 command_start = Qtrue;

+

3841 case ‘(’: +3842 command_start = Qtrue;

+

(parse.y) +

+

From this we understand that command_start becomes true when one of the +parse.y static variables \n ; ( is scanned.

+

Summing up what we’ve covered up to now, first, when \n ; ( is read, +command_start becomes true and during the next yylex() run cmd_state +becomes true.

+

And here is the code in yylex() that uses cmd_state

+

yylex-Identifiers-State transitions +

+4201              if (lex_state == EXPR_BEG ||
+4202                  lex_state == EXPR_MID ||
+4203                  lex_state == EXPR_DOT ||
+4204                  lex_state == EXPR_ARG ||
+4205                  lex_state == EXPR_CMDARG) {
+4206                  if (cmd_state)
+4207                      lex_state = EXPR_CMDARG;
+4208                  else
+4209                      lex_state = EXPR_ARG;
+4210              }
+4211              else {
+4212                  lex_state = EXPR_END;
+4213              }

+

(parse.y) +

+

From this we understand the following: when after \n ; ( the state is +EXPR_BEG MID DOT ARG CMDARG and an identifier is read, a transition to +EXPR_CMDARG occurs. However, lex_state can only become EXPR_BEG following +a \n ; ( so when a transition occurs to EXPR_CMDARG the lex_state loses +its meaning. The lex_state restriction is only important to transitions +dealing with EXPR_ARG

+

Based on the above we can now think of a situation where the state is +EXPR_CMDARG. For example, see the one below. The underscore is the current +position.

+
+m _
+m(m _
+m m _
+
+

Conclusion

+

Let us now return to the do decision code.

+

yylex-Identifiers-Reserved words-kDO-kDO_BLOCK +

+4185                          if (CMDARG_P() && state != EXPR_CMDARG)
+4186                              return kDO_BLOCK;

+

(parse.y) +

+

Inside the parameter of a method call with parentheses omitted but not before +the first parameter. That means from the second parameter of command_call +onward. Basically, like this:

+
+m arg, arg do .... end
+m (arg), arg do .... end
+
+

Why is the case of EXPR_CMDARG excluded? This example should clear It up

+
+m do .... end
+
+

This pattern can already be handled using the doend iterator which uses +kDO and is defined in primary Thus, including that case would cause another +conflict.

+

Reality and truth

+

Did you think we’re done? Not yet. +Certainly, the theory is now complete, but only if everything that has been +written is correct. +As a matter of fact, there is one falsehood in this section. +Well, more accurately, it isn’t a falsehood but an inexact statement. +It’s in the part about CMDARG_P()

+
+

Actually, CMDARG_P() becomes true when inside command_args , that is to say, +inside the parameter of a method call with parentheses omitted.

+
+

But where exactly is “inside the parameter of a method call with parentheses +omitted”? Once again, let us use rubylex-analyser to inspect in detail.

+
+% rubylex-analyser -e  'm a,a,a,a;'
++EXPR_BEG
+EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG S         "a"  tIDENTIFIER          EXPR_ARG
+                                              1:cmd push-
+EXPR_ARG              ","  ','                  EXPR_BEG
+EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ","  ','                  EXPR_BEG
+EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ","  ','                  EXPR_BEG
+EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ";"  ';'                  EXPR_BEG
+                                              0:cmd resume
+EXPR_BEG     C       "\n"  '                    EXPR_BEG
+
+

The 1:cmd push- in the right column is the push to cmd_stack. When the +rightmost digit in that line is 1 CMDARG_P() become true. To sum up, the +period of CMDARG_P() can be described as:

+
+

From immediately after the first parameter of a method call with parentheses omitted +To the terminal symbol following the final parameter

+
+

But, very strictly speaking, even this is still not entirely accurate.

+
+% rubylex-analyser -e  'm a(),a,a;'
++EXPR_BEG
+EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG S         "a"  tIDENTIFIER          EXPR_ARG
+                                              1:cmd push-
+EXPR_ARG              "("  '('                  EXPR_BEG
+                                              0:cond push
+                                             10:cmd push
+EXPR_BEG     C        ")"  ')'                  EXPR_END
+                                              0:cond lexpop
+                                              1:cmd lexpop
+EXPR_END              ","  ','                  EXPR_BEG
+EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ","  ','                  EXPR_BEG
+EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG              ";"  ';'                  EXPR_BEG
+                                              0:cmd resume
+EXPR_BEG     C       "\n"  '                    EXPR_BEG
+
+

When the first terminal symbol of the first parameter has been read, +CMDARG_P() is true. Therefore, the complete answer would be:

+
+

From the first terminal symbol of the first parameter of a method call with parentheses omitted +To the terminal symbol following the final parameter

+
+

What repercussions does this fact have? Recall the code that uses CMDARG_P()

+

yylex-Identifiers-Reserved words-kDO-kDO_BLOCK +

+4185                          if (CMDARG_P() && state != EXPR_CMDARG)
+4186                              return kDO_BLOCK;

+

(parse.y) +

+

EXPR_CMDARG stands for “Before the first parameter of command_call” and is +excluded. But wait, this meaning is also included in CMDARG_P(). +Thus, the final conclusion of this section:

+
+

EXPR_CMDARG is completely useless

+
+

Truth be told, when I realized this, I almost broke down crying. I was sure it +had to mean SOMETHING and spent enormous effort analyzing the source, but +couldn’t understand anything. Finally, I ran all kind of tests on the code +using rubylex-analyser and arrived at the conclusion that it has no meaning +whatsoever.

+

I didn’t spend so much time doing something meaningless just to fill up more +pages. It was an attempt to simulate a situation likely to happen in reality. +No program is perfect, all programs contain their own mistakes. Complicated +situations like the one discussed here are where mistakes occur most easily, +and when they do, reading the source material with the assumption that it’s +flawless can really backfire. In the end, when reading the source code, you can +only trust the what actually happens.

+

Hopefully, this will teach you the importance of dynamic analysis. When +investigating something, focus on what really happens. The source code will not +tell you everything. It can’t tell anything other than what the reader infers.

+

And with this very useful sermon, I close the chapter.

+

Still not the end

+

Another thing I forgot. I can’t end the chapter without explaining why +CMDARG_P() takes that value. Here’s the problematic part:

+

command_args +

+1209  command_args    :  {
+1210                          $$ = cmdarg_stack;
+1211                          CMDARG_PUSH(1);
+1212                      }
+1213                    open_args
+1214                      {
+1215                          /* CMDARG_POP() */
+1216                          cmdarg_stack = $1;
+1217                          $$ = $2;
+1218                      }

+

1221 open_args : call_args

+

(parse.y) +

+

All things considered, this looks like another influence from lookahead. +command_args is always in the following context:

+
+tIDENTIFIER _
+
+

Thus, this looks like a variable reference or a method call. If it’s a variable +reference, it needs to be reduced to variable and if it’s a method call it +needs to be reduced to operation We cannot decide how to proceed without +employing lookahead. Thus a lookahead always occurs at the head of +command_args and after the first terminal symbol of the first parameter is +read, CMDARG_PUSH() is executed.

+

The reason why POP and LEXPOP exist separately in cmdarg_stack is also +here. Observe the following example:

+
+% rubylex-analyser -e 'm m (a), a'
+-e:1: warning: parenthesize argument(s) for future version
++EXPR_BEG
+EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG S         "m"  tIDENTIFIER          EXPR_ARG
+                                              1:cmd push-
+EXPR_ARG    S         "("  tLPAREN_ARG          EXPR_BEG
+                                              0:cond push
+                                             10:cmd push
+                                            101:cmd push-
+EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
+EXPR_CMDARG           ")"  ')'                  EXPR_END
+                                              0:cond lexpop
+                                             11:cmd lexpop
++EXPR_ENDARG
+EXPR_ENDARG           ","  ','                  EXPR_BEG
+EXPR_BEG    S         "a"  tIDENTIFIER          EXPR_ARG
+EXPR_ARG             "\n"  \n                   EXPR_BEG
+                                             10:cmd resume
+                                              0:cmd resume
+
+

Looking only at the parts related to cmd and how they correspond to each other…

+
+  1:cmd push-       parserpush(1)
+ 10:cmd push        scannerpush
+101:cmd push-       parserpush(2)
+ 11:cmd lexpop      scannerpop
+ 10:cmd resume      parserpop(2)
+  0:cmd resume      parserpop(1)
+
+

The cmd push- with a minus sign at the end is a parser push. Basically, +push and pop do not correspond. Originally there were supposed to be two +consecutive push- and the stack would become 110, but due to the lookahead +the stack became 101 instead. CMDARG_LEXPOP() is a last-resort measure to +deal with this. The scanner always pushes 0 so normally what it pops should +also always be 0. When it isn’t 0, we can only assume that it’s 1 due to the +parser push being late. Thus, the value is left.

+

Conversely, at the time of the parser pop the stack is supposed to be back in +normal state and usually pop shouldn’t cause any trouble. When it doesn’t do +that, the reason is basically that it should work right. Whether popping or +hiding in $$ and restoring, the process is the same. When you consider all +the following alterations, it’s really impossible to tell how lookahead’s +behavior will change. Moreover, this problem appears in a grammar that’s going +to be forbidden in the future (that’s why there is a warning). To make +something like this work, the trick is to consider numerous possible situations +and respond them. And that is why I think this kind of implementation is right +for Ruby. Therein lies the real solution.

+ + + +
+ + diff --git a/htmls/css/styles.css b/htmls/css/styles.css new file mode 100644 index 0000000..93e4f9c --- /dev/null +++ b/htmls/css/styles.css @@ -0,0 +1,173 @@ +body { + background-color: white; + color: black; + text-align: left; + line-height: 140%; + margin-top: 5%; + margin-left: 2em; + width: 40em; +} + +h1 { + text-align: left; + font-size: 200%; + margin-top: 0em; + margin-bottom: 1em; + padding-left: 12px; + border-left: 80px solid #33a; + line-height: 80px; +} + +h2 { + text-align: left; + font-size: 150%; + margin-top: 3em; + margin-bottom: 1em; + border-bottom: 2px solid #33a; +} + +h3 { + text-align: left; + font-size: 150%; + margin-top: 1em; + margin-bottom: 0.1em; + padding-left: 8px; + border-left: 12px solid #33a; +} + +h4 { + text-align: left; + font-size: 150%; + margin-top: 1em; + margin-bottom: 0.1em; +} + +ul { + padding-left: 1em; +} + +li { + padding-left: 0em; +} + +dl { + margin-top: 0em; + margin-bottom: 0em; + margin-left: 0em; + margin-right: 0em; +} + +dt { + margin-top: 0.5em; + margin-bottom: 0.2em; + margin-left: 0em; + margin-right: 0em; +} + +dd { + margin-top: 0em; + margin-bottom: 0em; + margin-left: 4em; + margin-right: 0em; +} + +p.caption { + margin-botton: 0px; +} + +pre { + line-height: 110%; + padding: 8px; + background: #eee; +} + +span.ami { + color: black; + background-color: #ccc; +} + +.image { + align: center; + margin-top: 2em; + margin-bottom: 2em; +} + +address { + font-style: normal; + line-height: 110%; + text-align: right; +} + +a:link, a:visited { + color: #33a; + text-decoration: none; +} + +a:active, a:visited { + color: #666; + text-decoration: none; +} + +a:hover, a:focus { + text-decoration: underline; +} + +/* -- */ +footer { + margin-top: 2em; +} + +body { + font-family: Georgia, serif; +} + +h1 code, h2 code, h3 code, h4 code, h5 code{ + font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; + font-weight: normal; +} + + +pre { + font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; + font-size: .8em; +} + +code { + font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; + font-size: .8em; +} + +h1#chapter { font-size: 150%; } + +th { padding-right: .5em } + +pre.longlist, pre.screen { + padding: 8px; + background: #eee; +} + +pre.emlist { + background: white; + padding-left: 2em; +} + +p { width: 35em } + +.image ul { + list-style-type: none; + padding-left: 0; + font-size: .8em; + margin: 0 +} + +.image p { margin: 0 } + +/* for chapter 16 */ +div.longlist { + padding: 8px; + background: #eee; + font-size: .8em; + font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; +} + +div.longlist p { margin: 0 } diff --git a/htmls/evaluator.html b/htmls/evaluator.html new file mode 100644 index 0000000..4506dbe --- /dev/null +++ b/htmls/evaluator.html @@ -0,0 +1,1236 @@ + + + + + Chapter 13: Structure of the evaluator | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 13: Structure of the evaluator

+

Outline

+

Interface

+

We are not familiar with the word “Hyo-ka-ki” (evaluator). Literally, it must +be a “-ki” (device) to “hyo-ka” (evaluating). Then, what is “hyo-ka”?

+

“Hyo-ka” is the definitive translation of “evaluate”. However, if the premise +is describing about programing languages, it can be considered as an error in +translation. It’s hard to avoid that the word “hyo-ka” gives the impression +of “whether it is good or bad”.

+

“Evaluate” in the context of programing languages has nothing to do with +“good or bad”, and its meaning is more close to “speculating” or “executing”. +The origin of “evaluate” is a Latin word “ex+value+ate”. +If I translate it directly, +it is “turn it into a value”. This may be the simplest way to understand: +to determine the value from an expression expressed in text.

+

Very frankly speaking, the bottom line is that evaluating is executing a +written expression and getting the result of it. Then why is it not called just +“execute”? It’s because evaluating is not only executing.

+

For example, in an ordinary programming language, when we write “3”, +it will be dealt with as an integer 3. +This situation is sometimes described as “the result of evaluating +”3" is 3". It’s hard to say an expression of a constant is executed, +but it is certainly an evaluation. +It’s all right if there exist a programming language in which the letter “3”, +when it is evaluated, will be dealt with (evaluated) as an integer 6.

+

I’ll introduce another example. +When an expression consists of multiple constants, +sometimes the constants are calculated during the compiling process (constant folding). + We usually don’t call it “executing” because executing indicates the process +that the created binary is working. However, no matter when it is calculated +you’ll get the same result from the same program.

+

In other words, “evaluating” is usually equals to “executing”, but essentially +“evaluating” is different from “executing”. For now, only this point is what +I’d like you to remember.

+

The characteristics of ruby's evaluator.

+

The biggest characteristic of ruby ’s evaluator is that, as this is also of +the whole ruby ’s interpretor, the difference in expressions between +the C-level code (extension libraries) and the Ruby-level code is small. +In ordinary programming languages, +the amount of the features of its interpretor we can use from extension +libraries is usually very limited, but there are awfully few limits in ruby . +Defining classes, defining methods and calling a method without limitation, +these can be taken for granted. We can also use exception handling, iterators. +Furthermore, threads.

+

But we have to compensate for the conveniences somewhere. +Some codes are weirdly hard to implement, some codes have a lot overhead, +and there are a lot of places implementing the almost same thing twice both for +C and Ruby.

+

Additionally, ruby is a dynamic language, +it means that you can construct and evaluate a string at runtime. +That is eval which is a function-like method. As you expected, +it is named after “evaluate”. By using it, you can even do something like this:

+
+lvar = 1
+answer = eval("lvar + lvar")    # the answer is 2
+
+

There are also Module#module_eval and Object#instance_eval , each method +behaves slightly differently. I’ll describe about them in detail in Chapter 17: Dynamic evaluation.

+

eval.c

+

The evaluator is implemented in eval.c . However, this eval.c is a +really huge file: it has 9000 lines, its size is 200K bytes, +and the number of the functions in it is 309. It is hard to fight against. +When the size becomes this amount, +it’s impossible to figure out its structure by just looking over it.

+

So how can we do? +First, the bigger the file, the less possibility of its content not separated at all. +In other words, the inside of it must be modularized into small portions. +Then, how can we find the modules? +I’ll list up some ways.

+

The first way is to print the list of the defined functions and look at the +prefixes of them. rb_dvar_ , rb_mod_ , rb_thread — there are plenty of +functions with these prefixes. +Each prefix clearly indicate a group of the same type of functions.

+

Alternatively, as we can tell when looking at the code of the class libraries, +Init_xxxx() is always put at the end of a block in ruby . +Therefore, Init_xxxx() also indicates a break between modules.

+

Additionally, the names are obviously important, too. +Since eval() and rb_eval() and eval_node() appear close to each other, +we naturally think there should be a deep relationship among them.

+

Finally, in the source code of ruby , the definitions of types or variables +and the declarations of prototypes often indicate a break between modules.

+

Being aware of these points when looking, +it seems that eval.c can be mainly divided into these modules listed below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Safe Level already explained in Chapter 7: Security
Method Entry Manipulations finding or deleting syntax trees which are actual method bodies
Evaluator Core the heart of the evaluator that rb_eval() is at its center.
Exception generations of exceptions and creations of backtraces
Method the implementation of method call
Iterator the implementation of functions that are related to blocks
Load loading and evaluating external files
Proc the implementation of Proc
Thread the implementation of Ruby threads
+

Among them, “Load” and “Thread” are the parts that essentially should not be in eval.c . +They are in eval.c merely because of the restrictions of C language. +To put it more precisely, they need the macros such as PUSH_TAG defined in eval.c . +So, I decided to exclude the two topics from Part 3 and deal with them +at Part 4. And, it’s probably all right if I don’t explain the safe level here +because I’ve already done in Part 1.

+

Excluding the above three, the six items are left to be described. +The below table shows the corresponding chapter of each of them:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Method Entry Manipulations the next chapter: Context
Evaluator Core the entire part of Part 3
Exception this chapter
Method Chapter 15: Methods
Iterator Chapter 16: Blocks
Proc Chapter 16: Blocks
+

From main by way of ruby_run to rb_eval

+

Call Graph

+

The true core of the evaluator is a function called rb_eval() . +In this chapter, we will follow the path from main() to that rb_eval() . +First of all, here is a rough call graph around rb_eval :

+
+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
+
+

I put the file names on the right side when moving to another file. +Gazing this carefully, the first thing we’ll notice is that the functions of +eval.c call the functions of ruby.c back.

+

I wrote it as “calling back” because main.c and ruby.c are relatively for +the implementation of ruby command. eval.c is the implementation of the +evaluator itself which keeps a little distance from ruby command. +In other words, eval.c is supposed to be used by ruby.c and calling the +functions of ruby.c from eval.c makes eval.c less independent.

+

Then, why is this in this way? It’s mainly because of the restrictions of C language. +Because the functions such as ruby_prog_init() and ruby_process_options() +start to use the API of the ruby world, it’s possible an exception occurs. +However, in order to stop an exception of Ruby, it’s necessary to use the macro +named PUSH_TAG() which can only be used in eval.c . In other words, essentially, +ruby_init() and ruby_run() should have been defined in ruby.c .

+

Then, why isn’t PUSH_TAG an extern function or something which is available +to other files? +Actually, PUSH_TAG can only be used as a pair with POP_TAG as follows:

+
+PUSH_TAG();
+/* do lots of things */
+POP_TAG();
+
+

Because of its implementation, the two macros should be put into the same function. +It’s possible to implement in a way to be able to divide them into different functions, +but not in such way because it’s slower.

+

The next thing we notice is, the fact that it sequentially calls the functions +named ruby_xxxx from main() seems very meaningful. +Since they are really obviously symmetric, it’s odd if there’s not any relationship.

+

Actually, these three functions have deep relationships. Simply speaking, all of +these three are “built-in Ruby interfaces”. That is, they are used only when +creating a command with built-in ruby interpretor and not when writing +extension libraries. Since ruby command itself can be considered as one of +programs with built-in Ruby in theory, to use these interfaces is natural.

+

What is the ruby_ prefix ? So far, the all of ruby ’s functions are prefixed +with rb_ . Why are there the two types: rb_ and ruby_ ? I investigated but +could not understand the difference, so I asked directly. The answer was, +“ruby_ is for the auxiliary functions of ruby command and rb_ is for the +official interfaces”

+

“Then, why are the variables like ruby_scope are ruby_ ?”, I asked further. +It seems this is just a coincidence. The variables like ruby_scope +are originally named as the_xxxx , but in the middle of the version 1.3 there’s +a change to add prefixes to all interfaces. At that time ruby_ was added to +the “may-be-internals-for-some-reasons” variables.

+

The bottom line is that what ruby_ is attached to are either what to support +ruby command or the internal variables and what rb_ is attached to are the +official interfaces of ruby interpretor.

+

main()

+

First, straightforwardly, I’ll start with main() . +It is nice that this is very short.

+

main()

+ +
+  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)
+
+

#if def NT is obviously the NT of Windows NT. But somehow NT is also +defined in Win9x. So, it means Win32 environment. +NtInitialize() initializes argc argv and the socket system (WinSock) for +Win32. Because this function is only doing the initialization, it’s not +interesting and not related to the main topic. Thus, I omit this.

+

And, __MACOS__ is not “Ma-Ko-Su” but Mac OS. In this case, it means +Mac OS 9 and before, and it does not include Mac OS X. Even though such +#ifdef remains, as I wrote at the beginning of this book, the current version +can not run on Mac OS 9 and before. It’s just a legacy from when ruby was +able to run on it. Therefore, I also omit this code.

+

By the way, as it is probably known by the readers who are familiar with C language, +the identifiers starting with an under bar are reserved for the system libraries or OS. +However, although they are called “reserved”, using it is almost never result in an error, +but if using a little weird cc it could result in an error. +For example, it is the cc of HP-US. HP-US is an UNIX which HP is creating. +If there’s any opinion such as HP-UX is not weird, I would deny it out loud.

+

Anyway, conventionally, we don’t define such identifiers in user applications.

+

Now, I’ll start to briefly explain about the built-in Ruby interfaces.

+

ruby_init()

+

ruby_init() initializes the Ruby interpretor. +Since only a single interpretor of the current Ruby can exist in a process, +it does not need neither arguments or a return value. +This point is generally considered as “lack of features”.

+

When there’s only a single interpretor, +what have difficulty most is probably around the development environment of Ruby. +Concretely, they are the applications such as irb , RubyWin, and RDE. +Although loading a rewritten program, the classes which are supposed to be +deleted would remain. To counter this with the reflection API is not impossible +but requires a lot of effort.

+

However, it seems that Mr. Matsumoto (Matz) purposefully limits the number of +interpretors to one. “it’s impossible to initialize completely” appears to be +its reason. For example, “the loaded extension libraries could not be removed” +is taken as an example.

+

The code of ruby_init() is omitted because it’s unnecessary to read.

+

ruby_options()

+

What to parse command-line options for the Ruby interpreter is ruby_options() . +Of course, depending on the command, we do not have to use this.

+

Inside this function, -r (load a library) and +-e (pass a program from command-line) are processed. +This is also where the file passed as a command-line argument is parsed as +a Ruby program.

+

ruby command reads the main program from a file if it was given, otherwise from stdin . +After that, using rb_compile_string() or rb_compile_file() introduced at Part 2, +it compiles the text into a syntax tree. +The result will be set into the global variable ruby_eval_tree .

+

I also omit the code of ruby_options() because it’s just doing necessary +things one by one and not interesting.

+

ruby_run()

+

Finally, ruby_run() starts to evaluate the syntax tree which was set to ruby_eval_tree . +We also don’t always need to call this function. Other than ruby_run() , +for instance, we can evaluate a string by using a function named rb_eval_string() .

+

ruby_run()

+ +
+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)
+
+

We can see the macros PUSH_xxxx() , but we can ignore them for now. I’ll +explain about around them later when the time comes. The important thing here +is only eval_node() . Its content is:

+

eval_node()

+ +
+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)
+
+

This calls rb_eval() on ruby_eval_tree . The ruby_eval_tree_begin is +storing the statements registered by BEGIN . But, this is also not important.

+

And, ruby_stop() inside of ruby_run() terminates all threads and +finalizes all objects and checks exceptions and, in the end, calls exit() . +This is also not important, so we won’t see this.

+

rb_eval()

+

Outline

+

Now, rb_eval() . This function is exactly the real core of ruby . +One rb_eval() call processes a single NODE , and the whole syntax tree will +be processed by calling recursively. (Fig.1)

+

+

(rbeval)
+Fig.1: rb_eval

+

+

rb_eval is, as the same as yylex() , made of a huge switch statement and +branching by each type of the nodes. First, let’s look at the outline.

+

rb_eval() Outline

+ +
+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:
+                   :
+              (plenty of case statements)
+                   :
+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)
+
+

In the omitted part, plenty of the codes to process all nodes are listed. +By branching like this, it processes each node. When the code is only a few, +it will be processed in rb_eval() . But when it becoming many, it will be a +separated function. Most of functions in eval.c are created in this way.

+

When returning a value from rb_eval() , it uses the macro RETURN() instead +of return , in order to always pass through CHECK_INTS . Since this macro is +related to threads, you can ignore this until the chapter about it.

+

And finally, the local variables result and node are volatile for GC.

+

NODE_IF

+

Now, taking the if statement as an example, let’s look at the process of +the rb_eval() evaluation concretely. +From here, in the description of rb_eval() ,

+
    +
  • The source code (a Ruby program)
  • +
  • Its corresponding syntax tree
  • +
  • The partial code of rb_eval() to process the node.
  • +
+

these three will be listed at the beginning.

+

▼source program

+ +
+if true
+  'true expr'
+else
+  'false expr'
+end
+
+

▼ its corresponding syntax tree ( nodedump )

+ +
+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
+
+

As we’ve seen in Part 2, elsif and unless can be, by contriving the ways to assemble, +bundled to a single NODE_IF type, so we don’t have to treat them specially.

+

rb_eval()NODE_IF

+ +
+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)
+
+

What is important is only the last if statement. +If rewriting it without any change in its meaning, it becomes this:

+
+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, at (A), evaluating (the node of) the Ruby’s condition statement and +testing its value with RTEST() . +I’ve mentioned that RTEST() is a macro to test whether or not +a VALUE is true of Ruby. +If that was true, evaluating the then side clause at (B). +If false, evaluating the else side clause at ©.

+

In addition, I’ve mentioned that if statement of Ruby also has its own value, +so it’s necessary to return a value. +Since the value of an if is the value of either the then side or the else +side which is the one executed, returning it by using the macro RETURN() .

+

In the original list, it does not call rb_eval() recursively but just does goto . +This is the "conversion from tail recursion to goto " which has also appeared +in the previous chapter “Syntax tree construction”.

+

NODE_NEW_LINE

+

Since there was NODE_NEWLINE at the node for a if statement, +let’s look at the code for it.

+

rb_eval()NODE_NEWLINE

+ +
+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)
+
+

There’s nothing particularly difficult.

+

call_trace_func() has already appeared at NODE_IF . Here is a simple +explanation of what kind of thing it is. This is a feature to trace a Ruby +program from Ruby level. The debugger ( debug.rb ) and the tracer ( tracer.rb ) +and the profiler ( profile.rb ) and irb (interactive ruby command) and more +are using this feature.

+

By using the function-like method set_trace_func you can register a Proc +object to trace, and that Proc object is stored into trace_func . If +trace_func is not 0, it means not QFalse , it will be considered as a Proc +object and executed (at call_trace_func() ).

+

This call_trace_func() has nothing to do with the main topic and not so +interesting as well. Therefore in this book, from now on, +I’ll completely ignore it. If you are interested in it, I’d like you to +challenge after finishing the Chapter 16: Blocks.

+

Pseudo-local Variables

+

NODE_IF and such are interior nodes in a syntax tree. +Let’s look at the leaves, too.

+

rb_eval() Ppseudo-Local Variable Nodes

+ +
+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)
+
+

We’ve seen self as the argument of rb_eval() . I’d like you to make sure it +by going back a little. +The others are probably not needed to be explained.

+

Jump Tag

+

Next, I’d like to explain NODE_WHILE which is corresponding to while , +but to implement break or next only with recursive calls of a function is difficult. +Since ruby enables these syntaxes by using what named “jump tag”, +I’ll start with describing it first.

+

Simply put, “jump tag” is a wrapper of setjmp() and longjump() which are +library functions of C language. Do you know about setjmp() ? +This function has already appeared at gc.c , +but it is used in very abnormal way there. +setjmp() is usually used to jump over functions. +I’ll explain by taking the below code as an example. +The entry point is parent() .

+

setjmp() and longjmp()

+ +
+jmp_buf buf;
+
+void child2(void) {
+    longjmp(buf, 34);   /* go back straight to parent
+                           the return value of setjmp becomes 34 */
+    puts("This message will never be printed.");
+}
+
+void child1(void) {
+    child2();
+    puts("This message will never be printed.");
+}
+
+void parent(void) {
+    int result;
+    if ((result = setjmp(buf)) == 0) {
+        /* normally returned from setjmp */
+        child1();
+    } else {
+        /* returned from child2 via longjmp */
+        printf("%d\n", result);   /* shows 34 */
+    }
+}
+
+

First, when setjmp() is called at parent() , +the executing state at the time is saved to the argument buf . +To put it a little more directly, the address of the top of the machine +stack and the CPU registers are saved. +If the return value of setjmp() was 0, it means it normally returned from setjmp() , +thus you can write the subsequent code as usual. +This is the if side. Here, it calls child1() .

+

Next, the control moves to child2() and calls longjump , +then it can go back straight to the place where the argument buf was setjmp ed. +So in this case, it goes back to the setjmp at parent() . +When coming back via longjmp , the return value of setjmp becomes +the value of the second argument of longjmp , so the else side is executed. +And, even if we pass 0 to longjmp , +it will be forced to be another value. Thus it’s fruitless.

+

Fig.2 shows the state of the machine stack. +The ordinary functions return only once for each call. +However, it’s possible setjmp() returns twice. +Is it helpful to grasp the concept if I say that it is something like fork() ?

+

+

(setjmp)
+Fig.2: setjmp() longjmp() Image

+

+

Now, we’ve learned about setjmp() as a preparation. +In eval.c , EXEC_TAG corresponds to setjmp() and JUMP_TAG() corresponds +to longjmp() respectively. (Fig.3)

+

+

(jumptag)
+Fig.3: “tag jump” image

+

+

Take a look at this image, it seems that EXEC_TAG() does not have any arguments. +Where has jmp_buf gone? +Actually, in ruby , jmp_buf is wrapped by the struct struct tag. +Let’s look at it.

+

struct tag

+ +
+ 783  struct tag {
+ 784      jmp_buf buf;
+ 785      struct FRAME *frame;   /* FRAME when PUSH_TAG */
+ 786      struct iter *iter;     /* ITER  when PUSH_TAG */
+ 787      ID tag;                /* tag type */
+ 788      VALUE retval;          /* the return value of this jump */
+ 789      struct SCOPE *scope;   /* SCOPE when PUSH_TAG */
+ 790      int dst;               /* the destination ID */
+ 791      struct tag *prev;
+ 792  };
+
+(eval.c)
+
+

Because there’s the member prev , we can infer that struct tag is probably +a stack structure using a linked list. Moreover, by looking around it, we can +find the macros PUSH_TAG() and POP_TAG , thus it definitely seems a stack.

+

PUSH_TAG() POP_TAG()

+ +
+ 793  static struct tag *prot_tag;   /* the pointer to the head of the machine stack */
+
+ 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)
+
+

I’d like you to be flabbergasted here because the actual tag is fully allocated +at the machine stack as a local variable. (Fig.4). Moreover, do ~ while is +divided between the two macros. +This might be one of the most awful usages of the C preprocessor. +Here is the macros PUSH / POP coupled and extracted to make it easy to read.

+
+do {
+    struct tag _tag;
+    _tag.prev = prot_tag;   /* save the previous tag */
+    prot_tag = &_tag;       /* push a new tag on the stack */
+    /* do several things */
+    prot_tag = _tag.prev;   /* restore the previous tag */
+} while (0);
+
+

This method does not have any overhead of function calls, +and its cost of the memory allocation is next to nothing. +This technique is only possible because the ruby evaluator is made of +recursive calls of rb_eval() .

+

+

(tagstack)
+Fig.4: the tag stack is embedded in the machine stack

+

+

Because of this implementation, it’s necessary that PUSH_TAG and POP_TAG +are in the same one function as a pair. Plus, since it’s not supposed to be +carelessly used at the outside of the evaluator, +we can’t make them available to other files.

+

Additionally, let’s also take a look at EXEC_TAG() and JUMP_TAG() .

+

EXEC_TAG() JUMP_TAG()

+ +
+ 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 are wrapped by EXEC_TAG() and JUMP_TAG() respectively. +The name EXEC_TAG() can look like a wrapper of longjmp() at first sight, +but this one is to execute setjmp() .

+

Based on all of the above, I’ll explain the mechanism of while . +First, when starting while it does EXEC_TAG() ( setjmp ). +After that, it executes the main body by calling rb_eval() +recursively. If there’s break or next , it does JUMP_TAG() ( longjmp ). +Then, it can go back to the start point of the while loop. (Fig.5)

+

+

(whilejmp)
+Fig.5: the implementation of while by using “tag jump”

+

+

Though break was taken as an example here, what cannot be implemented without +jumping is not only break . Even if we limit the case to while , +there are next and redo . +Additionally, return from a method and exceptions also should have to +climb over the wall of rb_eval() . +And since it’s cumbersome to use a different tag stack for each case, +we want for only one stack to handle all cases in one way or another.

+

What we need to make it possible is just attaching information about +“what the purpose of this jump is”. +Conveniently, the return value of setjmp() could be specified as the argument +of longjmp() , thus we can use this. The types are expressed by the following flags:

+

▼tag type

+ +
+ 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 exceptions */
+ 834  #define TAG_THROW       0x7    /* throw(won't be explained in this boook)*/
+ 835  #define TAG_FATAL       0x8    /* fatal : exceptions which are not catchable */
+ 836  #define TAG_MASK        0xf
+
+(eval.c)
+
+

The meanings are written as each comment. The last TAG_MASK is the bitmask to +take out these flags from a return value of setjmp() . This is because the +return value of setjmp() can also include information which is not about a +“type of jump”.

+

NODE_WHILE

+

Now, by examining the code of NODE_WHILE , let’s check the actual usage of tags.

+

▼ The Source Program

+ +
+while true
+  'true_expr'
+end
+
+

▼ Its corresponding syntax tree( nodedump-short

+ +
+NODE_WHILE
+nd_state = 1 (while)
+nd_cond:
+    NODE_TRUE
+nd_body:
+    NODE_STR
+    nd_lit = "true_expr":String
+
+

rb_evalNODE_WHILE

+ +
+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)
+
+

The idiom which will appear over and over again appeared in the above code.

+
+PUSH_TAG(PROT_NONE);
+switch (state = EXEC_TAG()) {
+  case 0:
+    /* process normally */
+    break;
+  case TAG_a:
+    state = 0;    /* clear state because the jump waited for comes */
+    /* do the process of when jumped with TAG_a */
+    break;
+  case TAG_b:
+    state = 0;    /* clear state because the jump waited for comes */
+    /* do the process of when jumped with TAG_b */
+    break;
+  default
+    break;        /* this jump is not waited for, then ... */
+}
+POP_TAG();
+if (state) JUMP_TAG(state);   /* .. jump again here */
+
+

First, as PUSH_TAG() and POP_TAG() are the previously described mechanism, +it’s necessary to be used always as a pair. Also, they need to be written +outside of EXEC_TAG() . And, apply EXEC_TAG() to the just pushed jmp_buf . +This means doing setjmp() . +If the return value is 0, since it means immediately returning from setjmp() , +it does the normal processing (this usually contains rb_eval() ). +If the return value of EXEC_TAG() is not 0, since it means returning via longjmp() , +it filters only the own necessary jumps by using case and +lets the rest ( default ) pass.

+

It might be helpful to see also the code of the jumping side. +The below code is the handler of the node of redo .

+

rb_eval()NODE_REDO

+ +
+2560  case NODE_REDO:
+2561    CHECK_INTS;
+2562    JUMP_TAG(TAG_REDO);
+2563    break;
+
+(eval.c)
+
+

As a result of jumping via JUMP_TAG() , it goes back to the last EXEC_TAG() . +The return value at the time is the argument TAG_REDO . Being aware of this, +I’d like you to look at the code of NODE_WHILE and check what route is taken.

+

The idiom has enough explained, now I’ll explain about the code of NODE_WHILE +a little more in detail. As mentioned, since the inside of case 0: is the main +process, I extracted only that part. +Additionally, I moved some labels to enhance readability.

+
+  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:
+
+

There are the two places calling rb_eval() on node->nd_state which +corresponds to the conditional statement. It seems that only the first test of +the condition is separated. This is to deal with both do ~ while and while +at once. When node->nd_state is 0 it is a do ~ while , when 1 it is an +ordinary while . The rest might be understood by following step-by-step, +I won’t particularly explain.

+

By the way, I feel like it easily becomes an infinite loop if there is next +or redo in the condition statement. Since it is of course exactly what the +code means, it’s the fault of who wrote it, but I’m a little curious about it. +So, I’ve actually tried it.

+
+% ruby -e 'while next do nil end'
+-e:1: void value expression
+
+

It’s simply rejected at the time of parsing. +It’s safe but not an interesting result. +What produces this error is value_expr() of parse.y .

+

The value of an evaluation of while

+

while had not had its value for a long time, but it has been able to return +a value by using break since ruby 1.7. +This time, let’s focus on the flow of the value of an evaluation. +Keeping in mind that the value of the local variable result becomes the +return value of rb_eval() , I’d like you to look at the following code:

+
+        result = Qnil;
+        switch (state = EXEC_TAG()) {
+          case 0:
+            /* the main process */
+          case TAG_REDO:
+          case TAG_NEXT:
+            /* each jump */
+
+          case TAG_BREAK:
+            state = 0;
+            result = prot_tag->retval;     (A)
+          default:
+            break;
+        }
+        RETURN(result);
+
+

What we should focus on is only (A). The return value of the jump seems to be +passed via prot_tag->retval which is a struct tag. +Here is the passing side:

+

rb_eval()NODE_BREAK

+ +
+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, by using the macro return_value() , it assigns the value to the +struct of the top of the tag stack.

+

The basic flow is this, but in practice there could be another EXEC_TAG +between EXEC_TAG() of NODE_WHILE and JUMP_TAG() of NODE_BREAK . +For example, rescue of an exception handling can exist between them.

+
+while cond       # EXEC_TAG() for NODE_WHILE
+  begin          # EXEC_TAG() again for rescue
+    break 1
+  rescue
+  end
+end
+
+

Therefore, it’s hard to determine whether or not the strict tag of when doing +JUMP_TAG() at NODE_BREAK is the one which was pushed at NODE_WHILE . +In this case, because retval is propagated in POP_TAG() as shown below, +the return value can be passed to the next tag without particular thought.

+

POP_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)
+
+

This can probably be depicted as Fig.6.

+

+

(usetag)
+Fig.6: the return value propagation

+

+

Exception

+

As the second example of the usage of “tag jump”, we’ll look at how exceptions +are dealt with.

+

raise

+

When I explained while , we looked at the setjmp() side first. This time, +we’ll look at the longjmp() side first for a change. It’s rb_exc_raise() +which is the substance of raise .

+

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 (an instance of Exception or one of its subclass). +Notice that It seems to jump with TAG_RAISE this time. +And the below code is very simplified rb_longjmp() .

+

rb_longjmp() (simplified)

+ +
+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);
+}
+
+

Well, though this can be considered as a matter of course, this is just to jump +as usual by using JUMP_TAG() .

+

What is ruby_errinfo ? By doing grep a few times, I figured out that this +variable is the substance of the global variable $! of Ruby. +Since this variable indicates the exception which is currently occurring, +naturally its substance ruby_errinfo should have the same meaning as well.

+

The Big Picture

+

▼the source program

+ +
+begin
+  raise('exception raised')
+rescue
+  'rescue clause'
+ensure
+  'ensure clause'
+end
+
+

▼the syntax tree( nodedump-short

+ +
+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
+
+

As the right order of rescue and ensure is decided at parser level, +the right order is +strictly decided at syntax tree as well. NODE_ENSURE is always at the “top”, +NODE_RESCUE comes next, the main body (where raise exist) is the last. +Since NODE_BEGIN is a node to do nothing, you can consider NODE_ENSURE is +virtually on the top.

+

This means, since NODE_ENSURE and NODE_RESCUE are above the main body which +we want to protect, we can stop raise by merely doing EXEC_TAG() . Or rather, +the two nodes are put above in syntax tree for this purpose, is probably more +accurate to say.

+

ensure

+

We are going to look at the handler of NODE_ENSURE which is the node of ensure .

+

rb_eval()NODE_ENSURE

+ +
+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 branch using if is another idiom to deal with tag. +It interrupts a jump by doing EXEC_TAG() then evaluates the ensure clause ( +( node->nd_ensr ). As for the flow of the process, it’s probably straightforward.

+

Again, we’ll try to think about the value of an evaluation. +To check the specification first,

+
+begin
+  expr0
+ensure
+  expr1
+end
+
+

for the above statement, the value of the whole begin will be the value of +expr0 regardless of whether or not ensure exists. +This behavior is reflected to the code (A-1,2), +so the value of the evaluation of an ensure clause is completely discarded.

+

At (B-1,3), it deals with the evaluated value of when a jump occurred at the main body. +I mentioned that the value of this case is stored in prot_tag->retval , +so it saves the value to a local variable to prevent from being carelessly +overwritten during the execution of the ensure clause (B-1). +After the evaluation of the ensure clause, it restores the value by using +return_value() (B-2). +When any jump has not occurred, state==0 in this case, +prot_tag->retval is not used in the first place.

+

rescue

+

It’s been a little while, I’ll show the syntax tree of rescue again just in case.

+

▼Source Program

+ +
+begin
+  raise()
+rescue ArgumentError, TypeError
+  'error raised'
+end
+
+

▼ Its Syntax Tree ( nodedump-short )

+ +
+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)
+
+

I’d like you to make sure that (the syntax tree of) the statement to be +rescue ed is “under” NODE_RESCUE .

+

rb_eval()NODE_RESCUE

+ +
+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); /* evaluate the body */
+2598        }
+2599        POP_TAG();
+2600        if (state == TAG_RAISE) { /* an exception occurred at the body */
+2601            NODE * volatile resq = node->nd_resq;
+2602
+2603            while (resq) { /* deal with the rescue clause one by one */
+2604                ruby_current_node = resq;
+2605                if (handle_rescue(self, resq)) { /* If dealt with by this clause */
+2606                    state = 0;
+2607                    PUSH_TAG(PROT_NONE);
+2608                    if ((state = EXEC_TAG()) == 0) {
+2609                        result = rb_eval(self, resq->nd_body);
+2610                    }                            /* evaluate the rescue clause */
+2611                    POP_TAG();
+2612                    if (state == TAG_RETRY) { /* Since retry occurred, */
+2613                        state = 0;
+2614                        ruby_errinfo = Qnil;  /* the exception is stopped */
+2615                        goto retry_entry;     /* convert to goto */
+2616                    }
+2617                    if (state != TAG_RAISE) {  /* Also by rescue and such */
+2618                        ruby_errinfo = e_info; /* the exception is stopped  */
+2619                    }
+2620                    break;
+2621                }
+2622                resq = resq->nd_head; /* move on to the next rescue clause */
+2623            }
+2624        }
+2625        else if (node->nd_else) { /* when there is an else clause, */
+2626            if (!state) { /* evaluate it only when any exception has not occurred. */
+2627                result = rb_eval(self, node->nd_else);
+2628            }
+2629        }
+2630        if (state) JUMP_TAG(state); /* the jump was not waited for */
+2631    }
+2632    break;
+
+(eval.c)
+
+

Even though the size is not small, it’s not difficult because it only simply +deal with the nodes one by one. +This is the first time handle_rescue() appeared, +but for some reasons we cannot look at this function now. +I’ll explain only its effects here. Its prototype is this,

+
+static int handle_rescue(VALUE self, NODE *resq)
+
+

and it determines whether the currently occurring exception ( ruby_errinfo ) is +a subclass of the class that is expressed by resq ( TypeError , for instance). +The reason why passing self is that it’s necessary to call rb_eval() inside +this function in order to evaluate resq .

+ + + +
+ + diff --git a/htmls/fin.html b/htmls/fin.html new file mode 100644 index 0000000..801b11f --- /dev/null +++ b/htmls/fin.html @@ -0,0 +1,364 @@ + + + + + Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

第20章 Rubyの未来

+

第20章 Rubyの未来 +h2. 解決すべき課題

+

@ruby@は「完成してしまったソフトウェア」ではない。まだまだ発展途上で +あり、多くの課題を抱えている。まずは現在のインタプリタに内在する +問題を摘出してみよう。話題の順番はだいたい本書の章の順番に沿っている。

+

GCの性能

+

現在のGCの性能は「特に悪くないが、特に良くもない」と言ったところだろう +か。「特に悪くない」というのは「日常生活で困ることはない」ということで、 +「特に良くもない」というのは「高負荷になると弱点が露呈する」という意味 +である。例えば大量にオブジェクトを作ってそのまま保持し続けるアプリケー +ションだと速度が急激に低下してしまう。GCのたびに全オブジェクトをマーク +することになるうえ、オブジェクトが回収できないものでさらにGCの回数まで +増えてしまうからである。この問題には第5章で触れた世代別GCが効 +果的なはずだ(少なくとも理論的にはそういうことになっている)。

+

また反応速度の点でも改善の余地がある。現在のGCの実行中はインタプリタ全 +体が停止するので、エディタだとかGUIアプリケーションだと時々「ぐっ」と +固まって反応が中断することになる。例えそれが0.1秒程度だろうとも、 +文字をタイプしている途中に止まられたりすると非常に印象が悪い。今はそ +ういうアプリケーションはあまり作られていないか、あってもさほど大きくな +いためこの点があまり問題にならないのだろう。だがいずれそういうものが出 +てくればインクリメンタルGCの導入を考える必要もあるかもしれない。

+

パーサの実装

+

第二部で見たように@ruby@のパーサの実装は +既に@yacc@を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな +い。拡張の予定がないのならいいが、この後には「キーワード引数」という +大物の導入が予定されているし、@yacc@の制限のせいで欲しい文法が表現でき +ない、なんてことになったら悲しい。

+

パーサの再利用

+

Rubyのパーサは非常に複雑だ。特に@lex_state@のあたりを真面目に扱う +のがとても大変である。そのせいで、Rubyプログラムを埋め込んだり、 +Rubyプログラム自体を扱うプログラムを作るのが非常に難しくなっている。

+

例えば筆者が開発しているツールで@racc@というものがある。@yacc@のRuby版 +なのでRを付けて@racc@だ。その@racc@では文法ファイルの構文などはほとんど +@yacc@と同じで、 +アクションの部分だけがRubyのコードになっている。そのためにはRubyのコー +ドをちゃんとパースしないとアクションの終わりを判定できないが、「ちゃん +と」パースするのがとても難しい。仕方がないので今は「だいたい」パースで +きるというレベルで妥協している。

+

他にRubyプログラムの解析が必要になる例としては +@indent@や@lint@のようなツールが +挙げられるが、こういうものを作るのにも非常に苦労する。リファクタリング +ツールのような複雑なものになるともはや絶望的である。

+

ではどうしようか。同じものを作り直すのが無理なら、@ruby@のオリジナルの +パーサを部品として使えるようにすればいいのではないだろうか。つまり処理 +系のパーサ自体をライブラリ化するわけだ。これは是非とも欲しい機能である。

+

ただここで問題なのは、@yacc@を使う限りパーサがリエントラントにできない +ということだ。つまり@yyparse()@を再帰呼び出ししたり複数のスレッドから +呼んだりできないのである。だからパース中にRubyに制御が戻らないように実 +装しなければならない。

+

コード隠蔽

+

現在の@ruby@は動かすプログラムのソースコードがないと動かせない。 +つまりソースコードを他人に読ませたくない人達は困るだろう。

+

インタプリタオブジェクト

+

現在の@ruby@インタプリタはプロセスに一つしか持てない、ということは +第13章で話した。複数のインタプリタを持つことが現実に可能 +ならそのほうがよさそうではあるが、果たしてそういうことは実装可能なのだ +ろうか。

+

評価器の構造

+

いまの@eval.c@はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー +ムを埋め込むのも何かと厄介の元だし、@setjmp() longjmp()を使いまくるのも +わかりやすさと速度を下げている。特にレジスタの多いRISCマシンだと +@setjmp()を使いまくると速度が落ちやすい。@setjmp()@ではレジスタを全て +退避するからである。

+

評価器の速度

+

@ruby@は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理 +系は速ければ速いほどいいのは間違いない。速度を上げる、即ち最適化をする +にはどうしたらいいだろう。そういうときはまずプロファイルを採らねばなら +ない。というわけで採った。

+

p(=emlist). + % cumulative self self total + time seconds seconds calls ms/call ms/call name + 20.25 1.64 1.64 2638359 0.00 0.00 rb_eval + 12.47 2.65 1.01 1113947 0.00 0.00 ruby_re_match + 8.89 3.37 0.72 5519249 0.00 0.00 rb_call0 + 6.54 3.90 0.53 2156387 0.00 0.00 st_lookup + 6.30 4.41 0.51 1599096 0.00 0.00 rb_yield_0 + 5.43 4.85 0.44 5519249 0.00 0.00 rb_call + 5.19 5.27 0.42 388066 0.00 0.00 st_foreach + 3.46 5.55 0.28 8605866 0.00 0.00 rb_gc_mark + 2.22 5.73 0.18 3819588 0.00 0.00 call_cfunc +

+

これはとあるアプリケーションを動かしたときのプロファイルなのだが、一般 +的なRubyプログラムのプロファイルにもかなり近い。つまりトップに圧倒的割 +合で@rb_eval()が登場し、そのあとにGCと評価器中枢部、加えて処理に特有 +の関数が混じる。例えばこのアプリケーションの場合は正規表現マッチ +(ruby_re_match@)にかなり時間がかかっているようだ。

+

ただそれがわかったとしてどう解決するかが問題だ。単純に考えれば +rb_eval()を速くすればいい、ということになるだろうが、@ruby@のコアに +関しては小手先の最適化をやる余地はもうほとんどない。@NODE_IF@のところ +で使われていたような「末尾再帰→@goto@変換」もほとんどやり尽くした感が +ある。つまり根本的に考えかたを変えない限り向上の余地がないのだ。

+

スレッドの実装

+

これは第19章でも話した。現在のrubyのスレッドの実装は非常に +問題が多い。特にネイティブスレッドとの相性の悪さはどうしようもない。 +@ruby@スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確 +かに他に代え難い長所なのだが、さすがにあの実装はずっと使い続けるには無 +理があるのではなかろうか。

+

ruby 2

+

続いて今度はこれらの問題点に対するオリジナルの@ruby@の動向を示す。

+

Rite

+

現時点でのrubyの最新バージョンは安定版が1.6.7、開発版が1.7.3だ。 +だがそう遠くないうちに次の安定版1.8が出そうである。そうすると同時に +開発版の1.9.0がスタートする。そしてその次はちょっと変則的に1.9.1が +安定版となる。

+

安定版開発版開始時期 +1.6.×1.7.×2000-09-19に1.6.0リリース +1.8.×1.9.0半年以内には出るだろう +1.9.1〜2.0.0二年後くらいか

+

そして次々世代の開発版が@ruby@ 2、コードネームRite、である。 +この名前はLとRの区別がつけられない日本人へのオマージュらしい。

+

一言で2.0はどこが変わるかと言うと、コアほとんど全部だ。スレッド、評価 +器、パーサ、これが全部変わる。もっとも、コードがカケラも出てきていない +のであくまでここに書くのは全て「予定」である。あまり期待しすぎると失望 +するかもしれない。そういうわけで、軽く期待、ということにしておこう。

+

記述言語

+

まず使う言語。間違いなくCだろう。Rubyの英語メーリングリスト +ruby-talkでのまつもとさんの発言によると

+
+

I hate C++.

+
+

だそうなので、C++を使うというのはまずありえない。いくら全面作り直しと +言ってもオブジェクトシステムはほぼそのまま残ると考えられるので、そのあ +たりでの手間が増えないようする必要もある。ただしCはCでも今度はANSI Cに +なる可能性は高いだろう。

+

GC

+

GCの実装では、 +まず@Boehm GC@footnote{Boehm GC http://www.hpl.hp.com/personal/Hans_Boehm/gc}から +試してみるということだ。Boehm GCは +conservativeかつincrementalかつgenerationalなGCで、しかも +ネイティブスレッドが動いてい +ても全スレッドのスタック領域をマークできるというかなりの優れものGCであ +る。一度導入したとしてそのままBoehm GCをそのまま使い続けるのかどうか +はわからないが、どちらにしてもなんらかの速度向上が期待できる方向に +進むだろう。

+

パーサ

+

仕様の点では、括弧を省略したメソッド呼び出しのネストが一律禁止になりそ +うである。見てきたように@command_call@は文法全域にかなりの影響を与えてい +た。これが簡略化されればパーサもスキャナも随分すっきりするはずだ。 +ただし括弧の省略自体がなくなることはありえない。

+

また実装面では@yacc@を使い続けるかどうかでまだ思案中ということだ。使わ +ないとすれば手書きで、ということだが、あれだけ複雑なものを手で実装でき +るか、不安は残る。どちらを選んでも茨の道には違いない。

+

評価器

+

評価器は完全に作り直しとなる。目的は主に高速化と実装の簡略化であり、 +主眼は二点だ。

+

rb_eval()のような再帰呼び出しをなくす +バイトコードインタプリタへの移行

+

まず@rb_eval()の再帰呼び出しをなくす。なくす方法については「末尾再帰 +→goto@変換」のような感じ、と言うのが一番直感的だろうか。一つの +rb_eval()の中で@goto@を使い、ぐるぐる回るわけだ。するとまず関数呼び +出しが減るし、@return@や@break@のために使っていた@setjmp()も不要にな +る。ただしCで定義されたメソッドの呼び出しが入れば嫌でも関数を呼ばざ +るを得ないので、その区切りではやはりsetjmp()@が必要だ。

+

バイトコード(byte code)というのはようするに機械語のプログラムみたい +なものである。Smalltalk80の仮想マシンで有名になった用語で、命令がバイ +ト単位で構成されているのでバイトコードと呼ばれる。上のレベルばかりいじっ +ている人間からするとバイト単位なんてのはあたりまえに思えてしまうのだが、 +機械語では命令がビット単位になっていることは多い。例えばAlphaだと命令 +コード32ビットのうち先頭6ビットが命令種を表している。

+

バイトコード型にする利点は主に高速化である。理由は二つで、一つめは構文 +木のようにポインタをたぐる必要がないこと。もう一つは局所的な最適化 +(peephole optimization)がやりやすいことだ。

+

またバイトコードを保存しておいて読み込む場合はパースがなくなるのでそ +こでも多少は速くなると考えられる。しかしパースはプログラムの開始時点に +一回しか行われない作業だし、元々パースにはあまり時間がかかっていない +ので、そう大きな影響はない。

+

バイトコードの評価器がどんなふうになるか知りたければ@regex.c@を見てみ +るとよい。あとはPythonがバイトコードインタプリタだ。

+

スレッド

+

スレッドはネイティブスレッド対応。Rubyが誕生した1994年当時に比べると +スレッドを取り巻く環境は格段に良くなっているし、ネイティブスレッドで +いける、と判断されたのだろう。

+

ネイティブスレッドを使うということはCレベルでもプリエンプティブになる +わけだからインタプリタ自体をマルチスレッドセーフにしなければならないが、 +その点はとりあえずグローバルロックをかけて解決するようである。

+

それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。@ruby@の +継続はスレッドの実装に大きく依存しているので、スレッドがネイティブスレッ +ドになれば継続も自然と消滅する。あれが付いているのは「実装できて +しまった」からだし、ほとんど使われていないので問題ないだろう。

+

M17N

+

ついでにクラスライブラリについても少しだけ触れておこう。多言語化 +(Multilingualization、略してM17N)についてだ。プログラミングに +おいてM17Nとは何をすることか有体に言うと、複数の文字コードを扱えるよう +にすることである。

+

似た話題では他に国際化(Internationalization、略してI18N)と +いうのもあ +る。こちらの例を挙げれば、エラーメッセージをユーザの好みの言語で出した +り、日付の表現を国の慣習に合わせたりすることである。この例えでわかると +おり、I18Nを実現するためにはM17Nの実現が必須である。しかし逆は成立しな +い。

+

具体的にRubyを多言語化するためには何が必要か。一つにはパーサの対応、も +う一つは文字列関係のライブラリ、具体的には@String@と@Regexp@の対応、の +二つが必要である。

+

パーサの対応とは、コメントや文字列リテラル、正規表現リテラルに任意言語 +(正確にはエンコーディング)を許すことだ。これが易しそうで難しい。 +まず、@ruby@のパーサに +エンコーディングを伝える方法が必要である。これまで見てきたよ +うにRubyのプログラムは例外なくパーサを抜けたあとに評価される。つまりパー +サにエンコーディングを伝えるのに通常の構文を使うことはできない。だから +エンコーディングを指定するためになんらかの構文を追加する必要がある。

+

ライブラリでの対応はわりと簡単だ。現在ある@mbclen()@という仕組みを +素直に拡張したものになっている。

+

M17N対応@ruby@は既に実装されており、CVSレポジトリの +@ruby_m17n@ブランチから +取得可能だ。実装されたのに取り込まれていないのは仕様が成熟していな +いと判断されたためである。いいインターフェイスさえ設計できれば1.9の途中 +にでも入るのではないだろうか。

+

IO

+

現在のRubyの@IO@クラスは単純な@stdio@のラッパーなのだが、 +このアプローチは

+

プラットフォーム間の微妙な挙動の違いが多すぎる +バッファリングを細かく制御したい

+

という二点で不満があった。そこでRiteでは@stdio@を自前で持つ +ことになりそうである。

+

Ruby Hacking Guide

+

ここまで我々は常に@ruby@を外から観察する者として行動してきた。だがもち +ろん@ruby@は展示ケースに収められた製品とは違う。即ち我々の行動いかんに +よってはこちらから影響を与えることができるのである。本書最後の節はコミュ +ニティから提案された@ruby@に対する働きかけについて話し、現在と未来の +Ruby Hackerたちに対する餞とする。

+

世代別GC

+

まず、第5章でも触れた、木山真人さんによる世代別GC。 +既に述べた通り現在のパッチだと

+

思ったより速度が出ない +最新の@ruby@に合わせてアップデートが必要

+

という点が問題なのだが、この場では初めての大型非公式パッチで +あるという点を何より高評価したい。

+

鬼車

+

いまのRubyが使っている正規表現エンジンはGNU regexの改造版である。その +GNU regexはもともとEmacsのために書かれたもので、それをマルチバイト対応 +にしたものをさらにまつもとさんがPerl互換に改造した。という経緯から容易 +に想像できるように、非常に複雑怪奇な構造になってしまっている。またこの +GNU regexpのライセンスがLGPLであるために@ruby@のライセンスが非常にやや +こしくなっており、かねてからこのエンジンの置き換えが課題になってきた。

+

そこでいきなり登場したのが小迫清美さんの手による正規表現エンジン「鬼車」 +である。これがかなり出来がよいらしく、すぐにでも本体に取りこまれそうだ。

+

鬼車は@ruby@のCVSレポジトリから以下のようにして入手できる。

+

p(=screen). +% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma + +h3. ripper

+

続いて拙作のripper。@parse.y@を改造して拡張ライブラリにしたものだ。 +@ruby@本体に対する変更というわけではないが、パーサのコンポーネント化の +一つの方向性としてここで紹介しておく。

+

ストリーム系のインターフェイスで実装しており、トークンのスキャンだの +パーサでの還元だのをイベント形式で拾うことができる。添付CD-ROMに入れて +おいたfootnote{ripper:添付CD-ROMの@archives/ripper-0.0.5.tar.gz@}ので +使ってみてほしい。なお、このバージョンは半年ほど前の@ruby@ 1.7ベース +なので今の文法とは少し違う。

+

これを作ったのはただ「アイデアを思い付いてしまった」というのが理由だっ +たりするだが、そのわりにはうまくいったと思う。実装時間も三日くらいで実 +にお手軽であった。

+

代替パーサ

+

まだ影も形もないプロダクトではあるが、@ruby@とは全く独立に使える +RubyのパーサをC++で書いている人もいるようだ(@[ruby-talk:50497]@)。

+

JRuby

+

さらに過激に、インタプリタ全体を書き直してしまえー、 +という動きもある。例えばJavaで書いたRuby +「JRubyfootnote{JRuby http://jruby.sourceforge.net}」 +というものが登場している。Jan Arne Petersenさん以下、 +かなりの大所帯で実装しているようだ。

+

ちょっといじってみた感想としては

+

パーサはかなりちゃんとできている。ヒアドキュメントや空白の微妙な挙動まで正確に再現されている。 +@instance_eval@が効かないようだ(これは仕方ないか) +組み込みライブラリはまだ少ない(これも仕方ない) +拡張ライブラリは使えない(あたりまえ) +RubyのUNIX centricなところが全部削られているので既存のスクリプトがそのまま動く可能性は低いと思われる +遅い

+

ということは言えそうだ。ちなみに最後の「遅い」がどのくらいかと言うと、 +オリジナルの@ruby@の20倍くらい(実行時間が)である。ここまで遅いとさす +がに苦しい。やはりJava VMの上でRuby VMが動いているわけだから、遅くない +はずがないのだ。マシンが20倍速になってくれるのを待つしかあるまい。

+

しかし全体としては想像よりずっとよくできている、という印象を受けた。

+

NETRuby

+

Javaで動くならC#でも動くだろう。というわけでC#で書いたRuby、 +「NETRubyfootnote{NETRuby http://sourceforge.jp/projects/netruby/}」 +というのが登場した。作者はartonさんである。

+

筆者の手元には.NET環境がないのでソースコードしか見ていないのだが、 +本人の弁によると

+

何より遅い +クラスライブラリがあまりない +例外処理の互換性がいまいち

+

というあたりが問題らしい。しかし@instance_eval@は動くらしい(驚愕)。

+

@ruby@の開発に参加するには

+

@ruby@の開発者はあくまでまつもとゆきひろさん個人であり、最終的な +@ruby@の方向については絶対的な権限がある。だが同時に@ruby@は +オープンソースソフトウェアであり、誰でも開発に参加できる。参加できる、 +というのは、意見を提案したりパッチを出したりできるということだ。 +以下、具体的な参加方法について話す。

+

@ruby@の場合はメーリングリストを中心に開発が進んでいるので、各メーリン +グリストに参加するのがよい。現在コミュニティの中心となっているメーリ +ングリストは +ruby-list、@ruby-dev@、@ruby-talk@の三つである。@ruby-list@は +「Rubyに関係することならなんでもOK」のメーリングリストで、日本語である。 +ruby-devは開発版@ruby@の話をするメーリングリストで、これも日本語であ +る。@ruby-talk@は英語のメーリングリストだ。参加方法はRubyの +公式サイトfootnote{Rubyの公式サイト:@http://www.ruby-lang.org/ja/@} +の「メーリングリスト」のページに載っている。これらのメーリングリストは +どれも読むだけのメンバーも歓迎なので、とりあえずしばらく参加してみて +議論を眺め、雰囲気を捕むといいのではないだろうか。

+

日本から活動が始まったRubyだが、最近は「主導権は@ruby-talk@に移った」 +と言われてしまったりすることもある。 +だが開発の中心が相変わらず@ruby-dev@であることに変わりはない。なにしろ +@ruby@のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語 +ユーザなのでわざわざ英語で話すのも面倒だし、自然と@ruby-dev@に足が向い +てしまう。将来英語を使うコアメンバーが増えてくれば状況も変わるかもしれ +ないが、当分の間は@ruby@開発のコアは@ruby-dev@だろう。

+

ただ日本語が使えないと開発に参加できないというのも困るので、今は +ruby-devの要約を一週間に一度英訳して@ruby-talk@に流すようになってい +る。筆者もその要約に参加しているのだが、現在は三人の持ち回りで +やっているため非常に厳しい。要約を手伝ってくれるメンバーは常時 +募集中である。我こそはと思うかたは是非@ruby-list@で参加表明して +いただきたい。

+

そして最後に、ソフトウェアはソースコードがあればいいというものでもない。 +各種ドキュメントやウェブサイトの整備も必要である。そしてそういうことを +してくれる人は常に不足ぎみだ。 +ドキュメント関連の活動にもいちおう専用メーリングリストがあるが、とりあえ +ずは@ruby-list@で「何かやりたい」と言ってくれればいい。筆者もできるだ +け答えるようにするし、他のメンバーも反応してくれるだろう。

+

最後に

+

さて、長かった本書もこれで終わりだ。ページ数との兼ね合いもあるのであら +ゆる部分を懇切丁寧にというわけにはいかなかったが、@ruby@の根幹について +は全て語り尽くした。これ以上ウダウダと付け加えるのはよそう。まだわから +ないことがあれば納得するまで自分でソースコードを読んで確かめてほしい。

+

御意見・御感想・誤殖の指摘などは +“青木峰郎 <aamine@loveruby.net>”:mailto:aamine@loveruby.net +までお願いします。

+

『Rubyソースコード完全解説』 +はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。

+

Copyright © 2002-2004 Minero Aoki, All rights reserved.

+ + + +
+ + diff --git a/htmls/gc.html b/htmls/gc.html new file mode 100644 index 0000000..e803f51 --- /dev/null +++ b/htmls/gc.html @@ -0,0 +1,1652 @@ + + + + + Garbage Collection | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Sebastian Krause & ocha-

+

Chapter 5: Garbage Collection

+

A conception of an executing program

+

It’s all of a sudden but at the beginning of this chapter, we’ll +learn about the memory space of an executing program. In this chapter +we’ll step inside the lower level parts of a computer quite a bit, so without +preliminary knowledge it’ll be hard to follow. And it’ll be also necessary +for the following chapters. +Once we finish this here, the rest will be easier.

+

Memory Segments

+

A general C program has the following parts in the memory space:

+
    +
  1. the text area
  2. +
  3. a place for static and global variables
  4. +
  5. the machine stack
  6. +
  7. the heap
  8. +
+

The text area is where the code lies. Obviously the second area holds static and global variables. +Arguments and local variables of functions are piling up in the machine stack. +The heap is the place where allocated by malloc().

+

Let’s talk a bit more about number three, the machine stack. +Since it is called the machine “stack”, +obviously it has a stack structure. +In other words, new stuff is piled on top of it one after another. +When we actually pushes values on the stack, each value would be a tiny piece +such as int. But logically, there are a little larger pieces. +They are called stack frames.

+

One stack frame corresponds to one function call. Or in other words when there +is a function call, one stack frame is pushed. +When doing return, one stack frame will be popped. +Figure 1 shows the really simplified appearance of the machine stack.

+
+

(macstack)
+Figure 1: Machine Stack

+
    +
  • 上(先端)above (top)
  • +
  • 下(末端)below (bottom)
  • +
  • スタックフレーム stack frame
  • +
  • 現在実行中の関数フレーム presently executing function frame +
+ +

In this picture, “above” is written above the top of the stack, +but this it is not necessarily always the case that the machine stack goes +from low addresses to high addresses. For instance, on the x86 +machine the stack goes from high to low addresses.

+

alloca()

+

By using malloc(), we can get an arbitrarily large memory +area of the heap. alloca() is the machine stack version of it. +But unlike malloc() it’s not necessary to free the memory allocated +with alloca(). Or one should say: +it is freed automatically at the same moment of return of each function. +That’s why it’s not possible to use an allocated value as the return +value. It’s the same as “You must not return the pointer to +a local variable.”

+

There’s been not any difficulty. We can consider it something to locally +allocate an array whose size can be changed at runtime.

+

However there exist environments where there is no native alloca(). +There are still many who would like to use alloca() even if in such +environment, sometimes a function to do the same thing is written in C. +But in that case, only the feature that we don’t have to free it by ourselves +is implemented and it does not necessarily allocate the memory on the machine +stack. In fact, it often does not. +If it were possible, a native +alloca() could have been implemented in the first place.

+

How can one implement alloca() in C? The simplest implementation is: +first allocate memory normally with malloc(). Then remember the pair of the function +which called alloca() and the assigned addresses in a global list. +After that, check this list whenever alloca() is called, +if there are the memories allocated for the functions already finished, +free them by using free().

+
+

(calloca)
+Figure 2: The behavior of an alloca() implemented in C

+
    +
  • D→alloca(8)の対応を記録 record the relation D→ alloca(8)
  • +
  • B→alloca(32)の対応を記録 record the relation B→ alloca(32)
  • +
  • Dで割り当てたメモりを解放 release the memory allocated in D +
+ +

The missing/alloca.c of ruby is an example of an emulated alloca() .

+

Overview

+

From here on we can at last talk about the main subject of this chapter: +garbage collection.

+

What is GC?

+

Objects are normally on top of the memory. Naturally, if a lot of objects are created, a lot of memory is used. If memory +were infinite there would be no problem, but in reality there is always a memory +limit. That’s why the memory which is not +used anymore must be collected and recycled. More concretely the memory received through malloc() must be returned with +free().

+

However, it would require a lot of efforts if the management of malloc() and +free() were entirely left to programmers. +Especially in object oriented programs, because objects are referring each other, +it is difficult to tell when to release memory.

+

There garbage collection comes in. +Garbage Collection (GC) is a feature to automatically detect and free the memory +which has become unnecessary. +With garbage collection, +the worry “When should I have to free() ??” has become unnecessary. +Between when it exists and when it does not exist, +the ease of writing programs differs considerably.

+

By the way, in a book about something that I’ve read, +there’s a description “the thing to tidy up the fragmented usable memory is GC”. +This task is called “compaction”. +It is compaction because it makes a thing compact. +Because compaction makes memory cache more often hit, +it has effects for speed-up to some extent, +but it is not the main purpose of GC. +The purpose of GC is to collect memory. There are many GCs which collect +memories but don’t do compaction. +The GC of ruby also does not do compaction.

+

Then, in what kind of system is GC available? +In C and C++, there’s +Boehm GC\footnote{Boehm GC http://www.hpl.hp.com/personal/Hans_Boehm/gc} +which can be used as an add-on. +And, for the recent languages such as Java and Perl, Python, C#, Eiffel, +GC is a standard equipment. And of course, Ruby has its GC. +Let’s follow the details of ruby’s GC in this chapter. +The target file is gc.c.

+

What does GC do?

+

Before explaining the GC algorithm, I should explain “what garbage collection +is”. +In other words, what kind of state of the memory is “the unnecessary memory”?

+

To make descriptions more concrete, +let’s simplify the structure by assuming that there are only objects and links. +This would look as shown in Figure 3.

+

+

(objects)
+Figure 3: Objects

+

+

The objects pointed to by global variables and the objects on the stack of a +language are surely necessary. And objects pointed to by instance variables of +these objects are also necessary. Furthermore, the objects that are reachable by +following links from these objects are also necessary.

+

To put it more logically, the necessary objects are all objects which +can be reached recursively via links from the “surely necessary objects” as +the start points. +This is depicted in figure 4. What are on the left of the line are all “surely necessary objects”, +and the objects which can be reached from them are colored black. +These objects colored black are the +necessary objects. The rest of the objects can be released.

+
+

(gcimage)
+Figure 4: necessary objects and unnecessary objects

+
    +
  • ルートオブジェクト root objects
  • +
  • 不要なオブジェクト unnecessary objects
  • +
  • ルートオブジェクトから参照されているオブジェクト objects referenced by the + root objects +
+ +

In technical terms, “the surely necessary objects” are called “the roots of GC”. +That’s because they are the roots of tree structures that emerges as a +consequence of tracing necessary objects.

+

Mark and Sweep

+

GC was first implemented in Lisp. +The GC implemented in Lisp at first, +it means the world’s first GC, +is called mark&sweep GC. +The GC of ruby is one type of it.

+

The image of Mark-and-Sweep GC is pretty close to our definition of “necessary +object”. First, put “marks” on the root objects. Setting them as the start +points, put “marks” on all reachable objects. +This is the mark phase.

+

At the moment when there’s not any reachable object left, +check all objects in the object pool, release (sweep) all objects that have not marked. +“Sweep” is the “sweep” of Minesweeper.

+

There are two advantages.

+
    +
  • There does not need to be any (or almost any) concern for garbage collection +outside the implementation of GC.
  • +
  • Cycles can also be released. (As for cycles, see also the section of “Reference Count”)
  • +
+

There are also two disadvantages.

+
    +
  • In order to sweep every object must be touched at least once.
  • +
  • The load of the GC is concentrated at one point.
  • +
+

When using the emacs editor, there sometimes appears " Garbage collecting... " +and it completely stops reacting. That is an example of the second disadvantage. +But this point can be alleviated by modifying the algorithm (it is called incremental GC).

+

Stop and Copy

+

Stop and Copy is a variation of Mark and Sweep. First, prepare several object +areas. To simplify this description, assume there are two areas A and B here. +And put an “active” mark on the one of the areas. +When creating an object, create it only in the “active” one. (Figure 5)

+

+

(stop2)
+Figure 5: Stop and Copy (1)

+

+

When the GC starts, follow links from the roots in the same manner as +mark-and-sweep. However, move objects to another area instead of marking them +(Figure 6). When all the links have been followed, discard the all elements +which remain in A, and make B active next.

+

+

(stop3)
+Figure 6: Stop and Copy (2)

+

+

Stop and Copy also has two advantages:

+
    +
  • Compaction happens at the same time as collecting the memory
  • +
  • Since objects that reference each other move closer together, + there’s more possibility of hitting the cache.
  • +
+

And also two disadvantages:

+
    +
  • The object area needs to be more than twice as big
  • +
  • The positions of objects will be changed
  • +
+

It seems what exist in this world are not only positive things.

+

Reference counting

+

Reference counting differs a bit from the aforementioned GCs, +the reach-check code is distributed in several places.

+

First, attach an integer count to each element. +When referring via variables or arrays, the counter of the referenced object is +increased. When quitting to refer, decrease the counter. +When the counter of an object becomes zero, release the object. +This is the method called reference counting (Figure 7).

+

+

(refcnt)
+Figure 7: Reference counting

+

+

This method also has two advantages:

+
    +
  • The load of GC is distributed over the entire program.
  • +
  • The object that becomes unnecessary is immediately freed.
  • +
+

And also two disadvantages.

+
    +
  • The counter handling tends to be forgotten.
  • +
  • When doing it naively cycles are not released.
  • +
+

I’ll explain about the second point just in case. A cycle is +a cycle of references as shown in Figure 8. +If this is the case the counters will never decrease +and the objects will never be released.

+

+

(cycle)
+Figure 8: Cycle

+

+

By the way, latest Python(2.2) uses reference counting GC but it can free cycles. +However, it is not because of the reference counting itself, +but because it sometimes invokes mark and sweep GC to check.

+

Object Management

+

Ruby’s garbage collection is only concerned with ruby objects. +Moreover, it only concerned with the objects created and managed by ruby. +Conversely speaking, +if the memory is allocated without following a certain procedure, +it won’t be taken care of. +For instance, the following function will cause a memory leak +even if ruby is running.

+
+void not_ok()
+{
+    malloc(1024);  /* receive memory and discard it */
+}
+
+

However, the following function does not cause a memory leak.

+
+void this_is_ok()
+{
+    rb_ary_new();  /* create a ruby array and discard it */
+}
+
+

Since rb_ary_new() uses Ruby’s proper interface to allocate memory, +the created object is under the management of the GC of ruby, +thus ruby will take care of it.

+

struct RVALUE

+

Since the substance of an object is a struct, +managing objects means managing that structs. +Of course the non-pointer objects like Fixnum Symbol nil true false are +exceptions, but I won’t always describe about it to prevent descriptions +from being redundant.

+

Each struct type has its different size, +but probably in order to keep management simpler, +a union of all the structs of built-in classes is declared and +the union is always used when dealing with memory. +The declaration of that union is as follows.

+

RVALUE

+
+ 211  typedef struct RVALUE {
+ 212      union {
+ 213          struct {
+ 214              unsigned long flags;   /* 0 if not used */
+ 215              struct RVALUE *next;
+ 216          } free;
+ 217          struct RBasic  basic;
+ 218          struct RObject object;
+ 219          struct RClass  klass;
+ 220          struct RFloat  flonum;
+ 221          struct RString string;
+ 222          struct RArray  array;
+ 223          struct RRegexp regexp;
+ 224          struct RHash   hash;
+ 225          struct RData   data;
+ 226          struct RStruct rstruct;
+ 227          struct RBignum bignum;
+ 228          struct RFile   file;
+ 229          struct RNode   node;
+ 230          struct RMatch  match;
+ 231          struct RVarmap varmap;
+ 232          struct SCOPE   scope;
+ 233      } as;
+ 234  } RVALUE;
+
+(gc.c)
+
+

struct RVALUE is a struct that has only one element. +I’ve heard that the reason why union is not directly used is to enable to +easily increase its members when debugging or when extending in the future.

+

First, let’s focus on the first element of the union free.flags. The comment +says “0 if not used”, but is it true? +Is there not any possibility for free.flags to be 0 by chance?

+

As we’ve seen in Chapter 2: Objects, all object structs have struct RBasic as its first +element. Therefore, by whichever element of the union we access, +obj->as.free.flags means the same as it is written as obj->as.basic.flags. +And objects always have the struct-type flag (such as T_STRING), +and the flag is always not 0. Therefore, the flag of an “alive” object will +never coincidentally be 0. +Hence, we can confirm that setting their flags to 0 +is necessity and sufficiency to represent “dead” objects.

+

Object heap

+

The memory for all the object structs has been brought together in global variable heaps. +Hereafter, let’s call this an object heap.

+

▼ Object heap

+
+ 239  #define HEAPS_INCREMENT 10
+ 240  static RVALUE **heaps;
+ 241  static int heaps_length = 0;
+ 242  static int heaps_used   = 0;
+ 243
+ 244  #define HEAP_MIN_SLOTS 10000
+ 245  static int *heaps_limits;
+ 246  static int heap_slots = HEAP_MIN_SLOTS;
+
+(gc.c)
+
+

heaps is an array of arrays of struct RVALUE. Since it is heapS, +the each contained array is probably each heap. +Each element of heap is each slot (Figure 9).

+

+

(heapitems)
+Figure 9: heaps, heap, slot

+

+

The length of heaps is heap_length and it can be changed. The number of +the slots actually in use is heaps_used. The length of each heap +is in the corresponding heaps_limits[index]. +Figure 10 shows the structure of the object heap.

+

+

(heaps)
+Figure 10: conceptual diagram of heaps in memory

+

+

This structure has a necessity to be this way. +For instance, if all structs are stored in an array, +the memory space would be the most compact, +but we cannot do realloc() because it could change the addresses. +This is because VALUEs are mere pointers.

+

In the case of an implementation of Java, +the counterpart of VALUEs are not addresses but the indexes of objects. +Since they are handled through a pointer table, objects are movable. +However in this case, indexing of the array comes in every time +an object access occurs and it lowers the performance in some degree.

+

On the other hand, what happens if it is an one-dimensional array of pointers +to RVALUEs (it means VALUEs)? +This seems to be able to go well at the first glance, but it does not when GC. +That is, as I’ll describe in detail, the GC of ruby needs to know the +integers "which seems VALUE (the pointers to RVALUE). +If all RVALUE are allocated in addresses which are far from each other, +it needs to compare all address of RVALUE with all integers “which could be +pointers”. +This means the time for GC becomes the order more than O(n^2), +and not acceptable.

+

According to these requirements, it is good that the object heap form a +structure that the addresses are cohesive to some extent +and whose position and total amount are not restricted at the same time.

+

freelist

+

Unused RVALUEs are managed by being linked as a single line which is a linked +list that starts with freelist. +The as.free.next of RVALUE is the link used for this purpose.

+

freelist

+
+ 236  static RVALUE *freelist = 0;
+
+(gc.c)
+
+

add_heap()

+

As we understood the data structure, +let’s read the function add_heap() to add a heap. +Because this function contains a lot of lines not part of the main line, +I’ll show the one simplified by omitting error handlings and castings.

+

add_heap() (simplified)

+
+static void
+add_heap()
+{
+    RVALUE *p, *pend;
+
+    /* extend heaps if necessary */
+    if (heaps_used == heaps_length) {
+        heaps_length += HEAPS_INCREMENT;
+        heaps        = realloc(heaps,        heaps_length * sizeof(RVALUE*));
+        heaps_limits = realloc(heaps_limits, heaps_length * sizeof(int));
+    }
+
+    /* increase heaps by 1 */
+    p = heaps[heaps_used] = malloc(sizeof(RVALUE) * heap_slots);
+    heaps_limits[heaps_used] = heap_slots;
+    pend = p + heap_slots;
+    if (lomem == 0 || lomem > p) lomem = p;
+    if (himem < pend) himem = pend;
+    heaps_used++;
+    heap_slots *= 1.8;
+
+    /* link the allocated RVALUE to freelist */
+    while (p < pend) {
+        p->as.free.flags = 0;
+        p->as.free.next = freelist;
+        freelist = p;
+        p++;
+    }
+}
+
+

Please check the following points.

+
    +
  • the length of heap is heap_slots
  • +
  • the heap_slots becomes 1.8 times larger every time when a heap is added
  • +
  • the length of heaps[i] (the value of heap_slots when creating a heap) is + stored in heaps_limits[i].
  • +
+

Plus, since lomem and himem are modified only by this function, +only by this function you can understand the mechanism. +These variables hold the lowest and the highest addresses of the object heap. +These values are used later when determining the integers “which seems VALUE”.

+

rb_newobj()

+

Considering all of the above points, we can tell the way to create an object +in a second. +If there is at least a RVALUE linked from freelist, we can use it. +Otherwise, do GC or increase the heaps. +Let’s confirm this by reading the rb_newobj() function to create an object.

+

rb_newobj()

+
+ 297  VALUE
+ 298  rb_newobj()
+ 299  {
+ 300      VALUE obj;
+ 301
+ 302      if (!freelist) rb_gc();
+ 303
+ 304      obj = (VALUE)freelist;
+ 305      freelist = freelist->as.free.next;
+ 306      MEMZERO((void*)obj, RVALUE, 1);
+ 307      return obj;
+ 308  }
+
+(gc.c)
+
+

If freelest is 0, in other words, if there’s not any unused structs, +invoke GC and create spaces. +Even if we could not collect not any object, +there’s no problem because in this case a new space is allocated in rb_gc(). +And take a struct from freelist, zerofill it by MEMZERO(), and return it.

+

Mark

+

As described, ruby’s GC is Mark & Sweep. +Its “mark” is, concretely speaking, to set a FL_MARK flag: +look for unused VALUE, set FL_MARK flags to found ones, +then look at the object heap after investigating all +and free objects that FL_MARK has not been set.

+

rb_gc_mark()

+

rb_gc_mark() is the function to mark objects recursively.

+

rb_gc_mark()

+
+ 573  void
+ 574  rb_gc_mark(ptr)
+ 575      VALUE ptr;
+ 576  {
+ 577      int ret;
+ 578      register RVALUE *obj = RANY(ptr);
+ 579
+ 580      if (rb_special_const_p(ptr)) return; /* special const not marked */
+ 581      if (obj->as.basic.flags == 0) return;       /* free cell */
+ 582      if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
+ 583
+ 584      obj->as.basic.flags |= FL_MARK;
+ 585
+ 586      CHECK_STACK(ret);
+ 587      if (ret) {
+ 588          if (!mark_stack_overflow) {
+ 589              if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
+ 590                  *mark_stack_ptr = ptr;
+ 591                  mark_stack_ptr++;
+ 592              }
+ 593              else {
+ 594                  mark_stack_overflow = 1;
+ 595              }
+ 596          }
+ 597      }
+ 598      else {
+ 599          rb_gc_mark_children(ptr);
+ 600      }
+ 601  }
+
+(gc.c)
+
+

The definition of RANY() is as follows. It is not particularly important.

+

RANY()

+
+ 295  #define RANY(o) ((RVALUE*)(o))
+
+(gc.c)
+
+

There are the checks for non-pointers or already freed objects and the recursive +checks for marked objects at the beginning,

+
+obj->as.basic.flags |= FL_MARK;
+
+

and obj (this is the ptr parameter of this function) is marked. +Then next, it’s the turn to follow the references from obj and mark. +rb_gc_mark_children() does it.

+

The others, what starts with CHECK_STACK() and is written a lot is a device +to prevent the machine stack overflow. +Since rb_gc_mark() uses recursive calls to mark objects, +if there is a big object cluster, +it is possible to run short of the length of the machine stack. +To counter that, if the machine stack is nearly overflow, +it stops the recursive calls, piles up the objects on a global list, +and later it marks them once again. +This code is omitted because it is not part of the main line.

+

rb_gc_mark_children()

+

Now, as for rb_gc_mark_children(), +it just lists up the internal types and marks one by one, +thus it is not just long but also not interesting. +Here, it is shown but the simple enumerations are omitted:

+

rb_gc_mark_children()

+
+ 603  void
+ 604  rb_gc_mark_children(ptr)
+ 605      VALUE ptr;
+ 606  {
+ 607      register RVALUE *obj = RANY(ptr);
+ 608
+ 609      if (FL_TEST(obj, FL_EXIVAR)) {
+ 610          rb_mark_generic_ivar((VALUE)obj);
+ 611      }
+ 612
+ 613      switch (obj->as.basic.flags & T_MASK) {
+ 614        case T_NIL:
+ 615        case T_FIXNUM:
+ 616          rb_bug("rb_gc_mark() called for broken object");
+ 617          break;
+ 618
+ 619        case T_NODE:
+ 620          mark_source_filename(obj->as.node.nd_file);
+ 621          switch (nd_type(obj)) {
+ 622            case NODE_IF:         /* 1,2,3 */
+ 623            case NODE_FOR:
+ 624            case NODE_ITER:
+                /* ………… omitted ………… */
+ 749          }
+ 750          return;   /* not need to mark basic.klass */
+ 751      }
+ 752
+ 753      rb_gc_mark(obj->as.basic.klass);
+ 754      switch (obj->as.basic.flags & T_MASK) {
+ 755        case T_ICLASS:
+ 756        case T_CLASS:
+ 757        case T_MODULE:
+ 758          rb_gc_mark(obj->as.klass.super);
+ 759          rb_mark_tbl(obj->as.klass.m_tbl);
+ 760          rb_mark_tbl(obj->as.klass.iv_tbl);
+ 761          break;
+ 762
+ 763        case T_ARRAY:
+ 764          if (FL_TEST(obj, ELTS_SHARED)) {
+ 765              rb_gc_mark(obj->as.array.aux.shared);
+ 766          }
+ 767          else {
+ 768              long i, len = obj->as.array.len;
+ 769              VALUE *ptr = obj->as.array.ptr;
+ 770
+ 771              for (i=0; i < len; i++) {
+ 772                  rb_gc_mark(*ptr++);
+ 773              }
+ 774          }
+ 775          break;
+
+            /* ………… omitted ………… */
+
+ 837        default:
+ 838          rb_bug("rb_gc_mark(): unknown data type 0x%x(0x%x) %s",
+ 839                 obj->as.basic.flags & T_MASK, obj,
+ 840                 is_pointer_to_heap(obj) ? "corrupted object"
+                                             : "non object");
+ 841      }
+ 842  }
+
+(gc.c)
+
+

It calls rb_gc_mark() recursively, is only what I’d like you to confirm. +In the omitted part, NODE and T_xxxx are enumerated respectively. +NODE will be introduced in Part 2.

+

Additionally, let’s see the part to mark T_DATA (the struct used for extension +libraries) because there’s something we’d like to check. +This code is extracted from the second switch statement.

+

rb_gc_mark_children()T_DATA

+
+ 789        case T_DATA:
+ 790          if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
+ 791          break;
+
+(gc.c)
+
+

Here, it does not use rb_gc_mark() or similar functions, +but the dmark which is given from users. +Inside it, of course, it might use rb_gc_mark() or something, but not using +is also possible. +For example, in an extreme situation, if a user defined object does not +contain VALUE, there’s no need to mark.

+

rb_gc()

+

By now, we’ve finished to talk about each object. +From now on, let’s see the function rb_gc() that presides the whole. +The objects marked here are “objects which are obviously necessary”. +In other words, “the roots of GC”.

+

rb_gc()

+
+1110  void
+1111  rb_gc()
+1112  {
+1113      struct gc_list *list;
+1114      struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
+1115      jmp_buf save_regs_gc_mark;
+1116      SET_STACK_END;
+1117
+1118      if (dont_gc || during_gc) {
+1119          if (!freelist) {
+1120              add_heap();
+1121          }
+1122          return;
+1123      }
+
+          /* …… mark from the all roots …… */
+
+1183      gc_sweep();
+1184  }
+
+(gc.c)
+
+

The roots which should be marked will be shown one by one after this, +but I’d like to mention just one point here.

+

In ruby the CPU registers and the machine stack are also the roots. +It means that the local variables and arguments of C are automatically marked. +For example,

+
+static int
+f(void)
+{
+    VALUE arr = rb_ary_new();
+
+    /* …… do various things …… */
+}
+
+

like this way, we can protect an object just by putting it into a variable. +This is a very significant trait of the GC of ruby. +Because of this feature, ruby’s extension libraries are insanely easy to write.

+

However, what is on the stack is not only VALUE. +There are a lot of totally unrelated values. +How to resolve this is the key when reading the implementation of GC.

+

The Ruby Stack

+

First, it marks the (ruby‘s) stack frames used by the interpretor. +Since you will be able to find out who it is after reaching Part 3, +you don’t have to think so much about it for now.

+

▼ Marking the Ruby Stack

+
+1130      /* mark frame stack */
+1131      for (frame = ruby_frame; frame; frame = frame->prev) {
+1132          rb_gc_mark_frame(frame);
+1133          if (frame->tmp) {
+1134              struct FRAME *tmp = frame->tmp;
+1135              while (tmp) {
+1136                  rb_gc_mark_frame(tmp);
+1137                  tmp = tmp->prev;
+1138              }
+1139          }
+1140      }
+1141      rb_gc_mark((VALUE)ruby_class);
+1142      rb_gc_mark((VALUE)ruby_scope);
+1143      rb_gc_mark((VALUE)ruby_dyna_vars);
+
+(gc.c)
+
+

ruby_frame ruby_class ruby_scope ruby_dyna_vars are the variables to point to +each top of the stacks of the evaluator. These hold the frame, the class scope, +the local variable scope, and the block local variables at that time +respectively.

+

Register

+

Next, it marks the CPU registers.

+

▼ marking the registers

+
+1148      FLUSH_REGISTER_WINDOWS;
+1149      /* Here, all registers must be saved into jmp_buf. */
+1150      setjmp(save_regs_gc_mark);
+1151      mark_locations_array((VALUE*)save_regs_gc_mark,
+                               sizeof(save_regs_gc_mark) / sizeof(VALUE *));
+
+(gc.c)
+
+

FLUSH_REGISTER_WINDOWS is special. We will see it later.

+

setjmp() is essentially a function to remotely jump, +but the content of the registers are saved into the argument (which is a +variable of type jmp_buf) as its side effect. +Making use of this, it attempts to mark the content of the registers. +Things around here really look like secret techniques.

+

However only djgpp and Human68k are specially treated. +djgpp is a gcc environment for DOS. +Human68k is an OS of SHARP X680x0 Series. +In these two environments, the whole registers seem to be not saved only by the +ordinary setjmp(), setjmp() is redefined as follows as an inline-assembler +to explicitly write out the registers.

+

▼ the original version of setjmp

+ +
+1072  #ifdef __GNUC__
+1073  #if defined(__human68k__) || defined(DJGPP)
+1074  #if defined(__human68k__)
+1075  typedef unsigned long rb_jmp_buf[8];
+1076  __asm__ (".even\n\                   2-byte alignment
+1077  _rb_setjmp:\n\                       the label of rb_setjmp() function
+1078          move.l  4(sp),a0\n\          load the first argument to the a0 register
+1079          movem.l d3-d7/a3-a5,(a0)\n\  copy the registers to where a0 points to
+1080          moveq.l #0,d0\n\             set 0 to d0 (as the return value)
+1081          rts");                       return
+1082  #ifdef setjmp
+1083  #undef setjmp
+1084  #endif
+1085  #else
+1086  #if defined(DJGPP)
+1087  typedef unsigned long rb_jmp_buf[6];
+1088  __asm__ (".align 4\n\                order 4-byte alignment
+1089  _rb_setjmp:\n\                       the label for rb_setjmp() function
+1090          pushl   %ebp\n\              push ebp to the stack
+1091          movl    %esp,%ebp\n\         set the stack pointer to ebp
+1092          movl    8(%ebp),%ebp\n\      pick up the first argument and set to ebp
+1093          movl    %eax,(%ebp)\n\       in the followings, store each register
+1094          movl    %ebx,4(%ebp)\n\        to where ebp points to
+1095          movl    %ecx,8(%ebp)\n\
+1096          movl    %edx,12(%ebp)\n\
+1097          movl    %esi,16(%ebp)\n\
+1098          movl    %edi,20(%ebp)\n\
+1099          popl    %ebp\n\              restore ebp from the stack
+1100          xorl    %eax,%eax\n\         set 0 to eax (as the return value)
+1101          ret");                       return
+1102  #endif
+1103  #endif
+1104  int rb_setjmp (rb_jmp_buf);
+1105  #define jmp_buf rb_jmp_buf
+1106  #define setjmp rb_setjmp
+1107  #endif /* __human68k__ or DJGPP */
+1108  #endif /* __GNUC__ */
+
+(gc.c)
+
+

Alignment is the constraint when putting variables on memories. +For example, in 32-bit machine int is usually 32 bits, +but we cannot always take 32 bits from anywhere of memories. +Particularly, RISC machine has strict constraints, +it is decided like “from a multiple of 4 byte” or “from even byte”. +When there are such constraints, memory access unit can be more simplified +(thus, it can be faster). When there’s the constraint of “from a multiple of 4 byte”, +it is called “4-byte alignment”.

+

Plus, in cc of djgpp or Human68k, there’s a rule that the compiler put the +underline to the head of each function name. +Therefore, when writing a C function in Assembler, we need to put the underline +(_) to its head by ourselves. +This type of constraints are techniques in order to avoid the conflicts in +names with library functions. +Also in UNIX, it is said that the underline had been attached by some time ago, +but it almost disappears now.

+

Now, the content of the registers has been able to be written out into jmp_buf, +it will be marked in the next code:

+

▼ mark the registers (shown again)

+ +
+1151      mark_locations_array((VALUE*)save_regs_gc_mark,
+                               sizeof(save_regs_gc_mark) / sizeof(VALUE *));
+
+(gc.c)
+
+

This is the first time that mark_locations_array() appears. +I’ll describe it in the next section.

+

mark_locations_array()

+

mark_locations_array()

+ +
+ 500  static void
+ 501  mark_locations_array(x, n)
+ 502      register VALUE *x;
+ 503      register long n;
+ 504  {
+ 505      while (n--) {
+ 506          if (is_pointer_to_heap((void *)*x)) {
+ 507              rb_gc_mark(*x);
+ 508          }
+ 509          x++;
+ 510      }
+ 511  }
+
+(gc.c)
+
+

This function is to mark the all elements of an array, +but it slightly differs from the previous mark functions. +Until now, each place to be marked is where we know it surely holds a VALUE +(a pointer to an object). +However this time, where it attempts to mark is the register space, +it is enough to expect that there’re also what are not VALUE. +To counter that, it tries to detect whether or not the value is a VALUE (a +pointer), then if it seems, the value will be handled as a pointer. +This kind of methods are called “conservative GC”. +It seems that it is conservative because it “tentatively inclines things to the safe side”

+

Next, we’ll look at the function to check if “it looks like a VALUE”, +it is is_pointer_to_heap().

+

is_pointer_to_heap()

+

is_pointer_to_heap()

+ +
+ 480  static inline int
+ 481  is_pointer_to_heap(ptr)
+ 482      void *ptr;
+ 483  {
+ 484      register RVALUE *p = RANY(ptr);
+ 485      register RVALUE *heap_org;
+ 486      register long i;
+ 487
+ 488      if (p < lomem || p > himem) return Qfalse;
+ 489
+ 490      /* check if there's the possibility that p is a pointer */
+ 491      for (i=0; i < heaps_used; i++) {
+ 492          heap_org = heaps[i];
+ 493          if (heap_org <= p && p < heap_org + heaps_limits[i] &&
+ 494              ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0)
+ 495              return Qtrue;
+ 496      }
+ 497      return Qfalse;
+ 498  }
+
+(gc.c)
+
+

If I briefly explain it, it would look like the followings:

+
    +
  • check if it is in between the top and the bottom of the addresses where RVALUEs reside.
  • +
  • check if it is in the range of a heap
  • +
  • make sure the value points to the head of a RVALUE.
  • +
+

Since the mechanism is like this, it’s obviously possible that a non-VALUE +value is mistakenly handled as a VALUE. +But at least, it will never fail to find out the used VALUEs. +And, with this amount of tests, it may rarely pick up a non-VALUE value +unless it intentionally does. +Therefore, considering about the benefits we can obtain by GC, it’s sufficient +to compromise.

+

Register Window

+

This section is about FLUSH_REGISTER_WINDOWS() which has been deferred.

+

Register windows are the mechanism to enable to put a part of the machine stack +into inside the CPU. +In short, it is a cache whose purpose of use is narrowed down. +Recently, it exists only in Sparc architecture. +It’s possible that there are also VALUEs in register windows, +and it’s also necessary to get down them into memory.

+

The content of the macro is like this:

+

FLUSH_REGISTER_WINDOWS

+ +
+ 125  #if defined(sparc) || defined(__sparc__)
+ 126  # if defined(linux) || defined(__linux__)
+ 127  #define FLUSH_REGISTER_WINDOWS  asm("ta  0x83")
+ 128  # else /* Solaris, not sparc linux */
+ 129  #define FLUSH_REGISTER_WINDOWS  asm("ta  0x03")
+ 130  # endif
+ 131  #else /* Not a sparc */
+ 132  #define FLUSH_REGISTER_WINDOWS
+ 133  #endif
+
+(defines.h)
+
+

asm(...) is a built-in assembler. +However, even though I call it assembler, this instruction named ta is the +call of a privileged instruction. +In other words, the call is not of the CPU but of the OS. +That’s why the instruction is different for each OS. +The comments describe only about Linux and Solaris, +but actually FreeBSD and NetBSD are also works on Sparc, so this comment is wrong.

+

Plus, if it is not Sparc, it is unnecessary to flush, +thus FLUSH_REGISTER_WINDOWS is defined as nothing. +Like this, the method to get a macro back to nothing is very famous technique +that is also convenient when debugging.

+

Machine Stack

+

Then, let’s go back to the rest of rb_gc(). +This time, it marks VALUESs in the machine stack.

+

▼ mark the machine stack

+ +
+1152      rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END);
+1153  #if defined(__human68k__)
+1154      rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
+1155                           (VALUE*)((char*)STACK_END + 2));
+1156  #endif
+
+(gc.c)
+
+

rb_gc_stack_start seems the start address (the end of the stack) and +STACK_END seems the end address (the top). +And, rb_gc_mark_locations() practically marks the stack space.

+

There are rb_gc_mark_locations() two times in order to deal with the +architectures which are not 4-byte alignment. +rb_gc_mark_locations() tries to mark for each portion of sizeof(VALUE), so +if it is in 2-byte alignment environment, sometimes not be able to properly mark. +In this case, it moves the range 2 bytes then marks again.

+

Now, rb_gc_stack_start, STACK_END, rb_gc_mark_locations(), +let’s examine these three in this order.

+

Init_stack()

+

The first thing is rb_gc_starck_start. +This variable is set only during Init_stack(). +As the name Init_ might suggest, this function is called at the time when +initializing the ruby interpretor.

+

Init_stack()

+ +
+1193  void
+1194  Init_stack(addr)
+1195      VALUE *addr;
+1196  {
+1197  #if defined(__human68k__)
+1198      extern void *_SEND;
+1199      rb_gc_stack_start = _SEND;
+1200  #else
+1201      VALUE start;
+1202
+1203      if (!addr) addr = &start;
+1204      rb_gc_stack_start = addr;
+1205  #endif
+1206  #ifdef HAVE_GETRLIMIT
+1207      {
+1208          struct rlimit rlim;
+1209
+1210          if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
+1211              double space = (double)rlim.rlim_cur*0.2;
+1212
+1213              if (space > 1024*1024) space = 1024*1024;
+1214              STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+1215          }
+1216      }
+1217  #endif
+1218  }
+
+(gc.c)
+
+

What is important is only the part in the middle. +It defines an arbitrary local variable (it is allocated on the stack) and +it sets its address to rb_gc_stack_start. +The _SEND inside the code for __human68k__ is probably the variable defined +by a library of compiler or system. +Naturally, you can presume that it is the contraction of Stack END.

+

Meanwhile, the code after that bundled by HAVE_GETRLIMIT appears to check the +length of the stack and do mysterious things. +This is also in the same context of what is done at rb_gc_mark_children() to +prevent the stack overflow. +We can ignore this.

+

STACK_END

+

Next, we’ll look at the STACK_END which is the macro to detect the end of the stack.

+

STACK_END

+ +
+ 345  #ifdef C_ALLOCA
+ 346  # define SET_STACK_END VALUE stack_end; alloca(0);
+ 347  # define STACK_END (&stack_end)
+ 348  #else
+ 349  # if defined(__GNUC__) && defined(USE_BUILTIN_FRAME_ADDRESS)
+ 350  #  define SET_STACK_END  VALUE *stack_end = __builtin_frame_address(0)
+ 351  # else
+ 352  #  define SET_STACK_END  VALUE *stack_end = alloca(1)
+ 353  # endif
+ 354  # define STACK_END (stack_end)
+ 355  #endif
+
+(gc.c)
+
+

As there are three variations of SET_STACK_END, let’s start with the bottom one. +alloca() allocates a space at the end of the stack and returns it, +so the return value and the end address of the stack should be very close. +Hence, it considers the return value of alloca() as an approximate value of +the end of the stack.

+

Let’s go back and look at the one at the top. When the macro C_ALLOCA is +defined, alloca() is not natively defined, … in other words, it indicates a +compatible function is defined in C. I mentioned that in this case alloca() +internally allocates memory by using malloc(). +However, it does not help to get the position of the stack at all. +To deal with this situation, it determines that the local variable stack_end +of the currently executing function is close to the end of the stack and uses +its address (&stack_end).

+

Plus, this code contains alloca(0) whose purpose is not easy to see. +This has been a feature of the alloca() defined in C since early times, +and it means “please check and free the unused space”. +Since this is used when doing GC, +it attempts to free the memory allocated with alloca() at the same time. +But I think it’s better to put it in another macro instead of mixing into such +place …

+

And at last, in the middle case, it is about __builtin_frame_address(). +__GNUC__ is a symbol defined in gcc (the compiler of GNU C). +Since this is used to limit, it is a built-in instruction of gcc. +You can get the address of the n-times previous stack frame with __builtin_frame_address(n). +As for __builtin_frame_adress(0), it provides the address of the current frame.

+

rb_gc_mark_locations()

+

The last one is the rb_gc_mark_locations() function that actually marks the stack.

+

rb_gc_mark_locations()

+ +
+ 513  void
+ 514  rb_gc_mark_locations(start, end)
+ 515      VALUE *start, *end;
+ 516  {
+ 517      VALUE *tmp;
+ 518      long n;
+ 519
+ 520      if (start > end) {
+ 521          tmp = start;
+ 522          start = end;
+ 523          end = tmp;
+ 524      }
+ 525      n = end - start + 1;
+ 526      mark_locations_array(start,n);
+ 527  }
+
+(gc.c)
+
+

Basically, delegating to the function mark_locations_array() which marks a +space is sufficient. +What this function does is properly adjusting the arguments. +Such adjustment is required because in which direction the machine stack +extends is undecided. +If the machine stack extends to lower addresses, end is smaller, +if it extends to higher addresses, start is smaller. +Therefore, so that the smaller one becomes start, they are adjusted here.

+

The other root objects

+

Finally, it marks the built-in VALUE containers of the interpretor.

+

▼ The other roots

+ +
+1159      /* mark the registered global variables */
+1160      for (list = global_List; list; list = list->next) {
+1161          rb_gc_mark(*list->varptr);
+1162      }
+1163      rb_mark_end_proc();
+1164      rb_gc_mark_global_tbl();
+1165
+1166      rb_mark_tbl(rb_class_tbl);
+1167      rb_gc_mark_trap_list();
+1168
+1169      /* mark the instance variables of true, false, etc if exist */
+1170      rb_mark_generic_ivar_tbl();
+1171
+          /* mark the variables used in the ruby parser (only while parsing) */
+1172      rb_gc_mark_parser();
+
+(gc.c)
+
+

When putting a VALUE into a global variable of C, +it is required to register its address by user via rb_gc_register_address(). +As these objects are saved in global_List, all of them are marked.

+

rb_mark_end_proc() is to mark the procedural objects which are registered via +kind of END statement of Ruby and executed when a program finishes. (END +statements will not be described in this book).

+

rb_gc_mark_global_tbl() is to mark the global variable table rb_global_tbl. +(See also the next chapter “Variables and Constants”)

+

rb_mark_tbl(rb_class_tbl) is to mark rb_class_tbl which was discussed in the +previous chapter.

+

rb_gc_mark_trap_list() is to mark the procedural objects which are registered +via the Ruby’s function-like method trap. +(This is related to signals and will also not be described in this book.)

+

rb_mark_generic_ivar_tbl() is to mark the instance variable table prepared +for non-pointer VALUE such as true.

+

rb_gc_mark_parser() is to mark the semantic stack of the parser. +(The semantic stack will be described in Part 2.)

+

Until here, the mark phase has been finished.

+

Sweep

+

The special treatment for NODE

+

The sweep phase is the procedures to find out and free the not-marked objects. +But, for some reason, the objects of type T_NODE are specially treated. +Take a look at the next part:

+

▼ at the beggining of gc_sweep()

+ +
+ 846  static void
+ 847  gc_sweep()
+ 848  {
+ 849      RVALUE *p, *pend, *final_list;
+ 850      int freed = 0;
+ 851      int i, used = heaps_used;
+ 852
+ 853      if (ruby_in_compile && ruby_parser_stack_on_heap()) {
+ 854          /* If the yacc stack is not on the machine stack,
+ 855             do not collect NODE while parsing */
+ 856          for (i = 0; i < used; i++) {
+ 857              p = heaps[i]; pend = p + heaps_limits[i];
+ 858              while (p < pend) {
+ 859                  if (!(p->as.basic.flags & FL_MARK) &&
+                                          BUILTIN_TYPE(p) == T_NODE)
+ 860                      rb_gc_mark((VALUE)p);
+ 861                  p++;
+ 862              }
+ 863          }
+ 864      }
+
+(gc.c)
+
+

NODE is a object to express a program in the parser. +NODE is put on the stack prepared by a tool named yacc while compiling, +but that stack is not always on the machine stack. +Concretely speaking, when ruby_parser_stack_on_heap() is false, it indicates +it is not on the machine stack. +In this case, a NODE could be accidentally collected in the middle of its +creation, thus the objects of type T_NODE are unconditionally marked and +protected from being collected while compiling (ruby_in_compile) .

+

Finalizer

+

After it has reached here, all not-marked objects can be freed. +However, there’s one thing to do before freeing. +In Ruby the freeing of objects can be hooked, and it is necessary to call them. +This hook is called “finalizer”.

+

gc_sweep() Middle

+ +
+ 869      freelist = 0;
+ 870      final_list = deferred_final_list;
+ 871      deferred_final_list = 0;
+ 872      for (i = 0; i < used; i++) {
+ 873          int n = 0;
+ 874
+ 875          p = heaps[i]; pend = p + heaps_limits[i];
+ 876          while (p < pend) {
+ 877              if (!(p->as.basic.flags & FL_MARK)) {
+ 878  (A)             if (p->as.basic.flags) {
+ 879                      obj_free((VALUE)p);
+ 880                  }
+ 881  (B)             if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+ 882                      p->as.free.flags = FL_MARK; /* remains marked */
+ 883                      p->as.free.next = final_list;
+ 884                      final_list = p;
+ 885                  }
+ 886                  else {
+ 887                      p->as.free.flags = 0;
+ 888                      p->as.free.next = freelist;
+ 889                      freelist = p;
+ 890                  }
+ 891                  n++;
+ 892              }
+ 893  (C)         else if (RBASIC(p)->flags == FL_MARK) {
+ 894                  /* the objects that need to finalize */
+ 895                  /* are left untouched */
+ 896              }
+ 897              else {
+ 898                  RBASIC(p)->flags &= ~FL_MARK;
+ 899              }
+ 900              p++;
+ 901          }
+ 902          freed += n;
+ 903      }
+ 904      if (freed < FREE_MIN) {
+ 905          add_heap();
+ 906      }
+ 907      during_gc = 0;
+
+(gc.c)
+
+

This checks all over the object heap from the edge, +and frees the object on which FL_MARK flag is not set by using obj_free() (A). +obj_free() frees, for instance, only char[] used by String objects or +VALUE[] used by Array objects, +but it does not free the RVALUE struct and does not touch basic.flags at all. +Therefore, if a struct is manipulated after obj_free() is called, +there’s no worry about going down.

+

After it frees the objects, it branches based on FL_FINALIZE flag (B). +If FL_FINALIZE is set on an object, +since it means at least a finalizer is defined on the object, +the object is added to final_list. +Otherwise, the object is immediately added to freelist. +When finalizing, basic.flags becomes FL_MARK. +The struct-type flag (such as T_STRING) is cleared because of this, and +the object can be distinguished from alive objects.

+

Then, this phase completes by executing the all finalizers. +Notice that the hooked objects have already died when calling the finalizers. +It means that while executing the finalizers, one cannot use the hooked objects.

+

gc_sweep() the rest

+ +
+ 910      if (final_list) {
+ 911          RVALUE *tmp;
+ 912
+ 913          if (rb_prohibit_interrupt || ruby_in_compile) {
+ 914              deferred_final_list = final_list;
+ 915              return;
+ 916          }
+ 917
+ 918          for (p = final_list; p; p = tmp) {
+ 919              tmp = p->as.free.next;
+ 920              run_final((VALUE)p);
+ 921              p->as.free.flags = 0;
+ 922              p->as.free.next = freelist;
+ 923              freelist = p;
+ 924          }
+ 925      }
+ 926  }
+
+(gc.c)
+
+

The for in the last half is the main finalizing procedure. +The if in the first half is the case when the execution could not be moved to +the Ruby program for various reasons. +The objects whose finalization is deferred will be appear in the route © of +the previous list.

+

rb_gc_force_recycle()

+

I’ll talk about a little different thing at the end. +Until now, the ruby‘s garbage collector decides whether or not it collects each object, +but there’s also a way that users explicitly let it collect a particular object. +It’s rb_gc_force_recycle().

+

rb_gc_force_recycle()

+ +
+ 928  void
+ 929  rb_gc_force_recycle(p)
+ 930      VALUE p;
+ 931  {
+ 932      RANY(p)->as.free.flags = 0;
+ 933      RANY(p)->as.free.next = freelist;
+ 934      freelist = RANY(p);
+ 935  }
+
+(gc.c)
+
+

Its mechanism is not so special, but I introduced this because you’ll see it +several times in Part 2 and Part 3.

+

Discussions

+

To free spaces

+

The space allocated by an individual object, say, char[] of String, is +freed during the sweep phase, +but the code to free the RVALUE struct itself has not appeared yet. +And, the object heap also does not manage the number of structs in use and such. +This means that if the ruby’s object space is once allocated it would never be freed.

+

For example, the mailer what I’m creating now temporarily uses the space almost +40M bytes when constructing the threads for 500 mails, but if most of the space +becomes unused as the consequence of GC it will keep occupying the 40M bytes. +Because my machine is also kind of modern, +it does not matter if just the 40M bytes are used. +But, if this occurs in a server which keeps running, there’s the possibility of +becoming a problem.

+

However, one also need to consider that free() does not always mean the +decrease of the amount of memory in use. +If it does not return memory to OS, the amount of memory in use of the process +never decrease. And, depending on the implementation of malloc(), +although doing free() it often does not cause returning memory to OS.

+

… I had written so, but just before the deadline of this book, RVALUE became to be freed. +The attached CD-ROM also contains the edge ruby, so please check by diff. +… what a sad ending.

+

Generational GC

+

Mark & Sweep has an weak point, it is “it needs to touch the entire object space +at least once”. There’s the possibility that using the idea of Generational GC +can make up for the weak point.

+

The fundamental of Generational GC is the experiential rule that +“Most objects are lasting for either very long or very short time”. +You may be convinced about this point by thinking for seconds about the +programs you write.

+

Then, thinking based on this rule, one may come up with the idea that +“long-lived objects do not need to be marked or swept each and every time”. +Once an object is thought that it will be long-lived, +it is treated specially and excluded from the GC target. +Then, for both marking and sweeping, it can significantly decrease the number +of target objects. +For example, if half of the objects are long-lived at a particular GC time, +the number of the target objects is half.

+

There’s a problem, though. Generational GC is very difficult to do if objects can’t be moved. +It is because the long-lived objects are, as I just wrote, needed to “be treated specially”. +Since generational GC decreases the number of the objects dealt with and reduces the cost, +if which generation a object belongs to is not clearly categorized, +as a consequence it is equivalent to dealing with both generations. +Furthermore, the ruby’s GC is also a conservative GC, +so it also has to be created so that is_pointer_to_heap() work. +This is particularly difficult.

+

How to solve this problem is … By the hand of Mr. Kiyama Masato, +the implementation of Generational GC for ruby has been published. +I’ll briefly describe how this patch deals with each problem. +And this time, by courtesy of Mr. Kiyama, this Generational GC patch and its +paper are contained in attached CD-ROM. +(See also doc/generational-gc.html)

+

Then, I shall start the explanation. +In order to ease explaining, from now on, +the long-lived objects are called as “old-generation objects”, +the short-lived objects are called as “new-generation objects”,

+

First, about the biggest problem which is the special treatment for the old-generation objects. +This point is resolved by linking only the new-generation objects into a list named newlist. +This list is substantialized by increasing RVALUE’s elements.

+

Second, about the way to detect the old-generation objects. It is very simply +done by just removing the newlist objects which were not garbage collected +from the newlist. +In other words, once an object survives through GC, it will be treated as an +old-generation object.

+

Third, about the way to detect the references from old-generation objects to new-generation objects. +In Generational GC, it’s sort of, the old-generation objects keep being in the marked state. +However, when there are links from old-generation to new-generation, +the new-generation objects will not be marked. (Figure 11)

+
+

(gengc)
+Figure 11: reference over generations

+
    +
  • ルートオブジェクト the root objects
  • +
  • 新世代 new-generation
  • +
  • 旧世代 old-generation +
+ +

This is not good, so at the moment when an old-generational object refers to a new-generational object, +the new-generational object must be turned into old-generational. +The patch modifies the libraries and +adds checks to where there’s possibility that this kind of references happens.

+

This is the outline of its mechanism. It was scheduled that this patch is included ruby 1.7, +but it has not been included yet. It is said that the reason is its speed, +There’s an inference that the cost of the third point “check all references” matters, +but the precise cause has not figured out.

+

Compaction

+

Could the ruby’s GC do compaction? +Since VALUE of ruby is a direct pointer to a struct, +if the address of the struct are changed because of compaction, +it is necessary to change the all VALUEs that point to the moved structs.

+

However, since the ruby’s GC is a conservative GC, “the case when it is +impossible to determine whether or not it is really a VALUE” is possible. +Changing the value even though in this situation, +if it was not VALUE something awful will happen. +Compaction and conservative GC are really incompatible.

+

But, let’s contrive countermeasures in one way or another. +The first way is to let VALUE be an object ID instead of a pointer. (Figure 12) +It means sandwiching a indirect layer between VALUE and a struct. +In this way, as it’s not necessary to rewrite VALUE, structs can be safely moved. +But as trade-offs, accessing speed slows down and the compatibility of +extension libraries is lost.

+
+

(objid)
+Figure 12: reference through the object ID

+
    +
  • アドレスを入れる store addresses
  • +
  • インデックスを入れる store indexes
  • +
  • 移動できる can be moved +
+ +

Then, the next way is to allow moving the struct only when they are pointed +from only the pointers that “is surely VALUE” (Figure 13). +This method is called Mostly-copying garbage collection. +In the ordinary programs, there are not so many objects that +is_pointer_to_heap() is true, so the probability of being able to move the +object structs is quite high.

+
+

(mostcopy)
+Figure 13: Mostly-copying garbage collection

+
    +
  • (above) Since there’s a possibility of being referred to by non-VALUE, + this object is not moved.
  • +
  • (bottom) Since it is sure that this is referred only VALUEs, + this object can be moved.
  • +
  • 移動 move +
+ +

Moreover and moreover, by enabling to move the struct, +the implementation of Generational GC becomes simple at the same time. +It seems to be worth to challenge.

+

volatile to protect from GC

+

I wrote that GC takes care of VALUE on the stack, +therefore if a VALUE is located as a local variable the VALUE should certainly be marked. +But in reality due to the effects of optimization, it’s possible that the +variables disappear. +For example, there’s a possibility of disappearing in the following case:

+
+VALUE str;
+str = rb_str_new2("...");
+printf("%s\n", RSTRING(str)->ptr);
+
+

Because this code does not access the str itself, +some compilers only keeps str->ptr in memory and deletes the str. +If this happened, the str would be collected and the process would be down. +There’s no choice in this case

+
+volatile VALUE str;
+
+

we need to write this way. volatile is a reserved word of C, +and it has an effect of forbidding optimizations that have to do with this variable. +If volatile was attached in the code relates to Ruby, +you could assume almost certainly that its exists for GC. +When I read K & R, I thought “what is the use of this?”, +and totally didn’t expect to see the plenty of them in ruby.

+

Considering these aspects, the promise of the conservative GC “users don’t have +to care about GC” seems not always true. There was once a discussion that “the +Scheme’s GC named KSM does not need volatile”, +but it seems it could not be applied to ruby because its algorithm has a hole.

+

When to invoke

+

Inside gc.c

+

When to invoke GC? +Inside gc.c, there are three places calling rb_gc() +inside of gc.c,

+
    +
  • ruby_xmalloc()
  • +
  • ruby_xrealloc()
  • +
  • rb_newobj()
  • +
+

As for ruby_xmalloc() and ruby_xrealloc(), it is when failing to allocate memory. +Doing GC may free memories and it’s possible that a space becomes available again. +rb_newobj() has a similar situation, it invokes when freelist becomes empty.

+

Inside the interpritor

+

There’s several places except for gc.c where calling rb_gc() in the interpretor.

+

First, in io.c and dir.c, when it runs out of file descriptors and could not open, +it invokes GC. If IO objects are garbage collected, it’s possible that the +files are closed and file descriptors become available.

+

In ruby.c, rb_gc() is sometimes done after loading a file. +As I mentioned in the previous Sweep section, it is to compensate for the fact +that NODE cannot be garbage collected while compiling.

+

Object Creation

+

We’ve finished about GC and come to be able to deal with the Ruby objects from +its creation to its freeing. +So I’d like to describe about object creations here. +This is not so related to GC, rather, it is related a little to the discussion +about classes in the previous chapter.

+

Allocation Framework

+

We’ve created objects many times. For example, in this way:

+
+class C
+end
+C.new()
+
+

At this time, how does C.new create a object?

+

First, C.new is actually Class#new. Its actual body is this:

+

rb_class_new_instance()

+ +
+ 725  VALUE
+ 726  rb_class_new_instance(argc, argv, klass)
+ 727      int argc;
+ 728      VALUE *argv;
+ 729      VALUE klass;
+ 730  {
+ 731      VALUE obj;
+ 732
+ 733      obj = rb_obj_alloc(klass);
+ 734      rb_obj_call_init(obj, argc, argv);
+ 735
+ 736      return obj;
+ 737  }
+
+(object.c)
+
+

rb_obj_alloc() calles the allocate method against the klass. +In other words, it calls C.allocate in this example currently explained. +It is Class#allocate by default and its actual body is rb_class_allocate_instance().

+

rb_class_allocate_instance()

+ +
+ 708  static VALUE
+ 709  rb_class_allocate_instance(klass)
+ 710      VALUE klass;
+ 711  {
+ 712      if (FL_TEST(klass, FL_SINGLETON)) {
+ 713          rb_raise(rb_eTypeError,
+                       "can't create instance of virtual class");
+ 714      }
+ 715      if (rb_frame_last_func() != alloc) {
+ 716          return rb_obj_alloc(klass);
+ 717      }
+ 718      else {
+ 719          NEWOBJ(obj, struct RObject);
+ 720          OBJSETUP(obj, klass, T_OBJECT);
+ 721          return (VALUE)obj;
+ 722      }
+ 723  }
+
+(object.c)
+
+

rb_newobj() is a function that returns a RVALUE by taking from the freelist. +NEWOBJ() is just a rb_newobj() with type-casting. +The OBJSETUP() is a macro to initialize the struct RBasic part, +you can think that this exists only in order not to forget to set the FL_TAINT flag.

+

The rest is going back to rb_class_new_instance(), then it calls rb_obj_call_init(). +This function calls initialize on the just created object, +and the initialization completes.

+

This is summarized as follows:

+
+SomeClass.new            = Class#new (rb_class_new_instance)
+    SomeClass.allocate       = Class#allocate (rb_class_allocate_instance)
+    SomeClass#initialize     = Object#initialize (rb_obj_dummy)
+
+

I could say that the allocate class method is to physically initialize, +the initialize is to logically initialize. +The mechanism like this, in other words the mechanism that an object creation +is divided into allocate / initialize and new presides them, is called +the “allocation framework”.

+

Creating User Defined Objects

+

Next, we’ll examine about the instance creations of the classes defined in +extension libraries. +As it is called user-defined, its struct is not decided, without telling +how to allocate it, ruby don’t understand how to create its object. +Let’s look at how to tell it.

+

Data_Wrap_Struct()

+

Whichever it is user-defined or not, its creation mechanism itself can follow +the allocation framework. +It means that when defining a new SomeClass class in C, +we overwrite both SomeClass.allocate and SomeClass#initialize.

+

Let’s look at the allocate side first. Here, it does the physical initialization. +What is necessary to allocate? +I mentioned that the instance of the user-defined class is a pair of +struct RData and a user-prepared struct. +We’ll assume that the struct is of type struct my. +In order to create a VALUE based on the struct my, you can use Data_Wrap_Struct(). +This is how to use:

+
+struct my *ptr = malloc(sizeof(struct my));  /* arbitrarily allocate in the heap */
+VALUE val = Data_Wrap_Struct(data_class, mark_f, free_f, ptr);
+
+

data_class is the class that val belongs to, ptr is the pointer to be wrapped. +mark_f is (the pointer to) the function to mark this struct. +However, this does not mark the ptr itself and is used when the struct +pointed by ptr contains VALUE. +On the other hand, free_f is the function to free the ptr itself. +The argument of the both functions is ptr. +Going back a little and reading the code to mark may help you to understand +things around here in one shot.

+

Let’s also look at the content of Data_Wrap_Struct().

+

Data_Wrap_Struct()

+ +
+ 369  #define Data_Wrap_Struct(klass, mark, free, sval) \
+ 370      rb_data_object_alloc(klass, sval,             \
+                               (RUBY_DATA_FUNC)mark,    \
+                               (RUBY_DATA_FUNC)free)
+
+ 365  typedef void (*RUBY_DATA_FUNC) _((void*));
+
+(ruby.h)
+
+

Most of it is delegated to rb_object_alloc().

+

rb_data_object_alloc()

+ +
+ 310  VALUE
+ 311  rb_data_object_alloc(klass, datap, dmark, dfree)
+ 312      VALUE klass;
+ 313      void *datap;
+ 314      RUBY_DATA_FUNC dmark;
+ 315      RUBY_DATA_FUNC dfree;
+ 316  {
+ 317      NEWOBJ(data, struct RData);
+ 318      OBJSETUP(data, klass, T_DATA);
+ 319      data->data = datap;
+ 320      data->dfree = dfree;
+ 321      data->dmark = dmark;
+ 322
+ 323      return (VALUE)data;
+ 324  }
+
+(gc.c)
+
+

This is not complicated. As the same as the ordinary objects, it prepares a +RVALUE by using NEWOBJ() OBJSETUP(), +and sets the members.

+

Here, let’s go back to allocate. +We’ve succeeded to create a VALUE by now, +so the rest is putting it in an arbitrary function +and defining the function on a class by rb_define_singleton_method().

+

Data_Get_Struct()

+

The next thing is initialize. Not only for initialize, the methods need a +way to pull out the struct my* from the previously created VALUE. In order +to do it, you can use the Data_Get_Struct() macro.

+

Data_Get_Struct()

+ +
+ 378  #define Data_Get_Struct(obj,type,sval) do {\
+ 379      Check_Type(obj, T_DATA); \
+ 380      sval = (type*)DATA_PTR(obj);\
+ 381  } while (0)
+
+ 360  #define DATA_PTR(dta) (RDATA(dta)->data)
+
+(ruby.h)
+
+

As you see, it just takes the pointer (to struct my) from a member of RData. +This is simple. Check_Type() just checks the struct type.

+

The Issues of the Allocation Framework

+

So, I’ve explained innocently until now, but actually the current allocation +framework has a fatal issue. +I just described that the object created with allocate appears to the +initialize or the other methods, but if the passed object that was created +with allocate is not of the same class, it must be a very serious problem. +For example, if the object created with the default Objct.allocate +(Class#allocate) is passed to the method of String, this cause a serious problem. +That is because even though the methods of String are written +based on the assumption that a struct of type struct RString is given, +the given object is actually a struct RObject. +In order to avoid such situation, +the object created with C.allocate must be passed only to the methods of C +or its subclasses.

+

Of course, this is always true when things are ordinarily done. +As C.allocate creates the instance of the class C, +it is not passed to the methods of the other classes. +As an exception, it is possible that it is passed to the method of Object, +but the methods of Object does not depend on the struct type.

+

However, what if it is not ordinarily done? +Since C.allocate is exposed at the Ruby level, +though I’ve not described about them yet, +by making use of alias or super or something, +the definition of allocate can be moved to another class. +In this way, you can create an object whose class is String but whose actual +struct type is struct RObject. +It means that you can freely let ruby down from the Ruby level. +This is a problem.

+

The source of the issue is that allocate is exposed to the Ruby level as a method. +Conversely speaking, a solution is to define the content of allocate on the +class by using a way that is anything but a method. +So,

+
+rb_define_allocator(rb_cMy, my_allocate);
+
+

an alternative like this is currently in discussion.

+ + + +
+ + diff --git a/htmls/index.html b/htmls/index.html new file mode 100644 index 0000000..696c4ac --- /dev/null +++ b/htmls/index.html @@ -0,0 +1,129 @@ + + + + + Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Table of contents

+

Some chapters are previews. It means they have not been fully reviewed, +some diagrams may be missing and some sentences may be a little +rough. But it also means they are in open review, so do not hesitate +to address issues on the mailing list.

+ +

Part 1: Objects

+ +

Part 2: Syntax analysis

+ +

Part 3: Evaluation

+ +

Part 4: Around the evaluator

+ + +

About this Guide

+

This is a new effort to gather efforts to help translate into English the Ruby +Hacking Guide. The RHG is a book +that explains how the ruby interpreter (the official +C implementation of the Ruby language) works +internally.

+

To fully understand it, you need a good knowledge of C and Ruby.

+

Please note that this book was based on the source code of ruby 1.7.3 +so there are a few small differences to the current version of +ruby. However, these differences may make the source code simpler to +understand and the Ruby Hacking Guide is a good starting point before +looking into the ruby source code. The version of the source code used +can be downloaded here: http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz.

+

Many thanks to RubyForge for hosting us and to +Minero AOKI for letting us translate his work.

+

Help us!

+

The original is available here +or hosted within this repo here +(currently with broken formatting)

+

This translation is done during our free time, do not expect too +much. The book is quite big (more than 500 pages) so we need help to +translate it.

+

People who are good at Ruby, C and Japanese or English are +needed. Those good at Japanese (native Japanese speakers are of course +welcome) can help translate and those good at English (preferably +native speakers) can help correct mistakes, and rewrite badly written +parts… Knowing Ruby and C well is really a requirement because it +helps avoiding many mistranslations and misinterpretations.

+

People good at making diagrams would also be helpful because there is +quite a lot to redo and translators would rather spend their time +translating instead of making diagrams.

+

There have been multiple efforts to translate this book, and we want to see if +we can renew efforts by creating an organisation on github. Interested parties +can join in by starting a pull request on this repo +https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com +There is a mostly derelict mailing list at +rhg-discussion mailing list +feel free to introduce yourself (who you are, your skills, how much free time you +have), but I think the best way to propose or send corrections/improvements +is to send a pull request. If you start a feature branch along with a pull +request at the start of your work then people can comment as you work.

+

There is an old SVN repo, that is hosted at +The RubyForge project page is http://rubyforge.org/projects/rhg. +It has been imported here, and I will attempt to give credit and re-write the +SVN/Git history when I can.

+

As for now the contributors to that repo were:

+
    +
  • Vincent ISAMBART
  • +
  • meinrad recheis
  • +
  • Laurent Sansonetti
  • +
  • Clifford Caoile
  • +
  • Jean-Denis Vauguet
  • +
+ + + +
+ + diff --git a/htmls/intro.html b/htmls/intro.html new file mode 100644 index 0000000..b546577 --- /dev/null +++ b/htmls/intro.html @@ -0,0 +1,1021 @@ + + + + + Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Preface: Introduction +h2. Characteristics of Ruby

+

Some of the readers may have already been familiar with Ruby, some may be not. +(I wish the latter for this chapter to be most useful) First let’s go though a +rough summary of the characteristics of Ruby for such people.

+

Hereafter capital “Ruby” refers to Ruby as a language scheme, and lowercase +“ruby” refers to the implementation of ruby command.

+

Development pattern

+

Ruby is a personally created language by Yukihiro Matsumoto. That means Ruby +doesn’t have a standard scheme that C or Java have. The specification is merely +shown as an implementation as ruby, and its varying continuously. Whichever +you mention good or bad, it’s unbind.

+

Furthermore ruby itself is a free software – source code being open and +being in public free of charge – this is what I must add in the introduction. +That’s why it allows the approach of this book into publication.

+

Giving the README and LEGAL included in the distribution package the +complete reading of the license, let’s list up what you can do for the time +being:

+

You can redistribute source code of ruby +You can modify source code of ruby +You can redistribute a copy of source code with your modification

+

There is no need for special permission and payment in all these cases.

+

By the way, the original ruby is the version referred to in this book unless +otherwise stated, because our main purpose is to read it. However, I modified +the code without notice at a certain extent such as to remove or add white +spaces, new lines, and comments.

+

It’s conservative

+

Ruby is a very conservative language. It is equipped with only carefully chosen +features that have been tested and washed out in a variety of languages​. +Therefore it doesn’t have plenty of fresh and experimental features very much. +So it has a tendency to appeal to programmers who put importance on practical +functionalities. The dyed-in-the-wool hackers like Scheme and Haskell lovers +don’t seem to find appeal in ruby in a short glance.

+

The library is conservative in the same way. Clear and unabbreviated names are +given for new functions, while names that appears in C and Perl libraries have +been took over from them. For example, printf, getpwent, sub, and tr.

+

It is also conservative in implementation. Assembler is not its option for +seeking speed. Portability is always considered a higher priority when it +conflicts with speed.

+

It is an object-oriented language

+

Ruby is an object-oriented language. It is not possible to forget about it +absolutely, when you talk about the features of Ruby.

+

I will not give a page to this book about what an object-oriented language is. +To tell about an object-oriented feature about Ruby, the expression of the code +that just going to be explained below is the exact sample.

+

It is a script language

+

Ruby is a script language. It is also not possible to forget about it +absolutely, when you talk about the features of Ruby. To gain agreement of +everyone, an introduction of Ruby must include “object-oriented” and “script +language”.

+

However, what is a “script language” for example? I couldn’t figure out the +definition successfully. For example, John K. Ousterhout, the author of Tcl/Tk, +gives a definition as “executable language using #! on UNIX”. There are other +definitions depending on the view points, such as one that can express a useful +program with only one line, or that can execute the code by passing a program +file from the command line, etc.

+

However, I dare to use another definition, because I don’t find much interest +in “what” a script language. To call it a script language, it at least has to +avoid gaining disagreement of calling it so. That’s the definition I suggest. +To fulfill this definition, I would define the meaning of “script language” as +follows.

+

p(=center). +Whether the author of the language calls it “script language” or not.

+

I’m sure this definition will have no failure. And Ruby fulfills this point. +Therefore I call Ruby a “script language”.

+

It’s an interpreter

+

ruby is an interpreter. That’s the fact. But why it’s an interpreter? For +example, couldn’t it be made as a compiler? The answer should be “no”, because +I guess Ruby has at least something better than being an interpreter than a +compiler. Well, what is good about being an interpreter?

+

As a preparation step to investigating into it, let’s start by thinking about +the difference between an interpreter and a compiler. If the matter is to +attempt a comparison with the process how a program is executed theoretically, +there’s no difference between an interpreter language and a compile language. +It may be possible to say that a compiler language involves an interpreter, +because of the fact that CPU “interprets” a code into a machine language using +a compiler. What’s the difference actually? I suppose it’s in a practical +things – in the process of development.

+

I know somebody, as soon as hearing “in the process of development”, would +claim using a stereotypical phrase, that an interpreter reduces effort of +compilation that makes the development procedure easier. But I don’t think it’s +accurate. A language could possibly be planned so that it won’t show the +process of compilation. Actually, Delphi can compile a project by hitting just +F5. A claim about a long time for compilation is derived from the size of the +project or optimization of the codes. Compilation itself doesn’t owe a negative +side.

+

Well, why people perceive an interpreter and compiler so much different like +this? I think that it is because the developers have long distinguished the use +of the implementations of these languages according to the characteristics. In +short, a comparatively small, a daily routine fits well with developing an +interpreter language. On the other hand, a compiler language is a goal for a +large project where a number of people are involved in the development and +accuracy is required. That may be because of the speed, as well as the +readiness of creating a language.

+

Therefore, “it’s handy because it’s an interpreter” is merely an outsized myth. +Being an interpreter doesn’t necessarily contribute the readiness in usage; +seeking readiness in usage naturally makes your path toward building an +interprer language.

+

Anyway, ruby is an interpreter; it has an important fact about where this +book is facing, so I emphasize it here again. It doesn’t matter whether it’s +easy being an interpreter; anyway ruby is implemented as an interpreter.

+

High portability

+

Even with a fundamental problem that the interface is built targeting Unix, I +would insist ruby possesses a high portability. It doesn’t often require an +unfamiliar library. It doesn’t have a part written in assembler gorigorily. +Therefore it’s easy to port to a new platform, comparatively. Namely, it works +on the following platforms currently.

+

Linux +Win32 (Windows 95, 98, Me, NT, 2000, XP) +Cygwin +djgpp +FreeBSD +NetBSD +OpenBSD +BSD/OS +Mac OS X +Solaris +Tru64 UNIX +HP-UX +AIX +VMS +UX/4800 +BeOS +OS/2 (emx) +Psion

+

The main machine of the author Matsumoto is Linux, reportedly. You can assume +that a Linux will not fail to build any version of ruby.

+

Furthermore, a typical Unix environment basically can expect a stable +functionality. Considering the release cycle of packages, the primary option +for the environment to hit around ruby should fall on a branch of PC UNIX, + currently.

+

On the other hand, the Win32 environment tends to cause problems definitely. +The large gaps in the targeting OS model tend to cause problems around the +machine stack and the linker. Yet, recently Windows hackers have contributed to +make better support. I use a native ruby on Windows 2000 and Me. Once it gets +successfully run, it doesn’t seem to show special concerns like frequent +crashing. The main problems on Windows may be the gaps in the specifications.

+

Another type of OS that many people may be interested in should probably be Mac +OS (prior to v9) and handheld OS like Palm.

+

Around ruby 1.2 and before, it supported legacy Mac OS, but the development +seems to be in suspension. Even a compiling can’t get through. The biggest +cause is that the compiler environment of legacy Mac OS and the decrease of +developers. Talking about Mac OS X, there’s no worries because the body is +UNIX.

+

There seem to be discussions the portability to Palm several branches, but I +have never heard of a successful project. I guess the difficulty lies in the +necessity of settling down the specification-level standards such as stdio on +the Palm platform, rather than the processes of actual implementation. Well I +saw a porting to Psion has been done. ([ruby-list:36028]).

+

How about hot stories about VM seen in Java and .NET? I need to mention these +together with implementation in the final chapter.

+

Automatic memory control

+

Functionally it’s called GC, or Garbage Collection. Saying it in C-language, +this feature allows you to skip free() after malloc(). Unused memory is +detected by the system automatically, and will be released. It’s so convenient +that once you get used to GC you will likely be unwilling to do it manual +memory control again.

+

The topics about GC have been common because of its popularity in recent +languages with GC as a standard set, and the GS is fun to talk about because it +has a lot to devise better algorithms.

+

Typeless variables

+

The variables in Ruby don’t have types. The reason is probably typeless +variables conforms more with polymorphism, which is one of the strongest +features of an object-oriented language. Of course a language with variable +type has a way to deal with polymorphism. What I mean here is a typeless +variables have better conformance.

+

The level of “better conformance” in this case refers to synonyms like “handy”. +It’s sometimes corresponds to crucial importance, sometimes it doesn’t matter +practically. Yet, this is certainly an appealing point if a language seeks for +“handy and easy”, and Ruby does.

+

Most of syntactic elements are expressions

+

This topic is probably difficult to understand it instantly without needs +supplemental explanation. For example, the following C-language program +contains a syntactic error.

+

p(=emlist). +result = if (cond) { process(val); } else { 0; } +

+

Because the C-language syntax defines if as a statement. See following rewrite.

+

p(=emlist). +result = cond ? process(val) : 0; +

+

This rewrite is possible because the conditional operator (a?b:c) is defined +as an expression.

+

On the other hand, Ruby acceps a following expression because if is an expression.

+

p(=emlist). +result = if cond then process(val) else nil end +

+

大雑把に言うと、関数やメソッドの引数にできるものは式だと思っていい。

+

もちろん「ほとんどの文法要素が式」という言語は他にもいろいろある。例えば +Lispはその最たるものだ。このあたりの特徴からなんとなく「RubyはLispに似 +てる」と感じる人が多いようである。

+

イテレータ

+

Rubyにはイテレータがある。イテレータとは何か。いやその前にイテレータと +いう言葉は最近嫌われているので別の言葉を使うべきかもしれない。だがい +い言葉を思いつかないので当面イテレータと呼ぶことにする。

+

それでイテレータとは何か。高階の関数を知っているなら、とりあえずはそれ +と似たようなものだと思っておけばいい。Cで言えば関数ポインタを引数 +に渡すやつである。C++で言えばSTLにある@Iterator@の操作部分までをメソッド +に封入したものである。shやPerlを知っているのなら、独自に定義できる +@for@文みたいなもんだと思って見てみるといい。

+

もっともあくまでここに挙げたのは全て「似たようなもの」であって、どれも +Rubyのイテレータと似てはいるが、同じでは、全くない。いずれその時が来た +らもう少し厳密な話をしよう。

+

C言語で書いてある

+

Cで書いたプログラムなどいまどき珍しくもないが、特徴であることは間違い +ない。少なくともHaskellやPL/Iで書いてあるわけではないので一般人にも +読める可能性が高い(本当にそうかどうかはこれから自分で確かめてほしい)。

+

それからC言語と言っても@ruby@が対象としているのは基本的にK&R Cだ。 +少し前まではK&R onlyの環境が、たくさんとは言わないが、それなりにあったからだ。 +しかしさすがに最近はANSI Cが通らない環境はなくなってきており技術的には +ANSI Cに移っても特に問題はない。だが作者のまつもとさん個人の趣味もあっ +てまだK&Rスタイルを通している。

+

そんなわけで関数定義は全てK&Rスタイルだし、プロトタイプ宣言もあまり真面 +目に書かれていない。@gcc@でうっかり@-Wall@を付けると大量に警告が出て +くるとか、 +C++コンパイラでコンパイルするとプロトタイプが合わないと怒られてコンパ +イルできない……なんて話がポロポロとメーリングリストに流れている。

+

拡張ライブラリ

+

RubyのライブラリをCで書くことができ、Rubyを再コンパイルすることなく +実行時にロードできる。このようなライブラリを「Ruby拡張ライブラリ」 +または単に「拡張ライブラリ」と言う。

+

単にCで書けるだけでなくRubyレベルとCレベルでのコードの表現の差が小さい +のも大きな特徴である。Rubyで使える命令はほとんどそのままCでも使うこと +ができる。例えば以下のように。

+

p(=emlist).

+
    +
  1. メソッド呼び出し +obj.method(arg) # Ruby +rb_funcall(obj, rb_intern(“method”), 1, arg); # C
  2. +
  3. ブロック呼び出し +yield arg # Ruby +rb_yield(arg); # C
  4. +
  5. 例外送出 +raise ArgumentError, ‘wrong number of arguments’ # Ruby +rb_raise(rb_eArgError, “wrong number of arguments”); # C
  6. +
  7. オブジェクトの生成 +arr = Array.new # Ruby +VALUE arr = rb_ary_new(); # C +
  8. +
+

拡張ライブラリを書くうえでは非常に楽をできていいし、現実に +このことが代えがたい@ruby@の長所にもなっている。しかしそのぶん +@ruby@の実装にとっては非常に重い足枷となっており、随所にその +影響を見ることができる。特にGCやスレッドへの影響は顕著である。

+

スレッド

+

Rubyにはスレッドがある。さすがに最近はスレッドを知らない人はほとんどい +ないと思うのでスレッド自体に関する説明は省略する。以下はもう少し細かい +話だ。

+

@ruby@のスレッドはオリジナルのユーザレベルスレッドである。この実装の +特徴は、仕様と実装、両方の移植性が非常に高いことである。なにしろDOS上で +さえスレッドが動き、どこでも同じ挙動で使えるのだ。この点を@ruby@の最大の +長所として挙げる人も多い。

+

しかし@ruby@スレッドは凄まじい移植性を実現した反面で速度をおもいきり犠牲 +にしている。どのくらい遅いかというと、世の中に数あるユーザレベルスレッ +ドの実装の中でも一番遅いのではないか、というくらい遅い。これほど@ruby@の +実装の傾向を明確に表しているところもないだろう。

+

ソースコードを読む技術

+

さて。@ruby@の紹介も終わっていよいよソースコード読みに入ろうか、というと +ころだが、ちょっと待ってほしい。

+

ソースコードを読む、というのはプログラマならば誰しもやらなければいけな +いことだが、その具体的な方法を教えてもらえることはあまりないのではない +だろうか。どうしてだろう。プログラムが書けるなら読むのも当然できるとい +うのだろうか。

+

しかし筆者には人の書いたプログラムを読むことがそんなに簡単なことだとは +思えない。プログラムを書くのと同じくらい、読むことにも技術や定石がある +はずだし、必要だと考える。そこで@ruby@を読んでいく前にもう少し一般的に、 +ソースコードを読むにはどういう考えかたをすればいいのか、整理することに +しよう。

+

原則

+

まずは原則について触れる。

+

目的の決定 +bq. +「ソースコードを読むための極意」は『目的をもって読む』ことです。

+

これはRuby作者のまつもとさんの言だ。なるほど、この言葉には非常にうなず +けるものがある。「カーネルくらいは読んどかなきゃいかんかなあ」と思って +ソースコードを展開したり解説本を買ったりしてはみたものの、いったいどう +していいのかわからないまま放ってしまった、という経験のある人は多いので +はないだろうか。その一方で、「このツールのどこかにバグがある、とにかく +これを速攻で直して動かさないと納期に間に合わない」……というときには他 +人のプログラムだろうとなんだろうと瞬く間に直せてしまうこともあるのでは +ないだろうか。

+

この二つのケースで違うのは、意識の持ちかたである。自分が何を知ろうと +しているのかわからなければ「わかる」ことはありえない。だからまず自分が +何を知りたいのか、それを明確に言葉にすることが全ての第一歩である。

+

だがこれだけではもちろん「技術」たりえない。「技術」とは、意識すれば誰に +でもできるものでなければならないからだ。続いて、この第一歩から最終的に +目的を達成するところまで敷衍する方法について延べる。

+

目的の具体化

+

いま「@ruby@全部を理解する」を最終目標に決めたとしよう。これでも「目的を +決めた」とは言えそうだが、しかし実際にソースコードを読む役に立たないこ +とは明らかである。具体的な作業には何にもつながっていないからだ。従って +まずはこの曖昧な目標を具体的なところまで引きずり下ろさなければならない。

+

どうすればいいだろうか。まず第一に、そのプログラムを書いた人間になった +つもりで考えてみることだ。そのときにはプログラムを作るときの知識が流用 +できる。例えば伝統的な「構造化」プログラムを読むとしたら、こちらも +構造化プログラムの手法に則って考えるようにする。即ち目的を徐々に徐々に分割 +していく。あるいはGUIプログラムのようにイベントループに入ってグルグル +するものならば、とりあえず適当にイベントループを眺めてからイベントハン +ドラの役割を調べてみる。あるいはMVC(Model View Controler)のMをまず調 +べてみる。

+

第二に解析の手法を意識することだ。誰しも自分なりの解析方法というのはそ +れなりに持っていると思うが、それは経験と勘に頼って行われていることが多 +い。どうしたらうまくソースコードを読めるのか、そのこと自体を考え、意識 +することが非常に重要である。

+

ではそのような手法にはどんなものがあるだろうか。それを次に説明する。

+

解析の手法

+

ソースコードを読む手法は大雑把に言って静的な手法と動的な手法の二つに分 +類できる。静的な手法とはプログラムを動かさずソースコードを読んだり解析 +したりすること。動的な手法とはデバッガなどのツールを使って実際の動きを +見ることだ。

+

プログラムを調査するときはまず動的な解析から始めたほうがよい。なぜなら +それは「事実」だからだ。静的な解析では現実にプログラムを動かしていない +のでその結果は多かれ少なかれ「予想」になってしまう。真実を知りたいのな +らばまず事実から始めるべきなのだ。

+

もちろん動的な解析の結果が本当に事実であるかどうかはわからない。デバッガがバ +グっているかもしれないし、CPUが熱暴走しているかもしれない。自分が設定 +した条件が間違っているかもしれない。しかし少なくとも静的解析よりは動的 +な解析の結果のほうが事実に近いはずである。

+

動的な解析 +h4. 対象プログラムを使う

+

これがなければ始まらない。そもそもそのプログラムがどういうものなのか、 +どういう動作をすべきなのか、あらかじめ知っておく。

+

デバッガで動きを追う

+

例えば実際にコードがどこを通ってどういうデータ構造を作るか、なんていう +ことは頭の中で考えているよりも実際にプログラムを動かしてみてその結果を +見たほうが早い。それにはデバッガを使うのが簡単だ。

+

実行時のデータ構造を絵にして見られるとさらに嬉しいのだが、そういうツー +ルはなかなかない(特にフリーのものは少ない)。比較的単純な構造のスナッ +プショットくらいならテキストでさらっと書き出し +@graphviz@footnote{@graphviz@……添付CD-ROMの@doc/graphviz.html@参照}の +ようなツールを使って絵にすることもできそうだが、汎用・リアルタイムを +目指すとかなり難しい。

+

トレーサ

+

コードがどの手続きを通っているか調査したければトレーサを使えばいい。 +C言語なら +@ctrace@footnote{@ctrace@……http://www.vicente.org/ctrace}と +いうツールがある。 +またシステムコールのトレースには +@strace@footnote{@strace@……http://www.wi.leidenuniv.nl/~wichert/strace/}、 +@truss@、@ktrace@と言ったツールがある。

+

printしまくる

+

@printf@デバッグという言葉があるが、この手法はデバッグでなくても役に立つ。 +特定の変数の移り変わりなどはデバッガでチマチマ辿ってみるよりもprint文を +埋め込んで結果だけまとめて見るほうがわかりやすい。

+

書き換えて動かす

+

例えば動作のわかりにくいところでパラメータやコードを少しだけ変えて動 +かしてみる。そうすると当然動きが変わるから、コードがどういう意味なのか +類推できる。

+

言うまでもないが、オリジナルのバイナリは残しておいて +同じことを両方にやってみるべきである。

+

静的な解析 +h4. 名前の大切さ

+

静的解析とはつまりソースコードの解析だ。そしてソースコードの解析とは名 +前の調査である。ファイル名・関数名・変数名・型名・メンバ名など、プログ +ラムは名前のかたまりだ。名前はプログラムを抽象化する最大の武器なのであ +たりまえと言えばあたりまえだが、この点を意識して読むとかなり効率が違う。

+

またコーディングルールについてもあたりをつけておきたい。例えばCの関数 +名なら@extern@関数にはプリフィクスを使っていることが多く、関数の種類を見 +分けるのに使える。またオブジェクト指向様式のプログラムだと関数の所属情 +報がプリフィクスに入っていることがあり、貴重な情報になる。 +(例:@rb_str_length@)

+

ドキュメントを読む

+

内部構造を解説したドキュメントが入っていることもある。 +特に「@HACKING@」といった名前のファイルには注意だ。

+

ディレクトリ構造を読む

+

どういう方針でディレクトリが分割されているのか見る。 +そのプログラムがどういう作りになっているのか、 +どういうパートがあるのか、概要を把握する。

+

ファイル構成を読む

+

ファイルの中に入っている関数(名)も合わせて見ながら、 +どういう方針でファイルが分割されているのか見る。ファイル名は +有効期間が非常に長いコメントのようなものであり、注目すべきである。

+

さらに、ファイルの中にまたモジュールがある場合、モジュールを構成する関 +数は近くにまとまっているはずだ。つまり関数の並び順からモジュール構成 +を見付けることができる。

+

略語の調査

+

わかりにくい略語があればリストアップしておいて早めに調べる。 +例えば「GC」と書いてあった場合、それがGarbage Collectionなのか +それともGraphic Contextなのかで随分と話が違ってしまう。

+

プログラム関係の略語はたいてい単語の頭文字を取るとか、単語から母音を落とす、 +という方法で作られる。特に対象プログラムの分野で有名な略語は問答無用で +使われるのであらかじめチェックしておこう。

+

データ構造を知る

+

データとコードが並んでいたら、まずデータ構造から調べるべきである。つま +りCならヘッダファイルから眺めるほうが、たぶんいい。そのときはファイル +名から想像力を最大限に働かせよう。例えば言語処理系で@frame.h@というファ +イルがあったら恐らくスタックフレームの定義だ。

+

また構造体の型とメンバ名だけでも随分といろいろなことがわかる。例え +ば構造体の定義中に自分の型へのポインタで@next@というメンバがあればリンク +リストだろうと想像できる。同様に、@parent@・@children@・@sibling@と言った要 +素があれば十中八九ツリーだ。@prev@ならスタックだろう。

+

関数同士の呼び出し関係を把握する

+

関数同士の関係は名前の次に重要な情報だ。呼び出し関係を表現したものを +特に「コールグラフ」と言うが、これは非常に便利である。このへんは +ツールを活用したい。

+

ツールはテキストベースで十分だが、図にしてくれれば文句無しだ。 +ただそういう便利なものはなかなかない(特にフリーのものは少ない)。 +筆者が本書のために@ruby@を解析したときは、小さなコマンド言語と +パーサを適当にRubyで書き、@graphviz@というツールに渡して半自動生成した。

+

関数を読む

+

動作を読んで、関数のやることを一言で説明できるようにする。関数関連図を +見ながらパートごとに読んでいくのがいい。

+

関数を読むときに重要なのは「何を読むか」ではなく「何を読まないか」であ +る。どれだけコードを削るかで読みやすさが決まると言ってよい。具体的に何 +を削ればいいか、というのは実際に見せてみないとわかりづらいので本文で解 +説する。

+

それとコーディングスタイルが気にいらないときは@indent@のようなツールを +使って変換してしまえばいい。

+

好みに書き換えてみる

+

人間の身体というのは不思議なもので、できるだけ身体のいろんな場所を使い +ながらやったことは記憶に残りやすい。パソコンのキーボードより原稿用紙の +ほうがいい、という人が少なからずいるのは、単なる懐古趣味ではなくそうい +うことも関係しているのではないかと思う。

+

そういうわけで単にモニタで読むというのは非常に身体に残りにくいので、 +書き換えながら読む。そうするとわりと早く身体がコードに馴染んでくること +が多い。気にくわない名前やコードがあったら書き換える。わかりづらい略語 +は置換して省略しないようにしてしまえばよい。

+

ただし当然のことだが書き換えるときはオリジナルのソースは別に残しておき、 +途中で辻褄が合わないと思ったら元のソースを見て確認すること。でないと自 +分の単純ミスで何時間も悩む羽目になる。それに書き換えるのはあくまで馴染 +むためであって書き換えること自体が目的ではないので熱中しすぎないように +注意してほしい。

+

歴史を読む

+

プログラムにはたいてい変更個所の履歴を書いた文書が付いている。例えば +GNUのソフトウェアだと必ず@ChangeLog@というファイルがある。これは +「プログラムがそうなっている理由」を知るのには最高に役に立つ。

+

またCVSやSCCSのようなバージョン管理システムを使っていてしかもそれにア +クセスできる場合は、@ChangeLog@以上に利用価値が高い。CVSを例に取ると、特 +定の行を最後に変更した場所を表示する@cvs annotate@、指定した版からの差分 +を取る@cvs diff@などが便利だ。

+

さらに、開発用のメーリングリストやニュースグループがある場合はその過去 +ログを入手してすぐに検索できるようにしておく。変更の理由がズバリ載って +いることが多いからだ。もちろんWeb上で検索できるならそれでもいい。

+

静的解析用ツール

+

いろいろな目的のためにいろいろなツールがあるので一口には言えないが、筆 +者が一つだけ選ぶとしたら@global@をお勧めする。なんと言っても他の用途に応 +用しやすい作りになっているところがポイントだ。例えば同梱されている +@gctags@は本当はタグファイルを作るためのツールなのだが、 +これを使ってファイルに含まれる関数名のリストを取ることもできる。

+

p(=screen). +~/src/ruby % gctags class.c | awk ‘{print $1}’ +SPECIAL_SINGLETON +SPECIAL_SINGLETON +clone_method +include_class_new +ins_methods_i +ins_methods_priv_i +ins_methods_prot_i +method_list + : + : +

+

とは言えこれはあくまでも筆者のお勧めなので読者は自分の好きなツールを使っ +てもらえばいい。ただその時は最低でも次の機能を備えているものを選ぶように +すべきだ。

+

ファイルに含まれる関数名をリストアップする +関数名や変数名から位置を探す(さらにそこに飛べるとなおよい) +関数クロスリファレンス

+

ビルド +h3. 対象バージョン

+

本書で解説している@ruby@のバージョンは1.7の2002-09-12版である。@ruby@はマ +イナーバージョンが偶数だと安定版で奇数だと開発版だから、1.7は開発版と +いうことになる。しかも9月12日は特に何かの区切りというわけではないの +で、該当バージョンの公式パッケージは配布されていない。従ってこの版を入 +手するには本書添付のCD-ROMまたはサポートサイト +footnote{本書のサポートサイト……http://i.loveruby.net/ja/rhg/} +から入手するか、後述のCVSを使うしかない。

+

安定版の1.6でなく1.7にした理由は、1.7のほうが仕様・実装ともに整理され +ていて扱いやすいことが一つ。次に、開発版先端のほうがCVSが使いやすい。 +さらに、わりと近いうちに次の安定版の1.8が出そうな雰囲気になってきたこと。 +そして最後に、最先端を見ていくほうが気分的に楽しい。

+

ソースコードを入手する

+

添付CD-ROMに解説対象の版のアーカイブを収録した。 +CD-ROMのトップディレクトリに

+

p(=emlist). +ruby-rhg.tar.gz +ruby-rhg.zip +ruby-rhg.lzh +

+

の三種類が置いてあるので、便利なものを選んで使ってほしい。 +もちろん中身はどれも同じだ。例えば@tar.gz@のアーカイブなら +次のように展開すればいいだろう。

+

p(=screen). +~/src % mount /mnt/cdrom +~/src % gzip -dc /mnt/cdrom/ruby-rhg.tar.gz | tar xf - +~/src % umount /mnt/cdrom + +h3. コンパイルする

+

ソースコードを見るだけでも「読む」ことはできる。しかしプログラムを知る +ためには実際にそれを使い、改造し、実験してみることが必要だ。実験をする +なら見ているソースコードと同じものを使わなければ意味がないので、当然自 +分でコンパイルすることになる。

+

そこでここからはコンパイルの方法を説明する。まずはUNIX系OSの場合から話 +を始めよう。Windows上ではいろいろあるので次の項でまとめて話す。ただし +CygwinはWindows上ではあるがほとんどUNIXなので、こちらの話を読んでほし +い。

+

UNIX系OSでのビルド

+

さて、UNIX系OSなら普通Cコンパイラは標準装備なので、次の手順でやれば +たいがい通ってしまう。 +~/src/rubyにソースコードが展開されているとする。

+

p(=screen). +~/src/ruby % ./configure +~/src/ruby % make +~/src/ruby % su +~/src/ruby # make install +

+

以下、いくつか注意すべき点を述べる。

+

Cygwin、UX/4800など一部のプラットフォームでは@configure@の段階で +--enable-sharedオプションを付けないとリンクに失敗する。 +--enable-sharedというのは@ruby@のほとんどを共有ライブラリ +(@libruby.so@)としてコマンドの外に出すオプションである。

+

p(=screen). +~/src/ruby % ./configure —enable-shared +

+

ビルドに関するより詳しいチュートリアルを添付CD-ROMの +doc/build.htmlに入れたので、それを読みながらやってみてほしい。

+

Windowsでのビルド

+

Windowsでのビルドとなるとどうも話がややこしくなる。 +問題の根源はビルド環境が複数あることだ。

+

Visual C++ +MinGW +Cygwin +Borland C++ Compiler

+

まずCygwin環境はWindowsよりもUNIXに条件が近いのでUNIX系のビルド手順に +従えばいい。

+

Visual C++でコンパイルする場合はVisual C++ 5.0以上が +必要である。バージョン6か.NETならまず問題ないだろう。

+

MinGW、Minimalist GNU for WindowsというのはGNUのコンパイル環境(ようするに +@gcc@と@binutils@)をWindowsに移植したものだ。CygwinがUNIX環境全体を移植し +たのに対し、MinGWはあくまでコンパイルのためのツールだけを移植してある。 +またMinGWでコンパイルしたプログラムは実行時に特別なDLLを必要としない。 +つまりMinGWでコンパイルした@ruby@はVisual C++版と全く同じに扱える。

+

また個人利用ならばBorland C++ Compilerのバージョン5.5がBorlandのサイト +footnote{Borlandのサイト:@http://www.borland.co.jp@} +から無料でダウンロードできる。@ruby@がサポートしたのがかなり最近なのが +多少不安だが、本書出版前に行ったビルドテストでは特に問題は出ていない。

+

さて以上四つの環境のうちどれを選べばいいだろうか。まず基本的には +Visual C++版が最も問題が出にくいのでそれをお勧めする。UNIXの経験がある +ならCygwin一式入れてCygwinを使うのもよい。UNIXの経験がなくVisual C++も +持っていない場合はMinGWを使うのがいいだろう。

+

以下ではVisual C++とMinGWでのビルド方法について説明するが、 +あくまで概要だけに留めた。より細かい解説とBorland C++ Compilerでの +ビルド方法は添付CD-ROMの@doc/build.html@に収録したので適宜そちらも +参照してほしい。

+

Visual C++

+

Visual C++と言っても普通はIDEは使わず、DOSプロンプトからビルドする。そ +のときはまずVisual C++自体を動かせるようにするために環境変数の初期化を +しなければいけない。Visual C++にそのためのバッチファイルが付いてくるの +で、まずはそれを実行しよう。

+

p(=screen). +C:> cd “Program FilesMicrosoft Visual Studio .NETVc7bin” +C:Program FilesMicrosoft Visual Studio .NETVc7bin> vcvars32 +

+

これはVisual C++.NETの場合だ。バージョン6なら以下の場所にある。

+

p(=emlist). +C:Program FilesMicrosoft Visual StudioVC98bin +

+

@vcvars32@を実行したらその後は@ruby@のソースツリーの中のフォルダ +@win32@に移動してビルドすればいい。以下、ソースツリーは@C:src@に +あるとしよう。

+

p(=screen). +C:> cd srcruby +C:srcruby> cd win32 +C:srcrubywin32> configure +C:srcrubywin32> nmake +C:srcrubywin32> nmake DESTDIR=“C:Program Filesruby” install +

+

これで@C:Program Filesrubybin@に@ruby@コマンドが、 +C:Program Filesrubylib以下にRubyのライブラリが、 +それぞれインストールされる。@ruby@はレジストリなどは一切使わない +ので、アンインストールするときは@C:ruby@以下を消せばよい。

+

MinGW

+

前述のようにMinGWはコンパイル環境のみなので、一般的なUNIXのツール、 +例えば@sed@や@sh@が存在しない。しかし@ruby@のビルドにはそれが必要なので +それをどこかから調達しなければならない。それにはまた二つの方法が +存在する。CygwinとMSYS(Minimal SYStem)である。

+

だがMSYSのほうは本書の出版前に行ったビルド大会でトラブルが続出してしまっ +たのでお勧めできない。対照的にCygwinを使う方法だと非常に素直に通った。 +従って本書ではCygwinを使う方法を説明する。

+

まずCygwinの@setup.exe@でMinGWと開発ツール一式を入れておく。 +CygwinとMinGWは添付CD-ROMにも収録した +footnote{CygwinとMinGW……添付CD-ROMの@doc/win.html@を参照}。 +あとはCygwinの@bash@プロンプトから以下のように打てばよい。

+

p(=screen). +~/src/ruby % ./configure —with-gcc=‘gcc -mno-cygwin’ + —enable-shared i386-mingw32 +~/src/ruby % make +~/src/ruby % make install +

+

これだけだ。ここでは@configure@の行を折り返しているが実際には一行に +入れる。またバックスラッシュを入れる必要はない。インストール先は +コンパイルしたドライブの@usrlocal@以下になる。このあたりはかなり +ややこしいことが起こっていて説明が長くなるので、 +添付CD-ROMの@doc/build.html@で徹底的に説明しよう。

+

ビルド詳細

+

ここまでが@README@的な解説である。今度はこれまでやったことが具体的に +何をしているのか、つっこんで見ていこう。ただしここの話は部分的に +かなり高度な知識が必要になる。わからない場合はいきなり次の節に +飛んでほしい。本書全体を読んでから戻ってきてもらえばわかるように +なっているはずだ。

+

さて、どのプラットフォームでも@ruby@のビルドは三段階に分かれている。 +即ち@configure@、@make@、@make install@だ。@make install@はいいとして、 +@configure@と@make@の段階について解説しよう。

+

configure

+

まず@configure@である。この中身はシェルスクリプトになっており、これ +でシステムのパラメータを検出する。例えば「ヘッダファイル@setjmp.h@が存 +在するか」とか、「@alloca()@は使えるか」ということを調べてくれる。調べ +る方法は意外と単純である。

+

チェック対象方法 +コマンド実際に実行してみて@$?を見る +ヘッダファイルif [ -f $includedir/stdio.h ]@ +関数小さいプログラムをコンパイルしてみてリンクが成功するかどうか試す

+

違いを検出したら、それをどうにかしてこちらに伝えてもらわないと +いけない。その方法は、まず@Makefile@が一つ。パラメータを@@PARAM@@の +ように埋め込んだ@Makefile.in@を置いておくと、それを実際の値に変換 +した@Makefile@を生成してくれる。例えば次のように。

+

p(=emlist). +Makefile.in: CFLAGS = CFLAGS + ↓ +Makefile : CFLAGS = -g -O2 +

+

もう一つ、関数やヘッダファイルがあるかどうかといった情報を +ヘッダファイルにして出力してくれる。出力ファイルの名前は変更 +できるのでプログラムによって違うが、@ruby@では@config.h@である。 +@configure@を実行した後にこのファイルができていることを確かめてほしい。 +中身はこんな感じだ。

+

p(=caption). ▼@config.h@ +p(=longlist). + : + : +#define HAVE_SYS_STAT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define FILE_OFFSET_BITS 64 +#define HAVE_LONG_LONG 1 +#define HAVE_OFF_T 1 +#define SIZEOF_INT 4 +#define SIZEOFSHORT 2 + : + : +

+

どれも意味はわかりやすい。@HAVE_xxxx_H@ならヘッダファイルが存在するか +どうかのチェックだろうし、@SIZEOF_SHORT@ならCの@short@型が何バイトかを +示しているに違いない。同じく@SIZEOF_INT@なら@int@のバイト長だし、 +@HAVE_OFF_T@は@offset_t@型が定義されているかを示している。これに限らず +@configure@では「ある/ない」の情報は@HAVE_xxxx@というマクロで定義される +(する)。

+

以上のことからわかるように、@configure@は違いを検出してはくれるが、 +その違いを自動的に吸収してくれるわけではない。ここで定義された値を +使って差を埋めるのはあくまで各プログラマの仕事である。例えば次の +ように。

+

p(=caption). ▼@HAVE_@マクロの典型的な使いかた +p(=longlist). + 24 #ifdef HAVE_STDLIB_H + 25 # include + 26 #endif +(ruby.h) + +h3. autoconf

+

@configure@は@ruby@の専用ツールではない。関数があるか、ヘッダファイルが +あるか……といったテストには明らかに規則性があるのだから、プログラムを +書く人がみんなでそれぞれに別のものを書くのは無駄だ。

+

そこで登場するのが@autoconf@というツールである。@configure.in@とか +configure.acというファイルに「こういうチェックがしたいんだ」と +書いておき、それを@autoconf@で処理すると適切な@configure@を作ってくれる。 +configure.inの@.in@は@input@の略だろう。@Makefile@と@Makefile.in@の関係と +同じである。@.ac@のほうはもちろん@AutoConf@の略だ。

+

ここまでを絵にすると図1のようになる。

+

p(=image). +

+(build)
+Figure 1: [build]

+

+

図1: @Makefile@ができるまで

+

もっと詳しいことが知りたい読者には『GNU Autoconf/Automake/Libtool』 +footnote{『GNU Autoconf/Automake/Libtool』Gary V.Vaughan, Ben Elliston, Tom Tromey, Ian Lance Taylor共著、でびあんぐる監訳、オーム社} +をお勧めする。

+

ところで@ruby@の@configure@は言ったとおり@autoconf@を使って生成してい +るのだが、世の中にある@configure@が必ずしも@autoconf@で生成されている +とは限らない。手書きだったり、別の自動生成ツールを使っていたりすること +もある。なんにせよ、最終的に@Makefile@や@config.h@やその他いろいろがで +きればそれでいいのだ。

+

make

+

第二段階、@make@では何をするのだろうか。もちろん@ruby@のソースコードを +コンパイルするわけだが、@make@の出力を見ているとどうもその他にいろいろ +やっているように見える。その過程を簡単に説明しておこう。

+

@ruby@自体を構成するソースコードをコンパイルする。 +@ruby@の主要部分を集めたスタティックライブラリ@libruby.a@を作る。 +常にスタティックリンクされる@ruby@「@miniruby@」を作る。 +--enable-sharedのときは共有ライブラリ@libruby.so@を作る。 +@miniruby@を使って拡張ライブラリ(@ext/以下)をコンパイルする。 +最後に、本物のruby@を生成する。

+

@miniruby@と@ruby@の生成が分かれているのには二つ理由がある。一つめは拡張ラ +イブラリのコンパイルに@ruby@が必要になることだ。@—enable-shared@の場合は +@ruby@自身がダイナミックリンクされるので、ライブラリのロードパスの関係で +すぐに動かせないかもしれない。そこでスタティックリンクした@miniruby@を作り、 +ビルドの過程ではそちらを使うようにする。

+

二つめの理由は、共有ライブラリが使えないプラットフォームでは拡張ライブ +ラリを@ruby@自体にスタティックリンクしてしまう場合があるということだ。そ +の場合、@ruby@は拡張ライブラリを全てコンパイルしてからでないと作れないが、 +拡張ライブラリは@ruby@がないとコンパイルできない。そのジレンマを解消する +ために@miniruby@を使うのである。

+

CVS

+

本書の添付CD-ROMに入っている@ruby@のアーカイブにしても公式のリリースパッ +ケージにしても、それは@ruby@という、変化しつづているプログラムのほんの一 +瞬の姿をとらえたスナップショットにすぎない。@ruby@がどう変わってきたか、 +どうしてそうだったのか、ということはここには記述されていない。では過去 +も含めた全体を見るにはどうしたらいいだろうか。CVSを使えばそれができる。

+

CVSとは

+

CVSを一言で言うとエディタのundoリストである。 +ソースコードをCVSの管理下に入れておけばいつでも昔の姿に戻せるし、誰が、 +どこを、いつ、どう変えたのかすぐにわかる。一般にそういうことをしてくれ +るプログラムのことをソースコード管理システムと言うが、オープンソースの +世界で一番有名なソースコード管理システムがCVSである。

+

@ruby@もやはりCVSで管理されているのでCVSの仕組みと使いかたについて少し説 +明しよう。まずCVSの最重要概念はレポジトリとワーキングコピーである。 +CVSはエディタのundoリストのようなものと言ったが、そのためには歴代の変更の +記録を +どこかに残しておかないといけない。それを全部まとめて保存しておく場所が +「CVSレポジトリ」である。

+

ぶっちゃけて言うと、過去のソースコードを全部集めてあるのがレポジトリで +ある。もちろんそれはあくまで概念であって、実際には容量を節約するために、 +最新の姿一つと、そこに至るまでの変更差分(ようするにパッチ)の形で集積 +されている。なんにしてもファイルの過去の姿をどの時点だろうと取り出せる +ようになっていればそれでいいのだ。

+

一方、レポジトリからある一点を選んでファイルを取り出したものが +「ワーキングコピー」だ。レポジトリは一つだけだがワーキングコピーは +いくつあってもいい(図2)。

+

p(=image). +

+(repo)
+Figure 2: [repo]

+

+

図2: レポジトリとワーキングコピー

+

自分がソースコードを変更したいときはまずワーキングコピーを取り出して、 +それをエディタなどで編集してからレポジトリに「戻す」。するとレポジトリ +に変更が記録される。レポジトリからワーキングコピーを取り出すことを +「チェックアウト(checkout)」、戻すことを「チェックイン +(checkin)」 +または「コミット(commit)」と言う(図3)。チェックインするとレ +ポジトリに変更が記録されて、いつでもそれを取り出せるようになる。

+

p(=image). +

+(ci)
+Figure 3: [ci]

+

+

図3: チェックインとチェックアウト

+

そしてCVS最大の特徴はCVSレポジトリにネットワーク越しにアクセスできると +いうところだ。つまりレポジトリを保持するサーバが一つあればインターネッ +ト越しに誰でもどこからでもチェックアウト・チェックインすることができる。 +ただし普通はチェックインにはアクセス制限がかかっているので無制限 +にできるというわけではない。

+

リビジョン

+

レポジトリから特定の版を取り出すにはどうしたらいいだろうか。一つには時 +刻で指定する方法がある。「この当時の最新版をくれ」と要求するとそれを選 +んでくれるわけだ。しかし実際には時刻で指定することはあまりない。普通は +「リビジョン(revision)」というものを使う。

+

「リビジョン」は「バージョン」とほとんど同じ意味である。ただ普通はプロ +ジェクト自体に「バージョン」が付いているので、バージョンという言葉を使 +うと紛らわしい。そこでもうちょっと細かい単位を意図してリビジョンという +言葉を使う。

+

CVSでは、レポジトリに入れたばかりのファイルはリビジョン1.1である。 +チェックアウトして、変更して、チェックインするとリビジョン1.2になる。 +その次は1.3になる。その次は1.4になる。

+

CVSの簡単な使用例

+

以上をふまえてごくごく簡単にCVSの使いかたを話す。まず@cvs@コマンドがな +いとどうにもならないのでインストールしておいてほしい。添付CD-ROMにも +@cvs@のソースコードを収録した +footnote{@cvs@:@archives/cvs-1.11.2.tar.gz@}。 +@cvs@のインストールの方法はあまりにも本筋から外れるのでここでは書かな +い。

+

インストールしたら試しに@ruby@のソースコードをチェックアウトしてみよう。 +インターネットに接続中に次のように打つ。

+

p(=screen). +% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login +CVS Password: anonymous +% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby +

+

何もオプションを付けないと自動的に最新版がチェックアウトされるので、 +ruby/以下に@ruby@の真の最新版が現れているはずだ。

+

また、とある日の版を取り出すには@cvs checkout@に@-D@オプションをつけれ +ばいい。次のように打てば本書が解説しているバージョンのワーキングコピー +が取り出せる。

+

p(=screen). +% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout -D2002-09-12 ruby +

+

このとき、オプションは必ず@checkout@の直後に書かないといけないことに注 +意。先に「@ruby@」を書いてしまうと「モジュールがない」という変なエラー +になる。

+

ちなみにこの例のようなanonymousアクセスだとチェックインはできないようになっている。 +チェックインの練習をするには適当に(ローカルの)レポジトリを作って +Hello, World!プログラムでも入れてみるのがいいだろう。具体的な入れかた +はここには書かない。@cvs@に付いてくるマニュアルが結構親切だ。日本語の書 +籍ならオーム社の『CVSによるオープンソース開発』 +footnote{『CVSによるオープンソース開発』Karl Fogel, Moshe Bar共著、竹内利佳訳、オーム社} +をお勧めする。

+

@ruby@の構成 +h3. 物理構造

+

さてそろそろソースコードを見ていこうと思うのだが、まず最初にしなければ +ならないことはなんだろうか。それはディレクトリ構造を眺めることである。 +たいていの場合ディレクトリ構造すなわちソースツリーはそのままプログラム +のモジュール構造を示している。いきなり@grep@で@main()を探して頭から処理順 +に読んでいく、なんていうのは賢くない。もちろんmain()を探すのも大切だが、 +まずはのんびりとls@したり@head@したりして全体の様子をつかもう。

+

以下はCVSレポジトリからチェックアウトした直後の +トップディレクトリの様子だ。 +スラッシュで終わっているのはサブディレクトリである。

+

p(=emlist). +COPYING compar.c gc.c numeric.c sample/ +COPYING.ja config.guess hash.c object.c signal.c +CVS/ config.sub inits.c pack.c sprintf.c +ChangeLog configure.in install-sh parse.y st.c +GPL cygwin/ instruby.rb prec.c st.h +LEGAL defines.h intern.h process.c string.c +LGPL dir.c io.c random.c struct.c +MANIFEST djgpp/ keywords range.c time.c +Makefile.in dln.c lex.c re.c util.c +README dln.h lib/ re.h util.h +README.EXT dmyext.c main.c regex.c variable.c +README.EXT.ja doc/ marshal.c regex.h version.c +README.ja enum.c math.c ruby.1 version.h +ToDo env.h misc/ ruby.c vms/ +array.c error.c missing/ ruby.h win32/ +bcc32/ eval.c missing.h rubyio.h x68/ +bignum.c ext/ mkconfig.rb rubysig.h +class.c file.c node.h rubytest.rb +

+

最近はプログラム自体が大きくなってきてサブディレクトリが細かく分割され +ているソフトウェアも多いが、@ruby@はかなり長いことトップディレクトリ +一筋である。あまりにファイル数が多いと困るが、この程度なら慣れればな +んでもない。

+

トップレベルのファイルは六つに分類できる。即ち

+

ドキュメント +@ruby@自身のソースコード +@ruby@ビルド用のツール +標準添付拡張ライブラリ +標準添付Rubyライブラリ +その他

+

である。ソースコードとビルドツールが重要なのは当然として、その他に +我々の役に立ちそうなものを挙げておこう。

+

ChangeLog

+

@ruby@への変更の記録。変更の理由を調べるうえでは非常に重要。

+

README.EXT README.EXT.ja

+

拡張ライブラリの作成方法が書いてあるのだが、その一環として +@ruby@自身の実装に関することも書いてある。

+

ソースコードの腑分け

+

ここからは@ruby@自身のソースコードについてさらに細かく分割していく。 +主要なファイルについては@README.EXT@に分類が書いてあったので +それに従う。記載がないものは筆者が分類した。

+

Ruby言語のコア

+

class.cクラス関連API +error.c例外関連API +eval.c評価器 +gc.cガーベージコレクタ +lex.c予約語テーブル +object.cオブジェクトシステム +parse.yパーサ +variable.c定数、グローバル変数、クラス変数 +ruby.h@ruby@の主要マクロとプロトタイプ +intern.h@ruby@のC APIのプロトタイプ。@intern@はinternalの略だと思われるが、ここに載っている関数を拡張ライブラリで使うのは別に構わない。 +rubysig.hシグナル関係のマクロを収めたヘッダファイル +node.h構文木ノード関連の定義 +env.h評価器のコンテキストを表現する構造体の定義

+

@ruby@インタプリタのコアを構成する部分。本書が解説するのは +ここのファイルがほとんどである。@ruby@全体のファイル数と比べれば +非常に少ないが、バイトベースでは全体の50%近くを占める。 +特に@eval.c@は200Kバイト、@parse.y@が100Kバイトと大きい。

+

ユーティリティ

+

dln.c動的ローダ +regex.c正規表現エンジン +st.cハッシュテーブル +util.c基数変換やソートなどのライブラリ

+

@ruby@にとってのユーティリティという意味。ただしユーティリティという +言葉からは想像できないほど大きいものもある。例えば@regex.c@は120Kバイトだ。

+

@ruby@コマンドの実装

+

dmyext.c拡張ライブラリ初期化ルーチンのダミー(DumMY EXTention) +inits.cコアとライブラリの初期化ルーチンのエントリポイント +main.cコマンドのエントリポイント(@libruby@には不要) +ruby.c@ruby@コマンドの主要部分(@libruby@にも必要) +version.c@ruby@のバージョン

+

コマンドラインで@ruby@と打って実行するときの@ruby@コマンドの実装。コマンドライン +オプションの解釈などを行っている部分だ。@ruby@コマンド以外に@ruby@コアを利 +用するコマンドとしては@mod_ruby@や@vim@が挙げられる。これらのコマンドは +ライブラリ@libruby@(@.a@/.so/.dllなど)とリンクして動作する。

+

クラスライブラリ

+

array.cclass Array +bignum.cclass Bignum +compar.cmodule Comparable +dir.cclass Dir +enum.cmodule Enumerable +file.cclass File +hash.cclass Hash(実体は@st.c@) +io.cclass IO +marshal.cmodule Marshal +math.cmodule Math +numeric.cclass Numeric、@Integer@、@Fixnum@、@Float@ +pack.cArray#pack、@String#unpack@ +prec.cmodule Precision +process.cmodule Process +random.cKernel#srand()、@rand()@ +range.cclass Range +re.cclass Regexp(実体は@regex.c@) +signal.cmodule Signal +sprintf.c@ruby@専用の@sprintf()@ +string.cclass String +struct.cclass Struct +time.cclass Time

+

Rubyのクラスライブラリの実装。ここにあるものは基本的に通常の +Ruby拡張ライブラリと全く同じ方法で実装されている。つまりこの +ライブラリが拡張ライブラリの書きかたの例にもなっているということだ。

+

プラットフォーム依存ファイル

+

bcc32/Borland C++(Win32) +beos/BeOS +cygwin/Cygwin(Win32でのUNIXエミュレーションレイヤー) +djgpp/djgpp(DOS用のフリーな開発環境) +vms/VMS(かつてDECがリリースしていたOS) +win32/Visual C++(Win32) +x68/Sharp X680x0系(OSはHuman68k)

+

各プラットフォーム特有のコードが入っている。

+

フォールバック関数 +p(=emlist). +missing/ +

+

各種プラットフォームにない関数を補うためのファイル。 +主に@libc@の関数が多い。

+

論理構造

+

さて、以上四つのグループのうちコアはさらに大きく三つに分けられる。 +一つめはRubyのオブジェクト世界を作りだす「オブジェクト空間(object space)」。 +二つめはRubyプログラム(テキスト)を内部形式に変換する「パーサ(parser)」。 +三つめはRubyプログラムを駆動する「評価器(evaluator)」。 +パーサも評価器もオブジェクト空間の上に成立し、 +パーサがプログラムを内部形式に変換し、 +評価器がプログラムを駆動する。 +順番に解説していこう。

+

オブジェクト空間

+

一つめのオブジェクト空間。これは非常に、理解しやすい。なぜならこれが扱 +うものは基本的にメモリ上のモノが全てであり、関数を使って直接表示したり +操作したりすることができるからだ。従って本書ではまずここから解説を +始める。第2章から +第7章までが第一部である。

+

パーサ

+

二つめのパーサ。これは説明が必要だろう。

+

@ruby@コマンドはRuby言語のインタプリタである。つまり起動時にテキストの入 +力を解析し、それに従って実行する。だから@ruby@はテキストとして書かれたプ +ログラムの意味を解釈できなければいけないのだが、不幸にしてテキストとい +うのはコンピュータにとっては非常に理解しづらいものである。コンピュータ +にとってはテキストファイルはあくまでバイト列であって、それ以上ではない。 +そこからテキストの意味を読みとるには何か特別な仕掛けが必要になる。そ +の仕掛けがパーサだ。このパーサを通すことでRubyプログラム(であるテキス +ト)は@ruby@専用の、プログラムから扱いやすい内部表現に変換される。

+

その内部表現とは具体的には「構文木」というものだ。構文木はプログラムを +ツリー構造で表現したもので、例えば@if@文ならば図4のように +表現される。

+

p(=image). +

+(syntree)
+Figure 4: [syntree]

+

+

図4: @if@文と、それに対応する構文木

+

パーサの解説は第二部『構文解析』で行う。 +第二部は第10章から第12章までだ。 +対象となるファイルは@parse.y@だけである。

+

評価器

+

オブジェクトは実際に触ることができるのでわかりやすい。パーサにしてもやっ +ていること自体はようするにデータ形式の変換なんだから、まあわかる。しか +し三つめの評価器、こいつはつかみどころが全くない。

+

評価器がやるのは構文木に従ってプログラムを「実行」していくことだ。と言 +うと簡単そうに見えるのだが、では「実行する」とはどういうことか、ちゃん +と考えるとこれが結構難しい。@if@文を実行するとはどういうことだろうか。 +@while@文を実行するとはどういうことだろうか。ローカル変数に代入するとは +どういうことだろうか。メソッドを呼ぶとはどういうことだろうか。その +全てにキチンキチンと答えを出していかなければ評価器はわからないのだ。

+

本書では第三部『評価』で評価器を扱う。対象ファイルは@eval.c@だ。 +「評価器」は英語でevaluatorと言うので、それを省略して@eval@である。

+

さて、@ruby@の作りについて簡単に説明してきたが、プログラムの動作なんてい +くら概念を説明してもわかりにくいものだ。次の章ではまず実際に@ruby@を使う +ことから始めるとしよう。

+

御意見・御感想・誤殖の指摘などは +“青木峰郎 ":mailto:aamine@loveruby.net +までお願いします。

+

『Rubyソースコード完全解説』 +はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。

+

Copyright © 2002-2004 Minero Aoki, All rights reserved.

+ + + +
+ + diff --git a/htmls/iterator.html b/htmls/iterator.html new file mode 100644 index 0000000..a0c5fe8 --- /dev/null +++ b/htmls/iterator.html @@ -0,0 +1,1094 @@ + + + + + Chapter 16: Blocks | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 16: Blocks

+

Iterator

+

In this chapter, BLOCK, which is the last big name among the seven Ruby stacks, +comes in. +After finishing this, the internal state of the evaluator is virtually understood.

+

The Whole Picture

+

What is the mechanism of iterators? +First, let’s think about a small program as below:

+

▼The Source Program

+ +
+iter_method() do
+  9   # a mark to find this block
+end
+
+

Let’s check the terms just in case. +As for this program, iter_method is an iterator method, +do ~ end is an iterator block. +Here is the syntax tree of this program being dumped.

+

▼Its Syntax Tree

+ +
+NODE_ITER
+nd_iter:
+    NODE_FCALL
+    nd_mid = 9617 (iter_method)
+    nd_args = (null)
+nd_var = (null)
+nd_body:
+    NODE_LIT
+    nd_lit = 9:Fixnum
+
+

Looking for the block by using the 9 written in the iterator block as a trace, +we can understand that NODE_ITER seems to represent the iterator block. +And NODE_FCALL which calls iter_method is at the “below” of that +NODE_ITER. In other words, the node of iterator block appears earlier than the call +of the iterator method. This means, before calling an iterator method, +a block is pushed at another node.

+

And checking by following the flow of code with debugger, +I found that the invocation of an iterator is separated into 3 steps: +NODE_ITER NODE_CALL and NODE_YIELD. +This means,

+
    +
  1. push a block (NODE_ITER)
  2. +
  3. call the method which is an iterator (NODE_CALL)
  4. +
  5. yield (NODE_YEILD)
  6. +
+

that’s all.

+

Push a block

+

First, let’s start with the first step, that is NODE_ITER, which is the node +to push a block.

+

rb_eval()NODE_ITER (simplified)

+ +
+case NODE_ITER:
+  {
+    iter_retry:
+      PUSH_TAG(PROT_FUNC);
+      PUSH_BLOCK(node->nd_var, node->nd_body);
+
+      state = EXEC_TAG();
+      if (state == 0) {
+          PUSH_ITER(ITER_PRE);
+          result = rb_eval(self, node->nd_iter);
+          POP_ITER();
+      }
+      else if (_block.tag->dst == state) {
+          state &= TAG_MASK;
+          if (state == TAG_RETURN || state == TAG_BREAK) {
+              result = prot_tag->retval;
+          }
+      }
+      POP_BLOCK();
+      POP_TAG();
+      switch (state) {
+        case 0:
+          break;
+
+        case TAG_RETRY:
+          goto iter_retry;
+
+        case TAG_BREAK:
+          break;
+
+        case TAG_RETURN:
+          return_value(result);
+          /* fall through */
+        default:
+          JUMP_TAG(state);
+      }
+  }
+  break;
+
+

Since the original code contains the support of the for statement, it is +deleted. After removing the code relating to tags, +there are only push/pop of ITER and BLOCK left. +Because the rest is ordinarily doing rb_eval() with NODE_FCALL, +these ITER and BLOCK are the necessary conditions to turn a method into an iterator.

+

The necessity of pushing BLOCK is fairly reasonable, but what’s ITER for? +Actually, to think about the meaning of ITER, you need to think from the +viewpoint of the side that uses BLOCK.

+

For example, suppose a method is just called. And ruby_block exists. +But since BLOCK is pushed regardless of the break of method calls, +the existence of a block does not mean the block is pushed for that method. +It’s possible that the block is pushed for the previous method. (Figure 1)

+
+

(stacks)
+Figure 1: no one-to-one correspondence between FRAME and BLOCK

+
    +
  • 上が先端 the end is above
  • +
  • FRAMEに対応するBLOCKがあるか? Is there any BLOCK that corresponds to FRAME ?
  • +
  • ある(けどイテレータではない) Yes. (But, this is not an iterator.)
  • +
  • ある(本当にイテレータ) Yes. (this is actually an iterator.)
  • +
  • ない No. +
+ +

So, in order to determine for which method the block is pushed, ITER is used. +BLOCK is not pushed for each FRAME +because pushing BLOCK is a little heavy. +How much heavy is, +let’s check it in practice.

+

PUSH_BLOCK()

+

The argument of PUSH_BLOCK() is (the syntax tree of) the block parameter and +the block body.

+

PUSH_BLOCK() POP_BLOCK()

+ +
+ 592  #define PUSH_BLOCK(v,b) do { \
+ 593      struct BLOCK _block;                  \
+ 594      _block.tag = new_blktag();            \
+ 595      _block.var = v;                       \
+ 596      _block.body = b;                      \
+ 597      _block.self = self;                   \
+ 598      _block.frame = *ruby_frame;           \
+ 599      _block.klass = ruby_class;            \
+ 600      _block.frame.node = ruby_current_node;\
+ 601      _block.scope = ruby_scope;            \
+ 602      _block.prev = ruby_block;             \
+ 603      _block.iter = ruby_iter->iter;        \
+ 604      _block.vmode = scope_vmode;           \
+ 605      _block.flags = BLOCK_D_SCOPE;         \
+ 606      _block.dyna_vars = ruby_dyna_vars;    \
+ 607      _block.wrapper = ruby_wrapper;        \
+ 608      ruby_block = &_block
+
+ 610  #define POP_BLOCK() \
+ 611     if (_block.tag->flags & (BLOCK_DYNAMIC))              \
+ 612         _block.tag->flags |= BLOCK_ORPHAN;                \
+ 613     else if (!(_block.scope->flags & SCOPE_DONT_RECYCLE)) \
+ 614         rb_gc_force_recycle((VALUE)_block.tag);           \
+ 615     ruby_block = _block.prev;                             \
+ 616  } while (0)
+
+(eval.c)
+
+

Let’s make sure that a BLOCK is “the snapshot of the environment of the moment +of creation”. As a proof of it, except for CREF and BLOCK, the six stack +frames are saved. CREF can be substituted by ruby_frame->cbase, there’s no +need to push.

+

And, I’d like to check the three points about the mechanism of push. +BLOCK is fully allocated on the stack. +BLOCK contains the full copy of FRAME at the moment. +BLOCK is different from the other many stack frame structs in having the +pointer to the previous BLOCK (prev).

+

The flags used in various ways at POP_BLOCK() is not explained now +because it can only be understood after seeing the implementation of Proc +later.

+

And the talk is about “BLOCK is heavy”, certainly it seems a little heavy. +When looking inside of new_blktag(), +we can see it does malloc() and store plenty of members. +But let’s defer the final judge until after looking at and comparing with PUSH_ITER().

+

PUSH_ITER()

+

PUSH_ITER() POP_ITER()

+ +
+ 773  #define PUSH_ITER(i) do {               \
+ 774      struct iter _iter;                  \
+ 775      _iter.prev = ruby_iter;             \
+ 776      _iter.iter = (i);                   \
+ 777      ruby_iter = &_iter
+
+ 779  #define POP_ITER()                      \
+ 780      ruby_iter = _iter.prev;             \
+ 781  } while (0)
+
+(eval.c)
+
+

On the contrary, this is apparently light. +It only uses the stack space and has only two members. +Even if this is pushed for each FRAME, +it would probably matter little.

+

Iterator Method Call

+

After pushing a block, the next thing is to call an iterator method (a method +which is an iterator). There also needs a little machinery. +Do you remember that there’s a code to modify +the value of ruby_iter at the beginning of rb_call0? +Here.

+

rb_call0() − moving to ITER_CUR

+ +
+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      }
+
+(eval.c)
+
+

Since ITER_PRE is pushed previously at NODE_TER, this code makes +ruby_iter ITER_CUR. +At this moment, a method finally “becomes” an iterator. +Figure 2 shows the state of the stacks.

+
+

(itertrans)
+Figure 2: the state of the Ruby stacks on an iterator call.

+
    +
  • 上が先端 the end is above
  • +
  • イテレータか?(FRAMEに対応するITERがITER_CURか?) + Is this an iterator? (Is the ITER corresponds to FRAME ITER_CUR ?) +
+ +

The possible value of ruby_iter is not the one of two boolean values +(for that method or not), but one of three steps because there’s a little gap +between the timings when pushing a block and invoking an iterator method. +For example, there’s the evaluation of the arguments of an iterator method. +Since it’s possible that it contains method calls inside it, +there’s the possibility that one of that methods mistakenly thinks that the +just pushed block is for itself and uses it during the evaluation. +Therefore, the timing when a method becomes an iterator, +this means turning into ITER_CUR, +has to be the place inside of rb_call() that is just before finishing the invocation.

+

▼ the processing order

+
+

method(arg) { block } # push a block
+method(arg) { block } # evaluate the aruguments
+method(arg) { block } # a method call

+
+

For example, in the last chapter “Method”, there’s a macro named BEGIN_CALLARGS at a handler of NODE_CALL. +This is where making use of the third step ITER. +Let’s go back a little and try to see it.

+

BEGIN_CALLARGS END_CALLARGS

+

BEGIN_CALLARGS END_CALLARGS

+ +
+1812  #define BEGIN_CALLARGS do {\
+1813      struct BLOCK *tmp_block = ruby_block;\
+1814      if (ruby_iter->iter == ITER_PRE) {\
+1815          ruby_block = ruby_block->prev;\
+1816      }\
+1817      PUSH_ITER(ITER_NOT)
+
+1819  #define END_CALLARGS \
+1820      ruby_block = tmp_block;\
+1821      POP_ITER();\
+1822  } while (0)
+
+(eval.c)
+
+

When ruby_iter is ITER_PRE, a ruby_block is set aside. +This code is important, for instance, in the below case:

+
+obj.m1 { yield }.m2 { nil }
+
+

The evaluation order of this expression is:

+
    +
  1. push the block of m2
  2. +
  3. push the block of m1
  4. +
  5. call the method m1
  6. +
  7. call the method m2
  8. +
+

Therefore, if there was not BEGIN_CALLARGS, +m1 will call the block of m2.

+

And, if there’s one more iterator connected, +the number of BEGIN_CALLARGS increases at the same time in this case, +so there’s no problem.

+

Block Invocation

+

The third phase of iterator invocation, it means the last phase, +is block invocation.

+

rb_eval()NODE_YIELD

+ +
+2579        case NODE_YIELD:
+2580          if (node->nd_stts) {
+2581              result = avalue_to_yvalue(rb_eval(self, node->nd_stts));
+2582          }
+2583          else {
+2584              result = Qundef;    /* no arg */
+2585          }
+2586          SET_CURRENT_SOURCE();
+2587          result = rb_yield_0(result, 0, 0, 0);
+2588          break;
+
+(eval.c)
+
+

nd_stts is the parameter of yield. +avalue_to_yvalue() was mentioned a little at the multiple assignments, +but you can ignore this. +
((errata: actually, it was not mentioned. You can ignore this anyway.))
+The heart of the behavior is not this but rb_yield_0(). +Since this function is also very long, +I show the code after extremely simplifying it. +Most of the methods to simplify are previously used.

+
    +
  • cut the codes relating to trace_func.
  • +
  • cut errors
  • +
  • cut the codes exist only to prevent from GC
  • +
  • As the same as massign(), there’s the parameter pcall. +This parameter is to change the level of restriction of the parameter check, +so not important here. Therefore, assume pcal=0 and perform constant foldings.
  • +
+

And this time, I turn on the “optimize for readability option” as follows.

+
    +
  • when a code branching has equivalent kind of branches, + leave the main one and cut the rest.
  • +
  • if a condition is true/false in the almost all case, assume it is true/false.
  • +
  • assume there’s no tag jump occurs, delete all codes relating to tag.
  • +
+

If things are done until this, +it becomes very shorter.

+

rb_yield_0() (simplified)

+ +
+static VALUE
+rb_yield_0(val, self, klass, /* pcall=0 */)
+    VALUE val, self, klass;
+{
+    volatile VALUE result = Qnil;
+    volatile VALUE old_cref;
+    volatile VALUE old_wrapper;
+    struct BLOCK * volatile block;
+    struct SCOPE * volatile old_scope;
+    struct FRAME frame;
+    int state;
+
+    PUSH_VARS();
+    PUSH_CLASS();
+    block = ruby_block;
+    frame = block->frame;
+    frame.prev = ruby_frame;
+    ruby_frame = &(frame);
+    old_cref = (VALUE)ruby_cref;
+    ruby_cref = (NODE*)ruby_frame->cbase;
+    old_wrapper = ruby_wrapper;
+    ruby_wrapper = block->wrapper;
+    old_scope = ruby_scope;
+    ruby_scope = block->scope;
+    ruby_block = block->prev;
+    ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
+    ruby_class = block->klass;
+    self = block->self;
+
+    /* set the block arguments */
+    massign(self, block->var, val, pcall);
+
+    PUSH_ITER(block->iter);
+    /* execute the block body */
+    result = rb_eval(self, block->body);
+    POP_ITER();
+
+    POP_CLASS();
+    /* ……collect ruby_dyna_vars…… */
+    POP_VARS();
+    ruby_block = block;
+    ruby_frame = ruby_frame->prev;
+    ruby_cref = (NODE*)old_cref;
+    ruby_wrapper = old_wrapper;
+    ruby_scope = old_scope;
+
+    return result;
+}
+
+

As you can see, the most stack frames are replaced with what saved at ruby_block. +Things to simple save/restore are easy to understand, +so let’s see the handling of the other frames we need to be careful about.

+

FRAME

+
+struct FRAME frame;
+
+frame = block->frame;     /* copy the entire struct */
+frame.prev = ruby_frame;  /* by these two lines…… */
+ruby_frame = &(frame);    /* ……frame is pushed */
+
+

Differing from the other frames, a FRAME is not used in the saved state, +but a new FRAME is created by duplicating. +This would look like Figure 3.

+
+

(framepush)
+Figure 3: push a copied frame

+
    +
  • コピーして作る creating by copying +
+ +

As we’ve seen the code until here, +it seems that FRAME will never be “reused”. +When pushing FRAME, a new FRAME will always be created.

+

BLOCK

+
+block = ruby_block;
+         :
+ruby_block = block->prev;
+         :
+ruby_block = block;
+
+

What is the most mysterious is this behavior of BLOCK. +We can’t easily understand whether it is saving or popping. +It’s comprehensible that the first statement and the third statement are as a pair, +and the state will be eventually back. +However, what is the consequence of the second statement?

+

To put the consequence of I’ve pondered a lot in one phrase, +“going back to the ruby_block of at the moment when pushing the block”. +An iterator is, in short, the syntax to go back to the previous frame. +Therefore, all we have to do is turning the state of the stack frame into what +was at the moment when creating the block. +And, the value of ruby_block at the moment when creating the block is, +it seems certain that it was block->prev. +Therefore, it is contained in prev.

+

Additionally, for the question “is it no problem to assume what invoked is +always the top of ruby_block?”, +there’s no choice but saying “as the rb_yield_0 side, you can assume so”. +To push the block which should be invoked on the top of the ruby_block is the +work of the side to prepare the block, +and not the work of rb_yield_0.

+

An example of it is BEGIN_CALLARGS which was discussed in the previous chapter. +When an iterator call cascades, the two blocks are pushed and the top of the +stack will be the block which should not be used. +Therefore, it is purposefully checked and set aside.

+

VARS

+

Come to think of it, +I think we have not looked the contents of PUSH_VARS() and POP_VARS() yet. +Let’s see them here.

+

PUSH_VARS() POP_VARS()

+ +
+ 619  #define PUSH_VARS() do { \
+ 620      struct RVarmap * volatile _old; \
+ 621      _old = ruby_dyna_vars;          \
+ 622      ruby_dyna_vars = 0
+
+ 624  #define POP_VARS() \
+ 625     if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {   \
+ 626         if (RBASIC(_old)->flags) /* if were not recycled */ \
+ 627             FL_SET(_old, DVAR_DONT_RECYCLE);                  \
+ 628      }                                                        \
+ 629      ruby_dyna_vars = _old;                                   \
+ 630  } while (0)
+
+(eval.c)
+
+

This is also not pushing a new struct, to say “set aside/restore” is closer. +In practice, in rb_yield_0, PUSH_VARS() is used only to set aside the value. +What actually prepares ruby_dyna_vars is this line.

+
+ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
+
+

This takes the dyna_vars saved in BLOCK and sets it. +An entry is attached at the same time. +I’d like you to recall the description of the structure of ruby_dyna_vars in Part 2, +it said the RVarmap whose id is 0 such as the one created here is used as +the break between block scopes.

+

However, in fact, between the parser and the evaluator, the form of the link +stored in ruby_dyna_vars is slightly different. +Let’s look at the dvar_asgn_curr() function, which assigns a block local +variable at the current block.

+

dvar_asgn_curr()

+ +
+ 737  static inline void
+ 738  dvar_asgn_curr(id, value)
+ 739      ID id;
+ 740      VALUE value;
+ 741  {
+ 742      dvar_asgn_internal(id, value, 1);
+ 743  }
+
+ 699  static void
+ 700  dvar_asgn_internal(id, value, curr)
+ 701      ID id;
+ 702      VALUE value;
+ 703      int curr;
+ 704  {
+ 705      int n = 0;
+ 706      struct RVarmap *vars = ruby_dyna_vars;
+ 707
+ 708      while (vars) {
+ 709          if (curr && vars->id == 0) {
+ 710              /* first null is a dvar header */
+ 711              n++;
+ 712              if (n == 2) break;
+ 713          }
+ 714          if (vars->id == id) {
+ 715              vars->val = value;
+ 716              return;
+ 717          }
+ 718          vars = vars->next;
+ 719      }
+ 720      if (!ruby_dyna_vars) {
+ 721          ruby_dyna_vars = new_dvar(id, value, 0);
+ 722      }
+ 723      else {
+ 724          vars = new_dvar(id, value, ruby_dyna_vars->next);
+ 725          ruby_dyna_vars->next = vars;
+ 726      }
+ 727  }
+
+(eval.c)
+
+

The last if statement is to add a variable. +If we focus on there, we can see a link is always pushed in at the “next” to +ruby_dyna_vars. This means, it would look like Figure 4.

+
+

(dynavarseval)
+Figure 4: the structure of ruby_dyna_vars

+
    +
  • ブロック起動時に(rb_yield_0で)追加 added (by using rb_yield_0) when invoking a block
  • +
  • ブロック起動直後 immediately after invoking a block
  • +
  • ブロック変数を追加 add block variables
  • +
  • 追加された変数 added variables +
+ +

This differs from the case of the parser in one point: +the headers (id=0) to indicate the breaks of scopes are attached before the +links. If a header is attached after the links, the first one of the scope +cannot be inserted properly. (Figure 5)
+((errata: It was described that ruby_dyna_vars of the evaluator always forms +a single straight link. +But according to the errata, it was wrong. That part and relevant descriptions +are removed.))

+
+

(insert)
+Figure 5: cannot properly insert an entry

+
    +
  • ここに挿入しないといけない must be inserted here +
+ +

Target Specified Jump

+

The code relates to jump tags are omitted in the previously shown code, +but there’s an effort that we’ve never seen before in the jump of rb_yield_0. +Why is the effort necessary? +I’ll tell the reason in advance. I’d like you to see the below program:

+
+[0].each do
+  break
+end
+# the place to reach by break
+
+

like this way, in the case when doing break from inside of a block, +it is necessary to get out of the block and go to the method that pushed the +block. +What does it actually mean? +Let’s think by looking at the (dynamic) call graph when invoking an iterator.

+
+rb_eval(NODE_ITER)                   .... catch(TAG_BREAK)
+    rb_eval(NODE_CALL)               .... catch(TAG_BREAK)
+        rb_eval(NODE_YIELD)
+            rb_yield_0
+                rb_eval(NODE_BREAK)  .... throw(TAG_BREAK)
+
+

Since what pushed the block is NODE_ITER, +it should go back to a NODE_ITER when doing break. +However, NODE_CALL is waiting for TAG_BREAK before NODE_ITER, +in order to turn a break over methods into an error. +This is a problem. We need to somehow find a way to go straight back to a NODE_ITER.

+

And actually, “going back to a NODE_ITER” will still be a problem. +If iterators are nesting, +there could be multiple NODE_ITERs, +thus the one corresponds to the current block is not always the first NODE_ITER. +In other words, we need to restrict only “the NODE_ITER that pushed the +currently being invoked block”

+

Then, let’s see how this is resolved.

+

rb_yield_0() − the parts relates to tags

+ +
+3826      PUSH_TAG(PROT_NONE);
+3827      if ((state = EXEC_TAG()) == 0) {
+              /* ……evaluate the body…… */
+3838      }
+3839      else {
+3840          switch (state) {
+3841            case TAG_REDO:
+3842              state = 0;
+3843              CHECK_INTS;
+3844              goto redo;
+3845            case TAG_NEXT:
+3846              state = 0;
+3847              result = prot_tag->retval;
+3848              break;
+3849            case TAG_BREAK:
+3850            case TAG_RETURN:
+3851              state |= (serial++ << 8);
+3852              state |= 0x10;
+3853              block->tag->dst = state;
+3854              break;
+3855            default:
+3856              break;
+3857          }
+3858      }
+3859      POP_TAG();
+
+(eval.c)
+
+

The parts of TAG_BREAK and TAG_RETURN are crucial.

+

First, serial is a static variable of rb_yield_0(), +its value will be different every time calling rb_yield_0. +“serial” is the serial of “serial number”.

+

The reason why left shifting by 8 bits seems in order to avoid overlapping the +values of TAG_xxxx. +TAG_xxxx is in the range between 0x1 ~ 0x8, 4 bits are enough. +And, the bit-or of 0x10 seems to prevent serial from overflow. +In 32-bit machine, serial can use only 24 bits (only 16 million times), +recent machine can let it overflow within less than 10 seconds. +If this happens, the top 24 bits become all 0 in line. +Therefore, if 0x10 did not exist, state would be the same value as TAG_xxxx +(See also Figure 6).

+
+

(dst)
+Fig.6: block->tag->dst

+
    +
  • 常に1 always 1 +
+ +

Now, tag->dst became the value which differs from TAG_xxxx and is unique for each call. +In this situation, because an ordinary switch as previous ones cannot receive it, +the side to stop jumps should need efforts to some extent. +The place where making an effort is this place of rb_eval:NODE_ITER:

+

rb_eval()NODE_ITER (to stop jumps)

+ +
+case NODE_ITER:
+  {
+      state = EXEC_TAG();
+      if (state == 0) {
+          /* …… invoke an iterator …… */
+      }
+      else if (_block.tag->dst == state) {
+          state &= TAG_MASK;
+          if (state == TAG_RETURN || state == TAG_BREAK) {
+              result = prot_tag->retval;
+          }
+      }
+  }
+
+

In corresponding NODE_ITER and rb_yield_0, block should point to the same thing, +so tag->dst which was set at rb_yield_0 comes in here. +Because of this, only the corresponding NODE_ITER can properly stop the jump.

+

Check of a block

+

Whether or not a currently being evaluated method is an iterator, +in other words, whether there’s a block, +can be checked by rb_block_given_p(). +After reading the above all, we can tell its implementation.

+

rb_block_given_p()

+ +
+3726  int
+3727  rb_block_given_p()
+3728  {
+3729      if (ruby_frame->iter && ruby_block)
+3730          return Qtrue;
+3731      return Qfalse;
+3732  }
+
+(eval.c)
+
+

I think there’s no problem. What I’d like to talk about this time is actually +another function to check, it is rb_f_block_given_p().

+

rb_f_block_given_p()

+ +
+3740  static VALUE
+3741  rb_f_block_given_p()
+3742  {
+3743      if (ruby_frame->prev && ruby_frame->prev->iter && ruby_block)
+3744          return Qtrue;
+3745      return Qfalse;
+3746  }
+
+(eval.c)
+
+

This is the substance of Ruby’s block_given?. +In comparison to rb_block_given_p(), +this is different in checking the prev of ruby_frame. +Why is this?

+

Thinking about the mechanism to push a block, +to check the current ruby_frame like rb_block_given_p() is right. +But when calling block_given? from Ruby-level, +since block_given? itself is a method, +an extra FRAME is pushed. +Hence, we need to check the previous one.

+

Proc

+

To describe a Proc object from the viewpoint of implementing, +it is “a BLOCK which can be bring out to Ruby level”. +Being able to bring out to Ruby level means having more latitude, +but it also means when and where it will be used becomes completely unpredictable. +Focusing on how the influence of this fact is, let’s look at the implementation.

+

Proc object creation

+

A Proc object is created with Proc.new. +Its substance is proc_new().

+

proc_new()

+ +
+6418  static VALUE
+6419  proc_new(klass)
+6420      VALUE klass;
+6421  {
+6422      volatile VALUE proc;
+6423      struct BLOCK *data, *p;
+6424      struct RVarmap *vars;
+6425
+6426      if (!rb_block_given_p() && !rb_f_block_given_p()) {
+6427          rb_raise(rb_eArgError,
+                "tried to create Proc object without a block");
+6428      }
+6429
+          /* (A)allocate both struct RData and struct BLOCK */
+6430      proc = Data_Make_Struct(klass, struct BLOCK,
+                                  blk_mark, blk_free, data);
+6431      *data = *ruby_block;
+6432
+6433      data->orig_thread = rb_thread_current();
+6434      data->wrapper = ruby_wrapper;
+6435      data->iter = data->prev?Qtrue:Qfalse;
+          /* (B)the essential initialization is finished by here */
+6436      frame_dup(&data->frame);
+6437      if (data->iter) {
+6438          blk_copy_prev(data);
+6439      }
+6440      else {
+6441          data->prev = 0;
+6442      }
+6443      data->flags |= BLOCK_DYNAMIC;
+6444      data->tag->flags |= BLOCK_DYNAMIC;
+6445
+6446      for (p = data; p; p = p->prev) {
+6447          for (vars = p->dyna_vars; vars; vars = vars->next) {
+6448              if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+6449              FL_SET(vars, DVAR_DONT_RECYCLE);
+6450          }
+6451      }
+6452      scope_dup(data->scope);
+6453      proc_save_safe_level(proc);
+6454
+6455      return proc;
+6456  }
+
+(eval.c)
+
+

The creation of a Proc object itself is unexpectedly simple. +Between (A) and (B), a space for an Proc object is allocated and its +initialization completes. +Data_Make_Struct() is a simple macro that does both malloc() and +Data_Wrap_Struct() at the same time.

+

The problems exist after that:

+
    +
  • frame_dup()
  • +
  • blk_copy_prev()
  • +
  • FL_SET(vars, DVAR_DONT_RECYCLE)
  • +
  • scope_dup()
  • +
+

These four have the same purposes. They are:

+
    +
  • move all of what were put on the machine stack to the heap.
  • +
  • prevent from collecting even if after POP
  • +
+

Here, “all” means the all things including prev. +For the all stack frames pushed there, it duplicates each frame by +doing malloc() and copying. +VARS is usually forced to be collected by rb_gc_force_recycle() at the same moment of POP, +but this behavior is stopped by setting the DVAR_DONT_RECYCLE flag. +And so on. Really extreme things are done.

+

Why are these extreme things necessary? This is because, unlike iterator blocks, +a Proc can persist longer than the method that created it. +And the end of a method means the things allocated on the machine stack such as +FRAME, ITER, and local_vars of SCOPE are invalidated. +It’s easy to predict what the consequence of using the invalidated memories. +(An example answer: it becomes troublesome).

+

I tried to contrive a way to at least use the same FRAME from multiple Proc, +but since there are the places such as old_frame where setting aside the +pointers to the local variables, it does not seem going well. +If it requires a lot efforts in anyway, +another effort, say, allocating all of them with malloc() from the frist place, +seems better to give it a try.

+

Anyway, I sentimentally think that it’s surprising that it runs with that speed +even though doing these extreme things. +Indeed, it has become a good time.

+

Floating Frame

+

Previously, I mentioned it just in one phrase “duplicate all frames”, +but since that was unclear, let’s look at more details. +The points are the next two:

+
    +
  • How to duplicate all
  • +
  • Why all of them are duplicated
  • +
+

Then first, let’s start with the summary of how each stack frame is saved.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Frame location has prev pointer?
FRAME stack yes
SCOPE stack no
local_tbl heap
local_vars stack
VARS heap no
BLOCK stack yes
+

CLASS CREF ITER are not necessary this time. Since CLASS is a general Ruby +object, rb_gc_force_recycle() is not called with it even by mistake (it’s +impossible) and both CREF and ITER becomes unnecessary after storing its +values at the moment in FRAME. +The four frames in the above table are important +because these will be modified or referred to multiple times later. +The rest three will not.

+

Then, this talk moves to how to duplicate all. +I said “how”, but it does not about such as “by malloc()”. +The problem is how to duplicate “all”. +It is because, here I’d like you to see the above table, +there are some frames without any prev pointer. +In other words, we cannot follow links. +In this situation, how can we duplicate all?

+

A fairly clever technique used to counter this. +Let’s take SCOPE as an example. +A function named scope_dup() is used previously in order to duplicate SCOPE, +so let’s see it first.

+

scope_dup() only the beginning

+ +
+6187  static void
+6188  scope_dup(scope)
+6189      struct SCOPE *scope;
+6190  {
+6191      ID *tbl;
+6192      VALUE *vars;
+6193
+6194      scope->flags |= SCOPE_DONT_RECYCLE;
+
+(eval.c)
+
+

As you can see, SCOPE_DONT_RECYCLE is set. +Then next, take a look at the definition of POP_SCOPE():

+

POP_SCOPE() only the beginning

+ +
+ 869  #define POP_SCOPE()                                      \
+ 870      if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {        \
+ 871         if (_old) scope_dup(_old);                        \
+ 872      }                                                    \
+
+(eval.c)
+
+

When it pops, if SCOPE_DONT_RECYCLE flag was set to the current SCOPE (ruby_scope), +it also does scope_dup() of the previous SCOPE (_old). +In other words, SCOPE_DONT_RECYCLE is also set to this one. +In this way, one by one, the flag is propagated at the time when it pops. +(Figure 7)

+

+

(flaginfect)
+Figure 7: flag propagation

+

+

Since VARS also does not have any prev pointer, +the same technique is used to propagate the DVAR_DONT_RECYCLE flag.

+

Next, the second point, try to think about “why all of them are duplicated”. +We can understand that the local variables of SCOPE can be referred to later +if its Proc is created. +However, is it necessary to copy all of them including the previous SCOPE in +order to accomplish that?

+

Honestly speaking, I couldn’t find the answer of this question and has been +worried about how can I write this section for almost three days, +I’ve just got the answer. Take a look at the next program:

+
+def get_proc
+  Proc.new { nil }
+end
+
+env = get_proc { p 'ok' }
+eval("yield", env)
+
+

I have not explained this feature, but by passing a Proc object as the second +argument of eval, you can evaluate the string in that environment.

+

It means, as the readers who have read until here can probably tell, it pushes +the various environments taken from the Proc (meaning BLOCK) and evaluates. +In this case, it naturally also pushes BLOCK and +you can turn the BLOCK into a Proc again. +Then, using the Proc when doing eval … if things are done like this, you +can access almost all information of ruby_block from Ruby level as you like. +This is the reason why the entire stacks need to be fully duplicated. +
((errata: we cannot access ruby_block as we like from Ruby level. +The reason why all SCOPEs are duplicated was not understood. +It seems all we can do is to investigate the mailing list archives of the time +when this change was applied. (It is still not certain whether we can find out +the reason in this way.) +
))

+

Invocation of Proc

+

Next, we’ll look at the invocation of a created Proc. +Since Proc#call can be used from Ruby to invoke, +we can follow the substance of it.

+

The substance of Proc#call is proc_call():

+

proc_call()

+ +
+6570  static VALUE
+6571  proc_call(proc, args)
+6572      VALUE proc, args;           /* OK */
+6573  {
+6574      return proc_invoke(proc, args, Qtrue, Qundef);
+6575  }
+
+(eval.c)
+
+

Delegate to proc_invoke(). When I look up invoke in a dictionary, +it was written such as “call on (God, etc.) for help”, +but when it is in the context of programming, +it is often used in the almost same meaning as “activate”.

+

The prototype of the proc_invoke() is,

+
+proc_invoke(VALUE proc, VALUE args, int pcall, VALUE self)
+
+

However, according to the previous code, pcall=Qtrue and self=Qundef in this case, +so these two can be removed by constant foldings.

+

proc_invoke (simplified)

+ +
+static VALUE
+proc_invoke(proc, args, /* pcall=Qtrue */, /* self=Qundef */)
+    VALUE proc, args;
+    VALUE self;
+{
+    struct BLOCK * volatile old_block;
+    struct BLOCK _block;
+    struct BLOCK *data;
+    volatile VALUE result = Qnil;
+    int state;
+    volatile int orphan;
+    volatile int safe = ruby_safe_level;
+    volatile VALUE old_wrapper = ruby_wrapper;
+    struct RVarmap * volatile old_dvars = ruby_dyna_vars;
+
+    /*(A)take BLOCK from proc and assign it to data */
+    Data_Get_Struct(proc, struct BLOCK, data);
+    /*(B)blk_orphan */
+    orphan = blk_orphan(data);
+
+    ruby_wrapper = data->wrapper;
+    ruby_dyna_vars = data->dyna_vars;
+    /*(C)push BLOCK from data */
+    old_block = ruby_block;
+    _block = *data;
+    ruby_block = &_block;
+
+    /*(D)transition to ITER_CUR */
+    PUSH_ITER(ITER_CUR);
+    ruby_frame->iter = ITER_CUR;
+
+    PUSH_TAG(PROT_NONE);
+    state = EXEC_TAG();
+    if (state == 0) {
+        proc_set_safe_level(proc);
+        /*(E)invoke the block */
+        result = rb_yield_0(args, self, 0, pcall);
+    }
+    POP_TAG();
+
+    POP_ITER();
+    if (ruby_block->tag->dst == state) {
+        state &= TAG_MASK;      /* target specified jump */
+    }
+    ruby_block = old_block;
+    ruby_wrapper = old_wrapper;
+    ruby_dyna_vars = old_dvars;
+    ruby_safe_level = safe;
+
+    switch (state) {
+      case 0:
+        break;
+      case TAG_BREAK:
+        result = prot_tag->retval;
+        break;
+      case TAG_RETURN:
+        if (orphan) {   /* orphan procedure */
+            localjump_error("return from proc-closure", prot_tag->retval);
+        }
+        /* fall through */
+      default:
+        JUMP_TAG(state);
+    }
+    return result;
+}
+
+

The crucial points are three: C, D, and E.

+

(C) At NODE_ITER a BLOCK is created from the syntax tree and pushed, +but this time, a BLOCK is taken from Proc and pushed.

+

(D) It was ITER_PRE before becoming ITER_CUR at rb_call0(), +but this time it goes directly into ITER_CUR.

+

(E) If the case was an ordinary iterator, +its method call exists before yeild occurs then going to rb_yield_0, +but this time rb_yield_() is directly called and invokes the just pushed block.

+

In other words, in the case of iterator, the procedures are separated into three places, +NODE_ITER ~ rb_call0() ~ NODE_YIELD. But this time, they are done all at once.

+

Finally, I’ll talk about the meaning of blk_orphan(). +As the name suggests, it is a function to determine the state of “the method +which created the Proc has finished”. +For example, the SCOPE used by a BLOCK has already been popped, +you can determine it has finished.

+

Block and Proc

+

In the previous chapter, various things about arguments and parameters of +methods are discussed, but I have not described about block parameters yet. +Although it is brief, here I’ll perform the final part of that series.

+
+def m(&block)
+end
+
+

This is a “block parameter”. The way to enable this is very simple. +If m is an iterator, +it is certain that a BLOCK was already pushed, +turn it into a Proc and assign into (in this case) the local variable block. +How to turn a block into a Proc is just calling proc_new(), which was previously described. +The reason why just calling is enough can be a little incomprehensible. +However whichever Proc.new or m, +the situation “a method is called and a BLOCK is pushed” is the same. +Therefore, from C level, anytime you can turn a block into a Proc +by just calling proc_new().

+

And if m is not an iterator, all we have to do is simply assigning nil.

+

Next, it is the side to pass a block.

+
+m(&block)
+
+

This is a “block argument”. This is also simple, +take a BLOCK from (a Proc object stored in) block and push it. +What differs from PUSH_BLOCK() is only whether a BLOCK has already been +created in advance or not.

+

The function to do this procedure is block_pass(). +If you are curious about, check and confirm around it. +However, it really does just only what was described here, +it’s possible you’ll be disappointed…

+ + + +
+ + diff --git a/htmls/load.html b/htmls/load.html new file mode 100644 index 0000000..c46c122 --- /dev/null +++ b/htmls/load.html @@ -0,0 +1,906 @@ + + + + + Loading | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Vincent ISAMBART

+

Chapter 18: Loading

+

Outline

+

Interface

+

At the Ruby level, there are two procedures that can be used for +loading: require and load.

+
+require 'uri'            # load the uri library
+load '/home/foo/.myrc'   # read a resource file
+
+

They are both normal methods, compiled and evaluated exactly like any +other code. It means loading occurs after compilation gave control to +the evaluation stage.

+

These two function each have their own use. ‘require’ is to load +libraries, and load is to load an arbitrary file. Let’s see this in +more details.

+

require

+

require has four features:

+
    +
  • the file is searched for in the load path
  • +
  • it can load extension libraries
  • +
  • the .rb/.so extension can be omitted
  • +
  • a given file is never loaded more than once
  • +
+

Ruby’s load path is in the global variable $:, which contains an +array of strings. For example, displaying the content of the $: in +the environment I usually use would show:

+
+% ruby -e 'puts $:'
+/usr/lib/ruby/site_ruby/1.7
+/usr/lib/ruby/site_ruby/1.7/i686-linux
+/usr/lib/ruby/site_ruby
+/usr/lib/ruby/1.7
+/usr/lib/ruby/1.7/i686-linux
+.
+
+

Calling puts on an array displays one element on each line so it’s easy +to read.

+

As I ran configure using --prefix=/usr, the library path is +/usr/lib/ruby and below, but if you compile it normally from the +source code, the libraries will be in /usr/local/lib/ruby and below. +In a Windows environment, there will also be a drive letter.

+

Then, let’s try to require the standard library nkf.so from the +load path.

+
+require 'nkf'
+
+

If the required name has no extension, require silently +compensates. First, it tries with .rb, then with .so. On some +platforms it also tries the platform’s specific extension for +extension libraries, for example .dll in a Windows environment or +.bundle on Mac OS X.

+

Let’s do a simulation on my environment. ruby checks the following +paths in sequential order.

+
+/usr/lib/ruby/site_ruby/1.7/nkf.rb
+/usr/lib/ruby/site_ruby/1.7/nkf.so
+/usr/lib/ruby/site_ruby/1.7/i686-linux/nkf.rb
+/usr/lib/ruby/site_ruby/1.7/i686-linux/nkf.so
+/usr/lib/ruby/site_ruby/nkf.rb
+/usr/lib/ruby/site_ruby/nkf.so
+/usr/lib/ruby/1.7/nkf.rb
+/usr/lib/ruby/1.7/nkf.so
+/usr/lib/ruby/1.7/i686-linux/nkf.rb
+/usr/lib/ruby/1.7/i686-linux/nkf.so    found!
+
+

nkf.so has been found in /usr/lib/ruby/1.7/i686-linux. Once the +file has been found, require’s last feature (not loading the file +more than once) locks the file. The locks are strings put in the +global variable $". In our case the string "nkf.so" has been put +there. Even if the extension has been omitted when calling require, +the file name in $" has the extension.

+
+require 'nkf'   # after loading nkf...
+p $"            # ["nkf.so"]  the file is locked
+
+require 'nkf'   # nothing happens if we require it again
+p $"            # ["nkf.so"]  the content of the lock array does not change
+
+

The are two reasons for adding the missing extension. The first one is +not to load it twice if the same file is later required with its +extension. The second one is to be able to load both nkf.rb and +nkf.so. In fact the extensions are disparate (.so .dll .bundle +etc.) depending on the platform, but at locking time they all become +.so. That’s why when writing a Ruby program you can ignore the +differences of extensions and consider it’s always so. So you can +say that ruby is quite UNIX oriented.

+

By the way, $" can be freely modified even at the Ruby level so we +cannot say it’s a strong lock. You can for example load an extension +library multiple times if you clear $".

+

load

+

load is a lot easier than require. Like require, it searches the +file in $:. But it can only load Ruby programs. Furthermore, the +extension cannot be omitted: the complete file name must always be +given.

+
+load 'uri.rb'   # load the URI library that is part of the standard library
+
+

In this simple example we try to load a library, but the proper way to +use load is for example to load a resource file giving its full +path.

+

Flow of the whole process

+

If we roughly split it, “loading a file” can be split in:

+
    +
  • finding the file
  • +
  • reading the file and mapping it to an internal form
  • +
  • evaluating it
  • +
+

The only difference between require and load is how to find the +file. The rest is the same in both.

+

We will develop the last evaluation part a little more. Loaded Ruby +programs are basically evaluated at the top-level. It means the +defined constants will be top-level constants and the defined methods +will be function-style methods.

+
+### mylib.rb
+MY_OBJECT = Object.new
+def my_p(obj)
+  p obj
+end
+
+### first.rb
+require 'mylib'
+my_p MY_OBJECT   # we can use the constants and methods defined in an other file
+
+

Only the local variable scope of the top-level changes when the file +changes. In other words, local variables cannot be shared between +different files. You can of course share them using for example Proc +but this has nothing to do with the load mechanism.

+

Some people also misunderstand the loading mechanism. Whatever the +class you are in when you call load, it does not change +anything. Even if, like in the following example, you load a file in +the module statement, it does not serve any purpose, as everything +that is at the top-level of the loaded file is put at the Ruby +top-level.

+
+require 'mylib'     # whatever the place you require from, be it at the top-level
+module SandBox
+  require 'mylib'   # or in a module, the result is the same
+end
+
+

Highlights of this chapter

+

Here the mechanism is a lot about details, so it’s a little difficult +to enumerate it simply. That’s why we will work a little differently +on it, and we are going to reduce the target to 3 points:

+
    +
  • loading serialisation
  • +
  • the repartition of the functions in the different source files
  • +
  • how extension libraries are loaded
  • +
+

Regarding the first point, you will understand it when you see it.

+

For the second point, the functions that appear in this chapter come +from 4 different files, eval.c ruby.c file.c dln.c. We’ll look at +the reason they are stretched in different places.

+

The third point is just like its name says. We will see how the +currently popular trend of execution time loading, more commonly +referred to as plug-ins, works. This is the most important part of this +chapter, so I’d like to use as many pages as possible to talk about it.

+

Searching the library

+

rb_f_require()

+

The body of require is rb_f_require. First, we will only look at +the part concerning the file search. Having many different cases is +bothersome so we will limit ourselves to the case when no file +extension is given.

+

rb_f_require() (simplified version) +

+5527  VALUE
+5528  rb_f_require(obj, fname)
+5529      VALUE obj, fname;
+5530  {
+5531      VALUE feature, tmp;
+5532      char ext, *ftptr; / OK /
+5533      int state;
+5534      volatile int safe = ruby_safe_level;
+5535
+5536      SafeStringValue(fname);
+5537      ext = strrchr(RSTRING→ptr, ‘.’);
+5538      if (ext) {
+              / …if the file extension has been given… /
+5584      }
+5585      tmp = fname;
+5586      switch (rb_find_file_ext(&tmp, loadable_ext)) {
+5587        case 0:
+5588          break;
+5589
+5590        case 1:
+5591          feature = fname = tmp;
+5592          goto load_rb;
+5593
+5594        default:
+5595          feature = tmp;
+5596          fname = rb_find_file(tmp);
+5597          goto load_dyna;
+5598      }
+5599      if (rb_feature_p(RSTRING→ptr, Qfalse))
+5600          return Qfalse;
+5601      rb_raise(rb_eLoadError, “No such file to load — %s”,
+                   RSTRING→ptr);
+5602
+5603    load_dyna:
+          / …load an extension library… /
+5623      return Qtrue;
+5624
+5625    load_rb:
+          / …load a Ruby program… */
+5648      return Qtrue;
+5649  }

+

5491 static const char const loadable_ext[] = { +5492 “.rb”, DLEXT, / DLEXT=“.so”, “.dll”, “.bundle”… / +5493 #ifdef DLEXT2 +5494 DLEXT2, / DLEXT2=“.dll” on Cygwin, MinGW */ +5495 #endif +5496 0 +5497 };

+

(eval.c) +

+

In this function the goto labels load_rb and load_dyna are +actually like subroutines, and the two variables feature and fname +are more or less their parameters. These variables have the following +meaning.

+ + + + + + + + + + + + + + + + +
variablemeaningexample
featurethe library file name that will be put in $"uri.rbnkf.so
fnamethe full path to the library/usr/lib/ruby/1.7/uri.rb
+

The name feature can be found in the function rb_feature_p(). This +function checks if a file has been locked (we will look at it just +after).

+

The functions actually searching for the library are rb_find_file() +and rb_find_file_ext(). rb_find_file() searches a file in the load +path $'. rb_find_file_ext() does the same but the difference is +that it takes as a second parameter a list of extensions +(i.e. loadable_ext) and tries them in sequential order.

+

Below we will first look entirely at the file searching code, then we +will look at the code of the require lock in load_rb.

+

rb_find_file()

+

First the file search continues in rb_find_file(). This function +searches the file path in the global load path $' +(rb_load_path). The string contamination check is tiresome so we’ll +only look at the main part.

+

rb_find_file() (simplified version) +

+2494  VALUE
+2495  rb_find_file(path)
+2496      VALUE path;
+2497  {
+2498      VALUE tmp;
+2499      char *f = RSTRING→ptr;
+2500      char *lpath;

+

2530 if (rb_load_path) { +2531 long i; +2532 +2533 Check_Type(rb_load_path, T_ARRAY); +2534 tmp = rb_ary_new(); +2535 for (i=0;i<RARRAY→len;i++) { +2536 VALUE str = RARRAY→ptr[i]; +2537 SafeStringValue(str); +2538 if (RSTRING→len > 0) { +2539 rb_ary_push(tmp, str); +2540 } +2541 } +2542 tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP)); +2543 if (RSTRING→len == 0) { +2544 lpath = 0; +2545 } +2546 else { +2547 lpath = RSTRING→ptr; +2551 } +2552 }

+

2560 f = dln_find_file(f, lpath); +2561 if (file_load_ok(f)) { +2562 return rb_str_new2(f); +2563 } +2564 return 0; +2565 }

+

(file.c) +

+

If we write what happens in Ruby we get the following:

+
+tmp = []                     # make an array
+$:.each do |path|            # repeat on each element of the load path
+  tmp.push path if path.length > 0 # check the path and push it
+end
+lpath = tmp.join(PATH_SEP)   # concatenate all elements in one string separated by PATH_SEP
+
+dln_find_file(f, lpath)      # main processing
+
+

PATH_SEP is the path separator: ':' under UNIX, ';' under +Windows. rb_ary_join() creates a string by putting it between the +different elements. In other words, the load path that had become an +array is back to a string with a separator.

+

Why? It’s only because dln_find_file() takes the paths as a string +with PATH_SEP as a separator. But why is dln_find_file() +implemented like that? It’s just because dln.c is not a library for +ruby. Even if it has been written by the same author, it’s a general +purpose library. That’s precisely for this reason that when I sorted +the files by category in the Introduction I put this file in the +Utility category. General purpose libraries cannot receive Ruby +objects as parameters or read ruby global variables.

+

dln_find_file() also expands for example ~ to the home directory, +but in fact this is already done in the omitted part of +rb_find_file(). So in ruby‘s case it’s not necessary.

+

Loading wait

+

Here, file search is finished quickly. Then comes is the loading +code. Or more accurately, it is “up to just before the load”. The code +of rb_f_require()’s load_rb has been put below.

+

rb_f_require():load_rb +

+5625    load_rb:
+5626      if (rb_feature_p(RSTRING→ptr, Qtrue))
+5627          return Qfalse;
+5628      ruby_safe_level = 0;
+5629      rb_provide_feature(feature);
+5630      /* the loading of Ruby programs is serialised /
+5631      if (!loading_tbl) {
+5632          loading_tbl = st_init_strtable();
+5633      }
+5634      / partial state /
+5635      ftptr = ruby_strdup(RSTRING→ptr);
+5636      st_insert(loading_tbl, ftptr, curr_thread);
+          / …load the Ruby program and evaluate it… /
+5643      st_delete(loading_tbl, &ftptr, 0); / loading done */
+5644      free(ftptr);
+5645      ruby_safe_level = safe;

+

(eval.c) +

+

Like mentioned above, rb_feature_p() checks if a lock has been put +in $". And rb_provide_feature() pushes a string in $", in other +words locks the file.

+

The problem comes after. Like the comment says “the loading of Ruby +programs is serialised”. In other words, a file can only be loaded +from one thread, and if during the loading another thread tries to load the +same file, that thread will wait for the first loading to be finished. +If it were not the case:

+
+Thread.fork {
+    require 'foo'   # At the beginning of require, foo.rb is added to $"
+}                   # However the thread changes during the evaluation of foo.rb
+require 'foo'   # foo.rb is already in $" so the function returns immediately
+# (A) the classes of foo are used...
+
+

By doing something like this, even though the foo library is not +really loaded, the code at (A) ends up being executed.

+

The process to enter the waiting state is simple. A st_table is +created in loading_tbl, the association “feature=>waiting thread” +is recorded in it. curr_thread is in eval.c’s functions, its value +is the current running thread.

+

The mechanism to enter the waiting state is very simple. A st_table +is created in the loading_tbl global variable, and a +“feature=>loading thread” association is created. curr_thread is +a variable from eval.c, and its value is the currently running +thread. That makes an exclusive lock. And in rb_feature_p(), we +wait for the loading thread to end like the following.

+

rb_feature_p() (second half) +

+5477  rb_thread_t th;
+5478
+5479  while (st_lookup(loading_tbl, f, &th)) {
+5480      if (th == curr_thread) {
+5481          return Qtrue;
+5482      }
+5483      CHECK_INTS;
+5484      rb_thread_schedule();
+5485  }

+

(eval.c) +

+

When rb_thread_schedule() is called, the control is transferred to +an other thread, and this function only returns after the control +returned back to the thread where it was called. When the file name +disappears from loading_tbl, the loading is finished so the function +can end. The curr_thread check is not to lock itself (figure 1).

+

+

(loadwait)
+Figure 1: Serialisation of loads

+

+

Loading of Ruby programs

+

rb_load()

+

We will now look at the loading process itself. Let’s start by the +part inside rb_f_require()’s load_rb loading Ruby programs.

+

rb_f_require()-load_rb- loading +

+5638      PUSH_TAG(PROT_NONE);
+5639      if ((state = EXEC_TAG()) == 0) {
+5640          rb_load(fname, 0);
+5641      }
+5642      POP_TAG();

+

(eval.c) +

+

The rb_load() which is called here is actually the “meat” of the +Ruby-level load. +ということは探索がもう一回必要になるわけで、同じ作業をもう一回見るなん +てやっていられない。そこでその部分は以下では省略してある。

+

And since the second argument (wrap) passed to rb_load in the above code is 0, the call is wrapped in 0. (* What is this supposed to mean??? That the nesting level is 0?) +また第二引数のwrapも、上記の呼び出しコードで0なので、0で畳み込んである。

+

rb_load() (simplified edition) +

+void
+rb_load(fname, /* wrap=0 */)
+    VALUE fname;
+{
+    int state;
+    volatile ID last_func;
+    volatile VALUE wrapper = 0;
+    volatile VALUE self = ruby_top_self;
+    NODE *saved_cref = ruby_cref;

+PUSH_VARS(); +PUSH_CLASS(); +ruby_class = rb_cObject; +ruby_cref = top_cref; /* (A-1) CREFを変える */ +wrapper = ruby_wrapper; +ruby_wrapper = 0; +PUSH_FRAME(); +ruby_frame→last_func = 0; +ruby_frame→last_class = 0; +ruby_frame→self = self; /* (A-2) ruby_frame→cbaseを変える */ +ruby_frame→cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0); +PUSH_SCOPE(); +/* at the top-level the visibility is private by default */ +SCOPE_SET(SCOPE_PRIVATE); +PUSH_TAG(PROT_NONE); +ruby_errinfo = Qnil; /* make sure it’s nil */ +state = EXEC_TAG(); +last_func = ruby_frame→last_func; +if (state == 0) { +NODE *node; +/* (B)なぜかevalと同じ扱い */ +ruby_in_eval++; +rb_load_file(RSTRING→ptr); +ruby_in_eval—; +node = ruby_eval_tree; +if (ruby_nerrs == 0) { /* no parse error occurred */ +eval_node(self, node); +} +} +ruby_frame→last_func = last_func; +POP_TAG(); +ruby_cref = saved_cref; +POP_SCOPE(); +POP_FRAME(); +POP_CLASS(); +POP_VARS(); +ruby_wrapper = wrapper; +if (ruby_nerrs > 0) { /* a parse error occurred */ +ruby_nerrs = 0; +rb_exc_raise(ruby_errinfo); +} +if (state) jump_tag_but_local_jump(state); +if (!NIL_P(ruby_errinfo)) /* an exception was raised during the loading */ +rb_exc_raise(ruby_errinfo); +

} +

+

やっとスタック操作の嵐から抜けられたと思った瞬間また突入するというのも +精神的に苦しいものがあるが、気を取りなおして読んでいこう。

+

長い関数の常で、コードのほとんどがイディオムで占められている。 +PUSH/POP、タグプロテクトと再ジャンプ。その中でも注目したいのは +(A)のCREF関係だ。ロードしたプログラムは常にトップレベル上で +実行されるので、ruby_crefを(プッシュではなく)退避しtop_crefに戻す。 +ruby_frame->cbaseも新しいものにしている。

+

それともう一ヶ所、(B)でなぜかruby_in_evalをオンにしている。そもそも +この変数はいったい何に影響するのか調べてみると、rb_compile_error()とい +う関数だけのようだ。ruby_in_evalが真のときは例外オブジェクトにメッセージを +保存、そうでないときはstderrにメッセージを出力、となっている。つまりコ +マンドのメインプログラムのパースエラーのときはいきなりstderrに出力した +いのだが評価器の中ではそれはまずいので止める、という仕組みらしい。すると +ruby_in_evalのevalはメソッドevalや関数eval()ではなくて一般動詞の +evaluateか、はたまたeval.cのことを指すのかもしれない。

+

rb_load_file()

+

ここでソースファイルは突然ruby.cへと移る。と言うよりも実際のところは +こうではないだろうか。即ち、ロード関係のファイルは本来ruby.cに置きたい。 +しかしrb_load()ではPUSH_TAG()などを使わざるを得ない。だから仕方なく +eval.cに置く。でなければ最初から全部eval.cに置くだろう。

+

それで、rb_load_file()だ。

+

rb_load_file() +

+ 865  void
+ 866  rb_load_file(fname)
+ 867      char *fname;
+ 868  {
+ 869      load_file(fname, 0);
+ 870  }

+

(ruby.c) +

+

まるごと委譲。load_file()の第二引数scriptは真偽値で、rubyコマンドの +引数のファイルをロードしているのかどうかを示す。今はそうではなく +ライブラリのロードと考えたいのでscript=0で疊み込もう。 +さらに以下では意味も考え本質的でないものを削ってある。

+

load_file() (simplified edition) +

+static void
+load_file(fname, /* script=0 */)
+    char *fname;
+{
+    VALUE f;
+    {
+        FILE *fp = fopen(fname, “r”);   (A)
+        if (fp == NULL) {
+            rb_load_fail(fname);
+        }
+        fclose(fp);
+    }
+    f = rb_file_open(fname, “r”);       (B)
+    rb_compile_file(fname, f, 1);       ©
+    rb_io_close(f);
+}
+

+

(A) The call to fopen() is to check if the +file can be opened. If there is no problem, it’s immediately closed. +It may seem a little useless but it’s an extremely simple and yet +highly portable and reliable way to do it.

+

(B) The file is opened once again, this time using the Ruby level +library File.open. The file was not opened with File.open from the +beginning so as not to raise any Ruby exception if the file cannot be +opened. Here if any exception occurred we would like to have a +loading error, but getting the errors related to open, for example +Errno::ENOENT, Errno::EACCESS…, would be problematic. We are in +ruby.c so we cannot stop a tag jump.

+

© Using the parser interface rb_compile_file(), the program is +read from an IO object, and compiled in a syntax tree. The syntax +tree is added to ruby_eval_tree so there is no need to get the +result.

+

That’s all for the loading code. Finally, the calls were quite deep so +let’s look at the callgraph of rb_f_require() bellow.

+
+rb_f_require           ....eval.c
+    rb_find_file            ....file.c
+        dln_find_file           ....dln.c
+            dln_find_file_1
+    rb_load
+        rb_load_file            ....ruby.c
+            load_file
+                rb_compile_file     ....parse.y
+        eval_node
+
+

We’ve seen a lot of callgraphs, they are now common sense.

+

The number of open required for loading

+

Like we’ve seen before, there are open used just to check if a file +can be open, but in fact during the loading process other functions +like for example rb_find_file_ext() also do checks using open. How +many times is open() called in the whole process?

+

If you’re wondering that, it’s just a matter of having the right program available to count and see. You can easily find out using a system call tracer. On Linux, the tool to use would be strace; on Solaris, truss; or on BSD, ktrace or truss.

+

というように +OSによって名前がてんでバラバラなのだが、Googleで検索すればすぐ見付かる

+

If you’re using Windows, probably your IDE will have a tracer built in. Well, as my main environment is Linux, I looked using strace.

+

The output is done on stderr so it was redirected using 2>&1.

+
+% strace ruby -e 'require "rational"' 2>&1 | grep '^open'
+open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT
+open("/etc/ld.so.cache", O_RDONLY)      = 3
+open("/usr/lib/libruby-1.7.so.1.7", O_RDONLY) = 3
+open("/lib/libdl.so.2", O_RDONLY)       = 3
+open("/lib/libcrypt.so.1", O_RDONLY)    = 3
+open("/lib/libc.so.6", O_RDONLY)        = 3
+open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
+open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
+open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
+open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
+
+

libc.so.6openまではダイナミックリンクの実装で使っているopenなので +残りのopenは計四回。つまり三回は無駄になっているようだ。

+

Loading of extension libraries

+

rb_f_require()-load_dyna

+

This time we will see the loading of extension libraries. We will +start with rb_f_require()’s load_dyna. However, we do not need the +part about locking anymore so it was removed.

+

rb_f_require()-load_dyna +

+5607  {
+5608      int volatile old_vmode = scope_vmode;
+5609
+5610      PUSH_TAG(PROT_NONE);
+5611      if ((state = EXEC_TAG()) == 0) {
+5612          void *handle;
+5613
+5614          SCOPE_SET(SCOPE_PUBLIC);
+5615          handle = dln_load(RSTRING→ptr);
+5616          rb_ary_push(ruby_dln_librefs, LONG2NUMhandle));
+5617      }
+5618      POP_TAG();
+5619      SCOPE_SET(old_vmode);
+5620  }
+5621  if (state) JUMP_TAG(state);

+

(eval.c) +

+

By now, there is very little here which is novel. タグはイディオム通りの使いかた +しかしていないし、可視性スコープの退避・復帰も見慣れた手法だ。 +All that remains is dln_load(). What on earth is that for? For the answer, continue to the next section.

+

リンクについて復習

+

dln_load()は拡張ライブラリをロードしているわけだが、拡張ライブラリを +ロードするとはどういうことなのだろうか。それを話すにはまず話を思い切り +物理世界方向に巻き戻し、リンクのことから始めなければならない。

+

Cのプログラムをコンパイルしたことはもちろんあると思う。筆者は +Linuxでgccを使っているので、次のようにすれば動くプログラムが +作成できる。

+
+% gcc hello.c
+
+

ファイル名からするときっとこれはHello, World!プログラムなんだろう。 +gccはUNIXではデフォルトでa.outというファイルにプログラムを +出力するので続いて次のように実行できる。

+
+% ./a.out
+Hello, World!
+
+

It prints out just as expected.

+

By the way, what is gcc actually doing here? Usually we just say is “compiles”, but actually it…

+
    +
  1. Preprocesses (cpp)
  2. +
  3. Compiles C into assembly (cc)
  4. +
  5. Assembles the assembly language into machine code (as)
  6. +
  7. Links (ld)
  8. +
+

という四つの段階を通っている。このうちプリプロセス・コンパイル・アセン +ブルまではいろいろなところで説明を見掛けるのだが、なぜかリンクの段階だ +けは明文化されずに終わることが多いようだ。学校の歴史の授業では絶対に +「現代」まで行き着かない、というのと同じようなものだろうか。そこで本書 +ではその断絶を埋めるべく、まずリンクとは何なのか簡単にまとめておくこと +にする。

+

アセンブルまでの段階が完了したプログラムはなんらかの形式の +「オブジェクトファイル」 +になっている。そのような形式でメジャーなものには以下のよう +なものがある。

+
    +
  • ELF, Executable and Linking Format(新しめのUNIX)
  • +
  • a.out, assembler output(比較的古いUNIX)
  • +
  • COFF, Common Object File Format(Win32)
  • +
+

念のため言っておくが、オブジェクトファイル形式のa.outccの +デフォルト出力ファイル名のa.outは全然別物である。例えば今時のLinuxで +普通に作ればELF形式のファイルa.outができる。

+

それで、このオブジェクトファイル形式がどう違うのか、という話はこのさい +どうでもいい。今認識しなければならないのは、これらのオブジェクトファイ +ルはどれも「名前の集合」と考えられるということだ。例えばこのファイルに +存在する関数名や変数名など。

+

またオブジェクトファイルに含まれる名前の集合には二種類がある。即ち

+
    +
  • 必要な名前の集合(例えば内部から呼んでいる外部関数。例:printf)
  • +
  • 提供する名前の集合(例えば内部で定義している関数。例:hello)
  • +
+

である。そしてリンクとは、複数のオブジェクトファイルを集めてきたときに +全てのオブジェクトファイルの「必要な名前の集合」が「提供する名前の集合」 +の中に含まれることを確認し、かつ互いに結び付けることだ。つまり全ての +「必要な名前」から線をひっぱって、どこかのオブジェクトファイルが「提供 +する名前」につなげられるようにしなければいけない(図2)。 +このことを用語を使って +言えば、未定義シンボルを解決する(resolving undefined symbol)、となる。

+

+

(link)
+Figure 2: オブジェクトファイルとリンク

+

+

論理的にはそういうことだが、現実にはそれだけではプログラムは走らないわ +けだ。少なくともCのプログラムは走らない。名前をアドレス(数)に変換し +てもらわなければ動けないからだ。

+

そこで論理的な結合の次には物理的な結合が必要になる。オブジェクトファイ +ルを現実のメモリ空間にマップし、全ての名前を数で置き換えないといけない。 +具体的に言えば関数呼び出し時のジャンプ先アドレスを調節したりする。

+

そしてこの二つの結合をいつやるかによってリンクは二種類に分かれる。即ち +スタティックリンクとダイナミックリンクである。スタティックリンクはコン +パイル時に全段階を終了してしまう。一方ダイナミックリンクは結合のうちい +くらかをプログラムの実行時まで遅らせる。そしてプログラムの実行時になっ +て初めてリンクが完了する。

+

もっともここで説明したのは非常に単純な理想的モデルであって現実をかなり +歪曲している面がある。論理結合と物理結合はそんなにキッパリ分かれるもの +ではないし、「オブジェクトファイルは名前の集合」というのもナイーブに過 +ぎる。しかしなにしろこのあたりはプラットフォームによってあまりに動作が +違いすぎるので、真面目に話していたら本がもう一冊書けてしまう。 +現実レベルの知識を得るためにはさらに +『エキスパートCプログラミング』\footnote{『エキスパートCプログラミング』Peter van der Linden著、梅原系訳、アスキー出版局、1996} +『Linkers&Loaders』@footnote{『Linkers&Loaders』John R.Levine著、榊原一矢監訳 ポジティブエッジ訳、オーム社、2001} +あたりも読んでおくとよい。

+

真にダイナミックなリンク

+

And finally we get into our main topic. The “dynamic” in “dynamic linking” naturally means it “occurs at execution time”, but what people usually refer to as “dynamic linking” is pretty much decided already at compile time. For example, the names of the needed functions, and which library they can be found in, are already known. For instance, if you need cos(), you know it’s in libm, so you use gcc -lm. If you didn’t specify the correct library at compile time, you’d get a link error.

+

But extension libraries are different. Neither the names of the needed functions, or the name of the library which defines them are known at compile time. +文字列をプログラムの実 +行中に組み立ててロード・リンクしなければいけないのである。つまり先程の +言葉で言う「論理結合」すらも全て実行時に行わなければならない。そのため +には普通に言うところのダイナミックリンクとはまた少し違う仕組みが必要に +なる。

+

この操作、つまり実行時に全てを決めるリンク、のことを普通は +「動的ロード(dynamic load)」と呼ぶ。本書の用語遣いからいくと +「ダイナミックロード」と片仮名にひらくべきなのだろうが、 +ダイナミックリンクと +ダイナミックロードだと紛らわしいのであえて漢字で「動的ロード」とする。

+

動的ロードAPI

+

概念の説明は以上だ。あとはその動的ロードをどうやればいいかである。とは +言っても難しいことはなくて、普通はシステムに専用APIが用意されているの +でこちらは単にそれを呼べばいい。

+

例えばUNIXならわりと広範囲にあるのがdlopenというAPIである。ただし +「UNIXならある」とまでは言えない。例えばちょっと前のHP-UXには全く違う +インターフェイスがあるしMac OS XだとNeXT風のAPIを使う。また同じ +dlopenでもBSD系だとlibcにあるのにLinuxだとlibdlとして外付けになっ +ている、などなど、壮絶なまでに移植性がない。いちおうUNIX系と並び称され +ていてもこれだけ違うわけだから、他のOSになれば全然違うのもあたりまえで +ある。同じAPIが使われていることはまずありえない。

+

そこでrubyはどうしているかというと、その全然違うインターフェイスを吸収 +するためにdln.cというファイルを用意している。dlnはdynamic linkの略だろ +う。dln_load()はそのdln.cの関数の一つなのである。

+

そんなふうに全くバラバラの動的ロードAPIだが、せめてもの救 +いはAPIの使用パターンが全く同じだということだ。どのプラットフォームだ +ろうと

+
    +
  1. ライブラリをプロセスのアドレス空間にマップする
  2. +
  3. ライブラリに含まれる関数へのポインタを取る
  4. +
  5. ライブラリをアンマップ
  6. +
+

という三段階で構成されている。例えばdlopen系APIならば

+
    +
  1. dlopen
  2. +
  3. dlsym
  4. +
  5. dlclose
  6. +
+

が対応する。Win32 APIならば

+
    +
  1. LoadLibrary(またはLoadLibraryEx)
  2. +
  3. GetProcAddress
  4. +
  5. FreeLibrary
  6. +
+

が対応する。

+

最後に、このAPI群を使ってdln_load()が何をするかを話そう。これが実は、 +Init_xxxx()の呼び出しなのだ。ここに至ってついにruby起動から終了までの全 +過程が欠落なく描けるようになる。即ち、rubyは起動すると評価器を初期化し +なんらかの方法で受け取ったメインプログラムの評価を開始する。その途中で +requireloadが起こるとライブラリをロードし制御を移す。制御を移す、と +は、Rubyライブラリならばパースして評価することであり、拡張ライブラリな +らばロード・リンクしてInit_xxxx()を呼ぶことである。

+

dln_load()

+

ようやくdln_load()の中身にたどりつけた。dln_load()も長い関数だが、これ +また理由があって構造は単純である。まず概形を見てほしい。

+

dln_load()(概形) +

+void*
+dln_load(file)
+    const char file;
+{
+#if defined _WIN32 && !defined CYGWIN
+    Win32 APIでロード
+#else
+    プラットフォーム独立の初期化
+#ifdef 各プラットフォーム
+    ……プラットフォームごとのルーチン……
+#endif
+#endif
+#if !defined(AIX) && !defined(NeXT)
+  failed:
+    rbloaderror(“%s – %s”, error, file);
+#endif
+    return 0;                   / dummy return */
+}
+

+

このようにメインとなる部分がプラットフォームごとに完璧に分離しているため、 +考えるときは一つ一つのプラットフォームのことだけを考えていればいい。 +サポートされているAPIは以下の通りだ。

+
    +
  • dlopen(多くのUNIX)
  • +
  • LoadLibrary(Win32)
  • +
  • shl_load(少し古いHP-UX)
  • +
  • a.out(かなり古いUNIX)
  • +
  • rld_load(NeXT4未満)
  • +
  • dyld(NeXTまたはMac OS X)
  • +
  • get_image_symbol(BeOS)
  • +
  • GetDiskFragment(Mac OS 9以前)
  • +
  • load(少し古いAIX)
  • +
+

dln_load()-dlopen()

+

First, let’s start with the API code for the dlopen series.

+

dln_load()-dlopen() +

+1254  void*
+1255  dln_load(file)
+1256      const char file;
+1257  {
+1259      const char *error = 0;
+1260  #define DLN_ERROR() (error = dln_strerror(),\
+                           strcpy(ALLOCA_N(char, strlen(error) + 1), error))
+1298      char *buf;
+1299      / Init_xxxxという文字列をbufに書き込む(領域はalloca割り当て) */
+1300      init_funcname(&buf, file);

+

1304 { +1305 void handle; +1306 void (init_fct)(); +1307 +1308 #ifndef RTLD_LAZY +1309 # define RTLD_LAZY 1 +1310 #endif +1311 #ifndef RTLD_GLOBAL +1312 # define RTLD_GLOBAL 0 +1313 #endif +1314 +1315 /* (A)ライブラリをロード / +1316 if ((handle = (void)dlopen(file, RTLD_LAZY | RTLD_GLOBAL)) + == NULL) { +1317 error = dln_strerror(); +1318 goto failed; +1319 } +1320 + /* (B)Init_xxxx()へのポインタを取る / +1321 init_fct = (void()())dlsym(handle, buf); +1322 if (init_fct == NULL) { +1323 error = DLN_ERROR(); +1324 dlclose(handle); +1325 goto failed; +1326 } +1327 /* ©Init_xxxx()を呼ぶ / +1328 (init_fct)(); +1329 +1330 return handle; +1331 }

+

1576 failed: +1577 rb_loaderror(“%s – %s”, error, file); +1580 }

+

(dln.c) +

+

(A)dlopen()の引数のRTLD_LAZYは「実際に関数を要求したときに +未解決シンボルを解決する」ことを示す。返り値はライブラリを識別する +ための印(ハンドル)で、dl*()には常にこれを渡さないといけない。

+

(B)dlsym()はハンドルの示すライブラリから関数ポインタを取る。返り値が +NULLなら失敗だ。ここでInit_xxxx()へのポインタを取り、呼ぶ。

+

dlclose()の呼び出しはない。Init_xxxx()の中でロードした +ライブラリの関数ポインタを +返したりしているはずだが、dlclose()するとライブラリ全体が使えなくなって +しまうのでまずいのだ。つまりプロセスが終了するまでdlclose()は呼べない。

+

dln_load()-Win32

+

Win32ではLoadLibrary()GetProcAddress()を使う。 +MSDNにも載っているごく一般的なWin32 APIである。

+

dln_load()-Win32 +

+1254  void*
+1255  dln_load(file)
+1256      const char *file;
+1257  {

+

1264 HINSTANCE handle; +1265 char winfile[MAXPATHLEN]; +1266 void (init_fct)(); +1267 char *buf; +1268 +1269 if (strlen(file) >= MAXPATHLEN) rb_loaderror(“filename too long”); +1270 +1271 / "Init_xxxx"という文字列をbufに書き込む(領域はalloca割り当て) / +1272 init_funcname(&buf, file); +1273 +1274 strcpy(winfile, file); +1275 +1276 / ライブラリをロード / +1277 if ((handle = LoadLibrary(winfile)) == NULL) { +1278 error = dln_strerror(); +1279 goto failed; +1280 } +1281 +1282 if ((init_fct = (void()())GetProcAddress(handle, buf)) == NULL) { +1283 rb_loaderror(“%s – %s\n%s”, dln_strerror(), buf, file); +1284 } +1285 +1286 /* Init_xxxx()を呼ぶ / +1287 (init_fct)(); +1288 return handle;

+

1576 failed: +1577 rb_loaderror(“%s – %s”, error, file); +1580 }

+

(dln.c) +

+

LoadLibrary()してGetProcAddress()。ここまでパターンが同じだと +言うこともないので、終わってしまうことにしよう。

+ + + +
+ + diff --git a/htmls/method.html b/htmls/method.html new file mode 100644 index 0000000..ac0d3d3 --- /dev/null +++ b/htmls/method.html @@ -0,0 +1,921 @@ + + + + + Chapter 15: Methods | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 15: Methods

+

In this chapter, I’ll talk about method searching and invoking.

+

Searching methods

+

Terminology

+

In this chapter, both method calls and method definitions are discussed, +and there will appear really various “arguments”. Therefore, to make it not +confusing, let’s strictly define terms here:

+
+m(a)          # a is a "normal argument"
+m(*list)      # list is an "array argument"
+m(&block)     # block is a "block argument"
+
+def m(a)      # a is a "normal parameter"
+def m(a=nil)  # a is an "option parameter", nil is "it default value".
+def m(*rest)  # rest is a "rest parameter"
+def m(&block) # block is a "block parameter"
+
+

In short, they are all “arguments” when passing and “parameters” when receiving, +and each adjective is attached according to its type.

+

However, among the above things, the “block arguments” and the “block +parameters” will be discussed in the next chapter.

+

Investigation

+

▼The Source Program

+ +
+obj.method(7,8)
+
+

▼Its 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
+    ]
+
+

The node for a method call is NODE_CALL. +The nd_args holds the arguments as a list of NODE_ARRAY.

+

Additionally, as the nodes for method calls, there are also NODE_FCALL and NODE_VCALL. +NODE_FCALL is for the “method(args)” form, +NODE_VCALL corresponds to method calls in the “method” form that is the same +form as the local variables. +FCALL and VCALL could actually be integrated into one, +but because there’s no need to prepare arguments when it is VCALL, +they are separated from each other only in order to save both times and memories for it.

+

Now, let’s look at the handler of NODE_CALL in rb_eval().

+

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)
+
+

The problems are probably the three macros, BEGIN_CALLARGS SETUP_ARGS() END_CALLARGS. +It seems that rb_eval() is to evaluate the receiver and +rb_call() is to invoke the method, we can roughly imagine that the evaluation +of the arguments might be done in the three macros, but what is actually done? +BEGIN_CALLARGS and END_CALLARGS are difficult to understand before talking +about the iterators, so they are explained in the next chapter “Block”. +Here, let’s investigate only about SETUP_ARGS().

+

SETUP_ARGS()

+

SETUP_ARGS() is the macro to evaluate the arguments of a method. +Inside of this macro, as the comment in the original program says, +the variables named argc and argv are used, +so they must be defined in advance. +And because it uses TMP_ALLOC(), it must use TMP_PROTECT in advance. +Therefore, something like the following is a boilerplate:

+
+int argc; VALUE *argv;   /* used in SETUP_ARGS */
+TMP_PROTECT;
+
+SETUP_ARGS(args_node);
+
+

args_node is (the node represents) the arguments of the method, +turn it into an array of the values obtained by evaluating it, +and store it in argv. +Let’s look at it:

+

SETUP_ARGS()

+ +
+1780  #define SETUP_ARGS(anode) do {\
+1781      NODE *n = anode;\
+1782      if (!n) {\                             no arguments
+1783          argc = 0;\
+1784          argv = 0;\
+1785      }\
+1786      else if (nd_type(n) == NODE_ARRAY) {\  only normal arguments
+1787          argc=n->nd_alen;\
+1788          if (argc > 0) {\   arguments present
+1789              int i;\
+1790              n = anode;\
+1791              argv = TMP_ALLOC(argc);\
+1792              for (i=0;i<argc;i++) {\
+1793                  argv[i] = rb_eval(self,n->nd_head);\
+1794                  n=n->nd_next;\
+1795              }\
+1796          }\
+1797          else {\            no arguments
+1798              argc = 0;\
+1799              argv = 0;\
+1800          }\
+1801      }\
+1802      else {\                                 both or one of an array argument
+1803          VALUE args = rb_eval(self,n);\      and a block argument
+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)
+
+

This is a bit long, but since it clearly branches in three ways, not so terrible +actually. The meaning of each branch is written as comments.

+

We don’t have to care about the case with no arguments, the two rest branches +are doing similar things. Roughly speaking, what they are doing consists of +three steps:

+
    +
  • allocate a space to store the arguments
  • +
  • evaluate the expressions of the arguments
  • +
  • copy the value into the variable space
  • +
+

If I write in the code (and tidy up a little), it becomes as follows.

+
+/***** else if clause、argc!=0 *****/
+int i;
+n = anode;
+argv = TMP_ALLOC(argc);                         /* 1 */
+for (i = 0; i < argc; i++) {
+    argv[i] = rb_eval(self, n->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 */
+
+

TMP_ALLOC() is used in the else if side, +but ALLOCA_N(), which is ordinary alloca(), is used in the else side. +Why? +Isn’t it dangerous in the C_ALLOCA environment because alloca() is +equivalent to malloc() ?

+

The point is that “in the else side the values of arguments are also stored in +args”. If I illustrate, it would look like Figure 1.

+
+

(anchor)
+Figure 1: All right if it is in the heap

+
    +
  • パターン case
  • +
  • 側 side
  • +
  • 同じ内容 the same contents
  • +
  • GCのルートとなる(主にスタック) will be the roots of GC (mainly in the stack)
  • +
  • GCのルートとならない(主にヒープ)will not be the roots of GC (mainly in the heap) +
+ +

If at least one VALUE is on the stack, others can be successively marked through +it. This kind of VALUE plays a role to tie up the other VALUEs to the stack +like an anchor. Namely, it becomes “anchor VALUE”. +In the else side, args is the anchor VALUE.

+

For your information, “anchor VALUE” is the word just coined now.

+

rb_call()

+

SETUP_ARGS() is relatively off the track. Let’s go back to the main line. The +function to invoke a method, it is rb_call(). In the original there’re codes +like raising exceptions when it could not find anything, as usual I’ll skip all +of them.

+

rb_call() (simplified)

+ +
+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;
+
+    /* search over 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 {
+        /* cache miss, searching step-by-step  */
+        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 way of searching methods was discussed in chapter 2: “Object”. +It is following its superclasses and searching m_tbl. This is done by +search_method().

+

The principle is certainly this, but when it comes to the phase to execute +actually, if it searches by looking up its hash many times for each method call, +its speed would be too slow. +To improve this, in ruby, once a method is called, it will be cached. +If a method is called once, it’s often immediately called again. +This is known as an experiential fact and this cache records the high hit rate.

+

What is looking up the cache is the first half of rb_call(). Only with

+
+ent = cache + EXPR1(klass, mid);
+
+

this line, the cache is searched. +We’ll examine its mechanism in detail later.

+

When any cache was not hit, the next rb_get_method_body() searches the class +tree step-by-step and caches the result at the same time. +Figure 2 shows the entire flow of searching.

+
+

(msearch)
+Figure 2: Method Search

+
    +
  • キャッシュ cache
  • +
  • クラスツリー the class tree +
+ +

Method Cache

+

Next, let’s examine the structure of the method cache in detail.

+

▼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)
+
+

If I describe the mechanism shortly, it is a hash table. I mentioned that the +principle of the hash table is to convert a table search to an indexing of an +array. Three things are necessary to accomplish: an array to store the data, +a key, and a hash function.

+

First, the array here is an array of struct cache_entry. And the method is +uniquely determined by only the class and the method name, so these two become +the key of the hash calculation. The rest is done by creating a hash function +to generate the index (0x000 ~ 0x7ff) of the cache array form the key. +It is EXPR1(). Among its arguments, c is the class object and m is the +method name (ID). (Figure 3)

+
+

(mhash)
+Figure 3: Method Cache

+
    +
  • クラス、メソッドID class, method ID +
+ +

However, EXPR1() is not a perfect hash function or anything, so a different +method can generate the same index coincidentally. But because this is nothing +more than a cache, conflicts do not cause a problem. +It just slows its performance down a little.

+

The effect of Method Cache

+

By the way, how much effective is the method cache in actuality? +We could not be convinced just by being said “it is known as …”. +Let’s measure by ourselves.

+ + + + + + + + + + + + + + + + + + + + + +
Type Program Hit Rate
generating LALR parser racc ruby.y 99.9%
generating a mail thread a mailer 99.1%
generating a document rd2html rubyrefm.rd 97.8%
+

Surprisingly, in all of the three experiments the hit rate is more than 95%. +This is awesome. Apparently, the effect of “it is know as …” is outstanding.

+

Invocation

+

rb_call0()

+

There have been many things and finally we arrived at the method invoking. +However, this rb_call0() is huge. As it’s more than 200 lines, it would come +to 5,6 pages. If the whole part is laid out here, it would be disastrous. Let’s +look at it by dividing into small portions. Starting with the outline:

+

rb_call0() (Outline)

+ +
+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)) {
+              /* ... main process ... */
+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, an ITER is pushed and whether or not the method is an iterator is +finally fixed. As its value is used by the PUSH_FRAME() which comes +immediately after it, PUSH_ITER() needs to appear beforehand. +PUSH_FRAME() will be discussed soon.

+

And if I first describe about the “… main process …” part, +it branches based on the following node types +and each branch does its invoking process.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NODE_CFUNC methods defined in C
NODE_IVAR attr_reader
NODE_ATTRSET attr_writer
NODE_SUPER super
NODE_ZSUPER super without arguments
NODE_DMETHOD invoke UnboundMethod
NODE_BMETHOD invoke Method
NODE_SCOPE methods defined in Ruby
+

Some of the above nodes are not explained in this book but not so important and +could be ignored. The important things are only NODE_CFUNC, NODE_SCOPE and +NODE_ZSUPER.

+

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, we’d like to make sure the entire FRAME is allocated on the stack. +This is identical to module_setup(). The rest is basically just doing +ordinary initializations.

+

If I add one more description, the flag FRAME_ALLOCA indicates the allocation +method of the FRAME. FRAME_ALLOCA obviously indicates “it is on the stack”.

+

rb_call0()NODE_CFUNC

+

A lot of things are written in this part of the original code, +but most of them are related to trace_func and substantive code is only the +following line:

+

rb_call0()NODE_CFUNC (simplified)

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

Then, as for call_cfunc()

+

call_cfunc() (simplified)

+ +
+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)
+
+

As shown above, it branches based on the argument count. +The maximum argument count is 15.

+

Note that neither SCOPE or VARS is pushed when it is NODE_CFUNC. It makes +sense because if a method is defined in C it would not use the Ruby’s local +variables. But it simultaneously means that if the “current” local variables are +accessed by C, they are actually the local variables of the previous FRAME. +And in some places, say, rb_svar (eval.c), it is actually done.

+

rb_call0()NODE_SCOPE

+

NODE_SCOPE is to invoke a method defined in Ruby. +This part forms the foundation of Ruby.

+

rb_call0()NODE_SCOPE (outline)

+ +
+4568  case NODE_SCOPE:
+4569    {
+4570        int state;
+4571        VALUE *local_vars;  /* OK */
+4572        NODE *saved_cref = 0;
+4573
+4574        PUSH_SCOPE();
+4575
+            /* (A)forward CREF */
+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)initialize ruby_scope->local_vars */
+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)assign the arguments to the local variables …… */
+
+4666            if (trace_func) {
+4667                call_trace_func("call", b2, recv, id, klass);
+4668            }
+4669            ruby_last_node = b2;
+                /* (D)method body */
+4670            result = rb_eval(recv, body);
+4671        }
+4672        else if (state == TAG_RETURN) { /* back via 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) CREF forwarding, which was described at the section of constants in the +previous chapter. +In other words, cbase is transplanted to FRAME from the method entry.

+

(B) The content here is completely identical to what is done at module_setup(). +An array is allocated at local_vars of SCOPE. With this and +PUSH_SCOPE() and PUSH_VARS(), the local variable scope creation is completed. +After this, one can execute rb_eval() in the exactly same environment as the +interior of the method.

+

(C) This sets the received arguments to the parameter variables. +The parameter variables are in essence identical to the local variables. Things +such as the number of arguments are specified by NODE_ARGS, all it has to do +is setting one by one. Details will be explained soon. And,

+

(D) this executes the method body. Obviously, the receiver (recv) becomes +self. In other words, it becomes the first argument of rb_eval(). After all, +the method is completely invoked.

+

Set Parameters

+

Then, we’ll examine the totally skipped part, which sets parameters. +But before that, I’d like you to first check the syntax tree of the method 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 is the node to specify the parameters of a method. +I aggressively dumped several things, +and it seemed its members are used as follows:

+ + + + + + + + + + + + + +
nd_cnt the number of the normal parameters
nd_rest the variable ID of the rest parameter. -1 if the rest parameter is missing
nd_opt holds the syntax tree to represent the default values of the option parameters. a list of NODE_BLOCK
+

If one has this amount of the information, the local variable ID for each +parameter variable can be uniquely determined. +First, I mentioned that 0 and 1 are always $_ and $~. +In 2 and later, the necessary number of ordinary parameters are in line. +The number of option parameters can be determined by the length of NODE_BLOCK. +Again next to them, the rest-parameter comes.

+

For example, if you write a definition as below,

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

local variable IDs are assigned as follows.

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

Are you still with me? +Taking this into considerations, let’s look at the code.

+

rb_call0()NODE_SCOPE −assignments of arguments

+ +
+4601  if (nd_type(body) == NODE_ARGS) { /* no body */
+4602      node = body;           /* NODE_ARGS */
+4603      body = 0;              /* the method body */
+4604  }
+4605  else if (nd_type(body) == NODE_BLOCK) { /* has body */
+4606      node = body->nd_head;  /* NODE_ARGS */
+4607      body = body->nd_next;  /* the method body */
+4608  }
+4609  if (node) {  /* have somewhat 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) {  /* no rest parameter */
+              /* counting the number of parameters */
+4620          int opt = i;   /* the 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) {
+4628              rb_raise(rb_eArgError,
+4629                  "wrong number of arguments(%d for %d)", argc, opt);
+4630          }
+              /* assigning at the second time in rb_call0 */
+4631          ruby_frame->argc = opt;
+4632          ruby_frame->argv = local_vars+2;
+4633      }
+4634
+4635      if (local_vars) { /* has parameters */
+4636          if (i > 0) {             /* has normal parameters */
+4637              /* +2 to skip the spaces for $_ and $~ */
+4638              MEMCPY(local_vars+2, argv, VALUE, i);
+4639          }
+4640          argv += i; argc -= i;
+4641          if (node->nd_opt) {      /* has option 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) { /* has rest parameter */
+4655              VALUE v;
+4656
+                  /* make an array of the remainning parameters and assign it to a 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)
+
+

Since comments are added more than before, +you might be able to understand what it is doing by following step-by-step.

+

One thing I’d like to mention is about argc and argv of ruby_frame. +It seems to be updated only when any rest-parameter does not exist, +why is it only when any rest-parameter does not exist?

+

This point can be understood by thinking about the purpose of argc and argv. +These members actually exist for super without arguments. +It means the following form:

+
+super
+
+

This super has a behavior to directly pass the parameters of the currently executing method. +In order to enable to pass at the moment, the arguments are saved in ruby_frame->argv.

+

Going back to the previous story here, +if there’s a rest-parameter, passing the original parameters list somehow seems more convenient. +If there’s not, the one after option parameters are assigned seems better.

+
+def m(a, b, *rest)
+  super     # probably 5, 6, 7, 8 should be passed
+end
+m(5, 6, 7, 8)
+
+def m(a, b = 6)
+  super     # probably 5, 6 should be passed
+end
+m(5)
+
+

This is a question of which is better as a specification rather than “it must be”. +If a method has a rest-parameter, +it supposed to also have a rest-parameter at superclass. +Thus, if the value after processed is passed, there’s the high possibility of being inconvenient.

+

Now, I’ve said various things, but the story of method invocation is all done. +The rest is, as the ending of this chapter, looking at the implementation of +super which is just discussed.

+

super

+

What corresponds to super are NODE_SUPER and NODE_ZSUPER. +NODE_SUPER is ordinary super, +and NODE_ZSUPER is super without arguments.

+

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)case when super is forbidden */
+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)setup or evaluate parameters */
+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)yet mysterious 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)
+
+

For super without arguments, I said that ruby_frame->argv is directly used +as arguments, this is directly shown at (B).

+

(C) just before calling rb_call(), doing PUSH_ITER(). +This is also what cannot be explained in detail, but in this way the block +passed to the current method can be handed over to the next method (meaning, the +method of superclass that is going to be called).

+

And finally, (A) when ruby_frame->last_class is 0, calling super seems forbidden. +Since the error message says “must be enabled by rb_enable_super()”, +it seems it becomes callable by calling rb_enable_super(). +
((errata: The error message “must be enabled by rb_enable_super()” exists not +in this list but in rb_call_super().)) +
Why?

+

First, If we investigate in what kind of situation last_class becomes 0, +it seems that it is while executing the method whose substance is defined in C (NODE_CFUNC). +Moreover, it is the same when doing alias or replacing such method.

+

I’ve understood until there, but even though reading source codes, I couldn’t +understand the subsequents of them. +Because I couldn’t, I searched “rb_enable_super” over the ruby’s +mailing list archives and found it. +According to that mail, the situation looks like as follows:

+

For example, there’s a method named String.new. +Of course, this is a method to create a string. +String.new creates a struct of T_STRING. +Therefore, you can expect that the receiver is always of T_STRING when +writing an instance methods of String.

+

Then, super of String.new is Object.new. +Object.new create a struct of T_OBJECT. +What happens if String.new is replaced by new definition and super is called?

+
+def String.new
+  super
+end
+
+

As a consequence, an object whose struct is of T_OBJECT but whose class is String is created. +However, a method of String is written with expectation of a struct of T_STRING, +so naturally it downs.

+

How can we avoid this? The answer is to forbid to call any method expecting a +struct of a different struct type. +But the information of “expecting struct type” is not attached to method, +and also not to class. +For example, if there’s a way to obtain T_STRING from String class, +it can be checked before calling, but currently we can’t do such thing. +Therefore, as the second-best plan, +“super from methods defined in C is forbidden” is defined. +In this way, if the layer of methods at C level is precisely created, +it cannot be got down at least. +And, when the case is “It’s absolutely safe, so allow super”, +super can be enabled by calling rb_enable_super().

+

In short, the heart of the problem is miss match of struct types. +This is the same as the problem that occurs at the allocation framework.

+

Then, how to solve this is to solve the root of the problem that “the class +does not know the struct-type of the instance”. +But, in order to resolve this, at least new API is necessary, +and if doing more deeply, compatibility will be lost. +Therefore, for the time being, the final solution has not decided yet.

+ + + +
+ + diff --git a/htmls/minimum.html b/htmls/minimum.html new file mode 100644 index 0000000..3d50c18 --- /dev/null +++ b/htmls/minimum.html @@ -0,0 +1,1251 @@ + + + + + A Minimal Introduction to Ruby | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Sebastian Krause

+

Chapter 1: Introduction

+

A Minimal Introdution to Ruby

+

Here the Ruby prerequisites are explained, which one needs to know +in order to understand the first section. +I won’t point out programming techniques or points one should be +careful about. So don’t think you’ll be able to write Ruby programs just because +you read this chapter. Readers who have prior experience with Ruby +can skip this chapter.

+

We will talk about grammar extensively in the second section, hence +I won’t delve into the finer points of grammar here. From hash literals +and such I’ll show only the most widely used notations. On principle +I won’t omit things even if I can. This way the syntax becomes more simple. +I won’t always say “We can omit this”.

+

Objects

+

Strings

+

Everything that can be manipulated in a Ruby program is an object. +There are no primitives as Java’s int and long. For instance +if we write as below it denotes a string object with content content.

+
+"content"
+
+

I casually called it a string object but to be precise this is an expression which generates +a string object. Therefore if we write it several times each time +another string object is generated.

+
+"content"
+"content"
+"content"
+
+

Here three string objects with content content are generated.

+

Besides, a program won’t do any good without some output. Let’s show how to print on the terminal.

+
+p("content")   # Shows "content"
+
+

Everything after an # is a comment. From now on, I’ll put the result +of an expression in a comment behind.

+

p(……) calls the function p. It displays arbitrary objects “as such”. +It’s basically a debugging function.

+

Precisely speaking, there are no functions in Ruby, but just for now +we can think of it as a function.

+

Various Literals

+

Now, let’s explain some more the expressions which directly generate objects, +the so-called literals. +First the integers and floating point numbers.

+
+# Integer
+1
+2
+100
+9999999999999999999999999   # Arbitrarily big integers
+
+# Float
+1.0
+99.999
+1.3e4     # 1.3×10^4
+
+

Don’t forget that these are all expressions which generate objects. +I’m repeating myself but there are no primitives in Ruby.

+

Below an array object is generated.

+
+[1, 2, 3]
+
+

This program generates an array which consists of the three integers +1, 2 and 3 in that order. As the elements of an array can be arbitrary +objects the following is also possible.

+
+[1, "string", 2, ["nested", "array"]]
+
+

And finally, a hash table is generated by the expression below.

+
+{"key"=>"value", "key2"=>"value2", "key3"=>"value3"}
+
+

A hash table is a structure which establishes a one-on-one relation between pairs of +arbitrary objects. The above line creates a table which stores the following table.

+
+"key"   →  "value"
+"key2"  →  "value2"
+"key3"  →  "value3"
+
+

If we ask the hash table above “What’s corresponding to key?”, it’ll +answer “That’s value.” How can we ask? We use methods.

+

Method Calls

+

We can call methods on an object. In C++ Jargon they are member functions. +I don’t think it’s necessary to explain what a method is. I’ll just explain +the notation.

+
+"content".upcase()
+
+

Here the upcase method is called on a string object ( with content content). +As upcase is a method which +returns a new string with the small letters replaced by capital letters +we get the following result.

+
+p("content".upcase())   # Shows "CONTENT"
+
+

Method calls can be chained.

+
+"content".upcase().downcase()
+
+

Here the method downcase is called on the return value of "content".upcase().

+

There are no public fields (member variables) as in Java or C++ (Note: need to check this). The object interface consists of methods only.

+

The Program

+

Top Level

+

In Ruby we can just write expressions and it becomes a program. +One doesn’t need to define a main() as in C++ or Java.

+
+p("content")
+
+

This is a complete Ruby program. If we put this into a file called +first.rb we can execute it from the command line as follows.

+
+% ruby first.rb
+"content"
+
+

With the -e option of the ruby program we don’t even need to create a file.

+
+% ruby -e 'p("content")'
+"content"
+
+

By the way, the place where p is written is the lowest level of the program, +or the highest level from the program’s standpoint. Hence it’s called the +toplevel. +The existence of a toplevel is a characteristic trait of a scripting language.

+

In Ruby, one line is usually one statement. A semicolon at the end isn’t necessary. +Therefore the program below is interpreted as three statements.

+
+p("content")
+p("content".upcase())
+p("CONTENT".downcase())
+
+

When we execute it it looks like this.

+
+% ruby second.rb
+"content"
+"CONTENT"
+"content"
+
+

Local Variables

+

In Ruby all variables and constants store references to objects. +That’s why one can’t copy the content by assigning one variable to another variable. +Think of object type variables in Java or pointers in C++. But you can’t change the value +of these pointers.

+

In Ruby one can tell the scope of a variable by its name’s first letter. +Local variables start with a small letter or an underscore. One can write +an “=” for variable assignment.

+
+str = "content"
+arr = [1,2,3]
+
+

An initial assignment serves as declaration, an explicit declaration is +not necessary. Because variables don’t have a type we can assign any type without +distinction. The program below is completely legal.

+
+lvar = "content"
+lvar = [1,2,3]
+lvar = 1
+
+

But just because we can we shouldn’t necessarily do it. If different +objects are put in one variable it tends to become difficult to read. In a +real world Ruby program one doesn’t do this kind of things without a good reason. +The above was just an example for the sake of it.

+

Variable reference has also a pretty straightforward notation.

+
+str = "content"
+p(str)           # Shows "content"
+
+

Now let’s look at how a variable stores a reference.

+
+a = "content"
+b = a
+c = b
+
+

After we execute this program all three local variables a b c +point to the same object, a string object with content "content"

+

+

(reference)
+Figure 1: Ruby variables store references to objects

+

+

Besides, these variables are called local. Hence there should be a scope +but we cannot talk about this scope without reading a bit further. +Let’s say for now that the top level is one local scope.

+

Constants

+

Constants start with a capital letter. They can only be assigned +once (at their creation).

+
+Const = "content"
+PI = 3.1415926535
+
+p(Const)   # Shows "content"
+
+

I’d like to say that if we assign twice an error occurs. But there +is just a warning, not an error. That’s because of applications +which use Ruby, for instance development environments. There shouldn’t +be an error when they load the same file twice. I recognize that +it had to be that way for practicality but there really should be an error. +Up until version 1.1 there really was an error.

+
+C = 1
+C = 2   # There is a warning but ideally there should be an error.
+
+

A lot of people are fooled by the word constant. +A constant only does not switch objects once it is assigned. +But the object itself might as well change. The term “read only” +might capture the concept better than “constant”.

+

By the way, to indicate that an object itself shouldn’t be changed +another means is used: freeze.

+

+

(const)
+Figure 2: constant means read only

+

+

And we cannot talk about the scope yet. We talk about it later in +the context of classes.

+

Control Structures

+

Unfortunately Ruby has a wide abundance of control structures. +For the time being we pretend there are just if and while.

+
+if i < 10 then
+  # body
+end
+
+while i < 10 do
+  # body
+end
+
+

Only false and nil are false in a conditional expression, all +other various objects are true. 0 or the empty string are also true of course.

+

By the way, it wouldn’t be wise if there were just false, there is also true. +And it is of course true.

+

Classes and Methods

+

Classes

+

In object orientation methods belong to objects, in a perfect +world, though. But in a normal program there are a lot of objects which have the +same set of methods. Usually a mechanism like classes or +multimethods is used to get rid of the duplication of definitions.

+

In Ruby the traditional concept of classes is used to bind objects and +methods together. Namely every object belongs to a class, the methods +which can be called are determined by the class. Hence a method is +called an instance of a class.

+

For example the string "str" is called an instance of the class String. +And in this class String the methods upcase, downcase, strip and +many others are defined. So it looks as if each string object has all these +methods.

+
+# They all belong to the String class,
+# hence the same methods are defined
+       "content".upcase()
+"This is a pen.".upcase()
+    "chapter II".upcase()
+
+       "content".length()
+"This is a pen.".length()
+    "chapter II".length()
+
+

By the way, what happens if the called method isn’t defined? +In a static language a compiler error occurs but in Ruby there +is a runtime exception. Let’s try it out. For this kind of programs the +-e option is handy.

+
+% ruby -e '"str".bad_method()'
+-e:1: undefined method `bad_method' for "str":String (NoMethodError)
+
+

When the method isn’t found there’s apparently a NoMethodError.

+

Always talking about “the upcase method of String” and such is cumbersome. +Let’s introduce a special notation String#upcase refers to the method +upcase defined in the class String.

+

By the way, if we write String.upcase it has a completely different +meaning in the Ruby world. What could that be? I explain it in the +next paragraph.

+

Class Definition

+

Up to now we talked about already defined classes. +We can of course also define our own classes. +To define classes we use the word class.

+
+class C
+end
+
+

This is the definition of a new class C. After we defined it we +can use it as follows.

+
+class C
+end
+c = C.new()   # create an instance of C and assign it to the variable c
+
+

Note that the notation for creating a new instance is not new C. +The astute reader might think: +Hmm, this C.new() really looks like a method call. +In Ruby the object generating expressions are indeed just methods.

+

In Ruby class names and constant names are the same. But what is +contained in a class name, where there’s a constant with the same name? It’s the class. +In Ruby all things which a program can manipulate are objects. So +of course classes are also expressed as objects. Let’s call these +class objects. Every class is an instance of the class Class.

+

In other words a class statement creates a new class object and +it assigns a constant named +with the classname to the class. On the other hand +the generation of an instance references this constant and calls a method +on this object ( usually new). If we look at the example below, it’s +pretty obvious that the creation of an instance doesn’t differ +from a normal method call.

+
+S = "content"
+class C
+end
+
+S.upcase()  # Get the object the constant S points to and call upcase
+C.new()     # Get the object the constant C points to and call new
+
+

So new is not a keyword in Ruby.

+

And we can also use p for an instance of a created class.

+
+class C
+end
+
+c = C.new()
+p(c)       # #<C:0x2acbd7e4>
+
+

It won’t display as nicely as a string or an integer but it shows +its respective class and it’s internal ID. This ID is the pointer value +which points to the object.

+

Oh, I completely forgot but about the notation of method names: +Object.new calls the method new of the class object Object itself. +So Object#new and Object.new are completely different things, we have +to separate them strictly.

+
+obj = Object.new()   # Object.new
+obj.new()            # Object#new
+
+

In practice a method Object#new is almost never defined so the +second line will return an error. Please keep this example in mind.

+

Method Definition

+

If we can define classes we should also be able to define methods. +Let’s define a method for our class C.

+
+class C
+  def myupcase( str )
+    return str.upcase()
+  end
+end
+
+

To define a method we use the word def. In this example we +defined the method myupcase. The name of the only parameter is str. +As with variables it’s not necessary to write down the type of the parameter. +And we can use any number of parameters.

+

Let’s use the defined method. Methods are usually called from the +outside.

+
+c = C.new()
+result = c.myupcase("content")
+p(result)   # Shows "CONTENT"
+
+

Of course if you get used to it you don’t need to assign everything. +The line below gives the same result.

+
+p(C.new().myupcase("content"))   # Also shows "CONTENT"
+
+

self

+

During the execution of a method the information about itself (the instance +which called the method) is saved and can be picked up in self. +Like the this in C++ or Java. Let’s check this out.

+
+class C
+  def get_self()
+    return self
+  end
+end
+
+c = C.new()
+p(c)              # #<C:0x40274e44>
+p(c.get_self())   # #<C:0x40274e44>
+
+

As we see, the exact same object is returned. +We ascertained that for the called method self is c.

+

How should a method against oneself be called? +It comes to mind to do this also via self.

+
+class C
+  def my_p( obj )
+    self.real_my_p(obj)   # called a method against oneself
+  end
+
+  def real_my_p( obj )
+    p(obj)
+  end
+end
+
+C.new().my_p(1)   # Output 1
+
+

But always adding the self when calling an own method is tedious. +Hence, whenever one calls self one can omit the called object ( the receiver) by convention.

+
+class C
+  def my_p( obj )
+    real_my_p(obj)   # Calling without writing down the receiver.
+  end
+
+  def real_my_p( obj )
+    p(obj)
+  end
+end
+
+C.new().my_p(1)   # Output 1
+
+

Instance Variables

+

The saying goes “Objects are data and code”. So the definition +of methods alone would be useless. Objects must also be able +to store data. In other words instance variables. +Or in C++ jargon member variables. (Note: Check this.)

+

In the fashion of Ruby’s variable naming convention, the first +letter determines the variable type. For instance variables it’s +an @.

+
+class C
+  def set_i(value)
+    @i = value
+  end
+
+  def get_i()
+    return @i
+  end
+end
+
+c = C.new()
+c.set_i("ok")
+p(c.get_i())   # Shows "ok"
+
+

Instance variables differ a bit from the variables seen before: +We can reference them without assigning or defining them. +To see what happens we add the following lines to the code above.

+
+c = C.new()
+p(c.get_i())   # Shows nil
+
+

Calling get without set gives nil. nil is the object +which indicates “nothing”. It’s mysterious why there’s an object +where there should be nothing, but that’s just the way it is.

+

We can use nil like a literal as well.

+
+p(nil)   # Shows nil
+
+

initialize

+

As we saw before, when we call ‘new’ on a freshly defined class, +we can create an instance. That’s surely a good thing, but +sometimes we might want to have a peculiar instantiation. +In this case we don’t change method new, we change the method initialize. +When we do this it get’s called within new.

+
+class C
+  def initialize()
+    @i = "ok"
+  end
+  def get_i()
+    return @i
+  end
+end
+c = C.new()
+p(c.get_i())   # Shows "ok"
+
+

Strictly speaking this is the work of the new method not the +work of the language itself.

+

Inheritance

+

Classes can inherit from other classes. For instance String +inherits from Object. In this text we’’ll indicate this relation +by a vertical arrow as in Fig.3.

+

+

(supersub)
+Figure 3: Inheritance

+

+

In the illustration the inherited class (Object) is called +superclass or superior class. The inheriting class (String) is called +subclass or inferior class. This point differs from C++ jargon, be careful. +But it’s the same as in Java.

+

Anyway let’s try it out. Let’s inherit for our created class from another +class. To inherit from another class ( or designate a superclass) +write the following.

+
+class C < SuperClassName
+end
+
+

When we leave out the superclass like in the cases before the +class Object becomes tacitly the superclass.

+

Now, why should we want to inherit? Of course to hand over methods. +Handing over means that the methods which were defined in the +superclass also work in the subclass as if they were defined in there once more. +Let’s check it out.

+
+class C
+  def hello()
+    return "hello"
+  end
+end
+
+class Sub < C
+end
+
+sub = Sub.new()
+p(sub.hello())   # Shows "hello"
+
+

hello was defined in the class C but we could call it from +the class Sub as well. Of course we don’t need to assign variables. +The above is the same as the line below.

+
+p(Sub.new().hello())
+
+

When we define a method with the same name we overwrite a method. +In C++ and Object Pascal (Delphi) it’s only possible to overwrite +explicitly with the keyword virtual but in Ruby every method +can be overwritten unconditionally.

+
+class C
+  def hello()
+    return "Hello"
+  end
+end
+
+class Sub < C
+  def hello()
+    return "Hello from Sub"
+  end
+end
+
+p(Sub.new().hello())   # Shows "Hello from Sub"
+p(C.new().hello())     # Shows "Hello"
+
+

We can inherit over several steps. For instance as in Fig.4 +Fixnum inherits every method from Object, Numeric and Integer. +When there are methods with the same name the nearer classes take +preference. As type overloading isn’t there at all the requisites are +extremely straigtforward.

+

+

(multiinherit)
+Figure 4: Inheitance over multiple steps

+

+

In C++ it’s possible to create a class which inherits nothing. +While in Ruby one has to inherit from the Object class either +directly or indirectly. In other words when we draw the inheritance +relations it becomes a single tree with Object at the top.

+

+

(classtree)
+Figure 5: Ruby’s class tree

+

+

(Note: changed in 1.9: Socket isn’t builtin anymore, might want to add +Fiber, String, Symbol)

+

When the superclass is appointed ( in the definition statement ) it’s +not possible to change it anymore. In other words, one can add to the class tree +but cannot change a position or delete a class.

+

Inheritance of Variables……?

+

In Ruby (instance) variables aren’t inherited. +Even when inheriting, there’s no information what variables that class +uses.

+

But when an inherited method is called ( in an instance of a subclass), +assignment of instance variables happens. Which means they +become defined. Then, since the namespace of instance variables +is completely flat, it can be accessed by whichever method.

+
+class A
+  def initialize()   # called from when processing new()
+    @i = "ok"
+  end
+end
+
+class B < A
+  def print_i()
+    p(@i)
+  end
+end
+
+B.new().print_i()   # Shows "ok"
+
+

If you can’t agree with this behavior let’s think more about classses +and inheritance. When there’s an instance obj of the +the class C then all the methods of the superclass of C are as if +defined in C. Of course we keep the overwrite rule in mind. +Then the methods of C get attached to the instance obj (Fig.6). +This strong palpability is a specialty of Ruby’s object orientation.

+

+

(objimage)
+Figure 6: A conception of a Ruby object

+

+

(メソッド:method)

+

Modules

+

Only a single superclass can be designated. So Ruby looks like +single inheritance. But because of modules it has in practice +the same abilities as a multiple inheritance language. +Let’s explain these modules next.

+

In short, modules are classes for which a superclass cannot be +designated and instances cannot be created. +For the definition we write as follows.

+
+module M
+end
+
+

Here the module M was defined. Methods are defined exactly the +same way as for classes.

+
+module M
+  def myupcase( str )
+    return str.upcase()
+  end
+end
+
+

But because instances cannot be directly created we cannot call +these directly. What can we do about it? We can use these methods +by including the module into other classes. When doing so it’s as if +the module inherits to the class.

+
+module M
+  def myupcase( str )
+    return str.upcase()
+  end
+end
+
+class C
+  include M
+end
+
+p(C.new().myupcase("content"))  # "CONTENT" is shown
+
+

Even though no method was defined in the class C we can call +the method myupcase. It was inherited from the module M. +Inclusion is functionally completely the same as inheritance. +There’s no limit on the access of methods and instance variables.

+

A superclass cannot be assigned to a module, but +other modules can be included.

+
+module M
+end
+
+module M2
+  include M
+end
+
+

In other words it’s functionally the same as appointing a superclass. +But a class cannot come above a module. Only modules are allowed +above modules.

+

The example below also contains the inheritance of methods.

+
+module OneMore
+  def method_OneMore()
+    p("OneMore")
+  end
+end
+
+module M
+  include OneMore
+
+  def method_M()
+    p("M")
+  end
+end
+
+class C
+  include M
+end
+
+C.new().method_M()         # Output "M"
+C.new().method_OneMore()   # Output "OneMore"
+
+

As with classes when we sketch inheritance it looks like Fig.7

+

+

(modinherit)
+Figure 7: multilevel inheritance

+

+

Besides, the class C also has a superclass. What might be its +relationship with the included modules. For instance we could write +as follows.

+
+# modcls.rb
+
+class Cls
+  def test()
+    return "class"
+  end
+end
+
+module Mod
+  def test()
+    return "module"
+  end
+end
+
+class C < Cls
+  include Mod
+end
+
+p(B.new().test())   # "class"? "module"?
+
+

C inherits from Cls and includes Mod. What will be shown? +"class" or "module"? In other words which one is closer? +The superclass or the module? +We can ask Ruby about Ruby:

+
+% ruby modcls.rb
+"module"
+
+

Apparently a module takes preference before the superclass.

+

Broadly speaking, in Ruby an included module inherits by going in between +the class and the superclass. As a picture it might look like Fig.8.

+

+

(modclass)
+Figure 8: The relation between modules and classes

+

+

And modules included in modules look like Fig.9

+

+

(modclass2)
+Figure 9: The relation between modules and classes(2)

+

+

(SomeClassのスーパークラス:superclass of SomeClass)

+

The Program revisited

+

Caution. Now I explain an extremely important element which is probably +hard to get used to for programmers who have only used static languages before. +You can skip the rest but please read this carefully. I’ll +explain this also in relative depth.

+

Nesting of Constants

+

First a repetition of constants. As a constant begins with a capital +letter the definition goes as follows.

+
+Const = 3
+
+

Now we reference the constant in this way.

+
+p(Const)   # Shows 3
+
+

Actually we can also write this.

+
+p(::Const)   # Shows 3 in the same way.
+
+

The :: in front shows that it’s a constant defined at the top level. +You can think of the path in a filesystem. Assume there is a file vmunix +at rootlevel. Being at / one can write vmunix to access the file. One +can also write /vmunix. It’s the same with Const and ::Const. +At top level it’s okay to write only Const or to write the full path ::Const

+

And what corresponds to a filesystem’s directories in Ruby? +That should be class and module definition statements. +However mentioning both is cumbersome, so I’ll just subsume them under +class definition. When one enters a class definition the level +for constants rises ( as if entering a directory).

+
+class SomeClass
+  Const = 3
+end
+
+p(::SomeClass::Const)   # Shows 3
+p(  SomeClass::Const)   # The same. Shows 3
+
+

SomeClass is defined at toplevel. Hence one can reference it by writing +either SomeClass or ::SomeClass. And in class is the constant +Const. It becomes ::SomeClass::Const.

+

A class inside a class is like a directory in a directory. +For instance like this:

+
+class C        # ::C
+  class C2     # ::C::C2
+    class C3   # ::C::C2::C3
+    end
+  end
+end
+
+

Is it always necessary to reference a constant inside a class by its +full name? Of course not. As with the filesystem, if one is inside the +same class definition one can skip the ::. It becomes like that:

+
+class SomeClass
+  Const = 3
+  p(Const)   # Shows 3.
+end
+
+

“What?” you might think. Why’s the code inside a class definition executed? +People who are used to only static languages will find this quite exceptional. +I was also flabbergasted the first time I saw it.

+

Let’s add that we can of course also view a constant inside a method. +The reference rules are the same +as within the class definition (outside the method).

+
+class C
+  Const = "ok"
+  def test()
+    p(Const)
+  end
+end
+
+C.new().test()   # Shows "ok"
+
+

Everything is executed

+

Looking at the big picture I want to write one more thing. +In Ruby almost the whole program is executed. +Constant definitions, class definitions and method definitions +and the rest is executed in the apparent order.

+

Look for instance at the following code. +I used various constructions which haven’t been used before.

+
+ 1:  p("first")
+ 2:
+ 3:  class C < Object
+ 4:    Const = "in C"
+ 5:
+ 6:    p(Const)
+ 7:
+ 8:    def myupcase(str)
+ 9:       return str.upcase()
+10:    end
+11:  end
+12:
+13:  p(C.new().myupcase("content"))
+
+

This program is executed in the following order:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1: p("first")Shows "first"
3: < ObjectThe constant Object is referenced and the class object Object is gained
3: class CA new class object with superclass Object is generated, and assigned to the constant C
4: Const = "in C"Assigning the value "in C" to the constant ::C::Const
6: p(Const)Showing the constant ::C::Const hence "in C"
8: def myupcase(...)...endDefine C#myupcase
13: C.new().myupcase(...)Refer the constant C, call the method new on it, and then myupcase on the return value
9: return str.upcase()Returns "CONTENT"
13: p(...)Shows "CONTENT"
+

The Scope of Local Variables

+

At last we can talk about the scope of local variables.

+

The toplevel, the interior of a class definition, the interior of a module definition and a method body are all +scopes for independent local variables. In other words in the following program all variables +lvar are different. There’s no connection between them.

+
+lvar = 'toplevel'
+
+class C
+  lvar = 'in C'
+  def method()
+    lvar = 'in C#method'
+  end
+end
+
+p(lvar)   # Shows "toplevel"
+
+module M
+  lvar = 'in M'
+end
+
+p(lvar)   # Shows "toplevel"
+
+

self as context

+

I said before, that oneself is self during method execution. +That’s true but only half true. It’s really so that during execution +self is always set up. So also at toplevel and also in a class definition.

+

For instance the self at the toplevel is main. It’s an instance +of the Object class, as might be expected. main is provided +to set up self for the time being. There’s no deeper meaning attached +to it.

+

Hence the toplevel’s self i.e. main is an instance of Object, +such that one can call the methods of Object there. And in Object +the module Kernel is included. In there the function type methods +like p and puts are defined (Fig.10). That’s why one can +call puts and p also at the toplevel.

+

+

(Kernel)
+Figure 10: main, Object and Kernel

+

+

(トップレベル:toplevel)

+

Thus p isn’t a function, it’s a method. It’s just +defined in Kernel and thus can be called from everywhere. Or no matter what self is, + p is a method of self and can be called. +That’s why there aren’t really functions in Ruby. There are only methods.

+

By the way, besides p and puts there are the function type +methods print, puts, printf, sprintf, gets, fork, and exec +and many more with somewhat familiar names. When you look at the choice +of names you might imagine Ruby’s character.

+

I mentioned that self is set up everywhere, so it should also +be in a class definition. There it is the class ( class object) +itself. Hence we get this.

+
+class C
+  p(self)   # C
+end
+
+

What should this be good for? +Let’s look at a much more useful example.

+
+module M
+end
+class C
+  include M
+end
+
+

This include is a method call to the class object C. +I haven’t mentioned it yet but the parentheses around arguments +can be omitted for method calls. And I omitted the parantheses +around include such that it doesn’t look like a method call, which might +have been confusing without knowing the whole story.

+

Loading Libraries

+

In Ruby the loading of libraries also happens at runtime. +Normally one writes this.

+
+require("library_name")
+
+

The impression isn’t false, require is a method. It’s not even +a reserved word. When one writes that line the loaded library will be +executed where the line is written. As there is no concept like Java packages in Ruby, +one has to use files and directories to separate the namespace.

+
+require("somelib/file1")
+require("somelib/file2")
+
+

And in the library file there are usually class and module statements. The toplevel constant scope +is independent of the file, so one can see at once classes which where defined in another file. +To partition the namespace of class names one has to explicitly nest modules as shown below.

+
+# example of the namespace partion of the net library
+module Net
+  class SMTP
+    # ...
+  end
+  class POP
+    # ...
+  end
+  class HTTP
+    # ...
+  end
+end
+
+

More about Classes

+

Constants revisited

+

Up to now we used the filesystem metaphor for +the scope of constants, but I want you to completely forget that.

+

There is more about constants. Firstly one can also see constants outside +the class.

+
+Const = "ok"
+class C
+  p(Const)   # Shows "ok"
+end
+
+

This becomes useful, when modules are used as namespaces. +Let’s explain this by looking at the net library from before.

+
+module Net
+  class SMTP
+    # Uses Net::SMTPHelper in the methods
+  end
+  class SMTPHelper   # Supports the class Net::SMTP
+  end
+end
+
+

In this case it’s convenient to just refer to SMTPHelper +from within SMTP. That’s the reason why it’s convenient to +be able to see outside a class.

+

The outer class can be referenced over several levels. +When the same name is defined on different levels, the one which will +first be found from within will be referred to.

+
+Const = "far"
+class C
+  Const = "near" # This one is closer than the one above
+  class C2
+    class C3
+      p(Const)   # "near" is shown
+    end
+  end
+end
+
+

There’s another way of searching constants. If the toplevel is reached +when going further and further outside then the own superclass is +searched for the constant.

+
+class A
+  Const = "ok"
+end
+class B < A
+  p(Const)   # "ok" is shown
+end
+
+

Really, that’s pretty complicated.

+

Let’s summarize. When looking up a constant, first the outer class is +searched then the superclass. This is quite contrived, +but let’s assume a class hierarchy as follows.

+
+class A1
+end
+class A2 < A1
+end
+class A3 < A2
+  class B1
+  end
+  class B2 < B1
+  end
+  class B3 < B2
+    class C1
+    end
+    class C2 < C1
+    end
+    class C3 < C2
+      p(Const)
+    end
+  end
+end
+
+

When the constant Const in C3 is referenced, it’s looked +up in the order depicted in +Fig.11.

+

+

(constref)
+Figure 11: Search order for constants

+

+

Be careful about one point. The superclasses of the classes outside, +for instance A1 and B2, aren’t searched at all. +If it’s outside once it’s always outside and if it’s superclass once +it’s always superclass. If it weren’t so the number of classes would +become to big and the behavior would become unpredictable.

+

Metaclasses

+

We said, that one can call methods on objects. +We also said that the methods which we can call +are determined by the object’s class. Then shouldn’t there be +a class for class objects? (Fig.12)

+

+

(classclass)
+Figure 12: A class of classes?

+

+

For this we can check Ruby. +The method which returns the class of oneself is Object#class

+
+p("string".class())   # String is shown
+p(String.class())     # Class is shown
+p(Object.class())     # Class is shown
+
+

String belongs to the class Class. Then what’s the class of Class?

+
+p(Class.class())      # Class is shown
+
+

Again Class. In other words if one applies to any class +.class().class().class() long enough one reaches Class. +There the loop will stall. (Fig.13)

+

+

(ccc)
+Figure 13: The class of the class of the class…

+

+

Class is the class of classes. And whenever there is a +recursive structure from the form X of Xs we call it a meta-X. +Hence Class is a metaclass.

+

Metaobjects

+

Let’s change the subject and talk about modules. +As modules are also objects, there also should be a class for them. +Let’s see.

+
+module M
+end
+p(M.class())   # Module is shown
+
+

The class of a module seems to be Module. And what should be +the class of the class Module?

+
+p(Module.class())   # Class
+
+

It’s again Class

+

Now we change the direction and examine the inheritance relationships. +What’s the superclass of Class and Module? +We can find it out with Ruby’s Class#superclass.

+
+p(Class.superclass())    # Module
+p(Module.superclass())   # Object
+p(Object.superclass())   # nil
+
+

So Class is a subclass of Module. +A diagram of the important Ruby classes is in Fig.14.

+

+

(metaobjects)
+Figure 14: The class relationship between the important Ruby classes

+

+

Up to now we used new and include without an explanation of +their true form. new is really a method defined for the class Class. +That’s why new can be used in any class because it’s an instance +of Class. But new isn’t defined in Module. Hence it’s not +possible to create instances in a module. And include is defined +in the Module class. It can be called on modules and classes.

+

These three classes Object, Module and class are the centerpiece +of Ruby’s object world, they describe it. They are objects +describing objects. So Object, Module and Class are Ruby’s +metaobjects.

+

Singleton Methods

+

Methods can be called on objects. We said that the callable methods +are determined by the object’s class. But we also said that ideally, methods should +belong to the object. Classes are a means to +eliminate the effort of defining the same method more than once.

+

In Ruby there’s also a means to define methods for individual objects. +One writes this.

+
+obj = Object.new()
+def obj.my_first()
+  puts("My first singleton method")
+end
+obj.my_first()   # Shows My first singleton method
+
+

As you already know Object is the root for every class. +One sholdn’t add a weird method like my_first to such an important +class. And obj is an instance of Object. However the method my_first +can be called from obj. Hence we have created without doubt +a method which has nothing to do with the class the object belongs to. +These methods which are defined for each object individually are +called singleton methods.

+

When are singleton methods used? They are used in place of Java or C++ static +methods. In other words methods which can be used +without creating an instance. These methods are expressed in Ruby +as singleton methods of a class object.

+

For example in UNIX there’s a system call unlink. This command +deletes a file entry from the filesystem. In Ruby it can be used +directly as the singleton method unlink from the File class. +Let’s try it out.

+
+File.unlink("core")  # deletes the coredump
+
+

It’s cumbersome to say “the singleton method unlink +of the object File”. We simply write File.unlink. Don’t mix +it up and write File#unlink, or vice versa don’t write File.write +for the method write defined in File.

+

▼ A summary of the method notation

+ + + + + + + + + + + + + + + + +
notationcalled on objectexample
File.unlinkthe Fileclass itselfFile.unlink("core")
File#writean instance of Filef.write("str")
+

Class Variables

+

Class variables were added to Ruby from 1.6 on, they are a relatively new mechanism. +They can be referenced and assigned from both the class and its instances. +Let’s look at an example. The beginning of the name is @@.

+
+class C
+  @@cvar = "ok"
+  p(@@cvar)      # "ok" is shown
+
+  def print_cvar()
+    p(@@cvar)
+  end
+end
+
+C.new().print_cvar()  # "ok" is shown
+
+

As the first assignment serves as the definition, a reference +before an assignment leads to an error. This is shown below. +There is an ´@´ in front but the behavior differs completely +from instance variables.

+
+% ruby -e '
+class C
+  @@cvar
+end
+'
+-e:3: uninitialized class variable @@cvar in C (NameError)
+
+

Here I was a bit lazy and used the -e option. The program +is the three lines between the single quotes.

+

Class variables are inherited. Or saying it differently, +a variable in a superior class can be assigned and referenced in the +inferior class.

+
+class A
+  @@cvar = "ok"
+end
+
+class B < A
+  p(@@cvar)            # Shows "ok"
+  def print_cvar()
+    p(@@cvar)
+  end
+end
+
+B.new().print_cvar()   # Shows "ok"
+
+

Global Variables

+

At last there are also global variables. They can be referenced from +everywhere and assigned everywhere. The first letter of the name is a $.

+
+$gvar = "global variable"
+p($gvar)   # Shows "global variable"
+
+

As with instance variables all kinds of names are considered defined +for global variables. +In other words a reference before an assignment gives a nil and +doesn’t raise an error.

+
+

Copyright © 2002-2004 Minero Aoki, All rights reserved.

+

English Translation: Sebastian Krause <skra@pantolog.de>

+ + + +
+ + diff --git a/htmls/module.html b/htmls/module.html new file mode 100644 index 0000000..942d2b8 --- /dev/null +++ b/htmls/module.html @@ -0,0 +1,1560 @@ + + + + + Chapter 14: Context | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 14: Context

+

The range covered by this chapter is really broad. First of all, I’ll describe +about how the internal state of the evaluator is expressed. After that, as +an actual example, we’ll read how the state is changed on a class definition +statement. Subsequently, we’ll examine how the internal state influences method +definition statements. Lastly, we’ll observe how the both statements change the +behaviors of the variable definitions and the variable references.

+

The Ruby stack

+

Context and Stack

+

With an image of a typical procedural language, each time calling a procedure, +the information which is necessary to execute the procedure such as the local +variable space and the place to return is stored in a struct (a stack frame) +and it is pushed on the stack. +When returning from a procedure, the struct which is on the top of the stack +is popped and the state is returned to the previous method. +The executing image of a C program which was explained at Chapter 5: Garbage collection +is a perfect example.

+

What to be careful about here is, what is changing during the execution is only +the stack, on the contrary, the program remains unchanged wherever it is. +For example, if it is "a reference to the local variable i ", there’s just an +order of “give me i of the current frame”, it is not written as “give me i +of that frame”. In other words, “only” the state of the stack influences the +consequence. This is why, +even if a procedure is called anytime and any number of times, +we only have to write its code once (Fig. 1).

+

+

(stack)
+Fig.1: What is changing is only the stack

+

+

The execution of Ruby is also basically nothing but chained calls of methods +which are procedures, so essentially it has the same image as above. +In other words, with the same code, things being accessed such as local +variable scope and the block local scope will be changing. +And these kind of scopes are expressed by stacks.

+

However in Ruby, for instance, you can temporarily go back to the scope +previously used by using iterators or Proc . +This cannot be implemented with just simply pushing/popping a stack. +Therefore the frames of the Ruby stack will be intricately rearranged during +execution. Although I call it “stack”, it could be better to consider it +as a list.

+

Other than the method call, the local variable scope can also be changed on the +class definitions. So, the method calls does not match the transitions of the +local variable scope. Since there are also blocks, it’s necessary to handle them +separately. For these various reasons, surprisingly, there are seven stacks.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Stack Pointer Stack Frame Type Description
ruby_frame struct FRAME the records of method calls
ruby_scope struct SCOPE the local variable scope
ruby_block struct BLOCK the block scope
ruby_iter struct iter whether or not the current FRAME is an iterator
ruby_class VALUE the class to define methods on
ruby_cref NODE ( NODE_CREF ) the class nesting information
+

C has only one stack and Ruby has seven stacks, by simple arithmetic, the +executing image of Ruby is at least seven times more complicated than C. +But it is actually not seven times at all, +it’s at least twenty times more complicated.

+

First, I’ll briefly describe about these stacks and their stack frame structs. +The defined file is either eval.c or evn.h . Basically these stack frames +are touched only by eval.c … is what it should be if it were possible, +but gc.c needs to know the struct types when marking, +so some of them are exposed in env.h .

+

Of course, marking could be done in the other file but gc.c , but it requires +separated functions which cause slowing down. The ordinary programs had better +not care about such things, but both the garbage collector and the core of the +evaluator is the ruby’s biggest bottleneck, so it’s quite worth to optimize +even for just one method call.

+

ruby_frame

+

ruby_frame is a stack to record method calls. The stack frame struct is +struct FRAME. This terminology is a bit confusing but please be aware that +I’ll distinctively write it just a frame when it means a “stack frame” as a +general noun and FRAME when it means struct FRAME.

+

ruby_frame

+ +
+  16  extern struct FRAME {
+  17      VALUE self;          /* self */
+  18      int argc;            /* the argument count */
+  19      VALUE *argv;         /* the array of argument values */
+  20      ID last_func;        /* the name of this FRAME (when called) */
+  21      ID orig_func;        /* the name of this FRAME (when defined) */
+  22      VALUE last_class;    /* the class of last_func's receiver */
+  23      VALUE cbase;         /* the base point for searching constants and class variables */
+  24      struct FRAME *prev;
+  25      struct FRAME *tmp;   /* to protect from GC. this will be described later */
+  26      struct RNode *node;  /* the file name and the line number of the currently executed line. */
+  27      int iter;            /* is this called with a block? */
+  28      int flags;           /* the below two */
+  29  } *ruby_frame;
+
+  33  #define FRAME_ALLOCA 0   /* FRAME is allocated on the machine stack */
+  34  #define FRAME_MALLOC 1   /* FRAME is allocated by malloc */
+
+(env.h)
+
+

First af all, since there’s the prev member, you can infer that the stack is +made of a linked list. (Fig.2)

+

+

(framestack)
+Fig.2: ruby_frame

+

+

The fact that ruby_xxxx points to the top stack frame is common to all stacks +and won’t be mentioned every time.

+

The first member of the struct is self . +There is also self in the arguments of rb_eval() , +but why this struct remembers another self ? +This is for the C-level functions. More precisely, it’s for rb_call_super() that is +corresponding to super . In order to execute super , it requires the receiver +of the current method, but the caller side of rb_call_super() could not have +such information. However, the chain of rb_eval() is interrupted before the +time when the execution of the user-defined C code starts. Therefore, the +conclusion is that there need a way to obtain the information of self out of +nothing. And, FRAME is the right place to store it.

+

Thinking a little further, It’s mysterious that there are argc and argv . +Because parameter variables are local variables after all, it is unnecessary to +preserve the given arguments after assigning them into the local variable with +the same names at the beginning of the method, isn’t it? +Then, what is the use of them ? The answer is that this is actually for +super again. In Ruby, when calling super without any arguments, the values of +the parameter variables of the method will be passed to the method of the +superclass. +Thus, (the local variable space for) the parameter variables must be reserved.

+

Additionally, the difference between last_func and orig_func will be come +out in the cases like when the method is alias ed. +For instance,

+
+class C
+  def orig() end
+  alias ali orig
+end
+C.new.ali
+
+

in this case, last_func=ali and orig_func=orig . +Not surprisingly, these members also have to do with super .

+

ruby_scope

+

ruby_scope is the stack to represent the local variable scope. The method and +class definition statements, the module definition statements and the singleton +class definition statements, all of them are different scopes. The stack frame +struct is struct SCOPE. +I’ll call this frame SCOPE .

+

ruby_scope

+ +
+  36  extern struct SCOPE {
+  37      struct RBasic super;
+  38      ID *local_tbl;        /* an array of the local variable names */
+  39      VALUE *local_vars;    /* the space to store local variables */
+  40      int flags;            /* the below four */
+  41  } *ruby_scope;
+
+  43  #define SCOPE_ALLOCA  0         /* local_vars is allocated by alloca */
+  44  #define SCOPE_MALLOC  1         /* local_vars is allocated by malloc */
+  45  #define SCOPE_NOSTACK 2         /* POP_SCOPE is done  */
+  46  #define SCOPE_DONT_RECYCLE 4    /* Proc is created with this SCOPE */
+
+(env.h)
+
+

Since the first element is struct RBasic, this is a Ruby object. This is in +order to handle Proc objects. For example, let’s try to think about the case +like this:

+
+def make_counter
+  lvar = 0
+  return Proc.new { lvar += 1 }
+end
+
+cnt = make_counter()
+p cnt.call    # 1
+p cnt.call    # 2
+p cnt.call    # 3
+cnt = nil  # cut the reference. The created Proc finally becomes unnecessary here.
+
+

The Proc object created by this method will persist longer than the method that +creates it. And, because the Proc can refer to the local variable lvar , +the local variables must be preserved until the Proc will disappear. +Thus, if it were not handled by the garbage collector, no one can determine the +time to free.

+

There are two reasons why struct SCOPE is separated from struct FRAME. +Firstly, the things like class definition statements are not method +calls but create distinct local variable scopes. +Secondly, when a called method is defined in C the Ruby’s local +variable space is unnecessary.

+

ruby_block

+

struct BLOCK is the real body of a Ruby’s iterator block or a Proc object, +it is also kind of a snapshot of the evaluator at some point. +This frame will also be briefly written as BLOCK as in the same manner as +FRAME and SCOPE .

+

ruby_block

+ +
+ 580  static struct BLOCK *ruby_block;
+
+ 559  struct BLOCK {
+ 560      NODE *var;               /* the block parameters(mlhs) */
+ 561      NODE *body;              /* the code of the block body */
+ 562      VALUE self;              /* the self when this BLOCK is created */
+ 563      struct FRAME frame;      /* the copy of ruby_frame when this BLOCK is created */
+ 564      struct SCOPE *scope;     /* the ruby_scope when this BLOCK is created */
+ 565      struct BLOCKTAG *tag;    /* the identity of this BLOCK */
+ 566      VALUE klass;             /* the ruby_class when this BLOCK is created */
+ 567      int iter;                /* the ruby_iter when this BLOCK is created */
+ 568      int vmode;               /* the scope_vmode when this BLOCK is created */
+ 569      int flags;               /* BLOCK_D_SCOPE, BLOCK_DYNAMIC */
+ 570      struct RVarmap *dyna_vars;   /* the block local variable space */
+ 571      VALUE orig_thread;       /* the thread that creates this BLOCK */
+ 572      VALUE wrapper;           /* the ruby_wrapper when this BLOCK is created */
+ 573      struct BLOCK *prev;
+ 574  };
+
+ 553  struct BLOCKTAG {
+ 554      struct RBasic super;
+ 555      long dst;                /* destination, that is, the place to return */
+ 556      long flags;              /* BLOCK_DYNAMIC, BLOCK_ORPHAN */
+ 557  };
+
+ 576  #define BLOCK_D_SCOPE 1      /* having distinct block local scope */
+ 577  #define BLOCK_DYNAMIC 2      /* BLOCK was taken from a Ruby program */
+ 578  #define BLOCK_ORPHAN  4      /* the FRAME that creates this BLOCK has finished */
+
+
+(eval.c)
+
+

Note that frame is not a pointer. This is because the entire content of +struct FRAME will be all copied and preserved. The entire struct FRAME is +(for better performance) allocated on the machine stack, but BLOCK could +persist longer than the FRAME that creates it, the preservation is a +preparation for that case.

+

Additionally, struct BLOCKTAG is separated in order to detect the same block +when multiple Proc objects are created from the block. The Proc objects +which were created from the one same block have the same BLOCKTAG .

+

ruby_iter

+

The stack ruby_iter indicates whether currently calling method is an iterator +(whether it is called with a block). The frame is struct iter. +But for consistency I’ll call it ITER .

+

ruby_iter

+ +
+ 767  static struct iter *ruby_iter;
+
+ 763  struct iter {
+ 764      int iter;           /* the below three */
+ 765      struct iter *prev;
+ 766  };
+
+ 769  #define ITER_NOT 0      /* the currently evaluated method is not an iterator */
+ 770  #define ITER_PRE 1      /* the method which is going to be evaluated next is an iterator */
+ 771  #define ITER_CUR 2      /* the currently evaluated method is an iterator */
+(eval.c)
+
+

Although for each method we can determine whether it is an iterator or not, +there’s another struct that is distinct from struct FRAME. Why?

+

It’s obvious you need to inform it to the method when “it is an iterator”, +but you also need to inform the fact when “it is not an iterator”. +However, pushing a whole BLOCK just for this is very heavy. It will also +cause that in the caller side the procedures such as variable references +would needlessly increase. +Thus, it’s better to push the smaller and lighter ITER instead of BLOCK . +This will be discussed in detail in Chapter 16: Blocks.

+

ruby_dyna_vars

+

The block local variable space. The frame struct is struct RVarmap that has +already seen in Part 2. Form now on, I’ll call it just VARS .

+

struct RVarmap

+ +
+  52  struct RVarmap {
+  53      struct RBasic super;
+  54      ID id;                  /* the name  of the variable */
+  55      VALUE val;              /* the value of the variable */
+  56      struct RVarmap *next;
+  57  };
+
+(env.h)
+
+

Note that a frame is not a single struct RVarmap but a list of the structs (Fig.3). +And each frame is corresponding to a local variable scope. +Since it corresponds to “local variable scope” and not “block local variable scope”, +for instance, even if blocks are nested, only a single list is used to express. +The break between blocks are similar to the one of the parser, +it is expressed by a RVarmap (header) whose id is 0 . +Details are deferred again. It will be explained in Chapter 16: Blocks.

+

+

(vars)
+Fig.3: ruby_dyna_vars

+

+

ruby_class

+

ruby_class represents the current class to which a method is defined. Since +self will be that class when it’s a normal class definition statement, +ruby_class == self. But, when it is the top level or in the middle of +particular methods like eval and instance_eval , self != ruby_class is +possible.

+

The frame of ruby_class is a simple VALUE and there’s no particular frame +struct. Then, how could it be like a stack? Moreover, there were many structs +without the prev pointer, how could these form a stack? The answer is deferred +to the next section.

+

From now on, I’ll call this frame CLASS .

+

ruby_cref

+

ruby_cref represents the information of the nesting of a class. +I’ll call this frame CREF with the same way of naming as before. +Its struct is …

+

ruby_cref

+ +
+ 847  static NODE *ruby_cref = 0;
+
+(eval.c)
+
+

… surprisingly NODE . This is used just as a "defined struct which can be +pointed by a VALUE ". The node type is NODE_CREF and the assignments of its +members are shown below:

+ + + + + + + + + + + + + + + + + + + + + +
Union Member Macro To Access Usage
u1.value nd_clss the outer class ( VALUE )
u2
u3.node nd_next preserve the previous CREF
+

Even though the member name is nd_next , the value it actually has is the +“previous (prev)” CREF . Taking the following program as an example, I’ll +explain the actual appearance.

+
+class A
+  class B
+    class C
+      nil   # (A)
+    end
+  end
+end
+
+

Fig.4 shows how ruby_cref is when evaluating the code (A).

+

+

(crefstack)
+Fig.4: ruby_cref

+

+

However, illustrating this image everytime is tedious and its intention becomes unclear. +Therefore, the same state as Fig.4 will be expressed in the following notation:

+
+A ← B ← C
+
+

PUSH / POP Macros

+

For each stack frame struct, the macros to push and pop are available. +For instance, PUSH_FRAME and POP_FRAME for FRAME . +Because these will appear in a moment, +I’ll then explain the usage and content.

+

The other states

+

While they are not so important as the main stacks, the evaluator of ruby has +the several other states. This is a brief list of them. However, some of them +are not stacks. Actually, most of them are not.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable Name Type Meaning
scope_vmode int the default visibility when a method is defined
ruby_in_eval int whether or not parsing after the evaluation is started
ruby_current_node NODE* the file name and the line number of what currently being evaluated
ruby_safe_level int $SAFE
ruby_errinfo VALUE the exception currently being handled
ruby_wrapper VALUE the wrapper module to isolate the environment
+

Module Definition

+

The class statement and the module statement and the singleton class +definition statement, they are all implemented in similar ways.

+

Because seeing similar things continuously three times is not interesting, this time let’s +examine the module statement which has the least elements (thus, is simple).

+

First of all, what is the module statement? Conversely, what should happen is +the module statement ? Let’s try to list up several features:

+
    +
  • a new module object should be created
  • +
  • the created module should be self
  • +
  • it should have an independent local variable scope
  • +
  • if you write a constant assignment, a constant should be defined on the module
  • +
  • if you write a class variable assignment, + a class variable should be defined on the module.
  • +
  • if you write a def statement, a method should be defined on the module
  • +
+

What is the way to archive these things? … is the point of this section. +Now, let’s start to look at the codes.

+

Investigation

+

▼The Source Program

+ +
+module M
+  a = 1
+end
+
+

▼Its Syntax Tree

+ +
+NODE_MODULE
+nd_cname = 9621 (M)
+nd_body:
+    NODE_SCOPE
+    nd_rval = (null)
+    nd_tbl = 3 [ _ ~ a ]
+    nd_next:
+        NODE_LASGN
+        nd_cnt = 2
+        nd_value:
+            NODE_LIT
+            nd_lit = 1:Fixnum
+
+

nd_cname seems the module name. cname is probably either Const NAME or Class +NAME. I dumped several things and found that there’s always NODE_SCOPE in +nd_body . Since its member nd_tbl holds a local variable table and its name +is similar to struct SCOPE, it appears certain that this NODE_SCOPE +plays an important role to create a local variable scope.

+

NODE_MODULE

+

Let’s examine the handler of NODE_MODULE of rb_eval() . The parts that are +not close to the main line, such as ruby_raise() and error handling were cut +drastically. So far, there have been a lot of cutting works for 200 pages, +it has already became unnecessary to show the original code.

+

rb_eval()NODE_MODULE (simplified)

+ +
+case NODE_MODULE:
+  {
+      VALUE module;
+
+      if (rb_const_defined_at(ruby_class, node->nd_cname)) {
+          /* just obtain the already created module */
+          module = rb_const_get(ruby_class, node->nd_cname);
+      }
+      else {
+          /* create a new module and set it into the constant */
+          module = rb_define_module_id(node->nd_cname);
+          rb_const_set(ruby_cbase, node->nd_cname, module);
+          rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
+      }
+
+      result = module_setup(module, node->nd_body);
+  }
+  break;
+
+

First, we’d like to make sure the module is nested and defined above (the module holded by) ruby_class . +We can understand it from the fact that it calls ruby_const_xxxx() on ruby_class . +Just once ruby_cbase appears, but it is usually identical to ruby_class , +so we can ignore it. Even if they are different, it rarely causes a problem.

+

The first half, it is branching by if because it needs to check if the +module has already been defined. This is because, in Ruby, +we can do “additional” definitions on the same one module any number of times.

+
+module M
+  def a    # M#a is deifned
+  end
+end
+module M   # add a definition (not re-defining or overwriting)
+  def b    # M#b is defined
+  end
+end
+
+

In this program, the two methods, a and b , will be defined on the module M .

+

In this case, on the second definition of M the module M was already set to +the constant, just obtaining and using it would be sufficient. If the constant +M does not exist yet, it means the first definition and the module is created +(by rb_define_module_id() )

+

Lastly, module_setup() is the function executing the body of a module +statement. Not only the module statements but the class statements and the +singleton class statements are executed by module_setup() . +This is the reason why I said “all of these three type of statements are +similar things”. +For now, I’d like you to note that node->nd_body ( NODE_SCOPE ) is passed as +an argument.

+

module_setup

+

For the module and class and singleton class statements, module_setup() +executes their bodies. Finally, the Ruby stack manipulations will appear in +large amounts.

+

module_setup()

+ +
+3424  static VALUE
+3425  module_setup(module, n)
+3426      VALUE module;
+3427      NODE *n;
+3428  {
+3429      NODE * volatile node = n;
+3430      int state;
+3431      struct FRAME frame;
+3432      VALUE result;               /* OK */
+3433      TMP_PROTECT;
+3434
+3435      frame = *ruby_frame;
+3436      frame.tmp = ruby_frame;
+3437      ruby_frame = &frame;
+3438
+3439      PUSH_CLASS();
+3440      ruby_class = module;
+3441      PUSH_SCOPE();
+3442      PUSH_VARS();
+3443
+          /* (A)ruby_scope->local_vars initialization */
+3444      if (node->nd_tbl) {
+3445          VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
+3446          *vars++ = (VALUE)node;
+3447          ruby_scope->local_vars = vars;
+3448          rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+3449          ruby_scope->local_tbl = node->nd_tbl;
+3450      }
+3451      else {
+3452          ruby_scope->local_vars = 0;
+3453          ruby_scope->local_tbl  = 0;
+3454      }
+3455
+3456      PUSH_CREF(module);
+3457      ruby_frame->cbase = (VALUE)ruby_cref;
+3458      PUSH_TAG(PROT_NONE);
+3459      if ((state = EXEC_TAG()) == 0) {
+3460          if (trace_func) {
+3461              call_trace_func("class", ruby_current_node, ruby_class,
+3462                              ruby_frame->last_func,
+3463                              ruby_frame->last_class);
+3464          }
+3465          result = rb_eval(ruby_class, node->nd_next);
+3466      }
+3467      POP_TAG();
+3468      POP_CREF();
+3469      POP_VARS();
+3470      POP_SCOPE();
+3471      POP_CLASS();
+3472
+3473      ruby_frame = frame.tmp;
+3474      if (trace_func) {
+3475          call_trace_func("end", ruby_last_node, 0,
+3476                          ruby_frame->last_func, ruby_frame->last_class);
+3477      }
+3478      if (state) JUMP_TAG(state);
+3479
+3480      return result;
+3481  }
+
+(eval.c)
+
+

This is too big to read all in one gulp. +Let’s cut the parts that seems unnecessary.

+

First, the parts around trace_func can be deleted unconditionally.

+

We can see the idioms related to tags. Let’s simplify them by expressing with +the Ruby’s ensure.

+

Immediately after the start of the function, the argument n is purposefully +assigned to the local variable node , but volatile is attached to node and +it would never be assigned after that, thus this is to prevent from being +garbage collected. If we assume that the argument was node from the beginning, +it would not change the meaning.

+

In the first half of the function, there’s the part manipulating ruby_frame +complicatedly. It is obviously paired up with the part ruby_frame = frame.tmp +in the last half. We’ll focus on this part later, but for the time being this +can be considered as push pop of ruby_frame .

+

Plus, it seems that the code (A) can be, as commented, summarized as the +initialization of ruby_scope->local_vars . This will be discussed later.

+

Consequently, it could be summarized as follows:

+

module_setup (simplified)

+ +
+static VALUE
+module_setup(module, node)
+    VALUE module;
+    NODE *node;
+{
+    struct FRAME frame;
+    VALUE result;
+
+    push FRAME
+    PUSH_CLASS();
+    ruby_class = module;
+    PUSH_SCOPE();
+    PUSH_VARS();
+    ruby_scope->local_vars initializaion
+    PUSH_CREF(module);
+    ruby_frame->cbase = (VALUE)ruby_cref;
+    begin
+        result = rb_eval(ruby_class, node->nd_next);
+    ensure
+        POP_TAG();
+        POP_CREF();
+        POP_VARS();
+        POP_SCOPE();
+        POP_CLASS();
+        pop FRAME
+    end
+    return result;
+}
+
+

It does rb_eval() with node->nd_next , +so it’s certain that this is the code of the module body. +The problems are about the others. There are 5 points to see.

+
    +
  • Things occur on PUSH_SCOPE() PUSH_VARS()
  • +
  • How the local variable space is allocated
  • +
  • The effect of PUSH_CLASS
  • +
  • The relationship between ruby_cref and ruby_frame->cbase
  • +
  • What is done by manipulating ruby_frame
  • +
+

Let’s investigate them in order.

+

Creating a local variable scope

+

PUSH_SCOPE pushes a local variable space and PUSH_VARS() pushes a block +local variable space, thus a new local variable scope is created by these two. +Let’s examine the contents of these macros and what is done.

+

PUSH_SCOPE() POP_SCOPE()

+ +
+ 852  #define PUSH_SCOPE() do {               \
+ 853      volatile int _vmode = scope_vmode;  \
+ 854      struct SCOPE * volatile _old;       \
+ 855      NEWOBJ(_scope, struct SCOPE);       \
+ 856      OBJSETUP(_scope, 0, T_SCOPE);       \
+ 857      _scope->local_tbl = 0;              \
+ 858      _scope->local_vars = 0;             \
+ 859      _scope->flags = 0;                  \
+ 860      _old = ruby_scope;                  \
+ 861      ruby_scope = _scope;                \
+ 862      scope_vmode = SCOPE_PUBLIC
+
+ 869  #define POP_SCOPE()                                      \
+ 870      if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {        \
+ 871         if (_old) scope_dup(_old);                        \
+ 872      }                                                    \
+ 873      if (!(ruby_scope->flags & SCOPE_MALLOC)) {           \
+ 874          ruby_scope->local_vars = 0;                      \
+ 875          ruby_scope->local_tbl  = 0;                      \
+ 876          if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \
+ 877              ruby_scope != top_scope) {                   \
+ 878              rb_gc_force_recycle((VALUE)ruby_scope);      \
+ 879          }                                                \
+ 880      }                                                    \
+ 881      ruby_scope->flags |= SCOPE_NOSTACK;                  \
+ 882      ruby_scope = _old;                                   \
+ 883      scope_vmode = _vmode;                                \
+ 884  } while (0)
+
+(eval.c)
+
+

As the same as tags, SCOPE s also create a stack by being synchronized with the +machine stack. What differentiate slightly is that the spaces of the stack +frames are allocated in the heap, the machine stack is used in order to create +the stack structure (Fig.5.).

+

+

(scopestack)
+Fig.5. The machine stack and the SCOPE Stack

+

+

Additionally, the flags like SCOPE_ something repeatedly appearing in the +macros are not able to be explained until I finish to talk all about +in what form each stack frame is remembered and about blocks. +Thus, these will be discussed in Chapter 16: Blocks all at once.

+

Allocating the local variable space

+

As I mentioned many times, the local variable scope is represented by struct SCOPE. +But struct SCOPE is literally a “scope” and it does not have the real body +to store local variables. To put it more precisely, it has the pointer to a +space but there’s still no array at the place where the one points to. The +following part of module_setup prepares the array.

+

▼The preparation of the local variable slots

+ +
+3444  if (node->nd_tbl) {
+3445      VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
+3446      *vars++ = (VALUE)node;
+3447      ruby_scope->local_vars = vars;
+3448      rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+3449      ruby_scope->local_tbl = node->nd_tbl;
+3450  }
+3451  else {
+3452      ruby_scope->local_vars = 0;
+3453      ruby_scope->local_tbl  = 0;
+3454  }
+
+(eval.c)
+
+

The TMP_ALLOC() at the beginning will be described in the next section. If I +put it shortly, it is “alloca that is assured to allocate on the stack +(therefore, we do not need to worry about GC)”.

+

node->nd_tbl holds in fact the local variable name table that has appeared +in Chapter 12: Syntax tree construction. It means that nd_tbl[0] contains the table size and the rest is +an array of ID . This table is directly preserved to local_tbl of SCOPE +and local_vars is allocated to store the local variable values. +Because they are confusing, it’s a good thing writing some comments such as +“This is the variable name”, “this is the value”. +The one with tbl is for the names.

+

+

(localvars)
+Fig.6. ruby_scope->local_vars

+

+

Where is this node used? +I examined the all local_vars members but could not find the access to index +-1 in eval.c . Expanding the range of files to investigate, I found the +access in gc.c .

+

rb_gc_mark_children()T_SCOPE

+ +
+ 815  case T_SCOPE:
+ 816    if (obj->as.scope.local_vars &&
+            (obj->as.scope.flags & SCOPE_MALLOC)) {
+ 817        int n = obj->as.scope.local_tbl[0]+1;
+ 818        VALUE *vars = &obj->as.scope.local_vars[-1];
+ 819
+ 820        while (n--) {
+ 821            rb_gc_mark(*vars);
+ 822            vars++;
+ 823        }
+ 824    }
+ 825    break;
+
+(gc.c)
+
+

Apparently, this is a mechanism to protect node from GC. +But why is it necessary to to mark it here? +node is purposefully store into the volatile local variable, so +it would not be garbage-collected during the execution of module_setup() .

+

Honestly speaking, I was thinking it might merely be a mistake for a while but +it turned out it’s actually very important. The issue is this at the next +line of the next line:

+

ruby_scope->local_tbl

+ +
+3449  ruby_scope->local_tbl = node->nd_tbl;
+
+(eval.c)
+
+

The local variable name table prepared by the parser is directly used. When is +this table freed? It’s the time when the node become not to be referred from +anywhere. Then, when should node be freed? It’s the time after the SCOPE +assigned on this line will disappear completely. Then, when is that?

+

SCOPE sometimes persists longer than the statement that causes the creation +of it. As it will be discussed at Chapter 16: Blocks, +if a Proc object is created, it refers SCOPE . +Thus, If module_setup() has finished, the SCOPE created there is not +necessarily be what is no longer used. That’s why it’s not sufficient that +node is only referred from (the stack frame of) module_setup() . +It must be referred “directly” from SCOPE .

+

On the other hand, the volatile node of the local variable cannot be removed. +Without it, node is floating on air until it will be assigned to local_vars .

+

However then, local_vars of SCOPE is not safe, isn’t it? +TMP_ALLOC() is, as I mentioned, the allocation on the stack, it becomes +invalid at the time module_setup() ends. This is in fact, at the moment when +Proc is created, the allocation method is abruptly switched to malloc() . +Details will be described in Chapter 16: Blocks.

+

Lastly, rb_mem_clear() seems zero-filling but actually it is Qnil -filling to +an array of VALUE ( array.c ). By this, all defined local variables are +initialized as nil .

+

TMP_ALLOC

+

Next, let’s read TMP_ALLOC that allocates the local variable space. +This macro is actually paired with TMP_PROTECT existing silently at the +beginning of module_setup() . Its typical usage is this:

+
+VALUE *ptr;
+TMP_PROTECT;
+
+ptr = TMP_ALLOC(size);
+
+

The reason why TMP_PROTECT is in the place for the local variable definitions +is that … Let’s see its definition.

+

TMP_ALLOC()

+ +
+1769  #ifdef C_ALLOCA
+1770  # define TMP_PROTECT NODE * volatile tmp__protect_tmp=0
+1771  # define TMP_ALLOC(n) \
+1772      (tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA,                 \
+1773                               ALLOC_N(VALUE,n), tmp__protect_tmp, n), \
+1774       (void*)tmp__protect_tmp->nd_head)
+1775  #else
+1776  # define TMP_PROTECT typedef int foobazzz
+1777  # define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
+1778  #endif
+
+(eval.c)
+
+

… it is because it defines a local variable.

+

As described in Chapter 5: Garbage collection, in the environment of #ifdef C_ALLOCA (that is, +the native alloca() does not exist) malloca() is used to emulate alloca() . +However, the arguments of a method are obviously VALUE s and +the GC could not find a VALUE if it is stored in the heap. +Therefore, it is enforced that GC can find it through NODE .

+

+

(tmpprotecttmp)
+Fig.7. anchor the space to the stack through NODE

+

+

On the contrary, in the environment with the true alloca() , we can naturally +use alloca() and there’s no need to use TMP_PROTECT . Thus, a harmless +statement is arbitrarily written.

+

By the way, why do they want to use alloca() very much by all means. +It’s merely because " alloca() is faster than malloc() ", they said. +One can think that it’s not so worth to care about such tiny difference, +but because the core of the evaluator is the biggest bottleneck of ruby , +… the same as above.

+

Changing the place to define methods on.

+

The value of the stack ruby_class is the place to define a method on at the +time. Conversely, if one push a value to ruby_class , it changes the class to +define a method on. This is exactly what is necessary for a class statement. +Therefore, It’s also necessary to do PUSH_CLASS() in module_setup() . +Here is the code for it:

+
+PUSH_CLASS();
+ruby_class = module;
+     :
+     :
+POP_CLASS();
+
+

Why is there the assignment to ruby_class after doing PUSH_CLASS() . +We can understand it unexpectedly easily by looking at the definition.

+

PUSH_CLASS() POP_CLASS()

+ +
+ 841  #define PUSH_CLASS() do { \
+ 842      VALUE _class = ruby_class
+
+ 844  #define POP_CLASS() ruby_class = _class; \
+ 845  } while (0)
+
+(eval.c)
+
+

Because ruby_class is not modified even though PUSH_CLASS is done, +it is not actually pushed until setting by hand. +Thus, these two are closer to “save and restore” rather than “push and pop”.

+

You might think that it can be a cleaner macro if passing a class as the +argument of PUSH_CLASS() … It’s absolutely true, but because there are some +places we cannot obtain the class before pushing, it is in this way.

+

Nesting Classes

+

ruby_cref represents the class nesting information at runtime. Therefore, it’s +naturally predicted that ruby_cref will be pushed on the module statements or +on the class statements. +In module_setup() , it is pushed as follows:

+
+PUSH_CREF(module);
+ruby_frame->cbase = (VALUE)ruby_cref;
+   :
+   :
+POP_CREF();
+
+

Here, module is the module being defined. +Let’s also see the definitions of PUSH_CREF() and POP_CREF() .

+

PUSH_CREF() POP_CREF()

+ +
+ 849  #define PUSH_CREF(c) \
+          ruby_cref = rb_node_newnode(NODE_CREF,(c),0,ruby_cref)
+ 850  #define POP_CREF() ruby_cref = ruby_cref->nd_next
+
+(eval.c)
+
+

Unlike PUSH_SCOPE or something, there are not any complicated techniques and +it’s very easy to deal with. +It’s also not good if there’s completely not any such thing.

+

The problem remains unsolved is what is the meaning of ruby_frame->cbase . +It is the information to refer a class variable or a constant from the current FRAME . +Details will be discussed in the last section of this chapter.

+

Replacing frames

+

Lastly, let’s focus on the manipulation of ruby_frame . The first thing is its +definition:

+
+struct FRAME frame;
+
+

It is not a pointer. This means that the entire FRAME is allocated on the stack. +Both the management structure of the Ruby stack and the local variable +space are on the stack, but in the case of FRAME the entire struct is stored +on the stack. The extreme consumption of the machine stack by ruby is the +fruit of these “small techniques” piling up.

+

Then next, let’s look at where doing several things with frame .

+
+frame = *ruby_frame;      /* copy the entire struct */
+frame.tmp = ruby_frame;   /* protect the original FRAME from GC */
+ruby_frame = &frame;      /* replace ruby_frame */
+       :
+       :
+ruby_frame = frame.tmp;   /* restore */
+
+

That is, ruby_frame seems temporarily replaced (not pushing). +Why is it doing such thing?

+

I described that FRAME is “pushed on method calls”, but to be more precise, +it is the stack frame to represent “the main environment to execute a Ruby program”. +You can infer it from, for instance, ruby_frame->cbase which appeared previously. +last_func which is “the last called method name” also suggests it.

+

Then, why is FRAME not straightforwardly pushed? +It is because this is the place where it is not allowed to push FRAME . +FRAME is wanted to be pushed, but if FRAME is pushed, +it will appear in the backtraces of the program when an exception occurs. +The backtraces are things displayed like followings:

+
+% ruby t.rb
+t.rb:11:in `c': some error occured (ArgumentError)
+        from t.rb:7:in `b'
+        from t.rb:3:in `a'
+        from t.rb:14
+
+

But the module statements and the class statements are not method calls, +so it is not desirable to appear in this. That’s why it is “replaced” instead +of “pushed”.

+

The method definition

+

As the next topic of the module definitions, let’s look at the method definitions.

+

Investigation

+

▼The Source Program

+ +
+def m(a, b, c)
+  nil
+end
+
+

▼Its Syntax Tree

+ +
+NODE_DEFN
+nd_mid  = 9617 (m)
+nd_noex = 2 (NOEX_PRIVATE)
+nd_defn:
+    NODE_SCOPE
+    nd_rval = (null)
+    nd_tbl = 5 [ _ ~ a b c ]
+    nd_next:
+        NODE_ARGS
+        nd_cnt  = 3
+        nd_rest = -1
+        nd_opt = (null)
+        NODE_NIL
+
+

I dumped several things and found that there’s always NODE_SCOPE in nd_defn . +NODE_SCOPE is, as we’ve seen at the module statements, +the node to store the information to push a local variable scope.

+

NODE_DEFN

+

Subsequently, we will examine the corresponding code of rb_eval() . This part +contains a lot of error handlings and tedious, they are all omitted again. +The way of omitting is as usual, deleting the every parts to directly or +indirectly call rb_raise() rb_warn() rb_warning().

+

rb_eval()NODE_DEFN (simplified)

+ +
+NODE *defn;
+int noex;
+
+if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
+    noex = NOEX_PRIVATE;                 (A)
+}
+else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+    noex = NOEX_PROTECTED;               (B)
+}
+else if (ruby_class == rb_cObject) {
+    noex =  node->nd_noex;               (C)
+}
+else {
+    noex = NOEX_PUBLIC;                  (D)
+}
+
+defn = copy_node_scope(node->nd_defn, ruby_cref);
+rb_add_method(ruby_class, node->nd_mid, defn, noex);
+result = Qnil;
+
+

In the first half, there are the words like private or protected , so it is +probably related to visibility. noex , which is used as the names of flags, +seems NOde EXposure. Let’s examine the if statements in order.

+

(A) SCOPE_TEST() is a macro to check if there’s an argument flag in +scope_vmode . Therefore, the first half of this conditional statement means +“is it a private scope?”. +The last half means "it’s private if this is defining initialize ". +The method initialize to initialize an object will unquestionably become private .

+

(B) It is protected if the scope is protected (not surprisingly). +My feeling is that there’re few cases protected is required in Ruby.

+

© This is a bug. I found this just before the submission of this book, +so I couldn’t fix this beforehand. +In the latest code this part is probably already removed. +The original intention is to enforce the methods defined at top level to be private .

+

(D) If it is not any of the above conditions, it is public .

+

Actually, there’s not a thing to worth to care about until here. The important +part is the next two lines.

+
+defn = copy_node_scope(node->nd_defn, ruby_cref);
+rb_add_method(ruby_class, node->nd_mid, defn, noex);
+
+

copy_node_scope() is a function to copy (only) NODE_SCOPE attached to the +top of the method body. It is important that ruby_cref is passed … +but details will be described soon.

+

After copying, the definition is finished by adding it by rb_add_method() . +The place to define on is of course ruby_class .

+

copy_node_scope()

+

copy_node_scope() is called only from the two places: the method definition +( NODE_DEFN ) and the singleton method definition ( NODE_DEFS ) in rb_eval() . +Therefore, looking at these two is sufficient to detect how it is used. Plus, +the usages at these two places are almost the same.

+

copy_node_scope()

+ +
+1752  static NODE*
+1753  copy_node_scope(node, rval)
+1754      NODE *node;
+1755      VALUE rval;
+1756  {
+1757      NODE *copy = rb_node_newnode(NODE_SCOPE,0,rval,node->nd_next);
+1758
+1759      if (node->nd_tbl) {
+1760          copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1);
+1761          MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1);
+1762      }
+1763      else {
+1764          copy->nd_tbl = 0;
+1765      }
+1766      return copy;
+1767  }
+
+(eval.c)
+
+

I mentioned that the argument rval is the information of the class nesting +( ruby_cref ) of when the method is defined. Apparently, it is rval because it +will be set to nd_rval .

+

In the main if statement copies nd_tbl of NODE_SCOPE . +It is a local variable name table in other words. The +1 at ALLOC_N is to +additionally allocate the space for nd_tbl[0] . As we’ve seen in Part 2, +nd_tbl[0] holds the local variables count, that was “the actual length of +nd_tbl – 1”.

+

To summarize, copy_node_scope() makes a copy of the NODE_SCOPE which is the +header of the method body. However, nd_rval is additionally set and it is the +ruby_cref (the class nesting information) of when the class is defined. This +information will be used later when referring constants or class variables.

+

rb_add_method()

+

The next thing is rb_add_method() that is the function to register a method entry.

+

rb_add_method()

+ +
+ 237  void
+ 238  rb_add_method(klass, mid, node, noex)
+ 239      VALUE klass;
+ 240      ID mid;
+ 241      NODE *node;
+ 242      int noex;
+ 243  {
+ 244      NODE *body;
+ 245
+ 246      if (NIL_P(klass)) klass = rb_cObject;
+ 247      if (ruby_safe_level >= 4 &&
+              (klass == rb_cObject || !OBJ_TAINTED(klass))) {
+ 248          rb_raise(rb_eSecurityError, "Insecure: can't define method");
+ 249      }
+ 250      if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
+ 251      rb_clear_cache_by_id(mid);
+ 252      body = NEW_METHOD(node, noex);
+ 253      st_insert(RCLASS(klass)->m_tbl, mid, body);
+ 254  }
+
+(eval.c)
+
+

NEW_METHOD() is a macro to create NODE . +rb_clear_cache_by_id() is a function to manipulate the method cache. +This will be explained in the next chapter “Method”.

+

Let’s look at the syntax tree which is eventually stored in m_tbl of a class. +I prepared nodedump-method for this kind of purposes. +(nodedump-method : comes with nodedump . nodedump is tools/nodedump.tar.gz of the attached CD-ROM)

+
+% ruby -e '
+class C
+  def m(a)
+    puts "ok"
+  end
+end
+require "nodedump-method"
+NodeDump.dump C, :m        # dump the method m of the class C
+'
+NODE_METHOD
+nd_noex = 0 (NOEX_PUBLIC)
+nd_cnt = 0
+nd_body:
+    NODE_SCOPE
+    nd_rval = Object <- C
+    nd_tbl = 3 [ _ ~ a ]
+    nd_next:
+        NODE_ARGS
+        nd_cnt  = 1
+        nd_rest = -1
+        nd_opt = (null)
+        U牙S頏著
+
+
+** unhandled**
+
+
+
+

There are NODE_METHOD at the top +and NODE_SCOPE previously copied by copy_node_scope() at the next. +These probably represent the header of a method. +I dumped several things and there’s not any NODE_SCOPE with the methods defined in C, +thus it seems to indicate that the method is defined at Ruby level.

+

Additionally, at nd_tbl of NODE_SCOPE the parameter variable name ( a ) appears. +I mentioned that the parameter variables are equivalent to the local variables, +and this briefly implies it.

+

I’ll omit the explanation about NODE_ARGS here +because it will be described at the next chapter “Method”.

+

Lastly, the nd_cnt of the NODE_METHOD , it’s not so necessary to care about +this time. It is used when having to do with alias .

+

Assignment and Reference

+

Come to think of it, most of the stacks are used to realize a variety of +variables. We have learned to push various stacks, this time let’s examine the +code to reference variables.

+

Local variable

+

The all necessary information to assign or refer local variables has appeared, +so you are probably able to predict. +There are the following two points:

+
    +
  • local variable scope is an array which is pointed by ruby_scope->local_vars
  • +
  • the correspondence between each local variable name and each array index has + already resolved at the parser level.
  • +
+

Therefore, the code for the local variable reference node NODE_LVAR is as +follows:

+

rb_eval()NODE_LVAR

+ +
+2975  case NODE_LVAR:
+2976    if (ruby_scope->local_vars == 0) {
+2977        rb_bug("unexpected local variable");
+2978    }
+2979    result = ruby_scope->local_vars[node->nd_cnt];
+2980    break;
+
+(eval.c)
+
+

It goes without saying but node->nd_cnt is the value that local_cnt() of the +parser returns.

+

Constant

+

Complete Specification

+

In Chapter 6: Variables and constants, +I talked about in what form constants are stored and API. +Constants are belong to classes and inherited as the same as methods. +As for their actual appearances, they are registered to iv_tbl of +struct RClass with instance variables and class variables.

+

The searching path of a constant is firstly the outer class, secondly the +superclass, however, rb_const_get() only searches the superclass. Why? +To answer this question, I need to reveal the last specification of constants. +Take a look at the following code:

+
+class A
+  C = 5
+  def A.new
+    puts C
+    super
+  end
+end
+
+

A.new is a singleton method of A , so its class is the singleton class (A) . +If it is interpreted by following the rule, +it cannot obtain the constant C which is belongs to A .

+

But because it is written so close, to become to want refer the constant C +is human nature. Therefore, such reference is possible in Ruby. +It can be said that this specification reflects the characteristic of Ruby +“The emphasis is on the appearance of the source code”.

+

If I generalize this rule, when referring a constant from inside of a method, +by setting the place which the method definition is “written” as the start +point, it refers the constant of the outer class. +And, “the class of where the method is written” depends on its context, +thus it could not be handled without the information from both the parser and +the evaluator. This is why rb_cost_get() did not have the searching path of +the outer class.

+

cbase

+

Then, let’s look at the code to refer constants including the outer class. +The ordinary constant references to which :: is not attached, become +NODE_CONST in the syntax tree. The corresponding code in rb_eval() is …

+

rb_eval()NODE_CONST

+ +
+2994  case NODE_CONST:
+2995    result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid, self);
+2996    break;
+
+(eval.c)
+
+

First, nd_vid appears to be Variable ID and it probably means a constant name. +And, ruby_frame->cbase is “the class where the method definition is written”. +The value will be set when invoking the method, thus the code to set has not appeared yet. +And the place where the value to be set comes from is the nd_rval +that has appeared in copy_node_scope() of the method definition. +I’d like you to go back a little and check that the member holds the +ruby_cref of when the method is defined.

+

This means, first, the ruby_cref link is built when defining a class or a module. +Assume that the just defined class is C (Fig.81),

+

Defining the method m (this is probably C#m ) here, +then the current ruby_cref is memorized by the method entry (Fig.82).

+

After that, when the class statement finished the ruby_cref would start to +point another node, but node->nd_rval naturally continues to point to the +same thing. (Fig.83)

+

Then, when invoking the method C#m , get node->nd_rval +and insert into the just pushed ruby_frame->cbase . (Fig.84)

+

… This is the mechanism. Complicated.

+

+

(cbase)
+Fig 8. CREF Trasfer

+

+

ev_const_get()

+

Now, let’s go back to the code of NODE_CONST . +Since only ev_const_get() is left, we’ll look at it.

+

ev_const_get()

+ +
+1550  static VALUE
+1551  ev_const_get(cref, id, self)
+1552      NODE *cref;
+1553      ID id;
+1554      VALUE self;
+1555  {
+1556      NODE *cbase = cref;
+1557      VALUE result;
+1558
+1559      while (cbase && cbase->nd_next) {
+1560          VALUE klass = cbase->nd_clss;
+1561
+1562          if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
+1563          if (RCLASS(klass)->iv_tbl &&
+                  st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
+1564              return result;
+1565          }
+1566          cbase = cbase->nd_next;
+1567      }
+1568      return rb_const_get(cref->nd_clss, id);
+1569  }
+
+(eval.c)
+
+

(( According to the errata, the description of ev_const_get() was wrong. + I omit this part for now. ))

+

Class variable

+

What class variables refer to is also ruby_cref . Needless to say, +unlike the constants which search over the outer classes one after another, +it uses only the first element. +Let’s look at the code of NODE_CVAR which is the node to refer to a class +variable.

+

What is the cvar_cbase() ? As cbase is attached, +it is probably related to ruby_frame->cbase , but how do they differ? +Let’s look at it.

+

cvar_cbase()

+ +
+1571  static VALUE
+1572  cvar_cbase()
+1573  {
+1574      NODE *cref = RNODE(ruby_frame->cbase);
+1575
+1576      while (cref && cref->nd_next &&
+                 FL_TEST(cref->nd_clss, FL_SINGLETON)) {
+1577          cref = cref->nd_next;
+1578          if (!cref->nd_next) {
+1579    rb_warn("class variable access from toplevel singleton method");
+1580          }
+1581      }
+1582      return cref->nd_clss;
+1583  }
+
+(eval.c)
+
+

It traverses cbase up to the class that is not the singleton class, it +seems. This feature is added to counter the following kind of code:

+
+class C                           class C
+  @@cvar = 1                        @@cvar = 1
+  class << C                        def C.m
+    def m                             @@cvar
+      @@cvar                        end
+    end                             def C.m2
+    def m2                            @@cvar + @@cvar
+      @@cvar + @@cvar               end
+    end                           end
+  end
+end
+
+

Both the left and right code ends up defining the same method, +but if you write in the way of the right side it is tedious to write the class +name repeatedly as the number of methods increases. Therefore, when defining +multiple singleton methods, many people choose to write in the left side way +of using the singleton class definition statement to bundle.

+

However, these two differs in the value of ruby_cref . The one using the +singleton class definition is ruby_cref=(C) and the other one defining +singleton methods separately is ruby_cref=C . This may cause to differ in the +places where class variables refer to, so this is not convenient.

+

Therefore, assuming it’s rare case to define class variables on singleton +classes, it skips over singleton classes. This reflects again that the emphasis +is more on the usability rather than the consistency.

+

And, when the case is a constant reference, +since it searches all of the outer classes, +C is included in the search path in either way, so there’s no problem. +Plus, as for an assignment, since it couldn’t be written inside methods in the +first place, it is also not related.

+

Multiple Assignment

+

If someone asked “where is the most complicated specification of Ruby?”, I +would instantly answer that it is multiple assignment. +It is even impossible to understand the big picture of multiple assignment, I +have an account of why I think so. In short, the specification of the multiple +assignment is defined without even a subtle intention to construct so that the +whole specification is well-organized. The basis of the specification is always +“the behavior which seems convenient in several typical use cases”. This can be +said about the entire Ruby, but particularly about the multiple assignment.

+

Then, how could we avoid being lost in the jungle of codes. This is similar to +reading the stateful scanner and it is not seeing the whole picture. There’s +no whole picture in the first place, we could not see it. Cutting the code into +blocks like, this code is written for this specification, that code is written +for that specification, … understanding the +correspondences one by one in such manner is the only way.

+

But this book is to understand the overall structure of ruby and is not +“Advanced Ruby Programming”. Thus, dealing with very tiny things is not fruitful. +So here, we only think about the basic structure of multiple assignment +and the very simple “multiple-to-multiple” case.

+

First, following the standard, let’s start with the syntax tree.

+

▼The Source Program

+ +
+a, b = 7, 8
+
+

▼Its Syntax Tree

+ +
+NODE_MASGN
+nd_head:
+    NODE_ARRAY [
+    0:
+        NODE_LASGN
+        nd_cnt = 2
+        nd_value:
+    1:
+        NODE_LASGN
+        nd_cnt = 3
+        nd_value:
+    ]
+nd_value:
+    NODE_REXPAND
+    nd_head:
+        NODE_ARRAY [
+        0:
+            NODE_LIT
+            nd_lit = 7:Fixnum
+        1:
+            NODE_LIT
+            nd_lit = 8:Fixnum
+        ]
+
+

Both the left-hand and right-hand sides are the lists of NODE_ARRAY , +there’s additionally NODE_REXPAND in the right side. REXPAND may be “Right +value EXPAND”. We are curious about what this node is doing. Let’s see.

+

rb_eval()NODE_REXPAND

+ +
+2575  case NODE_REXPAND:
+2576    result = avalue_to_svalue(rb_eval(self, node->nd_head));
+2577    break;
+
+(eval.c)
+
+

You can ignore avalue_to_svalue() . +NODE_ARRAY is evaluated by rb_eval() , (because it is the node of the array +literal), it is turned into a Ruby array and returned back. +So, before the left-hand side is handled, all in the right-hand side are +evaluated. This enables even the following code:

+
+a, b = b, a    # swap variables in oneline
+
+

Let’s look at NODE_MASGN in the left-hand side.

+

rb_eval()NODE_MASGN

+ +
+2923  case NODE_MASGN:
+2924    result = massign(self, node, rb_eval(self, node->nd_value),0);
+2925    break;
+
+(eval.c)
+
+

Here is only the evaluation of the right-hand side, the rests are delegated to +massign() .

+

massign()

+

massi ……

+ +
+3917  static VALUE
+3918  massign(self, node, val, pcall)
+3919      VALUE self;
+3920      NODE *node;
+3921      VALUE val;
+3922      int pcall;
+3923  {
+
+(eval.c)
+
+

I’m sorry this is halfway, but I’d like you to stop and pay attention to the +4th argument. pcall is Proc CALL, this indicates whether or not the +function is used to call Proc object. Between Proc calls and the others +there’s a little difference in the strictness of the check of the multiple +assignments, so a flag is received to check. +Obviously, the value is decided to be either 0 or 1.

+

Then, I’d like you to look at the previous code calling massign() , it was +pcall=0 . Therefore, we probably don’t mind if assuming it is pcall=0 for the +time being and extracting the variables. That is, when there’s an argument like +pcall which is slightly changing the behavior, we always need to consider the +two patterns of scenarios, so it is really cumbersome. If there’s only one +actual function massign() , to think as if there were two functions, pcall=0 +and pcall=1 , is way simpler to read.

+

When writing a program we must avoid duplications as much as possible, +but this principle is unrelated if it is when reading. +If patterns are limited, +copying it and letting it to be redundant is rather the right approach. +There are wordings “optimize for speed” “optimize for the code size”, +in this case we’ll “optimize for readability”.

+

So, assuming it is pcall=0 and cutting the codes as much as possible and the +final appearance is shown as follows:

+

massign() (simplified)

+ +
+static VALUE
+massign(self, node, val  /* , pcall=0 */)
+    VALUE self;
+    NODE *node;
+    VALUE val;
+{
+    NODE *list;
+    long i = 0, len;
+
+    val = svalue_to_mvalue(val);
+    len = RARRAY(val)->len;
+    list = node->nd_head;
+    /* (A) */
+    for (i=0; list && i<len; i++) {
+        assign(self, list->nd_head, RARRAY(val)->ptr[i], pcall);
+        list = list->nd_next;
+    }
+    /* (B) */
+    if (node->nd_args) {
+        if (node->nd_args == (NODE*)-1) {
+            /* no check for mere `*' */
+        }
+        else if (!list && i<len) {
+            assign(self, node->nd_args,
+                   rb_ary_new4(len-i, RARRAY(val)->ptr+i), pcall);
+        }
+        else {
+            assign(self, node->nd_args, rb_ary_new2(0), pcall);
+        }
+    }
+
+    /* (C) */
+    while (list) {
+        i++;
+        assign(self, list->nd_head, Qnil, pcall);
+        list = list->nd_next;
+    }
+    return val;
+}
+
+

val is the right-hand side value. And there’s the suspicious conversion called +svalue_to_mvalue() , since mvalue_to_svalue() appeared previously and +svalue_to_mvalue() in this time, so you can infer “it must be getting back”. +((errata: it was avalue_to_svalue() in the previous case. +Therefore, it’s hard to infer “getting back”, but you can ignore them anyway.)) +Thus, the both are deleted. In the next line, since it uses RARRAY() , +you can infer that the right-hand side value is an Array of Ruby. +Meanwhile, the left-hand side is node->nd_head , so it is the value assigned to +the local variable list . This list is also a node ( NODE_ARRAY ).

+

We’ll look at the code by clause.

+

(A) assign is, as the name suggests, a function to perform an one-to-one +assignment. Since the left-hand side is expressed by a node, +if it is, for instance, NODE_IASGN (an assignment to an instance variable), +it assigns with rb_ivar_set() . +So, what it is doing here is adjusting to either list and val which is +shorter and doing one-to-one assignments. (Fig.9)

+

+

(massign)
+Fig.9. assign when corresponded

+

+

(B) if there are remainders on the right-hand side, turn them into a Ruby +array and assign it into (the left-hand side expressed by) the node->nd_args .

+

© if there are remainders on the left-hand side, assign nil to all of them.

+

By the way, the procedure which is assuming pcall=0 then cutting out is very +similar to the data flow analytics / constant foldings used on the optimization +phase of compilers. +Therefore, we can probably automate it to some extent.

+ + + +
+ + diff --git a/htmls/name.html b/htmls/name.html new file mode 100644 index 0000000..d6e5a38 --- /dev/null +++ b/htmls/name.html @@ -0,0 +1,591 @@ + + + + + Names and Name Table | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Clifford Escobar CAOILE

+

Chapter 3: Names and Name Table

+

st_table

+

st_table has already appeared several times as a method table and an instance +table. In this chapter let’s look at the structure of the st_table in detail.

+

Summary

+

I previously mentioned that the st_table is a hash table. What is a hash +table? It is a data structure that records one-to-one relations, for example, a +variable name and its value, or a function name and its body, etc.

+

However, data structures other than hash tables can, of course, record +one-to-one relations. For example, a list of the following structs will suffice +for this purpose.

+
+struct entry {
+    ID key;
+    VALUE val;
+    struct entry *next;  /* point to the next entry */
+};
+
+

However, this method is slow. If the list contains a thousand items, in the +worst case, it is necessary to traverse a thousand links. In other words, the +search time increases in proportion to the number of elements. This is bad. +Since ancient times, various speed improvement methods have been conceived. The +hash table is one of those improved methods. In other words, the point is not +that the hash table is necessary but that it can be made faster.

+

Now then, let us examine the st_table. As it turns out, this library is not +created by Matsumoto, rather:

+

st.c credits

+
+   1  /* This is a public domain general purpose hash table package
+         written by Peter Moore @ UCB. */
+
+(st.c)
+
+

as shown above.

+

By the way, when I searched Google and found another version, it mentioned +that st_table is a contraction of “STring TABLE”. However, I find it +contradictory that it has both “general purpose” and “string” aspects.

+

What is a hash table?

+

A hash table can be thought as the following: Let us think of an array with +n items. For example, let us make n=64 (figure 1).

+

+

(array)
+Figure 1: Array

+

+

Then let us specify a function f that takes a key and produces an integer i +from 0 to n-1 (0-63). We call this f a hash function. f when given the +same key always produces the same i. For example, if we can assume that the +key is limited to positive integers, when the key is divided by 64, the +remainder should always fall between 0 and 63. Therefore, this calculating +expression has a possibility of being the function f.

+

When recording relationships, given a key, function f generates i, and +places the value into index i of the array we have prepared. Index access +into an array is very fast. The key concern is changing a key into an integer.

+

+

(aset)
+Figure 2: Array assignment

+

+

However, in the real world it isn’t that easy. There is a critical problem with +this idea. Because n is only 64, if there are more than 64 relationships to +be recorded, it is certain that there will be the same index for two different +keys. It is also possible that with fewer than 64, the same thing can occur. +For example, given the previous hash function “key % 64”, keys 65 and 129 will +both have a hash value of 1. This is called a hash value collision. There are +many ways to resolve such a collision.

+

One solution is to insert into the next element when a collision occurs. +This is called open addressing. (Figure 3).

+

+

(nexti)
+Figure 3: Open addressing

+

+

Other than using the array like this, there are other possible approaches, like using +a pointer to a respective linked list in each element of the array. Then when a +collision occurs, grow the linked list. This is called chaining. (Figure +4) st_table uses this chaining method.

+

+

(chain)
+Figure 4: Chaining

+

+

However, if it can be determined a priori what set of keys will be used, +it is possible to imagine a hash function that will never create +collisions. This type of function is called a “perfect hash function”. +Actually, there are tools which create a perfect hash function given a set +of arbitrary strings. GNU gperf is one of those. ruby‘s parser +implementation uses GNU gperf but… this is not the time to discuss it. +We’ll discuss this in the second part of the book.

+

Data Structure

+

Let us start looking at the source code. As written in the introductory +chapter, if there is data and code, it is better to read the data first. +The following is the data type of st_table.

+

st_table

+
+   9  typedef struct st_table st_table;
+
+  16  struct st_table {
+  17      struct st_hash_type *type;
+  18      int num_bins;                   /* slot count */
+  19      int num_entries;                /* total number of entries */
+  20      struct st_table_entry **bins;   /* slot */
+  21  };
+
+(st.h)
+
+

struct st_table_entry

+
+  16  struct st_table_entry {
+  17      unsigned int hash;
+  18      char *key;
+  19      char *record;
+  20      st_table_entry *next;
+  21  };
+
+(st.c)
+
+

st_table is the main table structure. st_table_entry is a holder that +stores one value. st_table_entry contains a member called next which of +course is used to make st_table_entry into a linked list. This is the chain + part of the chaining method. The st_hash_type data type is used, but I will + explain this later. First let me explain the other parts so you can compare +and understand the roles.

+

+

(sttable)
+Figure 5: st_table data structure

+

+

So, let us comment on st_hash_type.

+

struct st_hash_type

+
+  11  struct st_hash_type {
+  12      int (*compare)();   /* comparison function */
+  13      int (*hash)();      /* hash function */
+  14  };
+
+(st.h)
+
+

This is still Chapter 3 so let us examine it attentively.

+
+int (*compare)()
+
+

This part shows, of course, the member compare which has a data type of +“a pointer to a function that returns an int”. hash is also of the same type. +This variable is substituted in the following way:

+
+int
+great_function(int n)
+{
+    /* ToDo: Do something great! */
+    return n;
+}
+
+{
+    int (*f)();
+    f = great_function;
+
+

And it is called like this:

+
+    (*f)(7);
+}
+
+

Here let us return to the st_hash_type commentary. Of the two members +hash and compare, hash is the hash function f explained previously.

+

On the other hand, compare is a function that evaluates if the key is actually the +same or not. With the chaining method, in the spot with the same hash value +n, multiple elements can be inserted. To know exactly which element is +being searched for, this time it is necessary to use a comparison function +that we can absolutely trust. compare will be that function.

+

This st_hash_type is a good generalized technique. The hash table itself +cannot determine what the stored keys’ data type will be. For example, in +ruby, st_table’s keys are ID or char* or VALUE, but to write the +same kind of hash for each (data type) is foolish. Usually, the things +that change with the different key data types are things like the hash +function. For things like memory allocation and collision detection, +typically most of the code is the same. Only the parts where the +implementation changes with a differing data type will be bundled up into a +function, and a pointer to that function will be used. In this fashion, the +majority of the code that makes up the hash table implementation can +use it.

+

In object-oriented languages, in the first place, you can attach a procedure +to an object and pass it (around), so this mechanism is not necessary. +Perhaps it more correct to say that this mechanism is built-in as a +language’s feature.

+

st_hash_type example

+

The usage of a data structure like st_hash_type is good as an +abstraction. On the other hand, what kind of code it actually passes +through may be difficult to understand. If we do not examine what sort of +function is used for hash or compare, we will not grasp the reality. +To understand this, it is probably sufficient to look at st_init_numtable() +introduced in the previous chapter. This function creates a table for +integer data type keys.

+

st_init_numtable()

+
+ 182  st_table*
+ 183  st_init_numtable()
+ 184  {
+ 185      return st_init_table(&type_numhash);
+ 186  }
+
+(st.c)
+
+

st_init_table() is the function that allocates the table memory and so +on. type_numhash is an st_hash_type (it is the member named “type” of st_table). +Regarding this type_numhash:

+

type_numhash

+
+  37  static struct st_hash_type type_numhash = {
+  38      numcmp,
+  39      numhash,
+  40  };
+
+ 552  static int
+ 553  numcmp(x, y)
+ 554      long x, y;
+ 555  {
+ 556      return x != y;
+ 557  }
+
+ 559  static int
+ 560  numhash(n)
+ 561      long n;
+ 562  {
+ 563      return n;
+ 564  }
+
+(st.c)
+
+

Very simple. The table that the ruby interpreter uses is by and large +this type_numhash.

+

st_lookup()

+

Now then, let us look at the function that uses this data structure. First, +it’s a good idea to look at the function that does the searching. Shown below is the +function that searches the hash table, st_lookup().

+

st_lookup()

+
+ 247  int
+ 248  st_lookup(table, key, value)
+ 249      st_table *table;
+ 250      register char *key;
+ 251      char **value;
+ 252  {
+ 253      unsigned int hash_val, bin_pos;
+ 254      register st_table_entry *ptr;
+ 255
+ 256      hash_val = do_hash(key, table);
+ 257      FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ 258
+ 259      if (ptr == 0) {
+ 260          return 0;
+ 261      }
+ 262      else {
+ 263          if (value != 0)  *value = ptr->record;
+ 264          return 1;
+ 265      }
+ 266  }
+
+(st.c)
+
+

The important parts are pretty much in do_hash() and FIND_ENTRY(). Let us +look at them in order.

+

do_hash()

+
+  68  #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
+
+(st.c)
+
+

Just in case, let us write down the macro body that is difficult to understand:

+
+(table)->type->hash
+
+

is a function pointer where the key is passed as a parameter. This is the +syntax for calling the function. * is not applied to table. In other words, +this macro is a hash value generator for a key, using the prepared hash +function type->hash for each data type.

+

Next, let us examine FIND_ENTRY().

+

FIND_ENTRY()

+
+ 235  #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
+ 236      bin_pos = hash_val%(table)->num_bins;\
+ 237      ptr = (table)->bins[bin_pos];\
+ 238      if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
+ 239          COLLISION;\
+ 240          while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
+ 241              ptr = ptr->next;\
+ 242          }\
+ 243          ptr = ptr->next;\
+ 244      }\
+ 245  } while (0)
+
+ 227  #define PTR_NOT_EQUAL(table, ptr, hash_val, key) ((ptr) != 0 && \
+          (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
+
+  66  #define EQUAL(table,x,y) \
+          ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
+
+(st.c)
+
+

COLLISION is a debug macro so we will (should) ignore it.

+

The parameters of FIND_ENTRY(), starting from the left are:

+
    +
  1. st_table
  2. +
  3. the found entry will be pointed to by this parameter
  4. +
  5. hash value
  6. +
  7. temporary variable
  8. +
+

And, the second parameter will point to the found st_table_entry*.

+

At the outermost level, a do .. while(0) is used to safely wrap up a +multiple expression macro. This is ruby‘s, or rather, C language’s preprocessor +idiom. In the case of if(1), there may be a danger of adding an else part. +In the case of while(1), it becomes necessary to add a break at the very +end.

+

Also, there is no semicolon added after the while(0).

+
+FIND_ENTRY();
+
+

This is so that the semicolon that is normally written at the end of an +expression will not go to waste.

+

st_add_direct()

+

Continuing on, let us examine st_add_direct() which is a function that adds a +new relationship to the hash table. This function does not check if the key is +already registered. It always adds a new entry. This is the meaning of direct +in the function name.

+

st_add_direct()

+
+ 308  void
+ 309  st_add_direct(table, key, value)
+ 310      st_table *table;
+ 311      char *key;
+ 312      char *value;
+ 313  {
+ 314      unsigned int hash_val, bin_pos;
+ 315
+ 316      hash_val = do_hash(key, table);
+ 317      bin_pos = hash_val % table->num_bins;
+ 318      ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ 319  }
+
+(st.c)
+
+

Just as before, the do_hash() macro that obtains a value is called here. +After that, the next calculation is the same as at the start of +FIND_ENTRY(), which is to exchange the hash value for a real index.

+

Then the insertion operation seems to be implemented by ADD_DIRECT(). +Since the name is all uppercase, we can anticipate that is a macro.

+

ADD_DIRECT()

+
+ 268  #define ADD_DIRECT(table, key, value, hash_val, bin_pos) \
+ 269  do {                                                     \
+ 270      st_table_entry *entry;                               \
+ 271      if (table->num_entries / (table->num_bins)           \
+                              > ST_DEFAULT_MAX_DENSITY) {      \
+ 272          rehash(table);                                   \
+ 273          bin_pos = hash_val % table->num_bins;            \
+ 274      }                                                    \
+ 275                                                           \
+          /* (A) */                                            \
+ 276      entry = alloc(st_table_entry);                       \
+ 277                                                           \
+ 278      entry->hash = hash_val;                              \
+ 279      entry->key = key;                                    \
+ 280      entry->record = value;                               \
+          /* (B) */                                            \
+ 281      entry->next = table->bins[bin_pos];                  \
+ 282      table->bins[bin_pos] = entry;                        \
+ 283      table->num_entries++;                                \
+ 284  } while (0)
+
+(st.c)
+
+

The first if is an exception case so I will explain it afterwards.

+

(A) Allocate and initialize a st_table_entry.

+

(B) Insert the entry into the start of the list. +This is the idiom for handling the list. In other words,

+
+entry->next = list_beg;
+list_beg = entry;
+
+

makes it possible to insert an entry to the front of the list. This is similar +to “cons-ing” in the Lisp language. Check for yourself that even if list_beg +is NULL, this code holds true.

+

Now, let me explain the code I left aside.

+

ADD_DIRECT()-rehash

+
+ 271      if (table->num_entries / (table->num_bins)           \
+                              > ST_DEFAULT_MAX_DENSITY) {      \
+ 272          rehash(table);                                   \
+ 273          bin_pos = hash_val % table->num_bins;            \
+ 274      }                                                    \
+
+(st.c)
+
+

DENSITY is “concentration”. In other words, this conditional checks if the +hash table is “crowded” or not. In the st_table, as the number of values that +use the same bin_pos increases, the longer the link list becomes. In other +words, search becomes slower. That is why for a given bin count, when the average elements +per bin become too many, bin is increased and the crowding is reduced.

+

The current ST_DEFAULT_MAX_DENSITY is

+

ST_DEFAULT_MAX_DENSITY

+
+  23  #define ST_DEFAULT_MAX_DENSITY 5
+
+(st.c)
+
+

Because of this setting, if in all bin_pos there are 5 st_table_entries, +then the size will be increased.

+

st_insert()

+

st_insert() is nothing more than a combination of st_add_direct() and +st_lookup(), so if you understand those two, this will be easy.

+

st_insert()

+
+ 286  int
+ 287  st_insert(table, key, value)
+ 288      register st_table *table;
+ 289      register char *key;
+ 290      char *value;
+ 291  {
+ 292      unsigned int hash_val, bin_pos;
+ 293      register st_table_entry *ptr;
+ 294
+ 295      hash_val = do_hash(key, table);
+ 296      FIND_ENTRY(table, ptr, hash_val, bin_pos);
+ 297
+ 298      if (ptr == 0) {
+ 299          ADD_DIRECT(table, key, value, hash_val, bin_pos);
+ 300          return 0;
+ 301      }
+ 302      else {
+ 303          ptr->record = value;
+ 304          return 1;
+ 305      }
+ 306  }
+
+(st.c)
+
+

It checks if the element is already registered in the table. Only when it is +not registered will it be added. If there is a insertion, return 0. If there is +no insertion, return a 1.

+

ID and Symbols

+

I’ve already discussed what an ID is. It is a correspondence between an +arbitrary string of characters and a value. It is used to declare various +names. The actual data type is unsigned int.

+

From char* to ID

+

The conversion from string to ID is executed by rb_intern(). This function +is rather long, so let’s omit the middle.

+

rb_intern() (simplified)

+
+5451  static st_table *sym_tbl;       /*  char* to ID   */
+5452  static st_table *sym_rev_tbl;   /*  ID to char*   */
+
+5469  ID
+5470  rb_intern(name)
+5471      const char *name;
+5472  {
+5473      const char *m = name;
+5474      ID id;
+5475      int last;
+5476
+          /* If for a name, there is a corresponding ID that is already
+          registered, then return that ID */
+5477      if (st_lookup(sym_tbl, name, &id))
+5478          return id;
+
+          /* omitted ... create a new ID */
+
+          /* register the name and ID relation */
+5538    id_regist:
+5539      name = strdup(name);
+5540      st_add_direct(sym_tbl, name, id);
+5541      st_add_direct(sym_rev_tbl, id, name);
+5542      return id;
+5543  }
+
+(parse.y)
+
+

The string and ID correspondence relationship can be accomplished by using the +st_table. There probably isn’t any especially difficult part here.

+

What is the omitted section doing? It is treating global variable names and +instance variables names as special and flagging them. This is because in the +parser, it is necessary to know the variable’s classification from the ID. +However, the fundamental part of ID is unrelated to this, so I won’t explain +it here.

+

From ID to char*

+

The reverse of rb_intern() is rb_id2name(), which takes an ID and +generates a char*. You probably know this, but the 2 in id2name is “to”. +“To” and “two” have the same pronounciation, so “2” is used for “to”. This +syntax is often seen.

+

This function also sets the ID classification flags so it is long. Let me +simplify it.

+

rb_id2name() (simplified)

+
+char *
+rb_id2name(id)
+    ID id;
+{
+    char *name;
+
+    if (st_lookup(sym_rev_tbl, id, &name))
+        return name;
+    return 0;
+}
+
+

Maybe it seems that it is a little over-simplified, but in reality if we remove +the details it really becomes this simple.

+

The point I want to emphasize is that the found name is not copied. The +ruby API does not require (or rather, it forbids) the free()-ing of the +return value. Also, when parameters are passed, it always +copies them. In other words, the creation and release is +completed by one side, either by the user or by ruby.

+

So then, when creation and release cannot be accomplished (when passed it is +not returned) on a value, then a Ruby object is used. I have not yet discussed +it, but a Ruby object is automatically released when it is no longer needed, +even if we are not taking care of the object.

+

Converting VALUE and ID

+

ID is shown as an instance of the Symbol class at the Ruby level. +And it can be obtained like so: "string".intern. The implementation of +String#intern is rb_str_intern().

+

rb_str_intern()

+
+2996  static VALUE
+2997  rb_str_intern(str)
+2998      VALUE str;
+2999  {
+3000      ID id;
+3001
+3002      if (!RSTRING(str)->ptr || RSTRING(str)->len == 0) {
+3003          rb_raise(rb_eArgError, "interning empty string");
+3004      }
+3005      if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
+3006          rb_raise(rb_eArgError, "string contains `\\0'");
+3007      id = rb_intern(RSTRING(str)->ptr);
+3008      return ID2SYM(id);
+3009  }
+
+(string.c)
+
+

This function is quite reasonable as a ruby class library code example. +Please pay attention to the part where RSTRING() is used and casted, and +where the data structure’s member is accessed.

+

Let’s read the code. First, rb_raise() is merely error handling so we ignore +it for now. The rb_intern() we previously examined is here, and also ID2SYM +is here. ID2SYM() is a macro that converts ID to Symbol.

+

And the reverse operation is accomplished using Symbol#to_s and such. +The implementation is in sym_to_s.

+

sym_to_s()

+
+ 522  static VALUE
+ 523  sym_to_s(sym)
+ 524      VALUE sym;
+ 525  {
+ 526      return rb_str_new2(rb_id2name(SYM2ID(sym)));
+ 527  }
+
+(object.c)
+
+

SYM2ID() is the macro that converts Symbol (VALUE) to an ID.

+

It looks like the function is not doing anything unreasonable. However, it +is probably necessary to pay attention to the area around the memory handling. +rb_id2name() returns a char* that must not be free(). rb_str_new2() +copies the parameter’s char* and uses the copy (and does not change the +parameter). In this way the policy is consistent, which allows the line to be +written just by chaining the functions.

+ + + +
+ + diff --git a/htmls/object.html b/htmls/object.html new file mode 100644 index 0000000..4d62593 --- /dev/null +++ b/htmls/object.html @@ -0,0 +1,1011 @@ + + + + + Objects - Structure of Ruby objects | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Vincent ISAMBART

+

Chapter 2: Objects

+

Structure of Ruby objects

+

Guideline

+

In this chapter we will begin exploring the ruby source code, starting by +studying the declaration of object structures.

+

What do objects need to exist? There are many answers to this question, but for +our purposes an object only needs three things:

+
    +
  1. The ability to differentiate itself from other objects (an identity)
  2. +
  3. The ability to respond to messages (methods)
  4. +
  5. The ability to store internal state (instance variables)
  6. +
+

In this chapter, we are going to confirm these three features one by one.

+

The most interesting file in this quest will be ruby.h, but we will also +briefly look at other files such as object.c, class.c or variable.c.

+

Structure of VALUE and objects

+

In ruby, the contents of an object are expressed by a C structure, always +handled via a pointer. A different kind of structure is used for each class, but +the pointer type will always be VALUE (figure 1).

+

+

(value)
+Figure 1: VALUE and structure

+

+

Here is the definition of VALUE:

+

VALUE

+
+  71  typedef unsigned long VALUE;
+
+(ruby.h)
+
+

In practice, a VALUE must be cast to different types of structure pointer. +Therefore if an unsigned long and a pointer have a different size, ruby +will not work well. Strictly speaking, it will not work for pointer types +bigger than sizeof(unsigned long). Fortunately, no recent machine feature +this capability, even if some time ago there were quite a few of them.

+

Several structures are available according to object classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
struct RObject all things for which none of the following + applies
struct RClass class object
struct RFloat small numbers
struct RString string
struct RArray array
struct RRegexp regular expression
struct RHash hash table
struct RFile IO, File, Socket, etc…
struct RData all the classes defined at C level, except the + ones mentioned above
struct RStruct Ruby’s Struct class
struct RBignum big integers
+

For example, for an string object, struct RString is used, so we will have +something like the following.

+

+

(string)
+Figure 2: String object

+

+

Let’s look at the definition of a few object structures.

+

▼ Examples of object structure

+
+      /* structure for ordinary objects */
+ 295  struct RObject {
+ 296      struct RBasic basic;
+ 297      struct st_table *iv_tbl;
+ 298  };
+
+      /* structure for strings (instance of String) */
+ 314  struct RString {
+ 315      struct RBasic basic;
+ 316      long len;
+ 317      char *ptr;
+ 318      union {
+ 319          long capa;
+ 320          VALUE shared;
+ 321      } aux;
+ 322  };
+
+      /* structure for arrays (instance of Array) */
+ 324  struct RArray {
+ 325      struct RBasic basic;
+ 326      long len;
+ 327      union {
+ 328          long capa;
+ 329          VALUE shared;
+ 330      } aux;
+ 331      VALUE *ptr;
+ 332  };
+
+(ruby.h)
+
+

Before looking at every one of them in detail, let’s begin with something more +general.

+

First, as VALUE is defined as unsigned long, it must be cast before +being used. That’s why Rxxxx() macros have been made for each object +structure. For example, for struct RString there is RSTRING(), for +struct RArray there is RARRAY(), etc… These macros are used like this:

+
+
+VALUE str = ....;
+VALUE arr = ....;
+RSTRING(str)->len;   /* ((struct RString*)str)->len */
+RARRAY(arr)->len;    /* ((struct RArray*)arr)->len */
+
+

Another important point to mention is that all object structures start with a +member basic of type struct RBasic. As a result, if you cast this VALUE to +struct RBasic*, you will be able to access the content of basic, regardless +of the type of structure pointed to by VALUE.

+

+

(rbasic)
+Figure 3: struct RBasic

+

+

You probably guessed that struct RBasic has been designed to contain some +important information shared by all object structures. Here is the definition +for struct RBasic:

+

struct RBasic

+
+ 290  struct RBasic {
+ 291      unsigned long flags;
+ 292      VALUE klass;
+ 293  };
+
+(ruby.h)
+
+

flags are multipurpose flags, mostly used to register the structure type +(for instance struct RObject). The type flags are named T_xxxx, and can be +obtained from a VALUE using the macro TYPE(). Here is an example:

+
+VALUE str;
+str = rb_str_new();    /* creates a Ruby string (its structure is RString) */
+TYPE(str);             /* the return value is T_STRING */
+
+

The names of these T_xxxx flags are directly linked to the corresponding type +name, like T_STRING for struct RString and T_ARRAY for struct RArray.

+

The other member of struct RBasic, klass, contains the class this object +belongs to. As the klass member is of type VALUE, what is stored is (a +pointer to) a Ruby object. In short, it is a class object.

+

+

(class)
+Figure 4: object and class

+

+

The relation between an object and its class will be detailed in the “Methods” +section of this chapter.

+

By the way, this member is named klass so as not to conflict with the reserved +word class when the file is processed by a C++ compiler.

+

About structure types

+

I said that the type of structure is stored in the flags member of +struct Basic. But why do we have to store the type of structure? It’s to be +able to handle all different types of structure via VALUE. If you cast a +pointer to a structure to VALUE, as the type information does not remain, +the compiler won’t be able to help. Therefore we have to manage the type +ourselves. That’s the consequence of being able to handle all the structure +types in a unified way.

+

OK, but the used structure is defined by the class so why are the structure +type and class are stored separately? Being able to find the structure type +from the class should be enough. There are two reasons for not doing this.

+

The first one is (I’m sorry for contradicting what I said before), in fact +there are structures that do not have a struct RBasic (i.e. they have no +klass member). For example struct RNode that will appear in the second +part of the book. However, flags is guaranteed to be in the beginning +members even in special structures like this. So if you put the type of +structure in flags, all the object structures can be differentiated in one +unified way.

+

The second reason is that there is no one-to-one correspondence between class +and structure. For example, all the instances of classes defined at the Ruby +level use struct RObject, so finding a structure from a class would require +to keep the correspondence between each class and structure. That’s why it’s +easier and faster to put the information about the type in the structure.

+

The use of basic.flags

+

As limiting myself to saying that basic.flags is used for different things +including the type of structure makes me feel bad, here’s a general +illustration for it (figure 5). There is no need to understand everything +right away, I just wanted to show its uses while it was bothering me.

+

+

(flags)
+Figure 5: Use of flags

+

+

When looking at the diagram, it looks like that 21 bits are not used on 32 bit +machines. On these additional bits, the flags FL_USER0 to FL_USER8 are +defined, and are used for a different purpose for each structure. In the +diagram I also put FL_USER0 (FL_SINGLETON) as an example.

+

Objects embedded in VALUE

+

As I said, VALUE is an unsigned long. As VALUE is a pointer, it may look +like void* would also be all right, but there is a reason for not doing +this. In fact, VALUE can also not be a pointer. The 6 cases for which +VALUE is not a pointer are the following:

+
    +
  1. small integers
  2. +
  3. symbols
  4. +
  5. true
  6. +
  7. false
  8. +
  9. nil
  10. +
  11. Qundef
  12. +
+

I’ll explain them one by one.

+

Small integers

+

Just like in Ruby itself, all data are objects. Likewise, integers are objects. +However during normal program execution, lots of instances of integers are +created. Using structures to express them would risk slowing down execution. For +example, if we created 50000 objects when incrementing from 0 to 50000 we’d +definitely have to consider the performance issues.

+

That’s why in ruby, to some extent, small integers are treated specially and +embedded directly into VALUE. “Small” means signed integers that can be held +in sizeof(VALUE)*8-1 bits. In other words, on 32 bits machines, the integers +have 1 bit for the sign, and 30 bits for the integer part. Integers in this +range will belong to the Fixnum class and the other integers will belong to +the Bignum class.

+

Let’s see in practice the INT2FIX() macro that converts from a C int +to a Fixnum, and confirm that Fixnum are directly embedded in VALUE.

+

INT2FIX

+
+ 123  #define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
+ 122  #define FIXNUM_FLAG 0x01
+
+(ruby.h)
+
+

In brief, shift 1 bit to the left, and bitwise or it with 1.

+ + + + + + + + + +
110100001000 before conversion
1101000010001 after conversion
+

That means that Fixnum as VALUE will always be an odd number. On the other +hand, as Ruby object structures are allocated with malloc(), they are +generally arranged on addresses multiple of 4. So they do not overlap with the +values of Fixnum as VALUE.

+

Also, to convert int or long to VALUE, we can use macros like +INT2NUM() or LONG2NUM(). Any conversion macro XXXX2XXXX with a name +containing NUM can manage both Fixnum and Bignum. For example if +INT2NUM() can’t convert an integer into a Fixnum, it will automatically +convert it to Bignum. NUM2INT() will convert both Fixnum and Bignum to +int. If the number can’t fit in an int, an exception will be raised, so +there is no need to check the value range.

+

Symbols

+

What are symbols?

+

As this question is quite troublesome to answer, let’s start with the reasons +why symbols were necessary. First, let’s start with the ID type used inside +ruby. It’s like this:

+

ID

+
+  72  typedef unsigned long ID;
+
+(ruby.h)
+
+

This ID is a number having a one-to-one association with a string. However, +in this world it’s not possible to have an association between all strings and +a numerical value. That’s why they are limited to the one to one relationships +inside one ruby process. I’ll speak of the method to find an ID in the +next chapter “Names and name tables”.

+

In language implementations, there are a lot of names to handle. Method names +or variable names, constant names, file names in class names… It’s +troublesome to handle all of them as strings (char*), because of memory +management and memory management and memory management… Also, lots of +comparisons would certainly be necessary, but comparing strings character by +character will slow down the execution. That’s why strings are not handled +directly, something will be associated and used instead. And generally that +“something” will be integers, as they are the simplest to handle.

+

These ID are found as symbols in the Ruby world. Up to ruby 1.4, the +values of ID were converted to Fixnum, but used as symbols. Even today +these values can be obtained using Symbol#to_i. However, as real use results +came piling up, it was understood that making Fixnum and Symbol the same +was not a good idea, so since 1.6 an independent class Symbol has been +created.

+

Symbol objects are used a lot, especially as keys for hash tables. That’s +why Symbol, like Fixnum, was made stored in VALUE. Let’s look at the +ID2SYM() macro converting ID to Symbol object.

+

ID2SYM

+
+ 158  #define SYMBOL_FLAG 0x0e
+ 160  #define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG))
+
+(ruby.h)
+
+

When shifting 8 bits left, x becomes a multiple of 256, that means a +multiple of 4. Then after with a bitwise or (in this case it’s the same as +adding) with 0x0e (14 in decimal), the VALUE expressing the symbol is not +a multiple of 4. Or even an odd number. So it does not overlap the range of +any other VALUE. Quite a clever trick.

+

Finally, let’s see the reverse conversion of ID2SYM(), SYM2ID().

+

SYM2ID()

+
+ 161  #define SYM2ID(x) RSHIFT((long)x,8)
+
+(ruby.h)
+
+

RSHIFT is a bit shift to the right. As right shift may keep or not the sign +depending of the platform, it became a macro.

+

true false nil

+

These three are Ruby special objects. true and false represent the boolean +values. nil is an object used to denote that there is no object. Their +values at the C level are defined like this:

+

true false nil

+
+ 164  #define Qfalse 0        /* Ruby's false */
+ 165  #define Qtrue  2        /* Ruby's true */
+ 166  #define Qnil   4        /* Ruby's nil */
+
+(ruby.h)
+
+

This time it’s even numbers, but as 0 or 2 can’t be used by pointers, they +can’t overlap with other VALUE. It’s because usually the first bloc of +virtual memory is not allocated, to make the programs dereferencing a NULL +pointer crash.

+

And as Qfalse is 0, it can also be used as false at C level. In practice, in +ruby, when a function returns a boolean value, it’s often made to return an +int or VALUE, and returns Qtrue/Qfalse.

+

For Qnil, there is a macro dedicated to check if a VALUE is Qnil or not, +NIL_P().

+

NIL_P()

+
+ 170  #define NIL_P(v) ((VALUE)(v) == Qnil)
+
+(ruby.h)
+
+

The name ending with p is a notation coming from Lisp denoting that it is a +function returning a boolean value. In other words, NIL_P means “is the +argument nil?”. It seems the “p” character comes from “predicate.” This +naming rule is used at many different places in ruby.

+

Also, in Ruby, false and nil are falsy (that is, they count as false in +conditional statements) and all the other objects are truthy. +However, in C, nil (Qnil) is true. That’s why in C a Ruby-style macro, +RTEST(), has been created.

+

RTEST()

+
+ 169  #define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
+
+(ruby.h)
+
+

As in Qnil only the third lower bit is 1, in ~Qnil only the third lower +bit is 0. Then only Qfalse and Qnil become 0 with a bitwise and.

+

!=0 has been added to be certain to only have 0 or 1, to satisfy the +requirements of the glib library that only wants 0 or 1 +([ruby-dev:11049]).

+

By the way, what is the ‘Q’ of Qnil? ‘R’ I would have understood but why +‘Q’? When I asked, the answer was “Because it’s like that in Emacs.” I did +not have the fun answer I was expecting…

+

Qundef

+

Qundef

+
+ 167  #define Qundef 6                /* undefined value for placeholder */
+
+(ruby.h)
+
+

This value is used to express an undefined value in the interpreter. It can’t +be found at all at the Ruby level.

+

Methods

+

I already brought up the three important points of a Ruby object: having an +identity, being able to call a method, and keeping data for each instance. In +this section, I’ll explain in a simple way the structure linking objects and +methods.

+

struct RClass

+

In Ruby, classes exist as objects during the execution. Of course. So there +must be a structure for class objects. That structure is struct RClass. Its +structure type flag is T_CLASS.

+

As class and modules are very similar, there is no need to differentiate their +content. That’s why modules also use the struct RClass structure, and are +differentiated by the T_MODULE structure flag.

+

struct RClass

+
+ 300  struct RClass {
+ 301      struct RBasic basic;
+ 302      struct st_table *iv_tbl;
+ 303      struct st_table *m_tbl;
+ 304      VALUE super;
+ 305  };
+
+(ruby.h)
+
+

First, let’s focus on the m_tbl (Method TaBLe) member. struct st_table is +an hashtable used everywhere in ruby. Its details will be explained in the +next chapter “Names and name tables”, but basically, it is a table mapping +names to objects. In the case of m_tbl, it keeps the +correspondence between the name (ID) of the methods possessed by this class +and the methods entity itself.

+

The fourth member super keeps, like its name suggests, the superclass. As +it’s a VALUE, it’s (a pointer to) the class object of the superclass. In Ruby +there is only one class that has no superclass (the root class): Object.

+

However I already said that all Object methods are defined in the Kernel +module, Object just includes it. As modules are functionally similar to +multiple inheritance, it may seem having just super is problematic, but +in ruby some clever changes are made to make it look like single +inheritance. The details of this process will be explained in the fourth +chapter “Classes and modules”.

+

Because of this, super of the structure of Object points to struct RClass +of the Kernel object. Only the super of Kernel is NULL. So contrary to +what I said, if super is NULL, this RClass is the Kernel object (figure +6).

+

+

(classtree)
+Figure 6: Class tree at the C level

+

+

Methods search

+

With classes structured like this, you can easily imagine the method call +process. The m_tbl of the object’s class is searched, and if the method was +not found, the m_tbl of super is searched, and so on. If there is no more +super, that is to say the method was not found even in Object, then it +must not be defined.

+

The sequential search process in m_tbl is done by search_method().

+

search_method()

+
+ 256  static NODE*
+ 257  search_method(klass, id, origin)
+ 258      VALUE klass, *origin;
+ 259      ID id;
+ 260  {
+ 261      NODE *body;
+ 262
+ 263      if (!klass) return 0;
+ 264      while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
+ 265          klass = RCLASS(klass)->super;
+ 266          if (!klass) return 0;
+ 267      }
+ 268
+ 269      if (origin) *origin = klass;
+ 270      return body;
+ 271  }
+
+(eval.c)
+
+

This function searches the method named id in the class object klass.

+

RCLASS(value) is the macro doing:

+
+((struct RClass*)(value))
+
+

st_lookup() is a function that searches in st_table the value +corresponding to a key. If the value is found, the function returns true and +puts the found value at the address given in third parameter (&body).

+

Nevertheless, doing this search each time whatever the circumstances would be +too slow. That’s why in reality, once called, a method is cached. So starting +from the second time it will be found without following super one by one. +This cache and its search will be seen in the 15th chapter “Methods”.

+

Instance variables

+

In this section, I will explain the implementation of the third essential +condition, instance variables.

+

rb_ivar_set()

+

Instance variables are what allows each object to store characteristic data. +Having it stored in the object itself (i.e. in the object structure) may seem +all right but how is it in practice? Let’s look at the function +rb_ivar_set() that puts an object in an instance variable.

+

rb_ivar_set()

+
+      /* write val in the id instance of obj */
+ 984  VALUE
+ 985  rb_ivar_set(obj, id, val)
+ 986      VALUE obj;
+ 987      ID id;
+ 988      VALUE val;
+ 989  {
+ 990      if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
+ 991          rb_raise(rb_eSecurityError,
+                       "Insecure: can't modify instance variable");
+ 992      if (OBJ_FROZEN(obj)) rb_error_frozen("object");
+ 993      switch (TYPE(obj)) {
+ 994        case T_OBJECT:
+ 995        case T_CLASS:
+ 996        case T_MODULE:
+ 997          if (!ROBJECT(obj)->iv_tbl)
+                  ROBJECT(obj)->iv_tbl = st_init_numtable();
+ 998          st_insert(ROBJECT(obj)->iv_tbl, id, val);
+ 999          break;
+1000        default:
+1001          generic_ivar_set(obj, id, val);
+1002          break;
+1003      }
+1004      return val;
+1005  }
+
+(variable.c)
+
+

rb_raise() and rb_error_frozen() are both error checks. Error checks are +necessary, but it’s not the main part of the treatment, so you should ignore +them at first read.

+

After removing error treatment, only the switch remains, but this

+
+switch (TYPE(obj)) {
+  case T_aaaa:
+  case T_bbbb:
+     ...
+}
+
+

form is characteristic of ruby. TYPE() is the macro returning the type +flag of the object structure (T_OBJECT, T_STRING, etc.). In other words as +the type flag is an integer constant, we can branch depending on it with a +switch. Fixnum or Symbol do not have structures, but inside TYPE() a +special treatment is done to properly return T_FIXNUM and T_SYMBOL, so +there’s no need to worry.

+

Well, let’s go back to rb_ivar_set(). It seems only the treatments of +T_OBJECT, T_CLASS and T_MODULE are different. These 3 have been chosen on +the basis that their second member is iv_tbl. Let’s confirm it in practice.

+

▼ Structures whose second member is iv_tbl

+
+      /* TYPE(val) == T_OBJECT */
+ 295  struct RObject {
+ 296      struct RBasic basic;
+ 297      struct st_table *iv_tbl;
+ 298  };
+
+      /* TYPE(val) == T_CLASS or T_MODULE */
+ 300  struct RClass {
+ 301      struct RBasic basic;
+ 302      struct st_table *iv_tbl;
+ 303      struct st_table *m_tbl;
+ 304      VALUE super;
+ 305  };
+
+(ruby.h)
+
+

iv_tbl is the Instance Variable TaBLe. It stores instance variable names and +their corresponding value.

+

In rb_ivar_set(), let’s look again the code for the structures having +iv_tbl.

+
+if (!ROBJECT(obj)->iv_tbl)
+    ROBJECT(obj)->iv_tbl = st_init_numtable();
+st_insert(ROBJECT(obj)->iv_tbl, id, val);
+break;
+
+

ROBJECT() is a macro that casts a VALUE into a `struct +RObject*. It's possible that obj` points to a struct RClass, but as +we’re only going to access the second member no problem will occur.

+

st_init_numtable() is a function creating a new st_table. st_insert() is +a function doing associations in a st_table.

+

In conclusion, this code does the following: if iv_tbl does not exist, it +creates it, then stores the [variable name → object] association.

+

Warning: as struct RClass is a class object, this instance variable table is +for the use of the class object itself. In Ruby programs, it corresponds to +something like the following:

+
+class C
+  @ivar = "content"
+end
+
+

generic_ivar_set()

+

For objects for which the structure used is not T_OBJECT, T_MODULE, or +T_CLASS, what happens when modifying an instance variable?

+

rb_ivar_set() in the case there is no iv_tbl

+
+1000  default:
+1001    generic_ivar_set(obj, id, val);
+1002    break;
+
+(variable.c)
+
+

The control is transferred to generic_ivar_set(). Before looking at this +function, let’s first explain its general idea.

+

Structures that are not T_OBJECT, T_MODULE or T_CLASS do not have an +iv_tbl member (the reason why they do not have it will be explained later). +However, a method linking an instance to a struct st_table would allow +instances to have instance variables. In ruby, this was solved by using a +global st_table, generic_iv_table (figure 7) for these associations.

+

+

(givtable)
+Figure 7: generic_iv_table

+

+

Let’s see this in practice.

+

generic_ivar_set()

+
+ 801  static st_table *generic_iv_tbl;
+
+ 830  static void
+ 831  generic_ivar_set(obj, id, val)
+ 832      VALUE obj;
+ 833      ID id;
+ 834      VALUE val;
+ 835  {
+ 836      st_table *tbl;
+ 837
+          /* for the time being you should ignore this */
+ 838      if (rb_special_const_p(obj)) {
+ 839          special_generic_ivar = 1;
+ 840      }
+          /* initialize generic_iv_tbl if it does not exist */
+ 841      if (!generic_iv_tbl) {
+ 842          generic_iv_tbl = st_init_numtable();
+ 843      }
+ 844
+          /* the treatment itself */
+ 845      if (!st_lookup(generic_iv_tbl, obj, &tbl)) {
+ 846          FL_SET(obj, FL_EXIVAR);
+ 847          tbl = st_init_numtable();
+ 848          st_add_direct(generic_iv_tbl, obj, tbl);
+ 849          st_add_direct(tbl, id, val);
+ 850          return;
+ 851      }
+ 852      st_insert(tbl, id, val);
+ 853  }
+
+(variable.c)
+
+

rb_special_const_p() is true when its parameter is not a pointer. However, +as this if part requires knowledge of the garbage collector, we’ll skip it +for now. I’d like you to check it again after reading the chapter 5 “Garbage +collection”.

+

st_init_numtable() already appeared some time ago. It creates a new hash +table.

+

st_lookup() searches a value corresponding to a key. In this case it +searches for what’s attached to obj. If an attached value can be found, the +whole function returns true and stores the value at the address (&tbl) given +as third parameter. In short, !st_lookup(...) can be read “if a value can’t +be found”.

+

st_insert() was also already explained. It stores a new association in a +table.

+

st_add_direct() is similar to st_insert(), but the part before adding the +association that checks if the key was already stored or not is different. In +other words, in the case of st_add_direct(), if a key already registered is +being used, two associations linked to this same key will be stored. +st_add_direct() can be used when the check for existence has already been +done, as is the case here, or when a new table has just been created.

+

FL_SET(obj, FL_EXIVAR) is the macro that sets the FL_EXIVAR flag in the +basic.flags of obj. The basic.flags flags are all named FL_xxxx and +can be set using FL_SET(). These flags can be unset with FL_UNSET(). The +EXIVAR from FL_EXIVAR seems to be the abbreviation of EXternal Instance +VARiable.

+

The setting of these flags is done to speed up the reading of instance +variables. If FL_EXIVAR is not set, even without searching in +generic_iv_tbl, we directly know if the object has instance variables. And +of course a bit check is way faster than searching a struct st_table.

+

Gaps in structures

+

Now you should understand how the instance variables are stored, but why are +there structures without iv_tbl? Why is there no iv_tbl in +struct RString or struct RArray? Couldn’t iv_tbl be part of RBasic?

+

Well, this could have been done, but there are good reasons why it was not. As +a matter of fact, this problem is deeply linked to the way ruby manages +objects.

+

For example, in ruby, memory used by string data (char[]) is directly +allocated using malloc(). However, the object structures are handled in a +particular way. ruby allocates them by clusters, and then distribute them +from these clusters. As at allocation time the diversity of types (and sizes) +of structures is difficult to handle, a type (union) that combines all +structures RVALUE was declared and an array of this type is managed. As this +type’s size is the same as the biggest one of its members, if there is only +one big structure, there is a lot of unused space. That’s why doing as much as +possible to regroup structures of similar size is desirable. The details about +RVALUE will be explained in chapter 5 “Garbage collection”.

+

Generally the most used structure is struct RString. After that, in programs +there are struct RArray (array), RHash (hash), RObject (user defined +object), etc. However, this struct RObject only uses the space of +struct RBasic + 1 pointer. On the other hand, struct RString, RArray and +RHash take the space of struct RBasic + 3 pointers. In other words, when +putting a struct RObject in the shared entity, the space for 2 pointers is +useless. And beyond that, if RString had 4 pointers, RObject would use less +that half the size of the shared entity. As you would expect, it’s wasteful.

+

So the received merit for iv_tbl is more or less saving memory and speeding +up. Furthermore we do not know if it is used often or not. In fact, +generic_iv_tbl was not introduced before ruby 1.2, so it was not possible +to use instance variables in String or Array at that time. Nevertheless, it +was not much of a problem. Making large amounts of memory useless just for +such functionality looks stupid.

+

If you take all this into consideration, you can conclude that increasing the +size of object structures does not do any good.

+

rb_ivar_get()

+

We saw the rb_ivar_set() function that sets variables, so let’s see quickly +how to get them.

+

rb_ivar_get()

+
+ 960  VALUE
+ 961  rb_ivar_get(obj, id)
+ 962      VALUE obj;
+ 963      ID id;
+ 964  {
+ 965      VALUE val;
+ 966
+ 967      switch (TYPE(obj)) {
+      /* (A) */
+ 968        case T_OBJECT:
+ 969        case T_CLASS:
+ 970        case T_MODULE:
+ 971          if (ROBJECT(obj)->iv_tbl &&
+                  st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
+ 972              return val;
+ 973          break;
+      /* (B) */
+ 974        default:
+ 975          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
+ 976              return generic_ivar_get(obj, id);
+ 977          break;
+ 978      }
+      /* (C) */
+ 979      rb_warning("instance variable %s not initialized", rb_id2name(id));
+ 980
+ 981      return Qnil;
+ 982  }
+
+(variable.c)
+
+

The structure is strictly the same.

+

(A) For struct RObject or RClass, we search the variable in iv_tbl. As +iv_tbl can also be NULL, we must check it before using it. Then if +st_lookup() finds the relation, it returns true, so the whole if can be +read as “If the instance variable has been set, return its value”.

+

(C) If no correspondence could be found, in other words if we read an +instance variable that has not been set, we first leave the if then the +switch. rb_warning() will then issue a warning and nil will be returned. +That’s because you can read instance variables that have not been set in Ruby.

+

(B) On the other hand, if the structure is neither struct RObject nor +RClass, the instance variable table is searched in generic_iv_tbl. What +generic_ivar_get() does can be easily guessed, so I won’t explain it. I’d +rather want you to focus on the if.

+

I already told you that generic_ivar_set() sets the FL_EXIVAR flag to make +the check faster.

+

And what is rb_special_const_p()? This function returns true when its +parameter obj does not point to a structure. As no structure means no +basic.flags, no flag can be set, and FL_xxxx() will always returns false. +That’s why these objects have to be treated specially.

+

Structures for objects

+

In this section we’ll see simply, among object structures, what the important +ones contain and how they are handled.

+

struct RString

+

struct RString is the structure for the instances of the String class and +its subclasses.

+

struct RString

+
+ 314  struct RString {
+ 315      struct RBasic basic;
+ 316      long len;
+ 317      char *ptr;
+ 318      union {
+ 319          long capa;
+ 320          VALUE shared;
+ 321      } aux;
+ 322  };
+
+(ruby.h)
+
+

ptr is a pointer to the string, and len the length of that string. Very +straightforward.

+

Rather than a string, Ruby’s string is more a byte array, and can contain any +byte including NUL. So when thinking at the Ruby level, ending the string +with NUL does not mean anything. As C functions require NUL, for +convenience the ending NUL is there, however, it is not included in len.

+

When dealing with a string coming from the interpreter or an extension +library, you can write RSTRING(str)->ptr or RSTRING(str)->len, and access +ptr and len. But there are some points to pay attention to.

+
    +
  1. you have to check before if str really points to a struct RString
  2. +
  3. you can read the members, but you must not modify them
  4. +
  5. you can’t store RSTRING(str)->ptr in something like a local variable and +use it later
  6. +
+

Why is that? First, there is an important software engineering principle: +Don’t arbitrarily tamper with someone’s data. Interface functions are there +for a reason. However, there are concrete reasons in ruby‘s design +why you should not do such things as consulting or storing a pointer, and +that’s related to the fourth member aux. However, to explain properly how to +use aux, we have to explain first a little more of Ruby’s strings’ +characteristics.

+

Ruby’s strings can be modified (are mutable). By mutable I mean after the +following code:

+
+s = "str"        # create a string and assign it to s
+s.concat("ing")  # append "ing" to this string object
+p(s)             # show the string
+
+

the content of the object pointed by s will become “string”. It’s +different from Java or Python string objects. Java’s StringBuffer is closer.

+

And what’s the relation? First, mutable means the length (len) of the string +can change. We have to increase or decrease the allocated memory size each time +the length changes. We can of course use realloc() for that, but generally +malloc() and realloc() are heavy operations. Having to realloc() each +time the string changes is a huge burden.

+

That’s why the memory pointed by ptr has been allocated with a size a little +bigger than len. Because of that, if the added part can fit into the +remaining memory, it’s taken care of without calling realloc(), so it’s +faster. The structure member aux.capa contains the length including this +additional memory.

+

So what is this other aux.shared? It’s to speed up the creation of literal +strings. Have a look at the following Ruby program.

+
+while true do  # repeat indefinitely
+  a = "str"        # create a string with "str" as content and assign it to a
+  a.concat("ing")  # append "ing" to the object pointed by a
+  p(a)             # show "string"
+end
+
+

Whatever the number of times you repeat the loop, the fourth line’s p has to +show "string". That’s why the code "str" should create, each time, a string +object holding a different char[]. However, if no change occurs for a lot of +strings, useless copies of char[] can be created many times. It would be better +to share one common char[].

+

The trick that allows this to happen is aux.shared. String objects created +with a literal use one shared char[]. When a change occurs, the string is +copied in unshared memory, and the change is done on this new copy. This +technique is called “copy-on-write”. When using a shared char[], the flag +ELTS_SHARED is set in the object structure’s basic.flags, and aux.shared +contains the original object. ELTS seems to be the abbreviation of +ELemenTS.

+

But, well, let’s return to our talk about RSTRING(str)->ptr. Even if +consulting the pointer is OK, you must not modify it, first because the value +of len or capa will no longer agree with the content, and also because when +modifying strings created as litterals, aux.shared has to be separated.

+

To finish this section about RString, let’s write some examples how to use +it. str is a VALUE that points to RString.

+
+RSTRING(str)->len;               /* length */
+RSTRING(str)->ptr[0];            /* first character */
+str = rb_str_new("content", 7);  /* create a string with "content" as its content
+                                    the second parameter is the length */
+str = rb_str_new2("content");    /* create a string with "content" as its content
+                                    its length is calculated with strlen() */
+rb_str_cat2(str, "end");         /* Concatenate a C string to a Ruby string */
+
+

struct RArray

+

struct RArray is the structure for the instances of Ruby’s array class +Array.

+

struct RArray

+
+ 324  struct RArray {
+ 325      struct RBasic basic;
+ 326      long len;
+ 327      union {
+ 328          long capa;
+ 329          VALUE shared;
+ 330      } aux;
+ 331      VALUE *ptr;
+ 332  };
+
+(ruby.h)
+
+

Except for the type of ptr, this structure is almost the same as +struct RString. ptr points to the content of the array, and len is its +length. aux is exactly the same as in struct RString. aux.capa is the +“real” length of the memory pointed by ptr, and if ptr is shared, +aux.shared stores the shared original array object.

+

From this structure, it’s clear that Ruby’s Array is an array and not a +list. So when the number of elements changes in a big way, a realloc() must +be done, and if an element must be inserted at an other place than the end, a +memmove() will occur. But even if we do it, it’s moving so fast it’s really +impressive on current machines.

+

That’s why the way to access it is similar to RString. You can consult +RARRAY(arr)->ptr and RARRAY(arr)->len members, but can’t set them, etc., +etc. We’ll only look at simple examples:

+
+/* manage an array from C */
+VALUE ary;
+ary = rb_ary_new();             /* create an empty array */
+rb_ary_push(ary, INT2FIX(9));   /* push a Ruby 9 */
+RARRAY(ary)->ptr[0];            /* look what's at index 0 */
+rb_p(RARRAY(ary)->ptr[0]);      /* do p on ary[0] (the result is 9) */
+
+# manage an array from Ruby
+ary = []      # create an empty array
+ary.push(9)   # push 9
+ary[0]        # look what's at index 0
+p(ary[0])     # do p on ary[0] (the result is 9)
+
+

struct RRegexp

+

It’s the structure for the instances of the regular expression class Regexp.

+

struct RRegexp

+
+ 334  struct RRegexp {
+ 335      struct RBasic basic;
+ 336      struct re_pattern_buffer *ptr;
+ 337      long len;
+ 338      char *str;
+ 339  };
+
+(ruby.h)
+
+

ptr is the regular expression after compilation. str is the string before +compilation (the source code of the regular expression), and len is this +string’s length.

+

As the Regexp object handling code doesn’t appear in this book, we won’t see +how to use it. Even if you use it in extension libraries, as long as you do +not want to use it a very particular way, the interface functions are enough.

+

struct RHash

+

struct RHash is the structure for Ruby’s Hash objects.

+

struct RHash

+
+ 341  struct RHash {
+ 342      struct RBasic basic;
+ 343      struct st_table *tbl;
+ 344      int iter_lev;
+ 345      VALUE ifnone;
+ 346  };
+
+(ruby.h)
+
+

It’s a wrapper for struct st_table. st_table will be detailed in the next +chapter “Names and name tables”.

+

ifnone is the value when a key does not have an attached value, its default +is nil. iter_lev is to make the hashtable reentrant (multithread safe).

+

struct RFile

+

struct RFile is a structure for instances of the built-in IO class and +its subclasses.

+

struct RFile

+
+ 348  struct RFile {
+ 349      struct RBasic basic;
+ 350      struct OpenFile *fptr;
+ 351  };
+
+(ruby.h)
+
+

OpenFile

+
+  19  typedef struct OpenFile {
+  20      FILE *f;                    /* stdio ptr for read/write */
+  21      FILE *f2;                   /* additional ptr for rw pipes */
+  22      int mode;                   /* mode flags */
+  23      int pid;                    /* child's pid (for pipes) */
+  24      int lineno;                 /* number of lines read */
+  25      char *path;                 /* pathname for file */
+  26      void (*finalize) _((struct OpenFile*)); /* finalize proc */
+  27  } OpenFile;
+
+(rubyio.h)
+
+

All members have been transferred in struct OpenFile. As there aren’t many +instances of IO objects, it’s OK to do it like this. The purpose of each member +is written in the comments. Basically, it’s a wrapper around C’s stdio.

+

struct RData

+

struct RData has a different tenor from what we saw before. It is the +structure for implementation of extension libraries.

+

Of course structures for classes created in extension libraries as necessary, +but as the types of these structures depend of the created class, it’s +impossible to know their size or structure in advance. That’s why a “structure +for managing a pointer to a user defined structure” has been created on +ruby’s side to manage this. This structure is struct RData.

+

struct RData

+
+ 353  struct RData {
+ 354      struct RBasic basic;
+ 355      void (*dmark) _((void*));
+ 356      void (*dfree) _((void*));
+ 357      void *data;
+ 358  };
+
+(ruby.h)
+
+

data is a pointer to the user defined structure, +dfree is the function used to free this structure, and +dmark is the function for when the “mark” of the mark and sweep occurs.

+

Because explaining struct RData is still too complicated, for +the time being let’s just look at its representation (figure 8). You’ll read +a detailed explanation of its members in chapter 5 “Garbage collection” where +there’ll be presented once again.

+

+

(rdata)
+Figure 8: Representation of struct RData

+

+ + + +
+ + diff --git a/htmls/parser.html b/htmls/parser.html new file mode 100644 index 0000000..7ce5a6e --- /dev/null +++ b/htmls/parser.html @@ -0,0 +1,2014 @@ + + + + + Parser | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Robert GRAVINA & ocha-

+

Chapter 10: Parser

+

Outline of this chapter

+

Parser construction

+

The main source of the parser is parser.y. +Because it is *.y, it is the input for yacc +and parse.c is generated from it.

+

Although one would expect lex.c to contain the scanner, this is not the case. +This file is created by gperf, taking the file keywords as input, and +defines the reserved word hashtable. This tool-generated lex.c is #included +in (the also tool-generated) parse.c. The details of this process is somewhat +difficult to explain at this time, so we shall return to this later.

+

Figure 1 shows the parser construction process. For the benefit of those readers +using Windows who may not be aware, the mv (move) command creates a new copy +of a file and removes the original. cc is, of course, the C compiler and cpp +the C pre-processor.

+

+

(build)
+Figure 1: Parser construction process

+

+

Dissecting parse.y

+

Let’s now look at parse.y in a bit more detail. The following figure presents +a rough outline of the contents of parse.y.

+

▼ parse.y +

+%{
+header
+%}
+%union ….
+%token ….
+%type ….

+

%%

+

rules

+

%% +user code section + parser interface + scanner (character stream processing) + syntax tree construction + semantic analysis + local variable management + ID implementation +

+

As for the rules and definitions part, it is as previously described. +Since this part is indeed the heart of the parser, +I’ll start to explain it ahead of the other parts in the next section.

+

There are a considerable number of support functions defined in the user code +section, but roughly speaking, they can be divided into the six parts +written above. The following table shows where each of parts are +explained in this book.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PartChapterSection
Parser interfaceThis chapterSection 3 “Scanning”
ScannerThis chapterSection 3 “Scanning”
Syntax tree constructionChapter 12 “Syntax tree construction”Section 2 “Syntax tree construction”
Semantic analysisChapter 12 “Syntax tree construction”Section 3 “Semantic analysis”
Local variable managementChapter 12 “Syntax tree construction”Section 4 “Local variables”
ID implementationChapter 3 “Names and name tables”Section 2 “ID and symbols”
+

General remarks about grammar rules

+

Coding rules

+

The grammar of ruby conforms to a coding standard and is thus easy to read +once you are familiar with it.

+

Firstly, regarding symbol names, all non-terminal symbols are written in lower +case characters. Terminal symbols are prefixed by some lower case character and +then followed by upper case. Reserved words (keywords) are prefixed with the +character k. Other terminal symbols are prefixed with the character t.

+

▼ Symbol name examples

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TokenSymbol name
(non-terminal symbol)bodystmt
ifkIF
defkDEF
rescuekRESCUE
varnametIDENTIFIER
ConstNametCONST
1tINTEGER
+

The only exceptions to these rules are klBEGIN and klEND. These symbol names +refer to the reserved words for “BEGIN” and “END”, respectively, and the l +here stands for large. Since the reserved words begin and end already +exist (naturally, with symbol names kBEGIN and kEND), these non-standard +symbol names were required.

+

Important symbols

+

parse.y contains both grammar rules and actions, however, for now I would like +to concentrate on the grammar rules alone. The script sample/exyacc.rb can be +used to extract the grammar rules from this file. +Aside from this, running yacc -v will create a logfile y.output +which also contains the grammar rules, +however it is rather difficult to read. In this chapter I have used a slighty +modified version of exyacc.rb\footnote{modified exyacc.rb:tools/exyacc2.rb +located on the attached CD-ROM} to extract the grammar rules.

+

parse.y(rules) +

+program         : compstmt

+

bodystmt : compstmt + opt_rescue + opt_else + opt_ensure

+

compstmt : stmts opt_terms + : + : +

+

The output is quite long – over 450 lines of grammar rules – and as such I have +only included the most important parts in this chapter.

+

Which symbols, then, are the most important? The names such as program, expr, +stmt,primary, arg etc. are always very important. It’s because they +represent the general parts of the grammatical elements of a programming +language. The following table outlines the elements we should generally focus on +in the syntax of a program.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Syntax elementPredicted symbol names
Programprogram prog file input stmts whole
Sentencestatement stmt
Expressionexpression expr exp
Smallest elementprimary prim
Left hand side of an expressionlhs(left hand side)
Right hand side of an expressionrhs(right hand side)
Function callfuncall function_call call function
Method callmethod method_call call
Argumentargument arg
Function definitiondefun definition function fndef
Declarationsdeclaration decl
+

In general, programming languages tend to have the following hierarchy structure.

+ + + + + + + + + + + + + + + + + + + + + +
Program elementProperties
ProgramUsually a list of statements
StatementWhat can not be combined with the others. A syntax tree trunk.
ExpressionWhat is a combination by itself and can also be a part of another +expression. A syntax tree internal node.
PrimaryAn element which can not be further decomposed. A syntax tree leaf node.
+

The statements are things like function definitions in C or class definitions +in Java. An expression can be a procedure call, an arithmetic expression +etc., while a primary usually refers to a string literal or number. Some languages +do not contain all of these symbol types, however they generally contain some +kind of hierarchy of symbols such as programstmtexprprimary.

+

However, a structure at a low level can be contained by a superior structure. +For example, in C a function call is an expression but it can solely be put. +It means it is an expression but it can also be a statement.

+

Conversely, when surrounded in parentheses, expressions become primaries. +It is because the lower the level of a element the higher the precedence it has.

+

The range of statements differ considerably between programming languages. +Let’s consider assignment as an example. +In C, because it is part of expressions, we can use the value of the whole +assignment expression. But in Pascal, assignment is a statement, we cannot do +such thing. Also, +function and class definitions are typically statements however in languages +such as Lisp and Scheme, since everything is an expression, +they do not have statements in the first place. +Ruby is close to Lisp’s design in this regard.

+

Program structure

+

Now let’s turn our attention to the grammar rules of ruby. Firstly, +in yacc, the left hand side of the first rule represents the entire grammar. +Currently, it is program. +Following further and further from here, +as the same as the established tactic, +the four program stmt expr primary will be found. +With adding arg to them, let’s look at their rules.

+

ruby grammar (outline) +

+program         : compstmt

+

compstmt : stmts opt_terms

+

stmts : none + | stmt + | stmts terms stmt

+

stmt : kALIAS fitem fitem + | kALIAS tGVAR tGVAR + : + : + | expr

+

expr : kRETURN call_args + | kBREAK call_args + : + : + | ‘!’ command_call + | arg

+

arg : lhs ‘=’ arg + | var_lhs tOP_ASGN arg + | primary_value ‘[’ aref_args ‘]’ tOP_ASGN arg + : + : + | arg ‘?’ arg ‘:’ arg + | primary

+

primary : literal + | strings + : + : + | tLPAREN_ARG expr ‘)’ + | tLPAREN compstmt ‘)’ + : + : + | kREDO + | kRETRY +

+

If we focus on the last rule of each element, +we can clearly make out a hierarchy of programstmtexprarg→ +primary.

+

Also, we’d like to focus on this rule of primary.

+
+primary         : literal
+                    :
+                    :
+                | tLPAREN_ARG expr  ')'      /* here */
+
+

The name tLPAREN_ARG comes from t for terminal symbol, L for left and +PAREN for parentheses – it is the open parenthesis. Why this isn’t '(' +is covered in the next section “Context-dependent scanner”. Anyway, the purpose +of this rule is demote an expr to a primary. This creates +a cycle which can the seen in Figure 2, and the arrow shows how this rule is +reduced during parsing.

+

+

(exprloop)
+Figure 2: expr demotion

+

+

The next rule is also particularly interesting.

+
+primary         : literal
+                    :
+                    :
+                | tLPAREN compstmt ')'   /* here */
+
+

A compstmt, which equals to the entire program (program), can be demoted to +a primary with this rule. The next figure illustrates this rule in action.

+

+

(progloop)
+Figure 3: program demotion

+

+

This means that for any syntax element in Ruby, if we surround it with +parenthesis it will become a primary and can be passed as an argument to a +function, be used as the right hand side of an expression etc. +This is an incredible fact. +Let’s actually confirm it.

+
+p((class C; end))
+p((def a() end))
+p((alias ali gets))
+p((if true then nil else nil end))
+p((1 + 1 * 1 ** 1 - 1 / 1 ^ 1))
+
+

If we invoke ruby with the -c option (syntax check), we get the following +output.

+
+% ruby -c primprog.rb
+Syntax OK
+
+

Indeed, it’s hard to believe but, it could actually pass. +Apparently, we did not get the wrong idea.

+

If we care about the details, +since there are what rejected by the semantic analysis (see also Chapter 12 +“Syntax tree construction”), it is not perfectly possible. +For example passing a return statement as an argument to a +function will result in an error. +But at least at the level of the outlooks, the “surrounding +anything in parenthesis means it can be passed as an argument to a function” +rule does hold.

+

In the next section I will cover the contents of the important elements one by +one.

+

program

+

program +

+program         : compstmt

+

compstmt : stmts opt_terms

+

stmts : none + | stmt + | stmts terms stmt +

+

As mentioned earlier, +program represents the entire grammar that means the entire program. +That program equals to compstmts, +and compstmts is almost equivalent to stmts. +That stmts is a list of stmts delimited by terms. +Hence, the entire program is a list of stmts delimited by terms.

+

terms is (of course) an abbreviation for “terminators”, the symbols that +terminate the sentences, such as semicolons or newlines. +opt_terms means “OPTional terms”. The definitions are as follows:

+

opt_terms +

+opt_terms       :
+                | terms

+

terms : term + | terms ‘;’

+

term : ‘;’ + | ‘\n’ +

+

The initial ; or \n of a terms can be followed by any number of ; only; based on that, you might start thinking that if there are 2 or more consecutive newlines, it could cause a problem. Let’s try and see what actually happens.

+
+1 + 1   # first newline
+        # second newline
+        # third newline
+1 + 1
+
+

Run that with ruby -c.

+
+% ruby -c optterms.rb
+Syntax OK
+
+

Strange, it worked! What actually happens is this: consecutive newlines are simply discarded by the scanner, which returns only the first newline in a series.

+

By the way, although we said that program is the same as compstmt, if that was really true, you would question why compstmt exists at all. Actually, the distinction is there only for execution of semantic actions. program exists to execute any semantic actions which should be done once in the processing of an entire program. If it was only a question of parsing, program could be omitted with no problems at all.

+

To generalize this point, the grammar rules can be divided into 2 groups: those which are needed for parsing the program structure, and those which are needed for execution of semantic actions. The none rule which was mentioned earlier when talking about stmts is another one which exists for executing actions — it’s used to return a NULL pointer for an empty list of type NODE*.

+

stmt

+

Next is stmt. This one is rather involved, so we’ll look into it a bit at a time.

+

stmt(1) +

+stmt            : kALIAS fitem  fitem
+                | kALIAS tGVAR tGVAR
+                | kALIAS tGVAR tBACK_REF
+                | kALIAS tGVAR tNTH_REF
+                | kUNDEF undef_list
+                | stmt kIF_MOD expr_value
+                | stmt kUNLESS_MOD expr_value
+                | stmt kWHILE_MOD expr_value
+                | stmt kUNTIL_MOD expr_value
+                | stmt kRESCUE_MOD stmt
+                | klBEGIN ‘{’ compstmt ‘}’
+                | klEND ‘{’ compstmt ‘}’
+

+

Looking at that, somehow things start to make sense. The first few have alias, then undef, then the next few are all something followed by _MOD — those should be statements with postposition modifiers, as you can imagine.

+

expr_value and primary_value are grammar rules which exist to execute semantic actions. For example, expr_value represents an expr which has a value. Expressions which don’t have values are return and break, or return/break followed by a postposition modifier, such as an if clause. For a detailed definition of what it means to “have a value”, see chapter 12, “Syntax Tree Construction”. In the same way, primary_value is a primary which has a value.

+

As explained earlier, klBEGIN and klEND represent BEGIN and END.

+

stmt(2) +

+                | lhs ‘=’ command_call
+                | mlhs ‘=’ command_call
+                | var_lhs tOP_ASGN command_call
+                | primary_value ‘[’ aref_args ‘]’ tOP_ASGN command_call
+                | primary_value ‘.’ tIDENTIFIER tOP_ASGN command_call
+                | primary_value ‘.’ tCONSTANT tOP_ASGN command_call
+                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
+                | backref tOP_ASGN command_call
+

+

Looking at these rules all at once is the right approach. +The common point is that they all have command_call on the right-hand side. command_call represents a method call with the parentheses omitted. The new symbols which are introduced here are explained in the following table. I hope you’ll refer to the table as you check over each grammar rule.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
lhs the left hand side of an assignment (Left Hand Side)
mlhs the left hand side of a multiple assignment (Multiple Left Hand Side)
var_lhs the left hand side of an assignment to a kind of variable (VARiable Left Hand Side)
tOP_ASGNcompound assignment operator like += or *= (OPerator ASsiGN)
aref_argsargument to a [] method call (Array REFerence)
tIDENTIFIERidentifier which can be used as a local variable
tCONSTANTconstant identifier (with leading uppercase letter)
tCOLON2::
backref$1 $2 $3...
+

aref is a Lisp jargon. +There’s also aset as the other side of a pair, +which is an abbreviation of “array set”. +This abbreviation is used at a lot of places in the source code of ruby.

+

stmt (3)

+
+                | lhs '=' mrhs_basic
+                | mlhs '=' mrhs
+
+

These two are multiple assignments. +mrhs has the same structure as mlhs and it means multiple rhs (the right hand side). +We’ve come to recognize that knowing the meanings of names makes the comprehension much easier.

+

stmt (4)

+
+                | expr
+
+

Lastly, it joins to expr.

+

expr

+

expr

+
+expr            : kRETURN call_args
+                | kBREAK call_args
+                | kNEXT call_args
+                | command_call
+                | expr kAND expr
+                | expr kOR expr
+                | kNOT expr
+                | '!' command_call
+                | arg
+
+

Expression. The expression of ruby is very small in grammar. +That’s because those ordinary contained in expr are mostly went into arg. +Conversely speaking, those who could not go to arg are left here. +And what are left are, again, method calls without parentheses. +call_args is an bare argument list, +command_call is, as previously mentioned, a method without parentheses. +If this kind of things was contained in the “small” unit, +it would cause conflicts tremendously.

+

However, these two below are of different kind.

+
+expr kAND expr
+expr kOR expr
+
+

kAND is “and”, and kOR is “or”. +Since these two have their roles as control structures, +they must be contained in the “big” syntax unit which is larger than command_call. +And since command_call is contained in expr, +at least they need to be expr to go well. +For example, the following usage is possible …

+
+  valid_items.include? arg  or raise ArgumentError, 'invalid arg'
+# valid_items.include?(arg) or raise(ArgumentError, 'invalid arg')
+
+

However, if the rule of kOR existed in arg instead of expr, +it would be joined as follows.

+
+valid_items.include?((arg or raise)) ArgumentError, 'invalid arg'
+
+

Obviously, this would end up a parse error.

+

arg

+

arg

+
+arg             : lhs '=' arg
+                | var_lhs tOP_ASGN arg
+                | primary_value '[' aref_args ']' tOP_ASGN arg
+                | primary_value '.' tIDENTIFIER tOP_ASGN arg
+                | primary_value '.' tCONSTANT tOP_ASGN arg
+                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
+                | backref tOP_ASGN arg
+                | arg tDOT2 arg
+                | arg tDOT3 arg
+                | arg '+' arg
+                | arg '-' arg
+                | arg '*' arg
+                | arg '/' arg
+                | arg '%' arg
+                | arg tPOW arg
+                | tUPLUS arg
+                | tUMINUS arg
+                | arg '|' arg
+                | arg '^' arg
+                | arg '&' arg
+                | arg tCMP arg
+                | arg '>' arg
+                | arg tGEQ arg
+                | arg '<' arg
+                | arg tLEQ arg
+                | arg tEQ arg
+                | arg tEQQ arg
+                | arg tNEQ arg
+                | arg tMATCH arg
+                | arg tNMATCH arg
+                | '!' arg
+                | '~' arg
+                | arg tLSHFT arg
+                | arg tRSHFT arg
+                | arg tANDOP arg
+                | arg tOROP arg
+                | kDEFINED opt_nl  arg
+                | arg '?' arg ':' arg
+                | primary
+
+

Although there are many rules here, the complexity of the grammar is not +proportionate to the number of rules. +A grammar that merely has a lot of cases can be handled very easily by yacc, +rather, the depth or recursive of the rules has more influences the complexity.

+

Then, it makes us curious about the rules are defined recursively in the form +of arg OP arg at the place for operators, +but because for all of these operators their operator precedences are defined, +this is virtually only a mere enumeration. +Let’s cut the “mere enumeration” out from the arg rule by merging.

+
+arg: lhs '=' arg              /* 1 */
+   | primary T_opeq arg       /* 2 */
+   | arg T_infix arg          /* 3 */
+   | T_pre arg                /* 4 */
+   | arg '?' arg ':' arg      /* 5 */
+   | primary                  /* 6 */
+
+

There’s no meaning to distinguish terminal symbols from lists of terminal symbols, +they are all expressed with symbols with T_. +opeq is operator + equal, +T_pre represents the prepositional operators such as '!' and '~', +T_infix represents the infix operators such as '*' and '%'.

+

To avoid conflicts in this structure, +things like written below become important +(but, these does not cover all).

+
    +
  • T_infix should not contain '='.
  • +
+

Since args partially overlaps lhs, +if '=' is contained, the rule 1 and the rule 3 cannot be distinguished.

+
    +
  • T_opeq and T_infix should not have any common rule.
  • +
+

Since args contains primary, +if they have any common rule, the rule 2 and the rule 3 cannot be distinguished.

+
    +
  • T_infix should not contain '?'.
  • +
+

If it contains, the rule 3 and 5 would produce a shift/reduce conflict.

+
    +
  • T_pre should not contain '?' or ':'.
  • +
+

If it contains, the rule 4 and 5 would conflict in a very complicated way.

+

The conclusion is all requirements are met and this grammar does not conflict. +We could say it’s a matter of course.

+

primary

+

Because primary has a lot of grammar rules, we’ll split them up and show them in parts.

+

primary (1)

+
+primary         : literal
+                | strings
+                | xstring
+                | regexp
+                | words
+                | qwords
+
+

Literals. +literal is for Symbol literals (:sym) and numbers.

+

primary (2)

+
+                | var_ref
+                | backref
+                | tFID
+
+

Variables. +var_ref is for local variables and instance variables and etc. +backref is for $1 $2 $3 … +tFID is for the identifiers with ! or ?, say, include? reject!. +There’s no possibility of tFID being a local variable, +even if it appears solely, it becomes a method call at the parser level.

+

primary (3)

+
+                | kBEGIN
+                  bodystmt
+                  kEND
+
+

bodystmt contains rescue and ensure. +It means this is the begin of the exception control.

+

primary (4)

+
+                | tLPAREN_ARG expr  ')'
+                | tLPAREN compstmt ')'
+
+

This has already described. Syntax demoting.

+

primary (5)

+
+                | primary_value tCOLON2 tCONSTANT
+                | tCOLON3 cname
+
+

Constant references. tCONSTANT is for constant names (capitalized identifiers).

+

Both tCOLON2 and tCOLON3 are ::, +but tCOLON3 represents only the :: which means the top level. +In other words, it is the :: of ::Const. +The :: of Net::SMTP is tCOLON2.

+

The reason why different symbols are used for the same token +is to deal with the methods without parentheses. +For example, it is to distinguish the next two from each other:

+
+p Net::HTTP    # p(Net::HTTP)
+p Net  ::HTTP  # p(Net(::HTTP))
+
+

If there’s a space or a delimiter character such as an open parenthesis just before it, +it becomes tCOLON3. In the other cases, it becomes tCOLON2.

+

primary (6)

+
+                | primary_value '[' aref_args ']'
+
+

Index-form calls, for instance, arr[i].

+

primary (7)

+
+                | tLBRACK aref_args ']'
+                | tLBRACE assoc_list '}'
+
+

Array literals and Hash literals. +This tLBRACK represents also '[', +'[' means a '[' without a space in front of it. +The necessity of this differentiation is also a side effect of method calls +without parentheses.

+

The terminal symbols of this rule is very incomprehensible because they differs +in just a character. +The following table shows how to read each type of parentheses, +so I’d like you to make use of it when reading.

+

▼ English names for each parentheses

+ + + + + + + + + + + + + + + + + +
Symbol English Name
() parentheses
{} braces
[] brackets
+

primary (8)

+
+                | kRETURN
+                | kYIELD '(' call_args ')'
+                | kYIELD '(' ')'
+                | kYIELD
+                | kDEFINED opt_nl '('  expr ')'
+
+

Syntaxes whose forms are similar to method calls. +Respectively, return, yield, defined?.

+

There arguments for yield, but return does not have any arguments. Why? +The fundamental reason is that yield itself has its return value but +return does not. +However, even if there’s not any arguments here, +it does not mean you cannot pass values, of course. +There was the following rule in expr.

+
+kRETURN call_args
+
+

call_args is a bare argument list, +so it can deal with return 1 or return nil. +Things like return(1) are handled as return (1). +For this reason, +surrounding the multiple arguments of a return with parentheses +as in the following code should be impossible.

+
+return(1, 2, 3)   # interpreted as return  (1,2,3) and results in parse error
+
+

You could understand more about around here +if you will check this again after reading +the next chapter “Finite-State Scanner”.

+

primary (9)

+
+                | operation brace_block
+                | method_call
+                | method_call brace_block
+
+

Method calls. method_call is with arguments (also with parentheses), +operation is without both arguments and parentheses, +brace_block is either { ~ } or do ~ end +and if it is attached to a method, the method is an iterator. +For the question “Even though it is brace, why is do ~ end contained in +it?”, there’s a reason that is more abyssal than Marian Trench, +but again the only way to understand is reading +the next chapter “Finite-State Scanner”.

+

primary (10)

+
+  | kIF expr_value then compstmt if_tail kEND         # if
+  | kUNLESS expr_value then compstmt opt_else kEND    # unless
+  | kWHILE expr_value do compstmt kEND                # while
+  | kUNTIL expr_value do compstmt kEND                # until
+  | kCASE expr_value opt_terms case_body kEND         # case
+  | kCASE opt_terms case_body kEND                    # case(Form2)
+  | kFOR block_var kIN expr_value do compstmt kEND    # for
+
+

The basic control structures. +A little unexpectedly, things appear to be this big are put inside primary, +which is “small”. +Because primary is also arg, +we can also do something like this.

+
+p(if true then 'ok' end)   # shows "ok"
+
+

I mentioned “almost all syntax elements are expressions” +was one of the traits of Ruby. +It is concretely expressed by the fact that if and while are in primary.

+

Why is there no problem if these “big” elements are contained in primary? +That’s because the Ruby’s syntax has a trait that “it begins with the terminal +symbol A and ends with the terminal symbol B”. +In the next section, we’ll think about this point again.

+

primary (11)

+
+  | kCLASS cname superclass bodystmt kEND        # class definition
+  | kCLASS tLSHFT expr term bodystmt kEND        # singleton class definition
+  | kMODULE cname bodystmt kEND                  # module definition
+  | kDEF fname f_arglist bodystmt kEND           # method definition
+  | kDEF singleton dot_or_colon fname f_arglist bodystmt kEND
+                                                 # singleton method definition
+
+

Definition statements. +I’ve called them the class statements and the class statements, +but essentially I should have been called them the class primaries, probably. +These are all fit the pattern “beginning with the terminal symbol A and ending with B”, +even if such rules are increased a lot more, +it would never be a problem.

+

primary (12)

+
+                | kBREAK
+                | kNEXT
+                | kREDO
+                | kRETRY
+
+

Various jumps. +These are, well, not important from the viewpoint of grammar.

+

Conflicting Lists

+

In the previous section, the question “is it all right that if is in such +primary?” was suggested. +To proof precisely is not easy, +but explaining instinctively is relatively easy. +Here, let’s simulate with a small rule defined as follows:

+
+%token A B o
+%%
+element   : A item_list B
+
+item_list :
+          | item_list item
+
+item      : element
+          | o
+
+

element is the element that we are going to examine. +For example, if we think about if, it would be if. +element is a list that starts with the terminal symbol A and ends with B. +As for if, it starts with if and ends with end. +The o contents are methods or variable references or literals. +For an element of the list, the o or element is nesting.

+

With the parser based on this grammar, +let’s try to parse the following input.

+
+A  A  o  o  o  B  o  A  o  A  o  o  o  B  o  B  B
+
+

They are nesting too many times for humans to comprehend +without some helps such as indents. +But it becomes relatively easy if you think in the next way. +Because it’s certain that A and B which contain only several o between +them are going to appear, replace them to a single o when they appear. +All we have to do is repeating this procedure. +Figure 4 shows the consequence.

+

+

(ablist)
+Figure 4: parse a list which starts with A and ends with B

+

+

However, if the ending B is missing, …

+
+%token A o
+%%
+element   : A item_list    /* B is deleted for an experiment */
+
+item_list :
+          | item_list item
+
+item      : element
+          | o
+
+

I processed this with yacc and got 2 shift/reduce conflicts. +It means this grammar is ambiguous. +If we simply take B out from the previous one, +The input would be as follows.

+
+A  A  o  o  o  o  A  o  A  o  o  o  o
+
+

This is hard to interpret in any way. However, there was a rule that “choose +shift if it is a shift/reduce conflict”, +let’s follow it as an experiment and parse the input +with shift (meaning interior) which takes precedence. (Figure 5)

+

+

(alist)
+Figure 5: parse a list of lists which start with A

+

+

It could be parsed. However, this is completely different from the intention of +the input, there becomes no way to split the list in the middle.

+

Actually, the methods without parentheses of Ruby is in the similar situation +to this. It’s not so easy to understand but +a pair of a method name and its first argument is A. +This is because, since there’s no comma only between the two, +it can be recognized as the start of a new list.

+

Also, the “practical” HTML contains this pattern. +It is, for instance, when </p> or </i> is omitted. +That’s why yacc could not be used for ordinary HTML at all.

+

Scanner

+

Parser Outline

+

I’ll explain about the outline of the parser before moving on to the scanner. +Take a look at Figure 6.

+

+

(interf)
+Figure 6: Parser Interface (Call Graph)

+

+

There are three official interfaces of the parser: rb_compile_cstr(), +rb_compile_string(), rb_compile_file(). +They read a program from C string, +a Ruby string object and a Ruby IO object, respectively, and compile it.

+

These functions, directly or indirectly, call yycompile(), +and in the end, the control will be completely moved to yyparse(), +which is generated by yacc. +Since the heart of the parser is nothing but yyparse(), +it’s nice to understand by placing yyparse() at the center. +In other words, functions before moving on to yyparse() are all preparations, +and functions after yyparse() are merely chore functions being pushed around +by yyparse().

+

The rest functions in parse.y are auxiliary functions called by yylex(), +and these can also be clearly categorized.

+

First, the input buffer is at the lowest level of the scanner. +ruby is designed so that you can input source programs via both Ruby IO +objects and strings. +The input buffer hides that and makes it look like a single byte stream.

+

The next level is the token buffer. +It reads 1 byte at a time from the input buffer, +and keeps them until it will form a token.

+

Therefore, the whole structure of yylex can be depicted as Figure 7.

+
+

(scanner)
+Figure 7: The whole picture of the scanner

+
    +
  • 入力バッファ input buffer
  • +
  • バイト列 byte sequence
  • +
  • トークンバッファ token buffer
  • +
  • 記号列 symbol sequence +
+ +

The input buffer

+

Let’s start with the input buffer. Its interfaces are only the three: nextc(), pushback(), peek().

+

Although this is sort of insistent, +I said the first thing is to investigate data structures. +The variables used by the input buffer are the followings:

+

▼ the input buffer

+
+2279  static char *lex_pbeg;
+2280  static char *lex_p;
+2281  static char *lex_pend;
+
+(parse.y)
+
+

The beginning, the current position and the end of the buffer. +Apparently, this buffer seems a simple single-line string buffer (Figure 8).

+

+

(ibuffer)
+Figure 8: The input buffer

+

+

nextc()

+

Then, let’s look at the places using them. +First, I’ll start with nextc() that seems the most orthodox.

+

nextc()

+
+2468  static inline int
+2469  nextc()
+2470  {
+2471      int c;
+2472
+2473      if (lex_p == lex_pend) {
+2474          if (lex_input) {
+2475              VALUE v = lex_getline();
+2476
+2477              if (NIL_P(v)) return -1;
+2478              if (heredoc_end > 0) {
+2479                  ruby_sourceline = heredoc_end;
+2480                  heredoc_end = 0;
+2481              }
+2482              ruby_sourceline++;
+2483              lex_pbeg = lex_p = RSTRING(v)->ptr;
+2484              lex_pend = lex_p + RSTRING(v)->len;
+2485              lex_lastline = v;
+2486          }
+2487          else {
+2488              lex_lastline = 0;
+2489              return -1;
+2490          }
+2491      }
+2492      c = (unsigned char)*lex_p++;
+2493      if (c == '\r' && lex_p <= lex_pend && *lex_p == '\n') {
+2494          lex_p++;
+2495          c = '\n';
+2496      }
+2497
+2498      return c;
+2499  }
+
+(parse.y)
+
+

It seems that the first if is to test if it reaches the end of the input buffer. +And, the if inside of it seems, since the else returns -1 (EOF), +to test the end of the whole input. +Conversely speaking, when the input ends, lex_input becomes 0. +((errata: it does not. lex_input will never become 0 during ordinary scan.))

+

From this, we can see that strings are coming bit by bit into the input buffer. +Since the name of the function which updates the buffer is lex_getline, +it’s definite that each line comes in at a time.

+

Here is the summary:

+
+if ( reached the end of the buffer )
+    if (still there's more input)
+        read the next line
+    else
+        return EOF
+move the pointer forward
+skip reading CR of CRLF
+return c
+
+

Let’s also look at the function lex_getline(), which provides lines. +The variables used by this function are shown together in the following.

+

lex_getline()

+
+2276  static VALUE (*lex_gets)();     /* gets function */
+2277  static VALUE lex_input;         /* non-nil if File */
+
+2420  static VALUE
+2421  lex_getline()
+2422  {
+2423      VALUE line = (*lex_gets)(lex_input);
+2424      if (ruby_debug_lines && !NIL_P(line)) {
+2425          rb_ary_push(ruby_debug_lines, line);
+2426      }
+2427      return line;
+2428  }
+
+(parse.y)
+
+

Except for the first line, this is not important. +Apparently, lex_gets should be the pointer to the function to read a line, +lex_input should be the actual input. +I searched the place where setting lex_gets and this is what I found:

+

▼ set lex_gets

+
+2430  NODE*
+2431  rb_compile_string(f, s, line)
+2432      const char *f;
+2433      VALUE s;
+2434      int line;
+2435  {
+2436      lex_gets = lex_get_str;
+2437      lex_gets_ptr = 0;
+2438      lex_input = s;
+
+2454  NODE*
+2455  rb_compile_file(f, file, start)
+2456      const char *f;
+2457      VALUE file;
+2458      int start;
+2459  {
+2460      lex_gets = rb_io_gets;
+2461      lex_input = file;
+
+(parse.y)
+
+

rb_io_gets() is not a exclusive function for the parser +but one of the general-purpose library of Ruby. +It is the function to read a line from an IO object.

+

On the other hand, lex_get_str() is defined as follows:

+

lex_get_str()

+
+2398  static int lex_gets_ptr;
+
+2400  static VALUE
+2401  lex_get_str(s)
+2402      VALUE s;
+2403  {
+2404      char *beg, *end, *pend;
+2405
+2406      beg = RSTRING(s)->ptr;
+2407      if (lex_gets_ptr) {
+2408          if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
+2409          beg += lex_gets_ptr;
+2410      }
+2411      pend = RSTRING(s)->ptr + RSTRING(s)->len;
+2412      end = beg;
+2413      while (end < pend) {
+2414          if (*end++ == '\n') break;
+2415      }
+2416      lex_gets_ptr = end - RSTRING(s)->ptr;
+2417      return rb_str_new(beg, end - beg);
+2418  }
+
+(parse.y)
+
+

lex_gets_ptr remembers the place it have already read. +This moves it to the next \n, +and simultaneously cut out at the place and return it.

+

Here, let’s go back to nextc. +As described, by preparing the two functions with the same interface, +it switch the function pointer when initializing the parser, +and the other part is used in common. +It can also be said that the difference of the code is converted to the data +and absorbed. There was also a similar method of st_table.

+

pushback()

+

With the knowledge of the physical structure of the buffer and nextc, +we can understand the rest easily. +pushback() writes back a character. If put it in C, it is ungetc().

+

pushback()

+
+2501  static void
+2502  pushback(c)
+2503      int c;
+2504  {
+2505      if (c == -1) return;
+2506      lex_p--;
+2507  }
+
+(parse.y)
+
+

peek()

+

peek() checks the next character without moving the pointer forward.

+

peek()

+
+2509  #define peek(c) (lex_p != lex_pend && (c) == *lex_p)
+
+(parse.y)
+
+

The Token Buffer

+

The token buffer is the buffer of the next level. +It keeps the strings until a token will be able to cut out. +There are the five interfaces as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
newtok begin a new token
tokadd add a character to the buffer
tokfix fix a token
tok the pointer to the beginning of the buffered string
toklen the length of the buffered string
toklast the last byte of the buffered string
+

Now, we’ll start with the data structures.

+

▼ The Token Buffer

+
+2271  static char *tokenbuf = NULL;
+2272  static int   tokidx, toksiz = 0;
+
+(parse.y)
+
+

tokenbuf is the buffer, tokidx is the end of the token +(since it is of int, it seems an index), +and toksiz is probably the buffer length. +This is also simply structured. If depicting it, +it would look like Figure 9.

+

+

(tbuffer)
+Figure 9: The token buffer

+

+

Let’s continuously go to the interface and +read newtok(), which starts a new token.

+

newtok()

+
+2516  static char*
+2517  newtok()
+2518  {
+2519      tokidx = 0;
+2520      if (!tokenbuf) {
+2521          toksiz = 60;
+2522          tokenbuf = ALLOC_N(char, 60);
+2523      }
+2524      if (toksiz > 4096) {
+2525          toksiz = 60;
+2526          REALLOC_N(tokenbuf, char, 60);
+2527      }
+2528      return tokenbuf;
+2529  }
+
+(parse.y)
+
+

The initializing interface of the whole buffer does not exist, +it’s possible that the buffer is not initialized. +Therefore, the first if checks it and initializes it. +ALLOC_N() is the macro ruby defines and is almost the same as calloc.

+

The initial value of the allocating length is 60, +and if it becomes too big (> 4096), +it would be returned back to small. +Since a token becoming this long is unlikely, +this size is realistic.

+

Next, let’s look at the tokadd() to add a character to token buffer.

+

tokadd()

+
+2531  static void
+2532  tokadd(c)
+2533      char c;
+2534  {
+2535      tokenbuf[tokidx++] = c;
+2536      if (tokidx >= toksiz) {
+2537          toksiz *= 2;
+2538          REALLOC_N(tokenbuf, char, toksiz);
+2539      }
+2540  }
+
+(parse.y)
+
+

At the first line, a character is added. +Then, it checks the token length and if it seems about to exceed the buffer end, +it performs REALLOC_N(). +REALLOC_N() is a realloc() which has the same way of specifying arguments +as calloc().

+

The rest interfaces are summarized below.

+

tokfix() tok() toklen() toklast()

+
+2511  #define tokfix() (tokenbuf[tokidx]='\0')
+2512  #define tok() tokenbuf
+2513  #define toklen() tokidx
+2514  #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
+
+(parse.y)
+
+

There’s probably no question.

+

yylex()

+

yylex() is very long. Currently, there are more than 1000 lines. +The most of them is occupied by a huge switch statement, +it branches based on each character. +First, I’ll show the whole structure that some parts of it are left out.

+

yylex outline

+
+3106  static int
+3107  yylex()
+3108  {
+3109      static ID last_id = 0;
+3110      register int c;
+3111      int space_seen = 0;
+3112      int cmd_state;
+3113
+3114      if (lex_strterm) {
+              /* ... string scan ... */
+3131          return token;
+3132      }
+3133      cmd_state = command_start;
+3134      command_start = Qfalse;
+3135    retry:
+3136      switch (c = nextc()) {
+3137        case '\0':                /* NUL */
+3138        case '\004':              /* ^D */
+3139        case '\032':              /* ^Z */
+3140        case -1:                  /* end of script. */
+3141          return 0;
+3142
+3143          /* white spaces */
+3144        case ' ': case '\t': case '\f': case '\r':
+3145        case '\13': /* '\v' */
+3146          space_seen++;
+3147          goto retry;
+3148
+3149        case '#':         /* it's a comment */
+3150          while ((c = nextc()) != '\n') {
+3151              if (c == -1)
+3152                  return 0;
+3153          }
+3154          /* fall through */
+3155        case '\n':
+              /* ... omission ... */
+
+            case xxxx:
+                :
+              break;
+                :
+            /* branches a lot for each character */
+                :
+                :
+4103        default:
+4104          if (!is_identchar(c) || ISDIGIT(c)) {
+4105              rb_compile_error("Invalid char `\\%03o' in expression", c);
+4106              goto retry;
+4107          }
+4108
+4109          newtok();
+4110          break;
+4111      }
+
+          /* ... deal with ordinary identifiers ... */
+      }
+
+(parse.y)
+
+

As for the return value of yylex(), +zero means that the input has finished, +non-zero means a symbol.

+

Be careful that a extremely concise variable named “c” is used all over this function. +space_seen++ when reading a space will become helpful later.

+

All it has to do as the rest is to keep branching for each character and processing it, +but since continuous monotonic procedure is lasting, it is boring for readers. +Therefore, we’ll narrow them down to a few points. +In this book not all characters will be explained, +but it is easy if you will amplify the same pattern.

+

'!'

+

Let’s start with what is simple first.

+

yylex'!'

+
+3205        case '!':
+3206          lex_state = EXPR_BEG;
+3207          if ((c = nextc()) == '=') {
+3208              return tNEQ;
+3209          }
+3210          if (c == '~') {
+3211              return tNMATCH;
+3212          }
+3213          pushback(c);
+3214          return '!';
+
+(parse.y)
+
+

I wroute out the meaning of the code, +so I’d like you to read them by comparing each other.

+
+case '!':
+  move to EXPR_BEG
+  if (the next character is '=' then) {
+      token is 「!=(tNEQ)」
+  }
+  if (the next character is '~' then) {
+      token is 「!~(tNMATCH)」
+  }
+  if it is neither, push the read character back
+  token is '!'
+
+

This case clause is short, but describes the important rule of the scanner. +It is “the longest match rule”. +The two characters "!=" can be interpreted in two ways: “! and =” or “!=”, +but in this case "!=" must be selected. +The longest match is essential for scanners of programming languages.

+

And, lex_state is the variable represents the state of the scanner. +This will be discussed too much +in the next chapter “Finite-State Scanner”, +you can ignore it for now. +EXPR_BEG indicates “it is clearly at the beginning”. +This is because +whichever it is ! of not or it is != or it is !~, +its next symbol is the beginning of an expression.

+

'<'

+

Next, we’ll try to look at '<' as an example of using yylval (the value of a symbol).

+

yylex'&gt;'

+
+3296        case '>':
+3297          switch (lex_state) {
+3298            case EXPR_FNAME: case EXPR_DOT:
+3299              lex_state = EXPR_ARG; break;
+3300            default:
+3301              lex_state = EXPR_BEG; break;
+3302          }
+3303          if ((c = nextc()) == '=') {
+3304              return tGEQ;
+3305          }
+3306          if (c == '>') {
+3307              if ((c = nextc()) == '=') {
+3308                  yylval.id = tRSHFT;
+3309                  lex_state = EXPR_BEG;
+3310                  return tOP_ASGN;
+3311              }
+3312              pushback(c);
+3313              return tRSHFT;
+3314          }
+3315          pushback(c);
+3316          return '>';
+
+(parse.y)
+
+

The places except for yylval can be ignored. +Concentrating only one point when reading a program is essential.

+

At this point, for the symbol tOP_ASGN of >>=, it set its value tRSHIFT. +Since the used union member is id, its type is ID. +tOP_ASGN is the symbol of self assignment, +it represents all of the things like += and -= and *=. +In order to distinguish them later, +it passes the type of the self assignment as a value.

+

The reason why the self assignments are bundled is, +it makes the rule shorter. +Bundling things that can be bundled at the scanner as much as possible +makes the rule more concise. +Then, why are the binary arithmetic operators not bundled? +It is because they differs in their precedences.

+

':'

+

If scanning is completely independent from parsing, this talk would be simple. +But in reality, it is not that simple. +The Ruby grammar is particularly complex, +it has a somewhat different meaning when there’s a space in front of it, +the way to split tokens is changed depending on the situation around. +The code of ':' shown below is an example that a space changes the behavior.

+

yylex':'

+
+3761        case ':':
+3762          c = nextc();
+3763          if (c == ':') {
+3764              if (lex_state == EXPR_BEG ||  lex_state == EXPR_MID ||
+3765                  (IS_ARG() && space_seen)) {
+3766                  lex_state = EXPR_BEG;
+3767                  return tCOLON3;
+3768              }
+3769              lex_state = EXPR_DOT;
+3770              return tCOLON2;
+3771          }
+3772          pushback(c);
+3773          if (lex_state == EXPR_END ||
+                  lex_state == EXPR_ENDARG ||
+                  ISSPACE(c)) {
+3774              lex_state = EXPR_BEG;
+3775              return ':';
+3776          }
+3777          lex_state = EXPR_FNAME;
+3778          return tSYMBEG;
+
+(parse.y)
+
+

Again, ignoring things relating to lex_state, +I’d like you focus on around space_seen.

+

space_seen is the variable that becomes true when there’s a space before a token. +If it is met, meaning there’s a space in front of '::', it becomes tCOLON3, +if there’s not, it seems to become tCOLON2. +This is as I explained at primary in the previous section.

+

Identifier

+

Until now, since there were only symbols, +it was just a character or 2 characters. +This time, we’ll look at a little long things. +It is the scanning pattern of identifiers.

+

First, the outline of yylex was as follows:

+
+yylex(...)
+{
+    switch (c = nextc()) {
+      case xxxx:
+        ....
+      case xxxx:
+        ....
+      default:
+    }
+
+   the scanning code of identifiers
+}
+
+

The next code is an extract from the end of the huge switch. +This is relatively long, so I’ll show it with comments.

+

yylex — identifiers

+
+4081        case '@':                 /* an instance variable or a class variable */
+4082          c = nextc();
+4083          newtok();
+4084          tokadd('@');
+4085          if (c == '@') {         /* @@, meaning a class variable */
+4086              tokadd('@');
+4087              c = nextc();
+4088          }
+4089          if (ISDIGIT(c)) {       /* @1 and such  */
+4090              if (tokidx == 1) {
+4091    rb_compile_error("`@%c' is not a valid instance variable name", c);
+4092              }
+4093              else {
+4094    rb_compile_error("`@@%c' is not a valid class variable name", c);
+4095              }
+4096          }
+4097          if (!is_identchar(c)) { /* a strange character appears next to @  */
+4098              pushback(c);
+4099              return '@';
+4100          }
+4101          break;
+4102
+4103        default:
+4104          if (!is_identchar(c) || ISDIGIT(c)) {
+4105              rb_compile_error("Invalid char `\\%03o' in expression", c);
+4106              goto retry;
+4107          }
+4108
+4109          newtok();
+4110          break;
+4111      }
+4112
+4113      while (is_identchar(c)) {   /* between characters that can be used as identifieres */
+4114          tokadd(c);
+4115          if (ismbchar(c)) {      /* if it is the head byte of a multi-byte character */
+4116              int i, len = mbclen(c)-1;
+4117
+4118              for (i = 0; i < len; i++) {
+4119                  c = nextc();
+4120                  tokadd(c);
+4121              }
+4122          }
+4123          c = nextc();
+4124      }
+4125      if ((c == '!' || c == '?') &&
+              is_identchar(tok()[0]) &&
+              !peek('=')) {      /* the end character of name! or name? */
+4126          tokadd(c);
+4127      }
+4128      else {
+4129          pushback(c);
+4130      }
+4131      tokfix();
+
+(parse.y)
+
+

Finally, I’d like you focus on the condition +at the place where adding ! or ?. +This part is to interpret in the next way.

+
+obj.m=1       # obj.m  =   1       (not obj.m=)
+obj.m!=1      # obj.m  !=  1       (not obj.m!)
+
+

((errata: this code is not relating to that condition))

+

This is “not” longest-match. +The “longest-match” is a principle but not a constraint. +Sometimes, you can refuse it.

+

The reserved words

+

After scanning the identifiers, there are about 100 lines of the code further +to determine the actual symbols. +In the previous code, instance variables, class variables and local variables, +they are scanned all at once, +but they are categorized here.

+

This is OK but, inside it there’s a little strange part. +It is the part to filter the reserved words. +Since the reserved words are not different from local variables in its +character type, scanning in a bundle and categorizing later is more efficient.

+

Then, assume there’s str that is a char* string, +how can we determine whether it is a reserved word? +First, of course, there’s a way of comparing a lot by if statements and strcmp(). +However, this is completely not smart. It is not flexible. +Its speed will also linearly increase. +Usually, only the data would be separated to a list or a hash +in order to keep the code short.

+
+/* convert the code to data */
+struct entry {char *name; int symbol;};
+struct entry *table[] = {
+    {"if",     kIF},
+    {"unless", kUNLESS},
+    {"while",  kWHILE},
+    /* …… omission …… */
+};
+
+{
+    ....
+    return lookup_symbol(table, tok());
+}
+
+

Then, how ruby is doing is that, it uses a hash table. +Furthermore, it is a perfect hash. +As I said when talking about st_table, +if you knew the set of the possible keys beforehand, +sometimes you could create a hash function that never conflicts. +As for the reserved words, +“the set of the possible keys is known beforehand”, +so it is likely that we can create a perfect hash function.

+

But, “being able to create” and actually creating are different. +Creating manually is too much cumbersome. +Since the reserved words can increase or decrease, +this kind of process must be automated.

+

Therefore, gperf comes in. gperf is one of GNU products, +it generates a perfect function from a set of values. +In order to know the usage of gperf itself in detail, +I recommend to do man gperf. +Here, I’ll only describe how to use the generated result.

+

In ruby the input file for gperf is keywords and the output is lex.c. +parse.y directly #include it. +Basically, doing #include C files is not good, +but performing non-essential file separation for just one function is worse. +Particularly, in ruby, there's the possibility that extern+ functions are +used by extension libraries without being noticed, thus +the function that does not want to keep its compatibility should be static.

+

Then, in the lex.c, a function named rb_reserved_word() is defined. +By calling it with the char* of a reserved word as key, you can look up. +The return value is NULL if not found, struct kwtable* if found +(in other words, if the argument is a reserved word). +The definition of struct kwtable is as follows:

+

kwtable

+
+   1  struct kwtable {char *name; int id[2]; enum lex_state state;};
+
+(keywords)
+
+

name is the name of the reserved word, id[0] is its symbol, +id[1] is its symbol as a modification (kIF_MOD and such). +lex_state is “the lex_state should be moved to after reading this reserved word”. +lex_state will be explained in the next chapter.

+

This is the place where actually looking up.

+

yylex() — identifier — call rb_reserved_word()

+
+4173                  struct kwtable *kw;
+4174
+4175                  /* See if it is a reserved word.  */
+4176                  kw = rb_reserved_word(tok(), toklen());
+4177                  if (kw) {
+
+(parse.y)
+
+

Strings

+

The double quote (") part of yylex() is this.

+

yylex'"'

+
+3318        case '"':
+3319          lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
+3320          return tSTRING_BEG;
+
+(parse.y)
+
+

Surprisingly it finishes after scanning only the first character. +Then, this time, when taking a look at the rule, +tSTRING_BEG is found in the following part:

+

▼ rules for strings

+
+string1         : tSTRING_BEG string_contents tSTRING_END
+
+string_contents :
+                | string_contents string_content
+
+string_content  : tSTRING_CONTENT
+                | tSTRING_DVAR string_dvar
+                | tSTRING_DBEG term_push compstmt '}'
+
+string_dvar     : tGVAR
+                | tIVAR
+                | tCVAR
+                | backref
+
+term_push       :
+
+

These rules are the part introduced to deal with embedded expressions inside of strings. +tSTRING_CONTENT is literal part, +tSTRING_DBEG is "#{". +tSTRING_DVAR represents “# that in front of a variable”. For example,

+
+".....#$gvar...."
+
+

this kind of syntax. +I have not explained but when the embedded expression is only a variable, +{ and } can be left out. +But this is often not recommended. +D of DVAR, DBEG seems the abbreviation of dynamic.

+

And, backref represents the special variables relating to regular expressions, +such as $1 $2 or $& $'.

+

term_push is “a rule defined for its action”.

+

Now, we’ll go back to yylex() here. +If it simply returns the parser, +since its context is the “interior” of a string, +it would be a problem if a variable and if and others are suddenly scanned in +the next yylex(). +What plays an important role there is …

+
+      case '"':
+        lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
+        return tSTRING_BEG;
+
+

lex_strterm. Let’s go back to the beginning of yylex().

+

▼ the beginning of yylex()

+
+3106  static int
+3107  yylex()
+3108  {
+3109      static ID last_id = 0;
+3110      register int c;
+3111      int space_seen = 0;
+3112      int cmd_state;
+3113
+3114      if (lex_strterm) {
+              /* scanning string */
+3131          return token;
+3132      }
+3133      cmd_state = command_start;
+3134      command_start = Qfalse;
+3135    retry:
+3136      switch (c = nextc()) {
+
+(parse.y)
+
+

If lex_strterm exists, it enters the string mode without asking. +It means, conversely speaking, if there’s lex_strterm, +it is while scanning string, +and when parsing the embedded expressions inside strings, +you have to set lex_strterm to 0. +And, when the embedded expression ends, you have to set it back. +This is done in the following part:

+

string_content

+
+1916  string_content  : ....
+1917                  | tSTRING_DBEG term_push
+1918                      {
+1919                          $<num>1 = lex_strnest;
+1920                          $<node>$ = lex_strterm;
+1921                          lex_strterm = 0;
+1922                          lex_state = EXPR_BEG;
+1923                      }
+1924                    compstmt '}'
+1925                      {
+1926                          lex_strnest = $<num>1;
+1927                          quoted_term = $2;
+1928                          lex_strterm = $<node>3;
+1929                          if (($$ = $4) && nd_type($$) == NODE_NEWLINE) {
+1930                              $$ = $$->nd_next;
+1931                              rb_gc_force_recycle((VALUE)$4);
+1932                          }
+1933                          $$ = NEW_EVSTR($$);
+1934                      }
+
+(parse.y)
+
+

In the embedded action, lex_stream is saved as the value of tSTRING_DBEG +(virtually, this is a stack push), +it recovers in the ordinary action (pop). +This is a fairly smart way.

+

But why is it doing this tedious thing? +Can’t it be done by, after scanning normally, +calling yyparse() recursively at the point when it finds #{ ? +There’s actually a problem. +yyparse() can’t be called recursively. +This is the well known limit of yacc. +Since the yyval that is used to receive or pass a value is a global variable, +careless recursive calls can destroy the value. +With bison (yacc of GNU), +recursive calls are possible by using %pure_parser directive, +but the current ruby decided not to assume bison. +In reality, byacc (Berkely yacc) is often used in BSD-derived OS and Windows and such, +if bison is assumed, it causes a little cumbersome.

+

lex_strterm

+

As we’ve seen, when you consider lex_stream as a boolean value, +it represents whether or not the scanner is in the string mode. +But its contents also has a meaning. +First, let’s look at its type.

+

lex_strterm

+
+  72  static NODE *lex_strterm;
+
+(parse.y)
+
+

This definition shows its type is NODE*. +This is the type used for syntax tree and will be discussed in detail +in Chapter 12: Syntax tree construction. +For the time being, it is a structure which has three elements, +since it is VALUE you don’t have to free() it, +you should remember only these two points.

+

NEW_STRTERM()

+
+2865  #define NEW_STRTERM(func, term, paren) \
+2866          rb_node_newnode(NODE_STRTERM, (func), (term), (paren))
+
+(parse.y)
+
+

This is a macro to create a node to be stored in lex_stream. +First, term is the terminal character of the string. +For example, if it is a " string, it is ", +and if it is a ' string, it is '.

+

paren is used to store the corresponding parenthesis when it is a % string. +For example,

+
+%Q(..........)
+
+

in this case, paren stores '('. And, term stores the closing parenthesis ')'. +If it is not a % string, paren is 0.

+

At last, func, this indicates the type of a string. +The available types are decided as follows:

+

func

+
+2775  #define STR_FUNC_ESCAPE 0x01  /* backslash notations such as \n are in effect  */
+2776  #define STR_FUNC_EXPAND 0x02  /* embedded expressions are in effect */
+2777  #define STR_FUNC_REGEXP 0x04  /* it is a regular expression */
+2778  #define STR_FUNC_QWORDS 0x08  /* %w(....) or %W(....) */
+2779  #define STR_FUNC_INDENT 0x20  /* <<-EOS(the finishing symbol can be indented) */
+2780
+2781  enum string_type {
+2782      str_squote = (0),
+2783      str_dquote = (STR_FUNC_EXPAND),
+2784      str_xquote = (STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
+2785      str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
+2786      str_sword  = (STR_FUNC_QWORDS),
+2787      str_dword  = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
+2788  };
+
+(parse.y)
+
+

Each meaning of enum string_type is as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
str_squote ' string / %q
str_dquote " string / %Q
str_xquote command string (not be explained in this book)
str_regexp regular expression
str_sword %w
str_dword %W
+

String scan function

+

The rest is reading yylex() in the string mode, +in other words, the if at the beginning.

+

yylex− string

+
+3114      if (lex_strterm) {
+3115          int token;
+3116          if (nd_type(lex_strterm) == NODE_HEREDOC) {
+3117              token = here_document(lex_strterm);
+3118              if (token == tSTRING_END) {
+3119                  lex_strterm = 0;
+3120                  lex_state = EXPR_END;
+3121              }
+3122          }
+3123          else {
+3124              token = parse_string(lex_strterm);
+3125              if (token == tSTRING_END || token == tREGEXP_END) {
+3126                  rb_gc_force_recycle((VALUE)lex_strterm);
+3127                  lex_strterm = 0;
+3128                  lex_state = EXPR_END;
+3129              }
+3130          }
+3131          return token;
+3132      }
+
+(parse.y)
+
+

It is divided into the two major groups: here document and others. +But this time, we won’t read parse_string(). +As I previously described, there are a lot of conditions, +it is tremendously being a spaghetti code. +If I tried to explain it, +odds are high that readers would complain that “it is as the code is written!”. +Furthermore, although it requires a lot of efforts, it is not interesting.

+

But, not explaining at all is also not a good thing to do, +The modified version that functions are separately defined for each target to be scanned +is contained in the attached CD-ROM (doc/parse_string.html). +I’d like readers who are interested in to try to look over it.

+

Here Document

+

In comparison to the ordinary strings, here documents are fairly interesting. +That may be because, unlike the other elements, it deal with a line at a time. +Moreover, it is terrific that the starting symbol can exist in the middle of a program. +First, I’ll show the code of yylex() to scan the starting symbol of a here document.

+

yylex'&lt;'

+
+3260        case '<':
+3261          c = nextc();
+3262          if (c == '<' &&
+3263              lex_state != EXPR_END &&
+3264              lex_state != EXPR_DOT &&
+3265              lex_state != EXPR_ENDARG &&
+3266              lex_state != EXPR_CLASS &&
+3267              (!IS_ARG() || space_seen)) {
+3268              int token = heredoc_identifier();
+3269              if (token) return token;
+
+(parse.y)
+
+

As usual, we’ll ignore the herd of lex_state. +Then, we can see that it reads only “<<” here +and the rest is scanned at heredoc_identifier().
+Therefore, here is heredoc_identifier().

+

heredoc_identifier()

+
+2926  static int
+2927  heredoc_identifier()
+2928  {
+          /* ... omission ... reading the starting symbol */
+2979      tokfix();
+2980      len = lex_p - lex_pbeg;   /*(A)*/
+2981      lex_p = lex_pend;         /*(B)*/
+2982      lex_strterm = rb_node_newnode(NODE_HEREDOC,
+2983                          rb_str_new(tok(), toklen()),  /* nd_lit */
+2984                          len,                          /* nd_nth */
+2985          /*(C)*/       lex_lastline);                /* nd_orig */
+2986
+2987      return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
+2988  }
+
+(parse.y)
+
+

The part which reads the starting symbol (<<EOS) is not important, so it is totally left out. +Until now, the input buffer probably has become as depicted as Figure 10. +Let’s recall that the input buffer reads a line at a time.

+

+

(lexparams)
+Figure 10: scanning "printf\(<<EOS,n\)"

+

+

What heredoc_identifier() is doing is as follows:
+(A) len is the number of read bytes in the current line.
+(B) and, suddenly move lex_p to the end of the line.
+It means that in the read line, the part after the starting symbol is read but +not parsed. When is that rest part parsed? +For this mystery, a hint is that at (C) the lex_lastline (the currently +read line) and len (the length that has already read) are saved.

+

Then, the dynamic call graph before and after heredoc_identifier is simply +shown below:

+
+yyparse
+    yylex(case '<')
+        heredoc_identifier(lex_strterm = ....)
+    yylex(the beginning if)
+        here_document
+
+

And, this here_document() is doing the scan of the body of the here document. +Omitting invalid cases and adding some comments, +heredoc_identifier() is shown below. +Notice that lex_strterm remains unchanged after it was set at heredoc_identifier().

+

here_document()(simplified)

+
+here_document(NODE *here)
+{
+    VALUE line;                      /* the line currently being scanned */
+    VALUE str = rb_str_new("", 0);   /* a string to store the results */
+
+    /* ... handling invalid conditions, omitted ... */
+
+    if (embeded expressions not in effect) {
+        do {
+            line = lex_lastline;     /*(A)*/
+            rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len);
+            lex_p = lex_pend;        /*(B)*/
+            if (nextc() == -1) {     /*(C)*/
+                goto error;
+            }
+        } while (the currently read line is not equal to the finishing symbol);
+    }
+    else {
+        /* the embeded expressions are available ... omitted */
+    }
+    heredoc_restore(lex_strterm);
+    lex_strterm = NEW_STRTERM(-1, 0, 0);
+    yylval.node = NEW_STR(str);
+    return tSTRING_CONTENT;
+}
+
+

rb_str_cat() is the function to connect a char* at the end of a Ruby string. +It means that the currently being read line lex_lastline is connected to +str at (A). After it is connected, there’s no use of the current line. +At (B), suddenly moving lex_p to the end of line. +And (C) is a problem, in this place, it looks like doing the check whether +it is finished, but actually the next “line” is read. +I’d like you to recall that nextc() automatically reads the next line when +the current line has finished to be read. +So, since the current line is forcibly finished at (B), +lex_p moves to the next line at (C).

+

And finally, leaving the do ~ while loop, it is heredoc_restore().

+

heredoc_restore()

+
+2990  static void
+2991  heredoc_restore(here)
+2992      NODE *here;
+2993  {
+2994      VALUE line = here->nd_orig;
+2995      lex_lastline = line;
+2996      lex_pbeg = RSTRING(line)->ptr;
+2997      lex_pend = lex_pbeg + RSTRING(line)->len;
+2998      lex_p = lex_pbeg + here->nd_nth;
+2999      heredoc_end = ruby_sourceline;
+3000      ruby_sourceline = nd_line(here);
+3001      rb_gc_force_recycle(here->nd_lit);
+3002      rb_gc_force_recycle((VALUE)here);
+3003  }
+
+(parse.y)
+
+

here->nd_orig holds the line which contains the starting symbol.
+here->nd_nth holds the length already read in the line contains the starting +symbol.
+It means it can continue to scan from the just after the starting symbol +as if there was nothing happened. (Figure 11)

+

+

(heredoc)
+Figure 11: The picture of assignation of scanning Here Document

+

+ + + +
+ + diff --git a/htmls/preface.html b/htmls/preface.html new file mode 100644 index 0000000..c2b0464 --- /dev/null +++ b/htmls/preface.html @@ -0,0 +1,247 @@ + + + + + Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Preface

+

This book explores several themes with the following goals in mind:

+

To have knowledge of the structure of ruby +To gain knowledge about language processing systems in general +To acquire skills in reading source code

+

Ruby is an object-oriented language developed by Yukihiro Matsumoto. The +official implementation of the Ruby language is called ruby. It is actively +developed and maintained by the open source community. Our first goal is to +understand the inner-workings of the ruby implementation. This book is going +to investigate ruby as a whole.

+

Secondly, by knowing about the implementation of Ruby, we will be able to know +about other language processing systems. I tried to cover all topics necessary +for implementing a language, such as hash table, scanner and parser, evaluation +procedure, and many others. Although this book is not intended as a text book +and I don’t go through entire topics and schemes for a language processing +system, I tried to include adequate explanations about these concepts. For +those who are not familiar with the Ruby language yet, a brief summary is +included to help understand the topics.

+

The main themes of this book are the first and the second point above. Though, +what I want to emphasize the most is the third one: To acquire skill in reading +source code. I dare to say it’s a “hidden” theme. I will explain why we need +this.

+

It is often said “To be a skilled programmer, you should read source code +written by others.” This is certainly true. But I haven’t found a book that +explains how you can actually do it. There are many books that explain OS +kernels and the interior of language processing systems by showing the concrete +structure or “the answer,” but they don’t explain the way to reach that answer. +It’s clearly one-sided.

+

Can you, perhaps, naturally read code just because you know how to write a +program? Is it so easy to read code that all programmers are already able to +read any code by another programmer? I don’t think so. To be skilled in +reading code is certainly as difficult as writing code.

+

In light of such questions, this book doesn’t simply provide a general +explanation of the ruby language, but demonstrates procedures for analyzing +source code. When I started writing this book, I had some experience with the +Ruby language, but I did not fully understand the inner structure of the ruby +implementation. In other words, this book begins exploring ruby from the same +starting place as the reader. This book is the summary of the process and +results of my code analysis from that point.

+

I asked Yukihiro Matsumoto, the author of ruby, for supervision. But I +thought the spirit of this book would be lost if each analysis was monitored by +the author of the language himself. Therefore I limited his review to the final +stage of writing. In this way, I tried to assure the correctness of the +contents, keeping the goal of reading code alive at the same time.

+

To be honest, this book is not easy. In the very least, it is limited in its +simplicity by the inherent complexity of its aim. However, this complexity may +be what makes the book interesting to you. Do you find it interesting to be +chattering around a piece of cake? Do you take to your desk to solve a puzzle +that you know the answer to in a heartbeat? How about a suspense novel whose +criminal you can guess halfway through? If you really want to come to new +knowledge, you need to solve a problem engaging all your capacities. This is +the book that lets you practice such idealism exhaustively. “I think, +therefore it’s fun!” Everybody who finds it fun gives pleasure to the author.

+

Target audience

+

Firstly, knowledge about the Ruby language isn’t required. However, since the +knowledge of the Ruby language is absolutely necessary to understand certain +explanations of its structure, supplementary explanations of the language are +inserted here and there.

+

Knowledge about the C language is required, to some extent. I assume you have +experience calling malloc() to assign a list or stack, and have used function +pointer at least a few times.

+

This book doesn’t provide a proper introduction to an object-oriented language. +You will have a difficult time if you don’t know the basics of at least one +object-oriented language. Furthermore, some examples are given in Java and C++.

+

Structure of this book

+

This book has four main parts:

+

Part 1: Objects +Part 2: Syntactic analysis +Part 3: Evaluation +Part 4: Peripheral around the evaluator

+

Supplementary chapters are included at the beginning of each part when +necessary. These provide a basic introduction for those who are not familiar +with Ruby and the general mechanism of a language processing system.

+

Now, we are going through the overview of the four main parts. The symbol in +parentheses after the explanation indicates the difficulty gauge. They are ©, +(B), (A) in order of easy to hard, (S) being the highest.

+

Part 1: Object

+

Chapter 1: Focuses the basics of Ruby to get ready to accomplish Part 1. © +Chapter 2: Gives concrete inner structure of Ruby objects. © +Chapter 3: States about hash table. © +Chapter 4: Writes about Ruby class system. You may read through this chapter quickly at first, because it tells plenty of abstract stories. (A) +Chapter 5: Shows the garbage collector which is responsible for generating and releasing objects. The first story in low-level series. (B) +Chapter 6: Describes the implementation of global variables, class variables, and constants. © +Chapter 7: Outline of the security features of Ruby. ©

+

Part 2: Syntactic analysis

+

Chapter 8: Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. © +Chapter 9: Introduction to yacc required to read the syntax file at least. (B) +Chapter 10: Look through the rules and physical structure of the parser. (A) +Chapter 11: Explore around the peripherals of lex_state, which is the most difficult part of the parser. The most difficult part of this book. (S) +Chapter 12: Finalization of Part 2 and connection to Part 3. ©

+

Part 3: Evaluator

+

Chapter 13: Describe the basic mechanism of the evaluator. © +Chapter 14: Reads the evaluation stack that creates the main context of Ruby. (A) +Chapter 15: Talks about search and initialization of methods. (B) +Chapter 16: Defies the implementation of the iterator, the most characteristic feature of Ruby. (A) +Chapter 17: Describe the implementation of the eval methods. (B)

+

Part 4: Peripheral around the evaluator

+

Chapter 18: Run-time loading of libraries in C and Ruby. (B) +Chapter 19: Describes the implementation of thread at the end of the core part. (A)

+

Environment

+

This book describes on ruby 1.7.3 2002-09-12 version. It’s attached on the +CD-ROM. Choose any one of ruby-rhg.tar.gz, ruby-rhg.lzh, or ruby-rhg.zip +according to your convenience. Content is the same for all. Alternatively you +can obtain from the support site (footnote{@http://i.loveruby.net/ja/rhg/@}) of +this book.

+

For the publication of this book, the following build environment was prepared +for confirmation of compiling and testing the basic operation. The details of +this build test are given in @ doc/buildtest.html@ in the attached CD-ROM. +However, it doesn’t necessarily assume the probability of the execution even +under the same environment listed in the table. The author doesn’t guarantee +in any form the execution of ruby.

+

BeOS 5 Personal Edition/i386 +Debian GNU/Linux potato/i386 +Debian GNU/Linux woody/i386 +Debian GNU/Linux sid/i386 +FreeBSD 4.4-RELEASE/Alpha (Requires the local patch for this book) +FreeBSD 4.5-RELEASE/i386 +FreeBSD 4.5-RELEASE/PC98 +FreeBSD 5-CURRENT/i386 +HP-UX 10.20 +HP-UX 11.00 (32bit mode) +HP-UX 11.11 (32bit mode) +Mac OS X 10.2 +NetBSD 1.6F/i386 +OpenBSD 3.1 +Plamo Linux 2.0/i386 +Linux for PlayStation2 Release 1.0 +Redhat Linux 7.3/i386 +Solaris 2.6/Sparc +Solaris 8/Sparc +UX/4800 +Vine Linux 2.1.5 +Vine Linux 2.5 +VineSeed +Windows 98SE (Cygwin, MinGW+Cygwin, MinGW+MSYS) +Windows Me (Borland C++ Compiler 5.5, Cygwin, MinGW+Cygwin, MinGW+MSYS, Visual C++ 6) +Windows NT 4.0 (Cygwin, MinGW+Cygwin) +Windows 2000 (Borland C++ Compiler 5.5, Visual C++ 6, Visual C++.NET) +Windows XP (Visual C++.NET, MinGW+Cygwin)

+

These numerous tests aren’t of a lone effort by the author. Those test build +couldn’t be achieved without magnificent cooperations by the people listed +below.

+

I’d like to extend warmest thanks from my heart.

+

Tietew +kjana +nyasu +sakazuki +Masahiro Sato +Kenichi Tamura +Morikyu +Yuya Kato +Yasuhiro Kubo +Kentaro Goto +Tomoyuki Shimomura +Masaki Sukeda +Koji Arai +Kazuhiro Nishiyama +Shinya Kawaji +Tetsuya Watanabe +Naokuni Fujimoto

+

However, the author owes the responsibility for this test. Please refrain from +attempting to contact these people directly. If there’s any flaw in execution, +please be advised to contact the author by e-mail: @aamine@loveruby.net@.

+

Web site

+

The web site for this book is http://i.loveruby.net/ja/rhg/. +I will add information about related programs and additional documentation, as +well as errata. In addition, I’m going to publisize the first few chapters of +this book at the same time of the release. I will look for a certain +circumstance to publicize more chapters, and the whole contents of the book +will beat this website. at the end.

+

Acknowledgment

+

First of all, I would like to thank Mr. Yukihiro Matsumoto. He is the author of +Ruby, and he made it in public as an open source software. Not only he +willingly approved me to publish a book about analyzing ruby, but also he +agreed to supervise the content of it. In addition, he helped my stay in +Florida with simultaneous translation. There are plenty of things beyond +enumeration I have to say thanks to him. Instead of writing all the things, I +give this book to him.

+

Next, I would like to thank arton, who proposed me to publish this book. The +words of arton always moves me. One of the things I’m currently struggled due +to his words is that I have no reason I don’t get a .NET machine.

+

Koji Arai, the ‘captain’ of documentation in the Ruby society, conducted a +scrutiny review as if he became the official editor of this book while I was +not told so. I thank all his review.

+

Also I’d like to mention those who gave me comments, pointed out mistakes and +submitted proposals about the construction of the book throughout all my work.

+

Tietew, +Yuya, +Kawaji, +Gotoken, +Tamura, +Funaba, +Morikyu, +Ishizuka, +Shimomura, +Kubo, +Sukeda, +Nishiyama, +Fujimoto, +Yanagawa, +(I’m sorry if there’s any people missing), +I thank all those people contributed.

+

As a final note, I thank Otsuka , Haruta, and Kanemitsu who you for arranging +everything despite my broke deadline as much as four times, and that the +manuscript exceeded 200 pages than originally planned.

+

I cannot expand the full list here to mention the name of all people +contributed to this book, but I say that I couldn’t successfully publish this +book without such assistance. Let me take this place to express my +appreciation. Thank you very much.

+

p(=right).

+

If you want to send remarks, suggestions and reports of typographcal errors, +please address to " <aamine@loveruby.net>":mailto:aamine@loveruby.net.

+

""Rubyソースコード完全解説" can be reserved/ordered at ImpressDirect. “:http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721”(Jump to the introduction page)":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721

+

Copyright © 2002-2004 Minero Aoki, All rights reserved.

+ + + +
+ + diff --git a/htmls/security.html b/htmls/security.html new file mode 100644 index 0000000..c68395d --- /dev/null +++ b/htmls/security.html @@ -0,0 +1,208 @@ + + + + + Security | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Clifford Escobar CAOILE & ocha-

+

Chapter 7: Security

+

Fundamentals

+

I say security but I don’t mean passwords or encryption. The Ruby security +feature is used for handling untrusted objects in a environment like CGI +programming.

+

For example, when you want to convert a string representing a number into a +integer, you can use the eval method. However. eval is a method that “runs +a string as a Ruby program.” If you eval a string from a unknown person from +the network, it is very dangerous. However for the programmer to fully +differentiate between safe and unsafe things is very tiresome and cumbersome. +Therefore, it is for certain that a mistake will be made. So, let us make it +part of the language, was reasoning for this feature.

+

So then, how Ruby protect us from that sort of danger? Causes of dangerous +operations, for example, opening unintended files, are roughly divided into two +groups:

+
    +
  • Dangerous data
  • +
  • Dangerous code
  • +
+

For the former, the code that handles these values is created by the +programmers themselves, so therefore it is (relatively) safe. For the latter, +the program code absolutely cannot be trusted.

+

Because the solution is vastly different between the two causes, it is important to +differentiate them by level. This are called security levels. The Ruby security +level is represented by the $SAFE global variable. The value ranges from +minimum value 0 to maximum value 4. When the variable is assigned, the level +increases. Once the level is raised it can never be lowered. And for each +level, the operations are limited.

+

I will not explain level 1 or 3. +Level 0 is the normal program environment and the security system is not +running. Level 2 handles dangerous values. Level 4 handles dangerous code. +We can skip 0 and move on to explain in detail levels 2 and 4.

+

((errata: Level 1 handles dangerous values. +“Level 2 has no use currently” is right.))

+

Level 1

+

This level is for dangerous data, for example, in normal CGI +applications, etc.

+

A per-object “tainted mark” serves as the basis for the Level 1 +implementation. All objects read in externally are marked tainted, and +any attempt to eval or File.open with a tainted object will cause an +exception to be raised and the attempt will be stopped.

+

This tainted mark is “infectious”. For example, when taking a part of a +tainted string, that part is also tainted.

+

Level 4

+

This level is for dangerous programs, for example, running external +(unknown) programs, etc.

+

At level 1, operations and the data it uses are checked, but at level +4, operations themselves are restricted. For example, exit, file +I/O, thread manipulation, redefining methods, etc. Of course, the +tainted mark information is used, but basically the operations are the +criteria.

+

Unit of Security

+

$SAFE looks like a global variable but is in actuality a thread +local variable. In other words, Ruby’s security system works on units +of thread. In Java and .NET, rights can be set per component (object), +but Ruby does not implement that. The assumed main target was probably +CGI.

+

Therefore, if one wants to raise the security level of one part of the +program, then it should be made into a different thread and have its +security level raised. I haven’t yet explained how to create a thread, +but I will show an example here:

+
+# Raise the security level in a different thread
+p($SAFE)   # 0 is the default
+Thread.fork {    # Start a different thread
+    $SAFE = 4    # Raise the level
+    eval(str)    # Run the dangerous program
+}
+p($SAFE)   # Outside of the block, the level is still 0
+
+

Reliability of $SAFE

+

Even with implementing the spreading of tainted marks, or restricting +operations, ultimately it is still handled manually. In other words, +internal libraries and external libraries must be completely +compatible and if they don’t, then the partway the “tainted” operations +will not spread and the security will be lost. And actually this kind +of hole is often reported. For this reason, this writer does not +wholly trust it.

+

That is not to say, of course, that all Ruby programs are dangerous. +Even at $SAFE=0 it is possible to write a secure program, and even +at $SAFE=4 it is possible to write a program that fits your whim. +However, one cannot put too much confidence on $SAFE (yet).

+

In the first place, functionality and security do not go together. It +is common sense that adding new features can make holes easier to +open. Therefore it is prudent to think that ruby can probably be +dangerous.

+

Implementation

+

From now on, we’ll start to look into its implementation. +In order to wholly grasp the security system of ruby, +we have to look at “where is being checked” rather than its mechanism. +However, this time we don’t have enough pages to do it, +and just listing them up is not interesting. +Therefore, in this chapter, I’ll only describe about the +mechanism used for security checks. +The APIs to check are mainly these below two:

+
    +
  • rb_secure(n) : If more than or equal to level n, it would raise SecurityError.
  • +
  • SafeStringValue() : + If more than or equal to level 1 and a string is tainted, + then it would raise an exception.
  • +
+

We won’t read SafeStringValue() here.

+

Tainted Mark

+

The taint mark is, to be concrete, the FL_TAINT flag, which is set to +basic->flags, and what is used to infect it is the OBJ_INFECT() macro. +Here is its usage.

+
+OBJ_TAINT(obj)            /* set FL_TAINT to obj */
+OBJ_TAINTED(obj)          /* check if FL_TAINT is set to obj */
+OBJ_INFECT(dest, src)     /* infect FL_TAINT from src to dest */
+
+

Since OBJ_TAINT() and OBJ_TAINTED() can be assumed not important, +let’s briefly look over only OBJ_INFECT().

+

OBJ_INFECT

+
+ 441  #define OBJ_INFECT(x,s) do {                             \
+          if (FL_ABLE(x) && FL_ABLE(s))                        \
+              RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT; \
+      } while (0)
+
+(ruby.h)
+
+

FL_ABLE() checks if the argument VALUE is a pointer or not. +If the both objects are pointers (it means each of them has its flags member), +it would propagate the flag.

+

$SAFE

+

ruby_safe_level

+
+ 124  int ruby_safe_level = 0;
+
+7401  static void
+7402  safe_setter(val)
+7403      VALUE val;
+7404  {
+7405      int level = NUM2INT(val);
+7406
+7407      if (level < ruby_safe_level) {
+7408          rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
+7409                   ruby_safe_level, level);
+7410      }
+7411      ruby_safe_level = level;
+7412      curr_thread->safe = level;
+7413  }
+
+(eval.c)
+
+

The substance of $SAFE is ruby_safe_level in eval.c. +As I previously wrote, $SAFE is local to each thread, +It needs to be written in eval.c where the implementation of threads is located. +In other words, it is in eval.c only because of the restrictions of C, +but it can essentially be located in another place.

+

safe_setter() is the setter of the $SAFE global variable. +It means, because this function is the only way to access it from Ruby level, +the security level cannot be lowered.

+

However, as you can see, from C level, +because static is not attached to ruby_safe_level, +you can ignore the interface and modify the security level.

+

rb_secure()

+

rb_secure()

+
+ 136  void
+ 137  rb_secure(level)
+ 138      int level;
+ 139  {
+ 140      if (level <= ruby_safe_level) {
+ 141          rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
+ 142                   rb_id2name(ruby_frame->last_func), ruby_safe_level);
+ 143      }
+ 144  }
+
+(eval.c)
+
+

If the current safe level is more than or equal to level, +this would raise SecurityError. It’s simple.

+ + + +
+ + diff --git a/htmls/spec.html b/htmls/spec.html new file mode 100644 index 0000000..151ac38 --- /dev/null +++ b/htmls/spec.html @@ -0,0 +1,1675 @@ + + + + + Ruby Language Details | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 8 : Ruby Language Details

+

I’ll talk about the details of Ruby’s syntax and evaluation, +which haven’t been covered yet. I didn’t intend a complete exposition, +so I left out everything which doesn’t come up in this book. +That’s why you won’t be able to write Ruby programs just by +reading this. A complete exposition can be found in the +\footnote{Ruby reference manual: archives/ruby-refm.tar.gz in the attached CD-ROM}

+

Readers who know Ruby can skip over this chapter.

+

Literals

+

The expressiveness of Ruby’s literals is extremely high. +What distinguishes Ruby as a scripting language +is firstly the existence of +the toplevel, secondly it’s the expressiveness of its literals in my +opinion. Thirdly it might be the richness of its standard library.

+

The literals have already as elements enormous power, but even more +when combined. Especially that one can create complex literals from +hash and array literals is a great advantage of Ruby. One can simply +write down a hash of arrays of regular expressions for instance.

+

Let’s look at the valid expressions one by one.

+

Strings

+

Strings and regular expressions can’t be missing in a scripting language. +There is a great variety of string literals.

+

Single Quoted Strings

+
+'string'              # 「string」
+'\\begin{document}'   # 「\begin{document}」
+'\n'                  # 「\n」backslash and an n, no newline
+'\1'                  # 「\1」backslash and 1
+'\''                  # 「'」
+
+

This is the simplest form. In C everything enclosed in single quotes becomes a +string, it’s the same in Ruby. Let’s call this a '-string. The backslash escape +is in effect only for \ itself and '. If one puts a backslash +in front of another character the backslash remains as for example +in the fourth example.

+

And Ruby’s strings aren’t divided by newline characters. +If we write a string over several lines the newlines are contained +in the string.

+
+'multi
+    line
+        string'
+
+

And if the -K option is given to the ruby command multibyte strings +will be accepted. At present the three encodings EUC-JP (-Ke), +Shift JIS (-Ks), and UTF8 (-Ku) can be specified. (Translator’s note: +-K option was removed in Ruby 1.9)

+
+'「漢字が通る」と「マルチバイト文字が通る」はちょっと違う'
+# 'There's a little difference between "Kanji are accepted" and "Multibyte characters are accepted".'
+
+

Double Quoted Strings

+
+"string"              # 「string」
+"\n"                  # newline
+"\x0f"               # a byte given in hexadecimal form
+"page#{n}.html"       # embedding a command
+
+

With double quotes we can use command expansion and backslash notation. +The backslash notation is classical, it was already supported in C, +\n is a newline, \b is a backspace, this kind of notation. +In Ruby also Ctrl-C and ESC can be expressed, that’s convenient. +It’s probably of no use to list the whole notation here.

+

On the other hand, expression expansion is even more fantastic. +We can write an arbitrary Ruby expression inside #{ } and it +will be evaluated at runtime and embedded into the string. There +are no limitations like only one variable or only one method. +This is not a mere literal anymore but a whole expression representing +a string.

+
+"embedded #{lvar} expression"
+"embedded #{@ivar} expression"
+"embedded #{1 + 1} expression"
+"embedded #{method_call(arg)} expression"
+"embedded #{"string in string"} expression"
+
+

Strings with %

+
+%q(string)            # same as 'string'
+%Q(string)            # same as "string"
+%(string)             # same as %Q(string) or "string"
+
+

If a lot of separator characters appear in a string, escaping all of them +becomes a burden. In that case the separator characters can be +changed. The string which contains the one character " can be +written with a % string as follows:

+
+"<a href=\"http://i.loveruby.net#{path}\">"
+%Q(")
+
+

The expression isn’t shorter, but nicer to look at. +When we have to escape more often, it even becomes more concise.

+

Here we have used parentheses as delimiters, but something else is fine, +too. Like brackets or braces or #. Almost every symbol is fine, even +%.

+
+%q#this is string#
+%q[this is string]
+%q%this is string%
+
+

Here Documents

+

Here documents are a syntactical device where one or more lines can +form a string. A normal string starts right after the delimiter " +and takes everything until the ending ". Here documents start +at the line after a <<EOS and end at the line before the ending EOS.

+
+
+<<EOS
+All lines between the starting and
+the ending line are in this
+here document
+EOS
+
+

Here we used EOS as identifier but any word is fine. +Precisely speaking all the character matching [a-zA-Z_0-9] can be used.

+

The characteristic of a here document is that every line between +the start symbol and the ending symbol will form a string. The line +which contains the start symbol delimits the string. +That’s why the position of the start symbol is not important. +It can even be in the middle of an expression:

+
+printf(<<EOS, count_n(str))
+count=%d
+EOS
+
+

In this case the string "count=%d\n" goes in the place of <<EOS. +So it’s the same as the following.

+
+printf("count=%d\n", count_n(str))
+
+

The start symbol can be somewhere in the line, but there are strict +rules for the ending symbol: It must be at the beginning of the line +and there must not be another letter in that line. However +if we write the start symbol with a minus like this <<-EOS we +can indent the line with the end symbol.

+
+     <<-EOS
+It would be convenient if one could indent the content
+of a here document. But that's not possible.
+If you want that, the best way is to write
+a method which delete the indent. But beware
+of tabs.
+     EOS
+
+

Furthermore, the start symbol can be enclosed in single or double quotes. +Then the properties of the whole here document change. +When we change <<EOS to <<"EOS" we can use command expression +imbedding and backslash notation.

+
+    <<"EOS"
+One day is #{24 * 60 * 60} seconds.
+Incredible.
+EOS
+
+

But <<'EOS' is not the same as a single quoted string. It starts +the complete literal mode. Everything even backslashes go +into the string as they are typed. This is useful for a string which +contains many backslashes.

+

In the second part we also explain how a here document is passed. +But I’d like you to guess it before. +(Translators Note: In Ruby 1.8 and 1.9 expression expansion and +backslash notation can be used in a normal here document. +There does not seem to be a difference anymore to a double quote enclosed +here document.)

+

Characters

+

Ruby strings are byte strings, there are no character objects. +Instead there are the following expressions which return the +integers which correspond a certain character in ASCII code.

+
+?a                    # the integer which corresponds to 「a」
+?.                    # the integer which corresponds to 「.」
+?\n                   # LF
+?\C-a                 # Ctrl-a
+
+

(Translator’s note: Strings in Ruby 1.9 are not byte strings anymore, +they have an attached encoding. ?a returns the string "a" in Ruby1.9)

+

Regular Expressions

+
+/regexp/
+/^Content-Length:/i
+/正規表現/
+/\/\*.*?\*\//m        # An expression which matches C comments
+/reg#{1 + 1}exp/      # the same as /reg2exp/
+
+

What is contained between slashes is a regular expression. +Regular expressions are a language to designate string patterns. +For example

+
+/abc/
+
+

This regular expression matches a string where there’s an a followed +by a b followed by a c. It matches “abc” or “fffffffabc” or +“abcxxxxx”.

+

One can designate more special patterns.

+
+/^From:/
+
+

This matches a string where there’s a From followed by a : at +the beginning. There are several more expressions of this kind, +such that one can create quite complex patterns.

+

The uses are infinite: +Changing the matched part to another string, deleting the matched part, +determining if there’s one match and and and…

+

A more concrete use case would be extracting the From: header +from a mail. Then changing the \n to an \r and +checking if the rest looks like a mail address.

+

The regular expressions form an independent language, it has +it’s own parser and evaluator within ruby. It can be found in regex.c +in the Ruby source. In effect from a grammar view point they are +treated the same as strings. Escapes, backslash notation and command +embedding can be used almost the same as in strings.

+

Of course regular expressions and strings are treated the same +in the Ruby syntax only. Regular expressions themselves are a language +of their own with own rules which have to be obeyed. This is a subject +of a whole other book. We won’t go deeper into that here. +Refer for instance to Jeffrey Friedl, Regular expressions.

+

Regular Expressions with %

+

Also as with strings, regular expressions also have a syntax for changing +delimiters. In this case it is %r. Here just some examples.

+
+%r(regexp)
+%r[/\*.*?\*/]            # matches a C comment
+%r("(?:[^"\\]+|\\.)*")   # matches a string in C
+%r{reg#{1 + 1}exp}       # imbedding a Ruby expression
+
+

Arrays

+

An array literal is contained in brackets [], elements are separated +by commas.

+
+[1, 2, 3]
+['This', 'is', 'an', 'array', 'of', 'string']
+
+[/regexp/, {'hash'=>3}, 4, 'string', ?\C-a]
+
+lvar = $gvar = @ivar = @@cvar = nil
+[lvar, $gvar, @ivar, @@cvar]
+[Object.new(), Object.new(), Object.new()]
+
+

Ruby’s arrays are a list of arbitrary objects. From a syntactical +standpoint it’s characteristic is, that +the elements can be arbitrary expressions. As mentioned earlier, +an array of hashes of regular expressions can easily be made. +Not just literals but also variables or method calls can also be +put together.

+

And as with the other literals note that this is really an “expression +which generates an array object”

+
+i = 0
+while i < 5
+  p([1,2,3].id)    # Each time another object id is shown.
+  i += 1
+end
+
+

Word Arrays

+

When writing scripts one uses arrays of strings a lot, hence +there is a special notation only for arrays of strings. +That is %w. With an example it’s immediately obvious.

+
+%w( alpha beta gamma delta )   # ['alpha','beta','gamma','delta']
+%w( 月 火 水 木 金 土 日 )
+%w( Jan Feb Mar Apr May Jun
+    Jul Aug Sep Oct Nov Dec )
+
+

There’s also %W where command embedding can be used. +It’s a relatively recent implementation.

+
+n = 5
+%w( list0 list#{n} )   # ['list0', 'list#{n}']
+%W( list0 list#{n} )   # ['list0', 'list5']
+
+

The author hasn’t come up with a good use yet.

+

Hashes

+

Hash tables are data structure which store a one-to-one relation between +arbitrary objects. The following expressions generate a table.

+
+{ 'key' => 'value', 'key2' => 'value2' }
+{ 3 => 0, 'string' => 5, ['array'] => 9 }
+{ Object.new() => 3, Object.new() => 'string' }
+
+# Of course we can put it in several lines.
+{ 0 => 0,
+  1 => 3,
+  2 => 6 }
+
+

We explained hashes in detail in the third chapter “Names and +Nametables”. They are fast lookup tables which allocate memory slots depending +on the hash values. In Ruby grammar, +both keys and values can be arbitrary expressions.

+

Furthermore inside the argument of a method call the {...} can be omitted.

+
+  some_method(arg, key => value, key2 => value2)
+# some_method(arg, {key => value, key2 => value2}) # same as above
+
+

With this we can imitate named arguments.

+
+button.set_geometry('x' => 80, 'y' => '240')
+
+

Of course in this case set_geometry must accept a hash as input. +Real keyword arguments will be transformed into parameter variables, though. +With a passed hash it is not quite the real thing.

+

Ranges

+

Range literals are oddballs which don’t appear in most other languages. +Here are some expressions which generate Range objects.

+
+0..5          # from 0 to 5 containing 5
+0...5         # from 0 to 5 not containing 5
+1+2 .. 9+0    # from 3 to 9 containing 9
+'a'..'z'      # strings from 'a' to 'z' containing 'z'
+
+

If there are two dots the last element is included. If there +are three dots it is not included. Not only integers but also floats +and strings can be made into ranges, even arbitrary objects can +be used in ranges. Syntactically arbitrary expressions can be +used as delimiters of a range object. If the returned object cannot +be made into a range there will be a runtime error.

+

Besides, the precedence of .. and ... is quite low. Here’s a surprising +interpretation.

+
+1..5.to_a()   # 1..(5.to_a())
+
+

I thinks the Ruby grammar is really intuitive, +but I do not like this.

+

Symbols

+

In the first part we talked about symbols at length. +They are something which corresponds one-to-one to strings. +In Ruby symbols are expressed with a : in front.

+
+:identifier
+:abcde
+
+

These are pretty standard examples. But all symbol and method +names become symbols with a : in front. Like this:

+
+:$gvar
+:@ivar
+:@@cvar
+:CONST
+
+

We haven’t shown any method names so far. Of course [] or attr= +can be used as symbols too.

+
+:[]
+:attr=
+
+

When one uses these symbols as values in an array, it’ll look quite +complicated.

+

Numerical Values

+

This is the least interesting. It might be added that

+
+1_000_000
+
+

becomes one million and that underscores can be used inside a number. +But that isn’t particularly interesting. This is it about numerical +values in this book. We’ll completely forget them from here on.

+

Methods

+

Let’s talk about the definition and calling of methods.

+

Definition and Calls

+
+def some_method( arg )
+  ....
+end
+
+class C
+  def some_method( arg )
+    ....
+  end
+end
+
+

Methods are defined with def. If they are defined at toplevel +they become function style methods, inside a class they become +methods of this class. To call a method which was defined in a class, +one usually has to create an instance with new as shown below.

+
+C.new().some_method(0)
+
+

The Return Value of Methods

+

The return value of a method is the value of a return statement +if it runs across one. +If there is none it’s the value of the last statement.

+
+def one()     # 1 is returned
+  return 1
+  999
+end
+
+def two()     # 2 is returned
+  999
+  2
+end
+
+def three()   # 3 is returned
+  if true then
+    3
+  else
+    999
+  end
+end
+
+

If the method body is empty nil is returned +and an expression without a value cannot put at the end. +Hence every method has a return value.

+

Optional Arguments

+

Optional arguments can also be defined. If the number of arguments +doesn’t suffice the parameters are automatically assigned to a +default value.

+
+def some_method( arg = 9 )  # default value is 9
+  p arg
+end
+
+some_method(0)    # 0 is shown.
+some_method()     # The default value 9 is shown.
+
+

There can also be several optional arguments. +But in that case they must all come at the end. It is not +possible to make an argument in the middle optional. +It would be unclear how this should be made sense of.

+
+def right_decl( arg1, arg2, darg1 = nil, darg2 = nil )
+  ....
+end
+
+# This is not possible
+def wrong_decl( arg, default = nil, arg2 )  # A middle argument cannot be optional
+  ....
+end
+
+

Omitting argument parantheses

+

The parentheses from a method call can be omitted.

+
+puts 'Hello, World!'   # puts("Hello, World")
+obj = Object.new       # obj = Object.new()
+
+

In Python leaving out parentheses gets the method object, but +there is no such thing in Ruby.

+

We can also omit parentheses within the arguments itself.

+
+  puts(File.basename fname)
+# puts(File.basename(fname)) same as the above
+
+

If we like we can even leave out more

+
+  puts File.basename fname
+# puts(File.basename(fname))  same as the above
+
+

In Ruby 2.0 such an expression will probably not pass anymore.

+

Actually let’s also leave out the parentheses in the definition

+
+def some_method param1, param2, param3
+end
+
+def other_method    # without arguments we see this a lot
+end
+
+

Parentheses are often left out in method calls, but leaving out +parentheses in the definition is not very popular. +Only if there are no arguments the parentheses are frequently omitted.

+

Arguments and Lists

+

Arguments form a list of objects. If we want to use the elements of a list as arguments we can do this as follows:

+
+def delegate(a, b, c)
+  p(a, b, c)
+end
+
+list = [1, 2, 3]
+delegate(*list)   # identical to delegate(1, 2, 3)
+
+

In this way we can distribute an array into arguments. +We call this device a *argument. Here we used a local variable +for demonstration, but of course there is no limitation. +We can also directly put a literal or a method call instead.

+
+m(*[1,2,3])    # We could have written the expanded form in the first place...
+m(*mcall())
+
+

The * argument can be used together with ordinary arguments, +but the * argument must come last.

+

In the definition on the other hand we can handle the arguments in +bulk when we put a * in front of the parameter variable.

+
+def some_method( *args )
+  p args
+end
+
+some_method()          # prints []
+some_method(0)         # prints [0]
+some_method(0, 1)      # prints [0,1]
+
+

The surplus arguments are gathered in an array. Only one *parameter +can be declared. It must also come after the default arguments.

+
+def some_method0( arg, *rest )
+end
+def some_method1( arg, darg = nil, *rest )
+end
+
+

If we combine list expansion and bulk reception together, the arguments +of one method can be passed as a whole to another method. This might +be the most practical use of the *parameter.

+
+# a method which passes its arguments to other_method
+def delegate(*args)
+  other_method(*args)
+end
+
+def other_method(a, b, c)
+  return a + b + c
+end
+
+delegate(0, 1, 2)      # same as other_method(0, 1, 2)
+delegate(10, 20, 30)   # same as other_method(10, 20, 30)
+
+

Various Method Call Expressions

+

There is only one mechanism for ‘method call’, but there still +can be several representations of the same mechanism. This is +colloquially called syntactic sugar.

+

In Ruby there is a ton of it, +and they are really attractive for a person who has a fetish for parsers. +For instance the examples below are all method calls.

+
+1 + 2                   # 1.+(2)
+a == b                  # a.==(b)
+~/regexp/               # /regexp/.~
+obj.attr = val          # obj.attr=(val)
+obj[i]                  # obj.[](i)
+obj[k] = v              # obj.[]=(k,v)
+<code>cvs diff abstract.rd</code>  # Kernel.`('cvs diff abstract.rd')
+
+

It’s hard to believe until you get used to it, but attr=, []=, \` +are all names of methods. They can appear as names in a method definition +and can also be used as symbols.

+
+class C
+  def []( index )
+  end
+  def +( another )
+  end
+end
+p(:attr=)
+p(:[]=)
+p(:`)
+
+

There are people who don’t like sweets and there are people who +hate syntactic sugar. Maybe because one cannot tell by the looks +that it’s really the same thing. It feels like a deception. +(Why’s everyone so serious?)

+

Let’s see some more details.

+

Symbol Appendices

+
+obj.name?
+obj.name!
+
+

First a small thing. It’s just appending a ? or a !. Call and Definition +do not differ, so it’s not too painful. There are convention for what +to use these method names, but there is no enforcement on language level. +It’s just a convention. +These method names are probably an influence from Lisp which has a great variety +of function names.

+

Binary Operators

+
+1 + 2    # 1.+(2)
+
+

Binary Operators will be converted to a method call to the object on the +left hand side. Here the method + from the object 1 is called. +As listed below there are many of them. There are the general operators ++ and -, also the equivalence operator == and the spaceship operator +`<=>’ as in Perl, all sorts. They are listed in order of their precedence.

+
+**
+* / %
++ -
+<< >>
+&
+| ^
+> >= < <=
+<=> == === =~
+
+

The symbols & and | are methods, but the double symbols && and || +are built-in operators. Remember how it is in C.

+

Unary Operators

+
++2
+-1.0
+~/regexp/
+
+

These are the unary operators. There are only three of them: + - ~. ++ and - work as one would imagine ( in the default setting). +The operator ~ matches a string or a regular expression +with the variable $_. With an integer it stands for bit conversion.

+

To distinguish the unary + from the binary + the method names +for the unary operators are +@ and -@ respectively. +Of course they can be called by just writing +n or -n.

+

((errata: + or – as the prefix of a numeric literal is actually scanned as a +part of the literal. This is a kind of optimizations.))

+

Attribute Assignment

+
+obj.attr = val   # obj.attr=(val)
+
+

This is an attribute assignment statement. The above will be translated +into the method call attr=. When using this together with method calls whose +parentheses are omitted, we can write code which looks like attribute access.

+
+class C
+  def i() @i end          # We can write the definition in one line
+  def i=(n) @i = n end
+end
+
+c = C.new
+c.i = 99
+p c.i    # prints 99
+
+

However both are method calls. +They are similar to get/set property in Delphi or slot accessors in CLOS.

+

Besides, we cannot define a attribute assignment which takes an argument like +obj.attr(arg)=.

+

Index Notation

+
+obj[i]    # obj.[](i)
+
+

The above will be translated into a method call for []. +Array and hash access are also implemented with this device.

+
+obj[i] = val   # obj.[]=(i, val)
+
+

When assigning to an index the []= method is used.

+

super

+

Often we don’t want to replace a method, but we want to add a little +bit to the behaviour of an already existing method. Here it becomes +necessary to not just overwrite the method in the superclass but +to also call the method in the superclass. +That’s what Ruby’s super is for.

+
+class A
+  def test
+    puts 'in A'
+  end
+end
+class B < A
+  def test
+    super   # launches A#test
+  end
+end
+
+

Ruby’s `super differs from the one in Java. This one here +calls the method with the same name in the superclass. +In other words super is a reserved word.

+

When using super be careful about the difference between the difference +of the zero arguments super and the omitted arguments `super. +The super with omitted arguments passes all the parameter variables.

+
+class A
+  def test( *args )
+    p args
+  end
+end
+
+class B < A
+  def test( a, b, c )
+    # super with no arguments
+    super()    # shows []
+
+    # super with omitted arguments. Same result as super(a, b, c)
+    super      # shows [1, 2, 3]
+  end
+end
+
+B.new.test(1,2,3)
+
+

Visibility

+

Depending on the location ( the object self) a method can or +cannot be called. This function was usually called visibility. +In Ruby there are three kinds of methods.

+
    +
  • public
  • +
  • private
  • +
  • protected
  • +
+

public methods can be called from anywhere in any form. +private methods can syntactically only be called without a receiver. +In effect they can only be called by instances of the class +in which they were defined and in instances of its subclass. +protected methods can only be called by instances of the defining class +and its subclasses. +It differs from private that methods can still be called from other +instances of the same class.

+

The terms are the same as in C++ but the meaning is slightly different. +Be careful.

+

Usually we control visibility as shown below.

+
+class C
+  public
+  def a1() end   # becomes public
+  def a2() end   # becomes public
+
+  private
+  def b1() end   # becomes private
+  def b2() end   # becomes private
+
+  protected
+  def c1() end   # becomes protected
+  def c2() end   # becomes protected
+end
+
+

Here public, private and `protected are method calls without +parentheses. These aren’t reserved words.

+

public and private can also be used with an argument to set +the visibility of a particular method. But that’s not really relevant. +We’ll leave this out.

+

Module functions

+

Given a module ‘M’. If there are two methods with the exact same +content

+
    +
  • M.method_name
  • +
  • M#method_name(Visibility is private)
  • +
+

then we call this a module function.

+

It is not apparent why this should be useful. But let’s look +at the next example which is happily used.

+
+Math.sin(5)       # If used for a few times this is more convenient
+
+include Math
+sin(5)            # If used more often this is more practical
+
+

It’s important that both functions have the same content. +With a different self but with the same code the behavior should +still be the same. Instance variables become extremely difficult to use. +Hence these methods are probably only used +for procedures like sin. That’s why they are called module functions.

+

Iterators

+

Ruby’s iterators differ a bit from Java’s or C++’s iterator classes +or ‘Iterator’ design patterns. Precisely speaking those iterators +are exterior iterators. Ruby’s iterators are called interior iterators. +It’s difficult to understand from the definition so +let’s explain it with a concrete example.

+
+arr = [0,2,4,6.8]
+
+

This array is given and we want to access the elements in +order. In C style we would write the following.

+
+i = 0
+while i < arr.length
+  print arr[i]
+  i += 1
+end
+
+

Using an iterator we can write:

+
+arr.each do |item|
+  print item
+end
+
+

Everything from each do to end is the call to an iterator method. +More precisely each is the iterator method and between +do and end is the iterator block. +The part between the vertical bars are the block parameters. +They are the arguments passed from the iterator method to the block where +they become variables.

+

Saying it quite abstractly, an iterator is something like +a piece of code which has been cut out and passed. In our example the +piece print item has been cut out and is passed to the each method. +Then each takes all the elements of the array in order and passes them +to the cut out piece of code.

+

We can also think the other way round. The other parts except print item +are being cut out and inserted into the each method.

+
+i = 0
+while i < arr.length
+  print arr[i]
+  i += 1
+end
+
+arr.each do |item|
+  print item
+end
+
+

Comparison with higher order functions

+

What comes closest in C to iterators are functions which receive function pointers, +or higher order functions. But there are two points in which iterators in Ruby +and higher order functions in C differ.

+

Firstly, Ruby iterators can only take one block. For instance we can’t +do the following.

+
+# Mistake. Several blocks cannot be passed.
+array_of_array.each do |i|
+  ....
+end do |j|
+  ....
+end
+
+

Secondly, Ruby’s blocks can share local variables with the code outside.

+
+lvar = 'ok'
+[0,1,2].each do |i|
+  p lvar    # Can acces local variable outside the block.
+end
+
+

That’s where iterators are convenient.

+

But variables can only be shared with the outside. They cannot be shared +with the inside of the iterator method ( e.g. each). Putting it intuitively, +only the local variables can be seen, which are on the outside of the code.

+

Block Local Variables

+

Local variables which are assigned inside a block stay local to that block. +They become block local variables. Let’s check it out.

+
+[0].each do
+  i = 0
+  p i     # 0
+end
+
+

For the time being we apply each to an array of length 1. ( We can +leave out the block parameter.) The variable i is first assigned +and declared inside the block. So i becomes a block local variable.

+

Block local means that it cannot be accessed from the outside. +Let’s test it.

+
+% ruby -e '
+[0].each do
+  i = 0
+end
+p i     # Here occurs an error.
+'
+-e:5: undefined local variable or method `i'
+for #<Object:0x40163a9c> (NameError)
+
+

When we referenced a block local variable from outside the block +an error occured. Without a doubt it stayed local to the block.

+

Iterators can also be nested repeatedly. Each time +the new block creates another scope.

+
+lvar = 0
+[1].each do
+  var1 = 1
+  [2].each do
+    var2 = 2
+    [3].each do
+      var3 = 3
+      #  Here lvar, var1, var2, var3 can be seen
+    end
+    # Here lvar, var1, var2 can be seen
+  end
+  # Here lvar, var1 can be seen
+end
+# Here only lvar can be seen
+
+

There’s one point which you have to keep in mind. Differing from +nowadays’ major languages Ruby’s block local variables don’t do shadowing. +Shadowing means for instance in C that in the code below the two declared +variables i are different.

+
+{
+    int i = 3;
+    printf("%d\n", i);         /* 3 */
+    {
+        int i = 99;
+        printf("%d\n", i);     /* 99 */
+    }
+    printf("%d\n", i);         /* 3 (元に戻った) */
+}
+
+

Inside the block the i inside overshadows the i outside. +That’s why it’s called shadowing.

+

But what happens in Ruby where there’s no shadowing. +Let’s look at this example.

+
+i = 0
+p i           # 0
+[0].each do
+  i = 1
+  p i         # 1
+end
+p i           # 1 the change is preserved
+
+

When we assign i inside the block and if there is a variable i +that same variable will be used. Hence if we assign to i inside +the value for i on the outside changes. On this point there +came many complains: “This is error prone. Please do shadowing.” +Each time there’s flaming but till now no conclusion was reached.

+

The syntax of iterators

+

There are some smaller topics left.

+

First, there are two ways to write an iterator. One is the +do ~ end as used above, the other one is the enclosing in braces. +The two expressions below have exactly the same meaning.

+
+arr.each do |i|
+  puts i
+end
+
+arr.each {|i|    # The author likes a four space indentation for
+    puts i       # an iterator with braces.
+}
+
+

But grammaticarly the precedence is different. +The braces bind much stronger than do~end.

+
+m m do .... end    # m(m) do....end
+m m { .... }       # m(m() {....})
+
+

And iterators are of course just methods so they also take +arguments.

+
+re = /^\d/                 # regular expression to match a digit at the beginning of the line
+$stdin.grep(re) do |line|  # look repeatedly for this regular expression
+  ....
+end
+
+

yield

+

Of course users can write their own iterators. Methods which have +a yield in their definition text are iterators. +Let’s try to write an iterator with the same effect as Array#each:

+
+# adding the definition to the Array class
+class Array
+  def my_each
+    i = 0
+    while i < self.length
+      yield self[i]
+      i += 1
+    end
+  end
+end
+
+# this is the original each
+[0,1,2,3,4].each do |i|
+  p i
+end
+
+# my_each works the same
+[0,1,2,3,4].my_each do |i|
+  p i
+end
+
+

yield calls the block. At this point control is passed to the block, +when the execution of the block finishes it returns back to the same +location. Think about it like calling a special function. When the +present method does not have a block a runtime error will occur.

+
+% ruby -e '[0,1,2].each'
+-e:1:in `each': no block given (LocalJumpError)
+        from -e:1
+
+

Proc

+

I said, that iterators are like cut out code which is passed as an +argument. But we can even more directly make code to an object +and carry it around.

+
+twice = Proc.new {|n| n * 2 }
+p twice.call(9)   # 18 will be printed
+
+

In short, it is like a function. It can be created with new and +as might be expected, the return value of Proc.new is an instance +of the Proc class.

+

Proc.new looks surely like an iterator and it is indeed so. +It is an ordinary iterator. There’s only some mechanism inside Proc.new +which turns an iterator block into an object.

+

Besides there is a function style method lambda provided which +has the same effect as Proc.new. Choose whatever suits you.

+
+twice = lambda {|n| n * 2 }
+
+

Iterators and Proc

+

Why did we start talking all of a sudden about Proc? Because there +is a deep relationship between iterators and Proc. +In fact iterators and Proc objects are quite the same thing. +That’s why one can be transformed into the other.

+

First, to turn an iterator block into a Proc object +one has to put an & in front of the parameter name.

+
+def print_block( &block )
+  p block
+end
+
+print_block() do end   # Shows something like <Proc:0x40155884>
+print_block()          # Without a block nil is printed
+
+

With an & in front of the argument name, the block is transformed to +a Proc object and assigned to the variable. If the method is not an +iterator (there’s no block attached) nil is assigned.

+

And in the other direction, if we want to pass a Proc to an iterator +we also use &.

+
+block = Proc.new {|i| p i }
+[0,1,2].each(&block)
+
+

This code means exactly the same as the code below.

+
+[0,1,2].each {|i| p i }
+
+

If we combine these two, we can delegate an iterator +block to a method somewhere else.

+
+def each_item( &block )
+  [0,1,2].each(&block)
+end
+
+each_item do |i|    # same as [0,1,2].each do |i|
+  p i
+end
+
+

Expressions

+

Expressions in Ruby can be combined to build new expressions or statements. +For instance a method call can be another method call’s argument, +and so it would become an expression. +The same goes for literals. But literals and method calls are not combinations +of other elements. From here on the expressions introduced will always be used +in combination with other expressions.

+

if

+

We probably do not need to explain the if expression. If the conditional +expression is true the body expression is executed. As explained in the +first part in Ruby every object except nil and false is true.

+
+if cond0 then
+  ....
+elsif cond1 then
+  ....
+elsif cond2 then
+  ....
+else
+  ....
+end
+
+

elsif and else can be omitted. Each then can also be omitted +elsif・But there are some finer requirements concerning then. +It will be apparent by looking at the examples below. +All of them are valid.

+
+# 1                                    # 4
+if cond then ..... end                 if cond
+                                       then .... end
+# 2
+if cond; .... end                      # 5
+                                       if cond
+# 3                                    then
+if cond then; .... end                   ....
+                                       end
+
+

Furthermore, as every expression has a return value, there +is also a return value here. It is the return value of the +body expression which holds. For instance if the condition +at the beginning is true it is the return value of the +following expression.

+
+p(if true  then 1 else 2 end)   #=> 1
+p(if false then 1 else 2 end)   #=> 2
+p(if false then 1 elsif true then 2 else 3 end)   #=> 2
+
+

If there’s no match, or the match is empty nil is returned.

+
+p(if false then 1 end)    #=> nil
+p(if true  then   end)    #=> nil
+
+

unless

+

An if with a negated condition is the same as an unless. +The following two examples have the same meaning.

+
+unless cond then          if not (cond) then
+  ....                      ....
+end                       end
+
+

unless can also have an else clause but there cannot be an elsif. +Of course then can be omitted.

+

unless also has a value. Analogous to if it is the value of the of the +clause which matches. If there’s no match or the match is empty nil +is returned.

+

and && or ||

+

The most useful utilization of the and is probably as a boolean operator. +For instance in the conditional clause of an if.

+
+if cond1 and cond2
+  puts 'ok'
+end
+
+

But as in Perl, the Shell or Lisp it can also be used as a conditional +branch expression. +The two following expressions have the same meaning.

+
+                                        if invalid?(key)
+invalid?(key) and return nil              return nil
+                                        end
+
+

&& and and have the same meaning. Different is the binding order.

+
+method arg0 &&  arg1    # method(arg0 && arg1)
+method arg0 and arg1    # method(arg0) and arg1
+
+

Basically the symbolic operator is used in an expression which becomes an argument. +The alphabetical operator is used in an expression which will not become +an argument.

+

As for and, if the evaluation of the left hand side is true, +the right hand side will also be evaluated.

+

On the other hand or is the opposite of and. If the evaluation of the left hand +side is false, the right hand side will also be evaluated.

+
+valid?(key) or return nil
+
+

or and || have the same relationship as && and and. Only the precedence is +different.

+

The Conditional Operator

+

There is a conditional operator similar to C:

+
+cond ? iftrue : iffalse
+
+

The space between the symbols is important. +If they bump together the following weirdness happens.

+
+cond?iftrue:iffalse   # cond?(iftrue(:iffalse))
+
+

The value of the conditional operator is the value of the last executed expression. +Either the value of the true side or the value of the false side.

+

while until

+

Here’s a while expression.

+
+while cond do
+  ....
+end
+
+

This is the most basic loop construct. As long as cond is true +the body is executed. The do can be omitted.

+
+until io_ready?(id) do
+  sleep 0.5
+end
+
+

until comes to the exact opposite conclusion as the while. +As long as the body expression is false it is executed. +The do can be omitted.

+

There is also a jump construct which exits the loop. +As in C/C++/Java it is called break. Instead of continue there +is next. That seems to have come from Perl.

+
+i = 0
+while true
+  if i > 10
+    break   # exit the loop
+  elsif i % 2 == 0
+    i *= 2
+    next    # next loop iteration
+  end
+  i += 1
+end
+
+

And there is another Perlism: the redo.

+
+while cond
+  # (A)
+  ....
+  redo
+  ....
+end
+
+

It will return to (A) and repeat from there. With next there +is a condition check, with redo there is none.

+

I might come into the world top 100, if the amount of Ruby programs +would be counted, but I haven’t used redo yet. It does not seem to be +that necessary after all.

+

case

+

A special form of the if expression. It performs branching on a series of +conditions. The following left and right expressions are identical in meaning.

+
+case value
+when cond1 then                if cond1 === value
+  ....                           ....
+when cond2 then                elsif cond2 === value
+  ....                           ....
+when cond3, cond4 then         elsif cond3 === value or cond4 === value
+  ....                           ....
+else                           else
+  ....                           ....
+end                            end
+
+

The threefold equals === is, as the same as the ==, actually a method call. +Notice that the receiver is the object on the left hand side. Concretely, +if it is the === of an Array, it would check if it contains the value +as its element. +If it is a Hash, it tests whether it has the value as its key. +If its is an regular expression, it tests if the value matches. +And so on. +Since case has many grammatical elements, +to list them all would be tedious, thus we will not cover them in this book.

+

Exceptions

+

This is a control structure which can pass method boundaries and +transmit errors. Readers who are acquainted to C++ or Java +will know about exceptions. Ruby exceptions are basically the +same.

+

In Ruby exceptions come in the form of the function style method raise. +raise is not a reserved word.

+
+raise ArgumentError, "wrong number of argument"
+
+

In Ruby exception are instances of the Exception class and it’s +subclasses. This form takes an exception class as its first argument +and an error message as its second argument. In the above case +an instance of ArgumentError is created and “thrown”. Exception +object ditch the part after the raise and return upwards the +method call stack.

+
+def raise_exception
+  raise ArgumentError, "wrong number of argument"
+  # the code after the exception will not be executed
+  puts 'after raise'
+end
+raise_exception()
+
+

If nothing blocks the exception it will move to the top level. +When it reaches the top level, ruby gives out a message and ends +with a non-zero exit code.

+
+% ruby raise.rb
+raise.rb:2:in `raise_exception': wrong number of argument (ArgumentError)
+        from raise.rb:7
+
+

However, for this an exit would be sufficient, for an exception ther +should be ways to handle it. In Ruby there is the begin, rescue, end for this. +It resembles the try and catch in C++ and Java.

+
+def raise_exception
+  raise ArgumentError, "wrong number of argument"
+end
+
+begin
+  raise_exception()
+rescue ArgumentError => err then
+  puts 'exception catched'
+  p err
+end
+
+

rescue is a control structure which captures an exception, it catches +the exceptions of the declared class and its subclasses. If in the +above example an instance of ArgumentError comes flying this rescue +matches it. By =>err the exception object will be assigned to the local variable +err, after that the rescue part is executed.

+
+% ruby rescue.rb
+exception catched
+#<ArgumentError: wrong number of argument>
+
+

If the exception is resuced the execution carries on after the rescue +as if nothing happened. We can also make it retry the critical part +with retry.

+
+begin    # return here
+  ....
+rescue ArgumentError => err then
+  retry  # beginning anew
+end
+
+

We can omit the =>err and the then after rescue. We can also leave +out the exception class. In this case the class StandardError is matched.

+

If we want to add more exception classes we can just list them after rescue. +When we want to handle different errors differently we can use several rescues +in one begin~end block.

+
+begin
+  raise IOError, 'port not ready'
+rescue ArgumentError, TypeError
+rescue IOError
+rescue NameError
+end
+
+

In this case the exception class is checked in order until there is a match. +Only the one matched part is executed. For instance in the above case only +IOError is executed.

+

On the othor hand, when there is an else clause, it is executed +only when there is no exception.

+
+begin
+  nil    # Of course here will no error occur
+rescue ArgumentError
+  # This part will not be executed
+else
+  # This part will be executed
+end
+
+

Moreover an ensure clause will be executed in every case: +when there is no exception, when there is an exception, rescued or not.

+
+begin
+  f = File.open('/etc/passwd')
+  # do stuff
+ensure   # this part will be executed anyway
+  f.close
+end
+
+

Besides, this begin expression also has a value. The value of the +whole begin~end expression is the value of the part which was executed +last. The ensure part does not count as it is normally used for cleanup only.

+

Variables and Constants

+

Referring a variable or a constant. The value is the object the variable points to. +We already talked in too much detail about the various behaviors.

+
+lvar
+@ivar
+@@cvar
+CONST
+$gvar
+
+

I want to add one more thing. The variables starting with $ are +of a special kind. Some have strange names, but they are not +necessarily global.

+

First the Perlish variables $_ and $~. $_ saves the return +value of gets and other methods, $~ contains the last match +of a regular expression. They are called local and thread local. +Incredible variables.

+

And the variable $! which saves the exceptional object when +an exception has occurred as well as the variable $? which +saves the status of a child process and $SAFE which represents +the security level are all thread local.

+

Assignment

+

Variable assignment are all performed by =. All variables are +typeless. What is saved is a reference to an object. It is +implemented with VALUE (pointer).

+
+var = 1
+obj = Object.new
+@ivar = 'string'
+@@cvar = ['array']
+PI = 3.1415926535
+$gvar = {'key' => 'value'}
+
+

However, as mentioned earlier obj.attr=val is not an assignment. +It is a method call.

+

Self Assignment

+
+var += 1
+
+

This syntax is also in C/C++/Java. In Ruby,

+
+var = var + 1
+
+

it is a shortcut of this code. +Differing from C, the Ruby + is a method and thus part of the library. +In the whole meaning of += is built in the language processor itself. +And in C++, += and *= can be wholly overwritten, +but we cannot do this in Ruby. +In Ruby <code>= is always defined as an operation of the combination of </code> and assignment.

+

We can also combine self assignment and an attribute-access-flavor method. +The result more looks like an attribute.

+
+class C
+  def i() @i end          # A method definition can be written in one line.
+  def i=(n) @i = n end
+end
+
+obj = C.new
+obj.i = 1
+obj.i += 2    # obj.i = obj.i + 2
+p obj.i       # 3
+
+

If there is += there might also be ++ but this is not the case. +Why is that so? In Ruby assignment is dealt with on the language level. +But on the other hand methods are in the library. Keeping these two, +the world of variables and the world of objects, strictly apart is an +important peculiarity of Ruby. If ++ were introduced the separation +might easily be broken. That’s why there’s no ++

+

Some people don’t want to go without the brevity of ++. It has been +proposed again and again in the mailing list but was always turned down. +I also am in favor of ++ but I can do without, there has never been +a ++ in Ruby so let’s forget about it.

+

defined?

+

defined? is a strange construct in Ruby. It tells whether an +expression value is defined or not.

+
+var = 1
+defined?(var)   #=> true
+
+

In other words it tells whether the received argument (is it okay to call +it so?) returns a value after evaluation. But it won’t tell you if there’s +a parse error or an exception is raised.

+

I would have loved to tell you more about defined? +but it will not appear again in this book. What a pity.

+

Statements

+

A statement is a syntactic construct which basically +cannot be combined with something else and is written +in a separate line.

+

But it still can be evaluated. For instance there are return values +for class definition statements and method definition statements. +However this is only rarely used, not recommended and isn’t useful. +We stick with this informal criteria. +Here we also don’t mention the various return values.

+

The Ending of a statement

+

Up to now we just said “For now one line’s one statement”. +But Ruby’s statement ending’s aren’t that straightforward.

+

First a statement can be ended explicitly with a semicolon as in C. +Of course then we can write two and more statements in one line.

+
+puts 'Hello, World!'; puts 'Hello, World once more!'
+
+

On the other hand after opened parentheses, dyadic operators, or commas +when the command apparently continues the sentence continues automatically.

+
+# 1 + 3 * method(6, 7 + 8)
+1 +
+  3 *
+     method(
+            6,
+            7 + 8)
+
+

But it’s also no problem to connect lines explicitly with a backslash.

+
+p 1 + \
+  2
+
+

The Modifiers if and unless

+

The if modifier is an irregular version of the normal if +The programs on the left and right mean exactly the same.

+
+on_true() if cond                if cond
+                                   on_true()
+                                 end
+
+

The unless is the negative version. +Guard statements ( statements which exclude exceptions) can +be conveniently written with it.

+

The Modifiers while and until

+

while and until also have a back notation.

+
+process() while have_content?
+sleep(1) until ready?
+
+

Combining this with begin and end gives a do-while-loop like in C.

+
+begin
+  res = get_response(id)
+end while need_continue?(res)
+
+

Class Definition

+
+class C < SuperClass
+  ....
+end
+
+

Defines the class C which inherits from SuperClass

+

We talked quite extensively about classes in the first part. +This statement will be executed, within the definition the class will +become self, arbitrary expressions can be written within. Class +definitions can be nested. They form the foundation of Ruby execution +image.

+

Method Definition

+
+def m(arg)
+end
+
+

I’ve already written about method definition and won’t add more. +They also belong to statements.

+

Singleton method definition

+

We already talked a lot about singleton methods in the first part. +They do not belong to classes but to objects, in fact, they belong +to singleton classes. We define singleton methods by putting the +receiver in front of the method name. Parameter declaration is done +the same way like with ordinary methods.

+
+def obj.some_method
+end
+
+def obj.some_method2( arg1, arg2, darg = nil, *rest, &block )
+end
+
+

Definition of Singleton methods

+
+class << obj
+  ....
+end
+
+

From the viewpoint of purposes, +it is the statement to define some singleton methods in a bundle. +From the viewpoint of measures, +it is the statement in which the singleton class of obj becomes self when +executed. +In all over the Ruby program, +this is the only place where a singleton class is exposed.

+
+class << obj
+  p self  #=> #<Class:#<Object:0x40156fcc>>   # Singleton Class 「(obj)」
+  def a() end   # def obj.a
+  def b() end   # def obj.b
+end
+
+

Multiple Assignment

+

With a multiple assignment several assignments can be combined into one. +The following is a simple example:

+
+a, b, c = 1, 2, 3
+
+

It’s exactly the same as the following.

+
+a = 1
+b = 2
+c = 3
+
+

It’s not just for brevity’s sake. When we bind variables to an elements +of an array it becomes delightful.

+
+a, b, c = [1, 2, 3]
+
+

This also has the same result as the above. +Furthermore, the right handside does not need to be a literal. +It can also be a variable or a method call.

+
+tmp = [1, 2, 3]
+a, b, c = tmp
+ret1, ret2 = some_method()   # some_method might probably return several values
+
+

Precisely speaking it is as follows. We will write the value of the +left hand side as obj.

+
    +
  1. obj if it is an array
  2. +
  3. if its to_ary method is defined, it is used to convert obj to an array.
  4. +
  5. [obj]
  6. +
+

Decide the right-hand side by following this procedure and perform assignments. +It means the evaluation of the right-hand side and the operation of assignments +are totally independent from each other.

+

And it goes on, the left and right hand side can be infinitely nested.

+
+a, (b, c, d) = [1, [2, 3, 4]]
+a, (b, (c, d)) = [1, [2, [3, 4]]]
+(a, b), (c, d) = [[1, 2], [3, 4]]
+
+

As the result of the execution of this program, +each line will be a=1 b=2 c=3 d=4.

+

And it goes on. The left hand side can be index or parameter assignments.

+
+i = 0
+arr = []
+arr[i], arr[i+1], arr[i+2] = 0, 2, 4
+p arr    # [0, 2, 4]
+
+obj.attr0, obj.attr1, obj.attr2 = "a", "b", "c"
+
+

And like with method parameters, +* can be used to receive in a bundle.

+
+first, *rest = 0, 1, 2, 3, 4
+p first  # 0
+p rest   # [1, 2, 3, 4]
+
+

If all of them are used all at once, you will easily get confused.

+

Block parameter and multiple assignment

+

We brushed over block parameters when we were talking about iterators. +But there is a deep relationship between them and multiple assignment. +For instance in the following case.

+
+array.each do |i|
+  ....
+end
+
+

When the block is called with a yield, the provided parameters are multi-assigned to i. +Here there’s only one variable on the left hand side, so it does not look like multi assignment. +But if there are two or more variables we see what’s going on. For instance Hash#each +provides a key and a value we usually call it like that:

+
+hash.each do |key, value|
+  ....
+end
+
+

In this case an array with elements key and value are yielded +from the hash.

+

Hence we can also use nested multiple assignment as shown below.

+
+# [[key,value],index] are given to yield
+hash.each_with_index do |(key, value), index|
+  ....
+end
+
+

alias

+
+class C
+  alias new orig
+end
+
+

Defining another method new with the same body as the already +defined method orig. alias are similar to hardlinks in a unix +file system. They are a means of assigning multiple names to one method body. I other words, +because the names themselves are independent of each other, +if one method name is overwritten by a subclass method, the +other one still returns the method as before.

+

undef

+
+class C
+  undef method_name
+end
+
+

Prohibits the calling of C#method_name. It’s not just a simple +revoking of the definition. If there even were a method in the +superclass it would also be forbidden. In other words the method is +exchanged for a sign which says “This method must not be called”.

+

undef is extremely powerful, once it is set it cannot be +deleted on the Ruby level, because it is used to cover up contradictions +in the internal structure. One must define a method in the lower class. +Even then when one calls super an +error occurs.

+

By the way the method which corresponds to unlink in a file system +is Module#remove_method. While defining a class, self refers +to that class, we can call it as follows ( Remember that Class is a +subclass of Module.

+
+class C
+  remove_method(:method_name)
+end
+
+

But even with a remove_method one cannot cancel the undef. +It’s because the sign put up by undef prohibits any kind of searches.

+

((errata: It can be redefined by using def))

+

Some more small topics

+

Comments

+
+# examples of bad comments.
+1 + 1            # compute 1+1.
+alias my_id id   # my_id is an alias of id.
+
+

From a # to the end of line is a comment. +It doesn’t have a meaning for the program.

+

Embedded documents

+
+=begin
+This is an embedded document.
+It's so called because it is embedded in the program.
+Plain and simple.
+=end
+
+

An embedded document stretches from +an =begin outside a string at the beginning of a line +to a =end. The interior can be arbitrary. +The program reads and ignores it like a simple comment.

+

Multi-byte strings

+

When the global variable $KCODE is set to either EUC, SJIS +or UTF8, strings encoded in euc-jp, shift_jis, or utf8 respectively can be +used in a string of a data.

+

And if the option -Ke, -Ks or -Ku is given to the ruby +command multibyte strings can be used within the Ruby code. +String literals, regular expressions and even operator names +can contain multibyte characters. Hence it is possible to do +something like this:

+
+def 表示( arg )
+  puts arg
+end
+
+表示 'にほんご'
+
+

But I really cannot recommend doing things like that.

+ + + +
+ + diff --git a/htmls/syntree.html b/htmls/syntree.html new file mode 100644 index 0000000..f572d14 --- /dev/null +++ b/htmls/syntree.html @@ -0,0 +1,1615 @@ + + + + + Chapter 12: Syntax tree construction | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 12: Syntax tree construction

+

Node

+

NODE

+

As I’ve already described, a Ruby program is first converted to a syntax tree. +To be more precise, a syntax tree is a tree structure made of structs called “nodes”. +In ruby , all nodes are of type NODE .

+

NODE

+ +
+ 128  typedef struct RNode {
+ 129      unsigned long flags;
+ 130      char *nd_file;
+ 131      union {
+ 132          struct RNode *node;
+ 133          ID id;
+ 134          VALUE value;
+ 135          VALUE (*cfunc)(ANYARGS);
+ 136          ID *tbl;
+ 137      } u1;
+ 138      union {
+ 139          struct RNode *node;
+ 140          ID id;
+ 141          int argc;
+ 142          VALUE value;
+ 143      } u2;
+ 144      union {
+ 145          struct RNode *node;
+ 146          ID id;
+ 147          long state;
+ 148          struct global_entry *entry;
+ 149          long cnt;
+ 150          VALUE value;
+ 151      } u3;
+ 152  } NODE;
+
+(node.h)
+
+

Although you might be able to infer from the struct name RNode , nodes are Ruby objects. +This means the creation and release of nodes are taken care of by the ruby ’s garbage collector.

+

Therefore, flags naturally has the same role as basic.flags of the object struct. +It means that T_NODE which is the type of a struct and flags such as FL_FREEZE are stored in it. +As for NODE , in addition to these, its node type is stored in flags .

+

What does it mean? Since a program could contain various elements +such as if and while and def and so on, there are also various corresponding node types. +The three available union are complicated, +but how these unions are used is decided to only one specific way for each node. +For example, the below table shows the case when it is NODE_IF that is the node of if .

+ + + + + + + + + + + + + + + + + + + + + +
member union member role
u1 u1.node the condition expression
u2 u2.node the body of true
u3 u3.node the body of false
+

And, in node.h , the macros to access each union member are available.

+

▼ the macros to access NODE

+ +
+ 166  #define nd_head  u1.node
+ 167  #define nd_alen  u2.argc
+ 168  #define nd_next  u3.node
+ 169
+ 170  #define nd_cond  u1.node
+ 171  #define nd_body  u2.node
+ 172  #define nd_else  u3.node
+ 173
+ 174  #define nd_orig  u3.value
+                 :
+                 :
+
+(node.h)
+
+

For example, these are used as follows:

+
+NODE *head, *tail;
+head->nd_next = tail;    /* head->u3.node = tail */
+
+

In the source code, it’s almost certain that these macros are used. +A very few exceptions are only the two places where creating NODE in parse.y +and where marking NODE in gc.c .

+

By the way, what is the reason why such macros are used? +For one thing, it might be because it’s cumbersome to remember numbers like u1 +that are not meaningful by just themselves. +But what is more important than that is, there should be no problem if the +corresponding number is changed and it’s possible that it will actually be changed. +For example, since a condition clause of if does not have to be stored in u1 , +someone might want to change it to u2 for some reason. But if u1 is directly used, +he needs to modify a lot of places all over the source codes, it is inconvenient. +Since nodes are all declared as NODE , it’s hard to find nodes that represent if . +By preparing the macros to access, this kind of trouble can be avoided +and conversely we can determine the node types from the macros.

+

Node Type

+

I said that in the flags of a NODE struct its node type is stored. +We’ll look at in what form this information is stored. +A node type can be set by nd_set_type() and obtained by nd_type() .

+

nd_type nd_set_type

+ +
+ 156  #define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0xff)
+ 157  #define nd_set_type(n,t) \
+ 158      RNODE(n)->flags = ((RNODE(n)->flags & ~FL_UMASK) \
+                             | (((t)<<FL_USHIFT) & FL_UMASK))
+
+(node.h)
+
+

FL_USHIFT FL_UMASK

+ +
+ 418  #define FL_USHIFT    11
+ 429  #define FL_UMASK  (0xff<<FL_USHIFT)
+
+(ruby.h)
+
+

It won’t be so much trouble if we’ll keep focus on around nd_type . +Fig.1 shows how it seems like.

+

+

(flagUsage)
+Fig.1: How RNode.flags is used

+

+

And, since macros cannot be used from debuggers, +the nodetype() function is also available.

+

nodetype

+ +
+4247  static enum node_type
+4248  nodetype(node)                  /* for debug */
+4249      NODE *node;
+4250  {
+4251      return (enum node_type)nd_type(node);
+4252  }
+
+(parse.y)
+
+

File Name and Line Number

+

The nd_file of a NODE holds (the pointer to) the name of the file where the +text that corresponds to this node exists. Since there’s the file name, we +naturally expect that there’s also the line number, but the corresponding member +could not be found around here. Actually, the line number is being embedded to +flags by the following macro:

+

nd_line nd_set_line

+ +
+ 160  #define NODE_LSHIFT (FL_USHIFT+8)
+ 161  #define NODE_LMASK  (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
+ 162  #define nd_line(n) \
+          ((unsigned int)((RNODE(n)->flags >> NODE_LSHIFT) & NODE_LMASK))
+ 163  #define nd_set_line(n,l) \
+ 164      RNODE(n)->flags = ((RNODE(n)->flags & ~(-1 << NODE_LSHIFT)) \
+                             | (((l)&NODE_LMASK) << NODE_LSHIFT))
+
+(node.h)
+
+

nd_set_line() is fairly spectacular. +However, as the names suggest, it is certain that nd_set_line() and nd_line +works symmetrically. Thus, if we first examine the simpler nd_line() and grasp +the relationship between the parameters, there’s no need to analyze nd_set_line() +in the first place.

+

The first thing is NODE_LSHIFT , as you can guess from the description of the +node types of the previous section, it is the number of used bits in flags . +FL_USHIFT is reserved by system of ruby (11 bits, ruby.h ), 8 bits are for +its node type.

+

The next thing is NODE_LMASK .

+
+sizeof(NODE*) * CHAR_BIT - NODE_LSHIFT
+
+

This is the number of the rest of the bits. +Let’s assume it is restbits . This makes the code a lot simpler.

+
+#define NODE_LMASK  (((long)1 << restbits) - 1)
+
+

Fig.2 shows what the above code seems to be doing. Note that a borrow occurs +when subtracting 1. We can eventually understand that NODE_LMASK is a sequence +filled with 1 whose size is the number of the bits that are still available.

+

+

(lmask)
+Fig.2: NODE_LMASK

+

+

Now, let’s look at nd_line() again.

+
+(RNODE(n)->flags >> NODE_LSHIFT) & NODE_LMASK
+
+

By the right shift, the unused space is shifted to the LSB. The bitwise AND +leaves only the unused space. Fig.3 shows how flags is used. Since FL_USHIFT +is 11, in 32-bit machine 32-(11+8)=13 bits are available for the line number.

+

+

(flags)
+Fig.3: How flags are used at NODE

+

+

… This means, if the line numbers becomes beyond 2^13=8192, +the line numbers should wrongly be displayed. Let’s try.

+
+File.open('overflow.rb', 'w') {|f|
+    10000.times { f.puts }
+    f.puts 'raise'
+}
+
+

With my 686 machine, ruby overflow.rb properly displayed 1809 as a line number. +I’ve succeeded. However, if you use 64-bit machine, you need to create a little +bigger file in order to successfully fail.

+

rb_node_newnode()

+

Lastly let’s look at the function rb_node_newnode() that creates a node.

+

rb_node_newnode()

+ +
+4228  NODE*
+4229  rb_node_newnode(type, a0, a1, a2)
+4230      enum node_type type;
+4231      NODE *a0, *a1, *a2;
+4232  {
+4233      NODE *n = (NODE*)rb_newobj();
+4234
+4235      n->flags |= T_NODE;
+4236      nd_set_type(n, type);
+4237      nd_set_line(n, ruby_sourceline);
+4238      n->nd_file = ruby_sourcefile;
+4239
+4240      n->u1.node = a0;
+4241      n->u2.node = a1;
+4242      n->u3.node = a2;
+4243
+4244      return n;
+4245  }
+
+(parse.y)
+
+

We’ve seen rb_newobj() in the Chapter 5: Garbage collection. It is the function to get a +vacant RVALUE . By attaching the T_NODE struct-type flag to it, +the initialization as a VALUE will complete. +Of course, it’s possible that some values that are not of type NODE* are +passed for u1 u2 u3, but received as NODE* for the time being. +Since the syntax trees of ruby does not contain double and such, +if the values are received as pointers, it will never be too small in size.

+

For the rest part, you can forget about the details you’ve learned so far, +and assume NODE is

+
    +
  • flags
  • +
  • nodetype
  • +
  • nd_line
  • +
  • nd_file
  • +
  • u1
  • +
  • u2
  • +
  • u3
  • +
+

a struct type that has the above seven members.

+

Syntax Tree Construction

+

The role of the parser is to convert the source code that is a byte sequence to a +syntax tree. Although the grammar passed, it does not finish even half of the task, +so we have to assemble nodes and create a tree. +In this section, we’ll look at the construction process of that syntax tree.

+

YYSTYPE

+

Essentially this chapter is about actions, +thus YYSTYPE which is the type of $$ or $1 becomes important. +Let’s look at the %union of ruby first.

+

%union declaration

+ +
+ 170  %union {
+ 171      NODE *node;
+ 172      ID id;
+ 173      int num;
+ 174      struct RVarmap *vars;
+ 175  }
+
+(parse.y)
+
+

struct RVarmap is a struct used by the evaluator and holds a block local variable. +You can tell the rest. The most used one is of course node .

+

Landscape with Syntax Trees

+

I mentioned that looking at the fact first is a theory of code reading. +Since what we want to know this time is how the generated syntax tree is, +we should start with looking at the answer (the syntax tree).

+

It’s also nice using debuggers to observe every time, +but you can visualize the syntax tree more handily +by using the tool nodedump contained in the attached CD-ROM, +This tool is originally the NodeDump made by Pragmatic Programmers +and remodeled for this book. +The original version shows quite explanatory output, +but this remodeled version deeply and directly displays the appearance of the +syntax tree.

+

For example, in order to dump the simple expression m(a) , you can do as follows:

+
+% ruby -rnodedump -e 'm(a)'
+NODE_NEWLINE
+nd_file = "-e"
+nd_nth  = 1
+nd_next:
+    NODE_FCALL
+    nd_mid = 9617 (m)
+    nd_args:
+        NODE_ARRAY
+        nd_alen = 1
+        nd_head:
+            NODE_VCALL
+            nd_mid = 9625 (a)
+        nd_next = (null)
+
+

The -r option is used to specify the library to be load, +and the -e is used to pass a program. +Then, the syntax tree expression of the program will be dumped.

+

I’ll briefly explain about how to see the content. +NODE_NEWLINE and NODE_FCALL and such are the node types. +What are written at the same indent level of each node are the contents of its node members. +For example, the root is NODE_NEWLINE , and it has the three members: +nd_file nd_nth nd_next. nd_file points to the "-e" string of C, +and ng_nth points to the 1 integer of C, and nd_next holds the next node NODE_CALL . +But since these explanation in text are probably not intuitive, +I recommend you to also check Fig.4 at the same time.

+

+

(stree)
+Fig.4: Syntax Tree

+

+

I’ll explain the meaning of each node. NODE_CALL is a Function CALL. +NODE_ARRAY is as its name suggests the node of array, and here it expresses +the list of arguments. NODE_VCALL is a Variable or CALL, a reference to +undefined local variable will become this.

+

Then, what is NODE_NEWLINE ? This is the node to join the name of the currently +executed file and the line number at runtime and is set for each stmt . +Therefore, when only thinking about the meaning of the execution, this node can +be ignored. When you require nodedump-short instead of nodedump , +distractions like NODE_NEWLINE are left out in the first place. Since it is +easier to see if it is simple, nodedump-short will be used later on except for +when particularly written.

+

Now, we’ll look at the three type of composing elements in order to grasp how +the whole syntax tree is. The first one is the leaves of a syntax tree. Next, +we’ll look at expressions that are combinations of that leaves, this means they +are branches of a syntax tree. +The last one is the list to list up the statements that is the trunk of a syntax +tree in other words.

+

Leaf

+

First, let’s start with the edges that are the leaves of the syntax tree. +Literals and variable references and so on, among the rules, they are what +belong to primary and are particularly simple even among the primary rules.

+
+% ruby -rnodedump-short -e '1'
+NODE_LIT
+nd_lit = 1:Fixnum
+
+

1 as a numeric value. There’s not any twist. However, notice that what is +stored in the node is not 1 of C but 1 of Ruby (1 of Fixnum ). This is because …

+
+% ruby -rnodedump-short -e ':sym'
+NODE_LIT
+nd_lit = 9617:Symbol
+
+

This way, Symbol is represented by the same NODE_LIT when it becomes a syntax tree. +As the above example, VALUE is always stored in nd_lit so it can be handled +completely in the same way whether it is a Symbol or a Fixnum when executing. +In this way, all we need to do when dealing with it are retrieving the value +in nd_lit and returning it. Since we create a syntax tree in order to execute it, +designing it so that it becomes convenient when executing is the right thing to do.

+
+% ruby -rnodedump-short -e '"a"'
+NODE_STR
+nd_lit = "a":String
+
+

A string. This is also a Ruby string. +String literals are copied when actually used.

+
+% ruby -rnodedump -e '[0,1]'
+NODE_NEWLINE
+nd_file = "-e"
+nd_nth  = 1
+nd_next:
+    NODE_ARRAY
+    nd_alen = 2
+    nd_head:
+        NODE_LIT
+        nd_lit = 0:Fixnum
+    nd_next:
+        NODE_ARRAY
+        nd_alen = 1
+        nd_head:
+            NODE_LIT
+            nd_lit = 1:Fixnum
+        nd_next = (null)
+
+

Array. I can’t say this is a leaf, but let’s allow this to be here because it’s +also a literal. It seems like a list of NODE_ARRAY hung with each element node. +The reason why only in this case I didn’t use nodedump-short is … +you will understand after finishing to read this section.

+

Branch

+

Next, we’ll focus on “combinations” that are branches. +if will be taken as an example.

+

if

+

I feel like if is always used as an example, that’s because its structure is +simple and there’s not any reader who don’t know about if , so it is convenient +for writers.

+

Anyway, this is an example of if . +For example, let’s convert this code to a syntax tree.

+

▼The Source Program

+ +
+if true
+  'true expr'
+else
+  'false expr'
+end
+
+

▼Its syntax tree expression

+ +
+NODE_IF
+nd_cond:
+    NODE_TRUE
+nd_body:
+    NODE_STR
+    nd_lit = "true expr":String
+nd_else:
+    NODE_STR
+    nd_lit = "false expr":String
+
+

Here, the previously described nodedump-short is used, so NODE_NEWLINE +disappeared. nd_cond is the condition, nd_body is the body of the true case, +nd_else is the body of the false case.

+

Then, let’s look at the code to build this.

+

if rule

+ +
+1373                  | kIF expr_value then
+1374                    compstmt
+1375                    if_tail
+1376                    kEND
+1377                      {
+1378                          $$ = NEW_IF(cond($2), $4, $5);
+1379                          fixpos($$, $2);
+1380                      }
+
+(parse.y)
+
+

It seems that NEW_IF() is the macro to create NODE_IF . Among the values of +the symbols, $2 $4 $5 are used, thus the correspondences between the symbols +of the rule and $n are:

+
+kIF    expr_value  then  compstmt  if_tail  kEND
+ $1          $2      $3        $4       $5    $6
+NEW_IF(expr_value,       compstmt, if_tail)
+
+

this way. In other words, expr_value is the condition expression, compstmt +( $4 ) is the case of true, if_tail is the case of false.

+

On the other hand, the macros to create nodes are all named NEW_xxxx , and they +are defined node.h . Let’s look at NEW_IF() .

+

NEW_IF()

+ +
+ 243  #define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e)
+
+(node.h)
+
+

As for the parameters, +it seems that c represents condition, t represents then, and e represents +else respectively. As described at the previous section, the order of +members of a node is not so meaningful, so you don’t need to be careful about +parameter names in this kind of place.

+

And, the code() which processes the node of the condition expression in the +action is a semantic analysis function. This will be described later.

+

Additionally, fixpos() corrects the line number. NODE is initialized with +the file name and the line number of the time when it is “created”. However, +for instance, the code of if should already be parsed by end by the time +when creating NODE_IF . Thus, the line number would go wrong if it remains +untouched. Therefore, it needs to be corrected by fixpos() .

+
+fixpos(dest, src)
+
+

This way, the line number of the node dest is set to the one of the node src . +As for if , the line number of the condition expression becomes the line number +of the whole if expression.

+

elsif

+

Subsequently, let’s look at the rule of if_tail .

+

if_tail

+ +
+1543  if_tail         : opt_else
+1544                  | kELSIF expr_value then
+1545                    compstmt
+1546                    if_tail
+1547                      {
+1548                          $$ = NEW_IF(cond($2), $4, $5);
+1549                          fixpos($$, $2);
+1550                      }
+
+1553  opt_else        : none
+1554                  | kELSE compstmt
+1555                      {
+1556                          $$ = $2;
+1557                      }
+
+(parse.y)
+
+

First, this rule expresses “a list ends with opt_else after zero or more +number of elsif clauses”. That’s because, if_tail appears again and again +while elsif continues, it disappears when opt_else comes in. We can +understand this by extracting arbitrary times.

+
+if_tail: kELSIF .... if_tail
+if_tail: kELSIF .... kELSIF .... if_tail
+if_tail: kELSIF .... kELSIF .... kELSIF .... if_tail
+if_tail: kELSIF .... kELSIF .... kELSIF .... opt_else
+if_tail: kELSIF .... kELSIF .... kELSIF .... kELSE compstmt
+
+

Next, let’s focus on the actions, surprisingly, elsif uses the same NEW_IF() as if . +It means, the below two programs will lose the difference after they become syntax trees.

+
+if cond1                  if cond1
+  body1                     body1
+elsif cond2               else
+  body2                     if cond2
+elsif cond3                   body2
+  body3                     else
+else                          if cond3
+  body4                         body3
+end                           else
+                                body4
+                              end
+                            end
+                          end
+
+

Come to think of it, in C language and such, there’s no distinction between +the two also at the syntax level. Thus this might be a matter of course. +Alternatively, the conditional operator ( a?b:c ) becomes indistinguishable +from if statement after they become syntax trees.

+

The precedences was very meaningful when it was in the context of grammar, +but they become unnecessary any more because the structure of a syntax tree +contains that information. And, the difference in appearance such as if and +the conditional operator become completely meaningless, +its meaning (its behavior) only matters. +Therefore, there’s perfectly no problem if if and the conditional operator +are the same in its syntax tree expression.

+

I’ll introduce a few more examples. add and && become the same. +or and || are also equal to each other. not and ! , if and modifier if , +and so on. These pairs also become equal to each other.

+

Left Recursive and Right Recursive

+

By the way, the symbol of a list was always written at the left side when expressing a list +in Chapter 9: yacc crash course. However, have you noticed it becomes opposite in if_tail ? +I’ll show only the crucial part again.

+
+if_tail: opt_else
+       | kELSIF ... if_tail
+
+

Surely, it is opposite of the previous examples. if_tail which is the symbol +of a list is at the right side.

+

In fact, there’s another established way of expressing lists,

+
+list: END_ITEM
+    | ITEM list
+
+

when you write in this way, it becomes the list that contains continuous zero +or more number of ITEM and ends with END_ITEM .

+

As an expression of a list, whichever is used it does not create a so much difference, +but the way that the actions are executed is fatally different. +With the form that list is written at the right, the actions are sequentially +executed from the last ITEM . We’ve already learned about the behavior of the +stack of when list is at the left, +so let’s try the case that list is at the right. +The input is 4 ITEM s and END_ITEM .

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
empty at first
ITEM shift ITEM
ITEM ITEM shift ITEM
ITEM ITEM ITEM shift ITEM
ITEM ITEM ITEM ITEM shift ITEM
ITEM ITEM ITEM ITEM END_ITEM shift END_ITEM
ITEM ITEM ITEM ITEM list reduce END_ITEM to list
ITEM ITEM ITEM list reduce ITEM list to list
ITEM ITEM list reduce ITEM list to list
ITEM list reduce ITEM list to list
list reduce ITEM list to list
accept.
+

When list was at the left, shifts and reductions were done in turns. +This time, as you see, there are continuous shifts and continuous reductions.

+

The reason why if_tail places “list at the right” is to create a syntax tree +from the bottom up. When creating from the bottom up, the node of if will be +left in hand in the end. But if defining if_tail by placing “list at the left”, +in order to eventually leave the node of if in hand, it needs to traverse all +links of the elsif and every time elsif +is found add it to the end. This is cumbersome. And, slow. +Thus, if_tail is constructed in the “list at the right” manner.

+

Finally, the meaning of the headline is, in grammar terms, +“the left is list " is called left-recursive, +“the right is list " is called right-recursive. +These terms are used mainly when reading papers about processing grammars or +writing a book of yacc .

+

Trunk

+

Leaf, branch, and finally, it’s trunk. +Let’s look at how the list of statements are joined.

+

▼The Source Program

+ +
+7
+8
+9
+
+

The dump of the corresponding syntax tree is shown below. +This is not nodedump-short but in the perfect form.

+

▼Its Syntax Tree

+ +
+NODE_BLOCK
+nd_head:
+    NODE_NEWLINE
+    nd_file = "multistmt"
+    nd_nth  = 1
+    nd_next:
+        NODE_LIT
+        nd_lit = 7:Fixnum
+nd_next:
+    NODE_BLOCK
+    nd_head:
+        NODE_NEWLINE
+        nd_file = "multistmt"
+        nd_nth  = 2
+        nd_next:
+            NODE_LIT
+            nd_lit = 8:Fixnum
+    nd_next:
+        NODE_BLOCK
+        nd_head:
+            NODE_NEWLINE
+            nd_file = "multistmt"
+            nd_nth  = 3
+            nd_next:
+                NODE_LIT
+                nd_lit = 9:Fixnum
+        nd_next = (null)
+
+

We can see the list of NODE_BLOCK is created and NODE_NEWLINE are attached +as headers. (Fig.5)

+

+

(blocklist)
+Fig.5: NODE_BLOCK and NODE_NEWLINE

+

+

It means, for each statement ( stmt ) NODE_NEWLINE is attached, +and when they are multiple, it will be a list of NODE_BLOCK . +Let’s also see the code.

+

stmts

+ +
+ 354  stmts           : none
+ 355                  | stmt
+ 356                      {
+ 357                          $$ = newline_node($1);
+ 358                      }
+ 359                  | stmts terms stmt
+ 360                      {
+ 361                          $$ = block_append($1, newline_node($3));
+ 362                      }
+
+(parse.y)
+
+

newline_node() caps NODE_NEWLINE , block_append() appends it to the list. +It’s straightforward. +Let’s look at the content only of the block_append() .

+

block_append()

+

It this function, the error checks are in the very middle and obstructive. +Thus I’ll show the code without that part.

+

block_append() (omitted)

+ +
+4285  static NODE*
+4286  block_append(head, tail)
+4287      NODE *head, *tail;
+4288  {
+4289      NODE *end;
+4290
+4291      if (tail == 0) return head;
+4292      if (head == 0) return tail;
+4293
+4294      if (nd_type(head) != NODE_BLOCK) {
+4295          end = NEW_BLOCK(head);
+4296          end->nd_end = end;    /*(A-1)*/
+4297          fixpos(end, head);
+4298          head = end;
+4299      }
+4300      else {
+4301          end = head->nd_end;   /*(A-2)*/
+4302      }
+
+          /* ……omitted…… */
+
+4325      if (nd_type(tail) != NODE_BLOCK) {
+4326          tail = NEW_BLOCK(tail);
+4327          tail->nd_end = tail;
+4328      }
+4329      end->nd_next = tail;
+4330      head->nd_end = tail->nd_end;   /*(A-3)*/
+4331      return head;
+4332  }
+
+(parse.y)
+
+

According to the previous syntax tree dump, NEW_BLOCK was a linked list uses nd_next . +Being aware of it while reading, it can be read “if either head or tail is not NODE_BLOCK , +wrap it with NODE_BLOCK and join the lists each other.”

+

Additionally, on (A-1~3), the nd_end of the NODE_BLOCK of the head of the +list always points to the NODE_BLOCK of the tail of the list. This is probably +because in this way we don’t have to traverse all elements when adding an +element to the tail (Fig.6). +Conversely speaking, when you need to add elements later, NODE_BLOCK is suitable.

+

+

(append)
+Fig.6: Appending is easy.

+

+

The two types of lists

+

Now, I’ve explained the outline so far. +Because the structure of syntax tree will also appear in Part 3 in large amounts, +we won’t go further as long as we are in Part 2. +But before ending, there’s one more thing I’d like to talk about. +It is about the two general-purpose lists.

+

The two general-purpose lists mean BLOCK and LIST . +BLOCK is, as previously described, a linked list of NODE_BLOCK to join the statements. +LIST is, although it is called LIST , a list of NODE_ARRAY . +This is what is used for array literals. +LIST is used to store the arguments of a method or the list of multiple assignments.

+

As for the difference between the two lists, +looking at the usage of the nodes is helpful to understand.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NODE_BLOCK nd_head holding an element
nd_end pointing to the NODE_BLOCK of the end of the list
nd_next pointing to the next NODE_BLOCK
NODE_ARRAY nd_head holding an element
nd_alen the length of the list that follows this node
nd_next pointing to the next NODE_ARRAY
+

The usage differs only in the second elements that are nd_end and nd_alen . +And this is exactly the significance of the existence of each type of the two nodes. +Since its size can be stored in NODE_ARRAY , we use an ARRAY list +when the size of the list will frequently be required. +Otherwise, we use a BLOCK list that is very fast to join. +I don’t describe this topic in details because the codes that use them is +necessary to understand the significance but not shown here, +but when the codes appear in Part 3, +I’d like you to recall this and think “Oh, this uses the length”.

+

Semantic Analysis

+

As I briefly mentioned at the beginning of Part 2, there are two types of analysis +that are appearance analysis and semantic analysis. +The appearance analysis is mostly done by yacc , the rest is doing the semantic +analysis inside actions.

+

Errors inside actions

+

What does the semantic analysis precisely mean? +For example, there are type checks in a language that has types. +Alternatively, check if variables with the same name are not defined multiple times, +and check if variables are not used before their definitions, +and check if the procedure being used is defined, +and check if return is not used outside of procedures, and so on. +These are part of the semantic analysis.

+

What kind of semantic analysis is done in the current ruby ? +Since the error checks occupies almost all of semantic analysis in ruby , +searching the places where generating errors seems a good way. +In a parser of yacc , yyerror() is supposed to be called when an error occurs. +Conversely speaking, there’s an error where yyerror() exists. +So, I made a list of the places where calling yyerror() inside the actions.

+
    +
  • an expression not having its value (void value expression) at a place where a value is required
  • +
  • an alias of $n
  • +
  • BEGIN inside of a method
  • +
  • END inside of a method
  • +
  • return outside of methods
  • +
  • a local variable at a place where constant is required
  • +
  • a class statement inside of a method
  • +
  • an invalid parameter variable ($gvar and CONST and such)
  • +
  • parameters with the same name appear twice
  • +
  • an invalid receiver of a singleton method (def ().method and such)
  • +
  • a singleton method definition on literals
  • +
  • an odd number of a list for hash literals
  • +
  • an assignment to self/nil/true/false/__FILE__/__LINE__
  • +
  • a constant assignment inside of a method
  • +
  • a multiple assignment inside of a conditional expression
  • +
+

These checks can roughly be categorized by each purpose as follows:

+
    +
  • for the better error message
  • +
  • in order not to make the rule too complex
  • +
  • the others (pure semantic analysis)
  • +
+

For example, “return outside of a method” is a check in order not to make the +rule too complex. Since this error is a problem of the structure, it can be +dealt with by grammar. +For example, it’s possible by defining the rules separately for both inside and +outside of methods and making the list of all what are allowed and what are not +allowed respectively. But this is in any way cumbersome and rejecting it in an +action is far more concise.

+

And, "an assignment to self " seems a check for the better error message. +In comparison to “return outside of methods”, rejecting it by grammar is much easier, +but if it is rejected by the parser, the output would be just "parse error". +Comparing to it, the current

+
+% ruby -e 'self = 1'
+-e:1: Can't change the value of self
+self = 1
+      ^
+
+

this error is much more friendly.

+

Of course, we can not always say that an arbitrary rule is exactly “for this purpose”. +For example, as for “return outside of methods”, +this can also be considered that this is a check “for the better error message”. +The purposes are overlapping each other.

+

Now, the problem is “a pure semantic analysis”, +in Ruby there are few things belong to this category. +In the case of a typed language, the type analysis is a big event, but +because variables are not typed in Ruby, it is meaningless. +What is standing out instead is the cheek of an expression that has its value.

+

To put “having its value” precisely, +it is “you can obtain a value as a result of evaluating it”. +return and break do not have values by themselves. Of course, a value is +passed to the place where return to, but not any values are left at the place +where return is written. +Therefore, for example, the next expression is odd,

+
+i = return(1)
+
+

Since this kind of expressions are clearly due to misunderstanding or simple mistakes, +it’s better to reject when compiling. +Next, we’ll look at value_expr which is one of the functions to check if it takes a value.

+

value_expr()

+

value_expr() is the function to check if it is an expr that has a value.

+

value_expr()

+ +
+4754  static int
+4755  value_expr(node)
+4756      NODE *node;
+4757  {
+4758      while (node) {
+4759          switch (nd_type(node)) {
+4760            case NODE_CLASS:
+4761            case NODE_MODULE:
+4762            case NODE_DEFN:
+4763            case NODE_DEFS:
+4764              rb_warning("void value expression");
+4765              return Qfalse;
+4766
+4767            case NODE_RETURN:
+4768            case NODE_BREAK:
+4769            case NODE_NEXT:
+4770            case NODE_REDO:
+4771            case NODE_RETRY:
+4772              yyerror("void value expression");
+4773              /* or "control never reach"? */
+4774              return Qfalse;
+4775
+4776            case NODE_BLOCK:
+4777              while (node->nd_next) {
+4778                  node = node->nd_next;
+4779              }
+4780              node = node->nd_head;
+4781              break;
+4782
+4783            case NODE_BEGIN:
+4784              node = node->nd_body;
+4785              break;
+4786
+4787            case NODE_IF:
+4788              if (!value_expr(node->nd_body)) return Qfalse;
+4789              node = node->nd_else;
+4790              break;
+4791
+4792            case NODE_AND:
+4793            case NODE_OR:
+4794              node = node->nd_2nd;
+4795              break;
+4796
+4797            case NODE_NEWLINE:
+4798              node = node->nd_next;
+4799              break;
+4800
+4801            default:
+4802              return Qtrue;
+4803          }
+4804      }
+4805
+4806      return Qtrue;
+4807  }
+
+(parse.y)
+
+

Algorithm

+

Summary: It sequentially checks the nodes of the tree, if it hits “an expression +certainly not having its value”, it means the tree does not have any value. +Then it warns about that by using rb_warning() and return Qfalse . If it +finishes to traverse the entire tree without hitting any “an expression not +having its value”, it means the tree does have a value. Thus it returns Qtrue .

+

Here, notice that it does not always need to check the whole tree. +For example, let’s assume value_expr() is called on the argument of a method. +Here:

+

▼ check the value of arg by using value_expr()

+ +
+1055  arg_value       : arg
+1056                      {
+1057                          value_expr($1);
+1058                          $$ = $1;
+1059                      }
+
+(parse.y)
+
+

Inside of this argument $1 , there can also be other nesting method calls again. +But, the argument of the inside method must have been already checked with +value_expr() , so you don’t have to check it again.

+

Let’s think more generally. Assume an arbitrary grammar element A exists, +and assume value_expr() is called against its all composing elements, +the necessity to check the element A again would disappear.

+

Then, for example, how is if ? Is it possible to be handled as if value_expr() +has already called for all elements? If I put only the bottom line, it isn’t. +That is because, since if is a statement (which does not use a value), +the main body should not have to return a value. +For example, in the next case:

+
+def method
+  if true
+    return 1
+  else
+    return 2
+  end
+  5
+end
+
+

This if statement does not need a value.
+But in the next case, its value is necessary.

+
+def method( arg )
+  tmp = if arg
+        then 3
+        else 98
+        end
+  tmp * tmp / 3.5
+end
+
+

So, in this case, the if statement must be checked when checking the entire +assignment expression. This kind of things are laid out in the switch +statement of value_expr() .

+

Removing Tail Recursion

+

By the way, when looking over the whole value_expr , we can see that there’s +the following pattern appears frequently:

+
+while (node) {
+    switch (nd_type(node)) {
+      case NODE_XXXX:
+        node = node->nd_xxxx;
+        break;
+         :
+         :
+    }
+}
+
+

This expression will also carry the same meaning after being modified to the below:

+
+return value_expr(node->nd_xxxx)
+
+

A code like this which does a recursive call just before return is called a +tail recursion. It is known that this can generally be converted to goto . +This method is often used when optimizing. +As for Scheme, it is defined in specifications that tail recursions must be +removed by language processors. This is because recursions are often used +instead of loops in Lisp-like languages.

+

However, be careful that tail recursions are only when "calling just before return ". +For example, take a look at the NODE_IF of value_expr() ,

+
+if (!value_expr(node->nd_body)) return Qfalse;
+node = node->nd_else;
+break;
+
+

As shown above, the first time is a recursive call. +Rewriting this to the form of using return ,

+
+return value_expr(node->nd_body) && value_expr(node->nd_else);
+
+

If the left value_expr() is false, the right value_expr() is also executed. +In this case, the left value_expr() is not “just before” return . +Therefore, it is not a tail recursion. +Hence, it can’t be extracted to goto .

+

The whole picture of the value check

+

As for value checks, we won’t read the functions further. +You might think it’s too early, but all of the other functions are, as the same +as value_expr() , step-by-step one-by-one only traversing and checking nodes, +so they are completely not interesting. +However, I’d like to cover the whole picture at least, +so I finish this section by just showing the call graph of the relevant functions (Fig.7).

+

+

(callgraph)
+Fig.7: the call graph of the value check functions

+

+

Local Variables

+

Local Variable Definitions

+

The variable definitions in Ruby are really various. +As for constants and class variables, these are defined on the first assignment. +As for instance variables and global variables, as all names can be considered +that they are already defined, you can refer them without assigning beforehand +(although it produces warnings).

+

The definitions of local variables are again completely different from the above all. +A local variable is defined when its assignment appears on the program. +For example, as follows:

+
+lvar = nil
+p lvar      # being defined
+
+

In this case, as the assignment to lvar is written at the first line, +in this moment lvar is defined. +When it is undefined, it ends up with a runtime exception NameError as follows:

+
+% ruby lvar.rb
+lvar.rb:1: undefined local variable or method `lvar'
+for #<Object:0x40163a9c> (NameError)
+
+

Why does it say "local variable or method"? +As for methods, the parentheses of the arguments can be omitted when calling, +so when there’s not any arguments, it can’t be distinguished from local variables. +To resolve this situation, ruby tries to call it as a method when it finds +an undefined local variable. Then if the corresponding method is not found, it +generates an error such as the above one.

+

By the way, it is defined when “it appears”, this means it is defined even +though it was not assigned. The initial value of a defined variable is nil.

+
+if false
+  lvar = "this assigment will never be executed"
+end
+p lvar   # shows nil
+
+

Moreover, since it is defined “when” it “appears”, the definition has to be +before the reference in a symbol sequence. +For example, in the next case, it is not defined.

+
+p lvar       # not defined !
+lvar = nil   # although appearing here ...
+
+

Be careful about the point of “in the symbol sequence”. +It has completely nothing to do with the order of evaluations. +For example, for the next code, naturally the condition expression is evaluated first, +but in the symbol sequence, at the moment when p appears the assignment +to lvar has not appeared yet. +Therefore, this produces NameError .

+
+p(lvar) if lvar = true
+
+

What we’ve learned by now is that the local variables are extremely influenced +by the appearances. When a symbol sequence that expresses an assignment appears, +it will be defined in the appearance order. Based on this information, we can +infer that ruby seems to define local variables while parsing because the +order of the symbol sequence does not exist after leaving the parser. +And in fact, it is true. In ruby , the parser defines local variables.

+

Block Local Variables

+

The local variables newly defined in an iterator block are called block local +variables or dynamic variables. Block local variables are, in language +specifications, identical to local variables. However, these two differ in +their implementations. +We’ll look at how is the difference from now on.

+

The data structure

+

We’ll start with the local variable table struct local_vars.

+

struct local_vars

+ +
+5174  static struct local_vars {
+5175      ID *tbl;                    /* the table of local variable names */
+5176      int nofree;                 /* whether it is used from outside */
+5177      int cnt;                    /* the size of the tbl array */
+5178      int dlev;                   /* the nesting level of dyna_vars */
+5179      struct RVarmap* dyna_vars;  /* block local variable names */
+5180      struct local_vars *prev;
+5181  } *lvtbl;
+
+(parse.y)
+
+

The member name prev indicates that the struct local_vars is a +opposite-direction linked list. … Based on this, we can expect a stack. +The simultaneously declared global variable lvtbl points to local_vars that +is the top of that stack.

+

And, struct RVarmap is defined in env.h , +and is available to other files and is also used by the evaluator. +This is used to store the block local variables.

+

struct RVarmap

+ +
+  52  struct RVarmap {
+  53      struct RBasic super;
+  54      ID id;                  /* the variable name */
+  55      VALUE val;              /* its value */
+  56      struct RVarmap *next;
+  57  };
+
+(env.h)
+
+

Since there’s struct RBasic at the top, this is a Ruby object. +It means it is managed by the garbage collector. +And since it is joined by the next member, it is probably a linked list.

+

Based on the observation we’ve done and the information that will be explained, +Fig.8 illustrates the image of both structs while executing the parser.

+

+

(localvars)
+Fig.8: The image of local variable tables at runtime

+

+

Local Variable Scope

+

When looking over the list of function names of parse.y , +we can find functions such as local_push() local_pop() local_cnt() are laid out. +In whatever way of thinking, they appear to be relating to a local variable. +Moreover, because the names are push pop, it is clearly a stack. +So first, let’s find out the places where using these functions.

+

local_push() local_pop() used examples

+ +
+1475                  | kDEF fname
+1476                      {
+1477                          $<id>$ = cur_mid;
+1478                          cur_mid = $2;
+1479                          in_def++;
+1480                          local_push(0);
+1481                      }
+1482                    f_arglist
+1483                    bodystmt
+1484                    kEND
+1485                      {
+1486                          /* NOEX_PRIVATE for toplevel */
+1487                          $$ = NEW_DEFN($2, $4, $5,
+                                  class_nest?NOEX_PUBLIC:NOEX_PRIVATE);
+1488                          if (is_attrset_id($2))
+                                  $$->nd_noex = NOEX_PUBLIC;
+1489                          fixpos($$, $4);
+1490                          local_pop();
+1491                          in_def--;
+1492                          cur_mid = $<id>3;
+1493                      }
+
+(parse.y)
+
+

At def , I could find the place where it is used. It can also be found in class +definitions and singleton class definitions, and module definitions. +In other words, it is the place where the scope of local variables is cut. +Moreover, as for how they are used, +it does push where the method definition starts and does pop when the definition ends. +This means, as we expected, it is almost certain that the functions start with +local_ are relating to local variables. And it is also revealed that the part +between push and pop is probably a local variable scope.

+

Moreover, I also searched local_cnt() .

+

NEW_LASGN()

+ +
+ 269  #define NEW_LASGN(v,val) rb_node_newnode(NODE_LASGN,v,val,local_cnt(v))
+
+(node.h)
+
+

This is found in node.h . Even though there are also the places where using in parse.y , +I found it in the other file. Thus, probably I’m in desperation.

+

This NEW_LASGN is “new local assignment”. This should mean the node of an +assignment to a local variable. And also considering the place where using it, +the parameter v is apparently the local variable name. val is probably +(a syntax tree that represents). the right-hand side value

+

Based on the above observations, local_push() is at the beginning of the local variable, +local_cnt() is used to add a local variable if there’s a local variable assignment in the halfway, +local_pop() is used when ending the scope. +This perfect scenario comes out. (Fig.9)

+

+

(localtbl)
+Fig.9: the flow of the local variable management

+

+

Then, let’s look at the content of the function.

+

push and pop

+

local_push()

+ +
+5183  static void
+5184  local_push(top)
+5185      int top;
+5186  {
+5187      struct local_vars *local;
+5188
+5189      local = ALLOC(struct local_vars);
+5190      local->prev = lvtbl;
+5191      local->nofree = 0;
+5192      local->cnt = 0;
+5193      local->tbl = 0;
+5194      local->dlev = 0;
+5195      local->dyna_vars = ruby_dyna_vars;
+5196      lvtbl = local;
+5197      if (!top) {
+5198          /* preserve the variable table of the previous scope into val  */
+5199          rb_dvar_push(0, (VALUE)ruby_dyna_vars);
+5200          ruby_dyna_vars->next = 0;
+5201      }
+5202  }
+
+(parse.y)
+
+

As we expected, it seems that struct local_vars is used as a stack. +Also, we can see lvtbl is pointing to the top of the stack. +The lines relates to rb_dvar_push() will be read later, so it is left untouched for now.

+

Subsequently, we’ll look at local_pop() and local_tbl() at the same time.

+

local_tbl local_pop

+ +
+5218  static ID*
+5219  local_tbl()
+5220  {
+5221      lvtbl->nofree = 1;
+5222      return lvtbl->tbl;
+5223  }
+
+5204  static void
+5205  local_pop()
+5206  {
+5207      struct local_vars *local = lvtbl->prev;
+5208
+5209      if (lvtbl->tbl) {
+5210          if (!lvtbl->nofree) free(lvtbl->tbl);
+5211          else lvtbl->tbl[0] = lvtbl->cnt;
+5212      }
+5213      ruby_dyna_vars = lvtbl->dyna_vars;
+5214      free(lvtbl);
+5215      lvtbl = local;
+5216  }
+
+(parse.y)
+
+

I’d like you to look at local_tbl() . +This is the function to obtain the current local variable table ( lvtbl->tbl ). +By calling this, the nofree of the current table becomes true. +The meaning of nofree seems naturally "Don’t free() ". +In other words, this is like reference counting, "this table will be used, so +please don’t free() ". Conversely speaking, +when local_tbl() was not called with a table even once, +that table will be freed at the moment when being popped and be discarded. +For example, this situation probably happens when a method without any local variables.

+

However, the “necessary table” here means lvtbl->tbl . +As you can see, lvtbl itself will be freed at the same moment when being popped. +It means only the generated lvtbl->tbl is used in the evaluator. +Then, the structure of lvtbl->tbl is becoming important. +Let’s look at the function local_cnt() (which seems) to add variables +which is probably helpful to understand how the structure is.

+

And before that, I’d like you to remember that lvtbl->cnt is stored +at the index 0 of the lvtbl->tbl .

+

Adding variables

+

The function (which seems) to add a local variable is local_cnt() .

+

local_cnt()

+ +
+5246  static int
+5247  local_cnt(id)
+5248      ID id;
+5249  {
+5250      int cnt, max;
+5251
+5252      if (id == 0) return lvtbl->cnt;
+5253
+5254      for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
+5255          if (lvtbl->tbl[cnt] == id) return cnt-1;
+5256      }
+5257      return local_append(id);
+5258  }
+
+(parse.y)
+
+

This scans lvtbl->tbl and searches what is equals to id . +If the searched one is found, it straightforwardly returns cnt-1 . +If nothing is found, it does local_append() . +local_append() must be, as it is called append , the procedure to append. +In other words, local_cnt() checks if the variable was already registered, +if it was not, adds it by using local_append() and returns it.

+

What is the meaning of the return value of this function? lvtbl->tbl seems an +array of the variables, so there’re one-to-one correspondences between the +variable names and “their index – 1 ( cnt-1 )”. (Fig.10)

+

+

(lvtbltbl)
+Fig.10: The correspondences between the variable names and the return values

+

+

Moreover, this return value is calculated so that the start point becomes 0, +the local variable space is probably an array. +And, this returns the index to access that array. +If it is not, like the instance variables or constants, +(the ID of) the variable name could have been used as a key in the first place.

+

You might want to know why it is avoiding index 0 (the loop start +from cnt=1 ) for some reasons, it is probably to store a value at local_pop() .

+

Based on the knowledge we’ve learned, we can understand the role of local_append() +without actually looking at the content. +It registers a local variable and returns +“(the index of the variable in lvtbl->tbl ) – 1”. +It is shown below, let’s make sure.

+

local_append()

+ +
+5225  static int
+5226  local_append(id)
+5227      ID id;
+5228  {
+5229      if (lvtbl->tbl == 0) {
+5230          lvtbl->tbl = ALLOC_N(ID, 4);
+5231          lvtbl->tbl[0] = 0;
+5232          lvtbl->tbl[1] = '_';
+5233          lvtbl->tbl[2] = '~';
+5234          lvtbl->cnt = 2;
+5235          if (id == '_') return 0;
+5236          if (id == '~') return 1;
+5237      }
+5238      else {
+5239          REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
+5240      }
+5241
+5242      lvtbl->tbl[lvtbl->cnt+1] = id;
+5243      return lvtbl->cnt++;
+5244  }
+
+(parse.y)
+
+

It seems definitely true. lvtbl->tbl is an array of the local variable names, +and its index – 1 is the return value (local variable ID).

+

Note that it increases lvtbl->cnt . +Since the code to increase lvtbl->cnt only exists here, +from only this code its meaning can be decided. +Then, what is the meaning? It is, +since “lvtbl->cnt increases by 1 when a new variable is added”, +“lvtbl->cnt holds the number of local variables in this scope”.

+

Finally, I’ll explain about tbl[1] and tbl[2] . These '_' and '~' are, +as you can guess if you are familiar with Ruby, +the special variables named $_ and $~ . +Though their appearances are identical to global variables, +they are actually local variables. +Even If you didn’t explicitly use it, when the methods such as Kernel#gets are called, +these variables are implicitly assigned, +thus it’s necessary that the spaces are always allocated.

+

Summary of local variables

+

Since the description of local variables were complex in various ways, +let’s summarize it.

+

First, It seems the local variables are different from the other variables +because they are not managed with st_table . +Then, where are they stored in? It seems the answer is an array. +Moreover, it is stored in a different array for each scope.

+

The array is lvtbl->tbl , and the index 0 holds the lvtbl->cnt which is set +at local_pop() . In other words, it holds the number of the local variables. +The index 1 or more hold the local variable names defined in the scope. +Fig.11 shows the final appearance we expect.

+

+

(tbl)
+Fig.11: correspondences between local variable names and the return values

+

+

Block Local Variables

+

The rest is dyna_vars which is a member of struct local_vars. +In other words, this is about the block local variables. +I thought that there must be the functions to do something with this, +looked over the list of the function names, +and found them as expected. +There are the suspicious functions named dyna_push() dyna_pop() dyna_in_block(). +Moreover, here is the place where these are used.

+

▼ an example using dyna_push dyna_pop

+ +
+1651  brace_block     : '{'
+1652                      {
+1653                          $<vars>$ = dyna_push();
+1654                      }
+1655                    opt_block_var
+1656                    compstmt '}'
+1657                      {
+1658                          $$ = NEW_ITER($3, 0, $4);
+1659                          fixpos($$, $4);
+1660                          dyna_pop($<vars>2);
+1661                      }
+
+(parse.y)
+
+

push at the beginning of an iterator block, pop at the end. +This must be the process of block local variables.

+

Now, we are going to look at the functions.

+

dyna_push()

+ +
+5331  static struct RVarmap*
+5332  dyna_push()
+5333  {
+5334      struct RVarmap* vars = ruby_dyna_vars;
+5335
+5336      rb_dvar_push(0, 0);
+5337      lvtbl->dlev++;
+5338      return vars;
+5339  }
+
+(parse.y)
+
+

Increasing lvtbl->dlev seems the mark indicates the existence of the block +local variable scope. +Meanwhile, rb_dvar_push() is …

+

rb_dvar_push()

+ +
+ 691  void
+ 692  rb_dvar_push(id, value)
+ 693      ID id;
+ 694      VALUE value;
+ 695  {
+ 696      ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
+ 697  }
+
+(eval.c)
+
+

It creates a struct RVarmap that has the variable name id and the value +val as its members, adds it to the top of the global variable ruby_dyna_vars . +This is again and again the form of cons. +In dyna_push() , ruby_dyan_vars is not set aside, +it seems it adds directly to the ruby_dyna_vars of the previous scope.

+

Moreover, the value of the id member of the RVarmap to be added here is 0. +Although it was not seriously discussed in this book, +the ID of ruby will never be 0 while it is normally created by rb_intern() . +Thus, we can infer that this RVarmap , as it is like NUL or NULL , +probably has a role as sentinel. +If we think based on this assumption, we can describe the reason why the holder +of a variable ( RVarmap ) is added even though not any variables are added.

+

Next, dyna_pop() .

+

dyna_pop()

+ +
+5341  static void
+5342  dyna_pop(vars)
+5343      struct RVarmap* vars;
+5344  {
+5345      lvtbl->dlev--;
+5346      ruby_dyna_vars = vars;
+5347  }
+
+(parse.y)
+
+

By reducing lvtbl->dlev , it writes down the fact that the block local +variable scope ended. +It seems that something is done by using the argument, +let’s see this later at once.

+

The place to add a block local variable has not appeared yet. +Something like local_cnt() of local variables is missing. +So, I did plenty of grep with dvar and dyna , and this code was found.

+

assignable() (partial)

+ +
+4599  static NODE*
+4600  assignable(id, val)
+4601      ID id;
+4602      NODE *val;
+4603  {
+                            :
+4634              rb_dvar_push(id, Qnil);
+4635              return NEW_DASGN_CURR(id, val);
+
+(parse.y)
+
+

assignable() is the function to create a node relates to assignments, +this citation is the fragment of that function only contains the part to deal +with block local variables. +It seems that it adds a new variable (to ruby_dyna_vars ) +by using rb_dvar_push() that we’ve just seen.

+

ruby_dyna_vars in the parser

+

Now, taking the above all into considerations, let’s imagine the appearance of +ruby_dyna_vars at the moment when a local variable scope is finished to be +parsed.

+

First, as I said previously, +the RVarmap of id=0 which is added at the beginning of a block scope is a +sentinel which represents a break between two block scopes. +We’ll call this "the header of ruby_dyna_vars ".

+

Next, among the previously shown actions of the rule of the iterator block, +I’d like you to focus on this part:

+
+$<vars>$ = dyna_push();    /* what assigned into $<vars>$ is ... */
+        :
+        :
+dyna_pop($<vars>2);        /* …… appears at $<vars>2 */
+
+

dyna_push() returns the ruby_dyna_vars at the moment. +dyna_pop() put the argument into ruby_dyna_vars . +This means ruby_dyna_vars would be saved and restored for each the block local +variable scope. +Therefore, when parsing the following program,

+
+iter {
+    a = nil
+    iter {
+        b = nil
+        iter {
+            c = nil
+            # nesting level 3
+        }
+        bb = nil
+        # nesting level 2
+        iter {
+            e = nil
+        }
+    }
+    # nesting level 1
+}
+
+

Fig.12 shows the ruby_dyna_vars in this situation.

+

+

(dynavars)
+Fig.12: ruby_dyna_vars when all scopes are finished to be parsed

+

+

This structure is fairly smart. +That’s because the variables of the higher levels can naturally be accessed by +traversing over all of the list even if the nesting level is deep. +This way has the simpler searching process than creating a different table for +each level.

+

Plus, in the figure, it looks like bb is hung at a strange place, +but this is correct. +When a variable is found at the nest level which is decreased after increased once, +it is attached to the subsequent of the list of the original level. +Moreover, in this way, the specification of local variable that +“only the variables which already exist in the symbol sequence are defined” +is expressed in a natural form.

+

And finally, at each cut of local variable scopes (this is not of block local +variable scopes), this link is entirely saved or restored to lvtbl->dyna_vars . +I’d like you to go back a little and check local_push() and local_pop() .

+

By the way, although creating the ruby_dyna_vars list was a huge task, +it is by itself not used at the evaluator. This list is used only to check the +existence of the variables and will be garbage collected at the same moment +when parsing is finished. And after entering the evaluator, another chain is +created again. +There’s a quite deep reason for this, … we’ll see around this once again in +Part 3.

+ + + +
+ + diff --git a/htmls/thread.html b/htmls/thread.html new file mode 100644 index 0000000..c361e1f --- /dev/null +++ b/htmls/thread.html @@ -0,0 +1,1153 @@ + + + + + Chapter 19: Threads | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Chapter 19: Threads

+

Outline

+

Ruby Interface

+

Come to think of it, I feel I have not introduced an actual code to use Ruby threads. +This is not so special, but here I’ll introduce it just in case.

+
+Thread.fork {
+    while true
+      puts 'forked thread'
+    end
+}
+while true
+  puts 'main thread'
+end
+
+

When executing this program, +a lot of "forked thread" and "main thread" are printed in the properly mixed +state.

+

Of course, other than just creating multiple threads, there are also various +ways to control. There’s not the synchronize as a reserved word like Java, +common primitives such as Mutex or Queue or Monitor are of course available, +and the below APIs can be used to control a thread itself.

+

▼ Thread API

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Thread.pass transfer the execution to any other thread
Thread.kill(th) terminates the th thread
Thread.exit terminates the thread itself
Thread.stop temporarily stop the thread itself
Thread#join waiting for the thread to finish
Thread#wakeup to wake up the temporarily stopped thread
+

ruby Thread

+

Threads are supposed to “run all together”, +but actually they are running for a little time in turns. +To be precise, by making some efforts on a machine of multi CPU, +it’s possible that, for instance, two of them are running at the same time. +But still, if there are more threads than the number of CPU, +they have to run in turns.

+

In other words, in order to create threads, someone has to switch the threads +in somewhere. There are roughly two ways to do it: +kernel-level threads and user-level threads. +They are respectively, as the names suggest, to create a thread in kernel or at +user-level. If it is kernel-level, by making use of multi-CPU, +multiple threads can run at the same time.

+

Then, how about the thread of ruby? It is user-level thread. +And (Therefore), the number of threads that are runnable at the same time is +limited to one.

+

Is it preemptive?

+

I’ll describe about the traits of ruby threads in more detail. +As an alternative point of view of threads, +there’s the point that is “is it preemptive?”.

+

When we say “thread (system) is preemptive”, +the threads will automatically be switched without being explicitly switched by +its user. +Looking this from the opposite direction, the user can’t control the timing of +switching threads.

+

On the other hand, in a non-preemptive thread system, +until the user will explicitly say +“I can pass the control right to the next thread”, +threads will never be switched. +Looking this from the opposite direction, +when and where there’s the possibility of switching threads is obvious.

+

This distinction is also for processes, +in that case, preemptive is considered as “superior”. +For example, if a program had a bug and it entered an infinite loop, +the processes would never be able to switch. +This means a user program can halt the whole system and is not good. +And, switching processes was non-preemptive on Windows 3.1 +because its base was MS-DOS, +but Windows 95 is preemptive. Thus, the system is more robust. +Hence, it is said that Windows 95 is “superior” to 3.1.

+

Then, how about the ruby thread? It is preemptive at Ruby-level, +and non-preemptive at C level. In other words, when you are writing C code, +you can determine almost certainly the timings of switching threads.

+

Why is this designed in this way? Threads are indeed convenient, +but its user also need to prepare certain minds. +It means that it is necessary the code is compatible to the threads. +(It must be multi-thread safe). In other words, in order to make it preemptive +also in C level, the all C libraries have to be thread safe.

+

But in reality, there are also a lot of C libraries that are still not thread safe. +A lot of efforts were made to ease to write extension libraries, +but it would be brown if the number of usable libraries is decreased by +requiring thread safety. +Therefore, non-preemptive at C level is a reasonable choice for ruby.

+

Management System

+

We’ve understand ruby thread is non-preemptive at C level. +It means after it runs for a while, it voluntarily let go of the controlling +right. Then, I’d like you to suppose that now a currently being executed thread +is about to quit the execution. Who will next receive the control right? +But before that, it’s impossible to guess it without knowing how threads are +expressed inside ruby in the first place. +Let’s look at the variables and the data types to manage threads.

+

▼ the structure to manage threads

+ +
+ 864  typedef struct thread * rb_thread_t;
+ 865  static rb_thread_t curr_thread = 0;
+ 866  static rb_thread_t main_thread;
+
+7301  struct thread {
+7302      struct thread *next, *prev;
+
+(eval.c)
+
+

Since struct thread is very huge for some reason, +this time I narrowed it down to the only important part. +It is why there are only the two. These next and prev are member names, +and their types are rb_thread_t, +thus we can expect rb_thread_t is connected by a dual-directional link list. +And actually it is not an ordinary dual-directional list, +the both ends are connected. It means, it is circular. +This is a big point. Adding the static main_thread and curr_thread variables +to it, the whole data structure would look like Figure 1.

+

+

(thread)
+Figure 1: the data structures to manage threads

+

+

main_thread (main thread) means the thread existed at the time when a program +started, meaning the “first” thread. curr_thread is obviously current thread, +meaning the thread currently running. +The value of main_thread will never change while the process is running, +but the value of curr_thread will change frequently.

+

In this way, because the list is being a circle, the procedure to chose “the +next thread” becomes easy. It can be done by merely following the next link. +Only by this, we can run all threads equally to some extent.

+

What does switching threads mean?

+

By the way, what is a thread in the first place? +Or, what makes us to say threads are switched?

+

These are very difficult questions. Similar to what a program is or what an +object is, when asked about what are usually understood by feelings, +it’s hard to answer clearly. +Especially, “what is the difference between threads and processes?” +is a good question.

+

Still, in a realistic range, we can describe it to some extent. +What necessary for threads is the context of executing. +As for the context of ruby, as we’ve seen by now, +it consists of ruby_frame and ruby_scope and ruby_class and so on. +And ruby allocates the substance of ruby_frame on the machine stack, +and there are also the stack space used by extension libraries, +therefore the machine stack is also necessary as a context of a Ruby program. +And finally, the CPU registers are indispensable. +These various contexts are the elements to enable threads, +and switching them means switching threads. +Or, it is called “context-switch”.

+

The way of context-switching

+

The rest talk is how to switch contexts. +ruby_scope and ruby_class are easy to replace: +allocate spaces for them somewhere such as the heap and +set them aside one by one. +For the CPU registers, we can make it +because we can save and write back them by using setjmp(). +The spaces for both purposes are respectively prepared in rb_thread_t.

+

struct thread (partial)

+ +
+7301  struct thread {
+7302      struct thread *next, *prev;
+7303      jmp_buf context;
+
+7315      struct FRAME *frame;        /* ruby_frame */
+7316      struct SCOPE *scope;        /* ruby_scope */
+7317      struct RVarmap *dyna_vars;  /* ruby_dyna_vars */
+7318      struct BLOCK *block;        /* ruby_block */
+7319      struct iter *iter;          /* ruby_iter */
+7320      struct tag *tag;            /* prot_tag */
+7321      VALUE klass;                /* ruby_class */
+7322      VALUE wrapper;              /* ruby_wrapper */
+7323      NODE *cref;                 /* ruby_cref */
+7324
+7325      int flags;  /* scope_vmode / rb_trap_immediate / raised */
+7326
+7327      NODE *node;                 /* rb_current_node */
+7328
+7329      int tracing;                /* tracing */
+7330      VALUE errinfo;              /* $! */
+7331      VALUE last_status;          /* $? */
+7332      VALUE last_line;            /* $_ */
+7333      VALUE last_match;           /* $~ */
+7334
+7335      int safe;                   /* ruby_safe_level */
+
+(eval.c)
+
+

As shown above, there are the members that seem to correspond to ruby_frame +and ruby_scope. There’s also a jmp_buf to save the registers.

+

Then, the problem is the machine stack. +How can we substitute them?

+

The way which is the most straightforward for the mechanism is directly writing +over the pointer to the position (end) of the stack. +Usually, it is in the CPU registers. +Sometimes it is a specific register, +and it is also possible that a general-purpose register is allocated for it. +Anyway, it is in somewhere. +For convenience, we’ll call it the stack pointer from now on. +It is obvious that the different space can be used as the stack by modifying it. +But it is also obvious in this way we have to deal with it for each CPU +and for each OS, thus it is really hard to serve the potability.

+

Therefore, ruby uses a very violent way to implement the substitution of the +machine stack. That is, if we can’t modify the stack pointer, let’s modify the +place the stack pointer points to. We know the stack can be directly modified +as we’ve seen in the description about the garbage collection, +the rest is slightly changing what to do. +The place to store the stack properly exists in struct thread.

+

struct thread (partial)

+ +
+7310      int   stk_len;      /* the stack length */
+7311      int   stk_max;      /* the size of memory allocated for stk_ptr */
+7312      VALUE*stk_ptr;      /* the copy of the stack */
+7313      VALUE*stk_pos;      /* the position of the stack */
+
+(eval.c)
+
+

How the explanation goes

+

So far, I’ve talked about various things, but the important points can be +summarized to the three:

+
    +
  • When
  • +
  • To which thread
  • +
  • How
  • +
+

to switch context. These are also the points of this chapter. +Below, I’ll describe them using a section for each of the three points +respectively.

+

Trigger

+

To begin with, it’s the first point, when to switch threads. +In other words, what is the cause of switching threads.

+

Waiting I/O

+

For example, when trying to read in something by calling IO#gets or IO#read, +since we can expect it will take a lot of time to read, +it’s better to run the other threads in the meantime. +In other words, a forcible switch becomes necessary here. +Below is the interface of getc.

+

rb_getc()

+ +
+1185  int
+1186  rb_getc(f)
+1187      FILE *f;
+1188  {
+1189      int c;
+1190
+1191      if (!READ_DATA_PENDING(f)) {
+1192          rb_thread_wait_fd(fileno(f));
+1193      }
+1194      TRAP_BEG;
+1195      c = getc(f);
+1196      TRAP_END;
+1197
+1198      return c;
+1199  }
+
+(io.c)
+
+

READ_DATA_PENDING(f) is a macro to check if the content of the buffer of the +file is still there. If there’s the content of the buffer, +it means it can move without any waiting time, +thus it would read it immediately. +If it was empty, it means it would take some time, +thus it would rb_thread_wait_fd(). +This is an indirect cause of switching threads.

+

If rb_thread_wait_fd() is “indirect”, there also should be a “direct” cause. +What is it? Let’s see the inside of rb_thread_wait_fd().

+

rb_thread_wait_fd()

+ +
+8047  void
+8048  rb_thread_wait_fd(fd)
+8049      int fd;
+8050  {
+8051      if (rb_thread_critical) return;
+8052      if (curr_thread == curr_thread->next) return;
+8053      if (curr_thread->status == THREAD_TO_KILL) return;
+8054
+8055      curr_thread->status = THREAD_STOPPED;
+8056      curr_thread->fd = fd;
+8057      curr_thread->wait_for = WAIT_FD;
+8058      rb_thread_schedule();
+8059  }
+
+(eval.c)
+
+

There’s rb_thread_schedule() at the last line. +This function is the “direct cause”. +It is the heart of the implementation of the ruby threads, +and does select and switch to the next thread.

+

What makes us understand this function has such role is, +in my case, I knew the word “scheduling” of threads beforehand. +Even if you didn’t know, because you remembers now, +you’ll be able to notice it at the next time.

+

And, in this case, it does not merely pass the control to the other thread, +but it also stops itself. +Moreover, it has an explicit deadline that is “by the time when it becomes readable”. +Therefore, this request should be told to rb_thread_schedule(). +This is the part to assign various things to the members of curr_thread. +The reason to stop is stored in wait_for, +the information to be used when waking up is stored in fd, +respectively.

+

Waiting the other thread

+

After understanding threads are switched at the timing of rb_thread_schedule(), +this time, conversely, from the place where rb_thread_schedule() appears, +we can find the places where threads are switched. +Then by scanning, I found it in the function named rb_thread_join().

+

rb_thread_join() (partial)

+ +
+8227  static int
+8228  rb_thread_join(th, limit)
+8229      rb_thread_t th;
+8230      double limit;
+8231  {
+
+8243          curr_thread->status = THREAD_STOPPED;
+8244          curr_thread->join = th;
+8245          curr_thread->wait_for = WAIT_JOIN;
+8246          curr_thread->delay = timeofday() + limit;
+8247          if (limit < DELAY_INFTY) curr_thread->wait_for |= WAIT_TIME;
+8248          rb_thread_schedule();
+
+(eval.c)
+
+

This function is the substance of Thread#join, +and Thread#join is a method to wait until the receiver thread will end. +Indeed, since there’s time to wait, running the other threads is economy. +Because of this, the second reason to switch is found.

+

Waiting For Time

+

Moreover, also in the function named rb_thread_wait_for(), +rb_thread_schedule() was found. +This is the substance of (Ruby’s) sleep and such.

+

rb_thread_wait_for (simplified)

+ +
+8080  void
+8081  rb_thread_wait_for(time)
+8082      struct timeval time;
+8083  {
+8084      double date;
+
+8124      date = timeofday() +
+                 (double)time.tv_sec + (double)time.tv_usec*1e-6;
+8125      curr_thread->status = THREAD_STOPPED;
+8126      curr_thread->delay = date;
+8127      curr_thread->wait_for = WAIT_TIME;
+8128      rb_thread_schedule();
+8129  }
+
+(eval.c)
+
+

timeofday() returns the current time. +Because the value of time is added to it, +date indicates the time when the waiting time is over. +In other words, this is the order “I’d like to stop until it will be the +specific time”.

+

Switch by expirations

+

In the above all cases, +because some manipulations are done from Ruby level, +consequently it causes to switch threads. +In other words, by now, the Ruby-level is also non-preemptive. +Only by this, if a program was to single-mindedly keep calculating, +a particular thread would continue to run eternally. Therefore, +we need to let it voluntary dispose the control right after running +for a while. +Then, how long a thread can run by the time when it will have to stop, +is what I’ll talk about next.

+

setitimer

+

Since it is the same every now and then, +I feel like lacking the skill to entertain, +but I searched the places where calling rb_thread_schedule() further. +And this time it was found in the strange place. +It is here.

+

catch_timer()

+ +
+8574  static void
+8575  catch_timer(sig)
+8576      int sig;
+8577  {
+8578  #if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
+8579      signal(sig, catch_timer);
+8580  #endif
+8581      if (!rb_thread_critical) {
+8582          if (rb_trap_immediate) {
+8583              rb_thread_schedule();
+8584          }
+8585          else rb_thread_pending = 1;
+8586      }
+8587  }
+
+(eval.c)
+
+

This seems something relating to signals. +What is this? +I followed the place where this catch_timer() function is used, +then it was used around here:

+

rb_thread_start_0() (partial)

+ +
+8620  static VALUE
+8621  rb_thread_start_0(fn, arg, th_arg)
+8622      VALUE (*fn)();
+8623      void *arg;
+8624      rb_thread_t th_arg;
+8625  {
+
+8632  #if defined(HAVE_SETITIMER)
+8633      if (!thread_init) {
+8634  #ifdef POSIX_SIGNAL
+8635          posix_signal(SIGVTALRM, catch_timer);
+8636  #else
+8637          signal(SIGVTALRM, catch_timer);
+8638  #endif
+8639
+8640          thread_init = 1;
+8641          rb_thread_start_timer();
+8642      }
+8643  #endif
+
+(eval.c)
+
+

This means, catch_timer is a signal handler of SIGVTALRM.

+

Here, “what kind of signal SIGVTALRM is” becomes the question. +This is actually the signal sent when using the system call named setitimer. +That’s why there’s a check of HAVE_SETITIMER just before it. +setitimer is an abbreviation of “SET Interval TIMER” +and a system call to tell OS to send signals with a certain interval.

+

Then, where is the place calling setitimer? It is the rb_thread_start_timer(), +which is coincidently located at the last of this list.

+

To sum up all, it becomes the following scenario. +setitimer is used to send signals with a certain interval. +The signals are caught by catch_timer(). +There, rb_thread_schedule() is called and threads are switched. Perfect.

+

However, signals could occur anytime, +if it was based on only what described until here, +it means it would also be preemptive at C level. +Then, I’d like you to see the code of catch_timer() again.

+
+if (rb_trap_immediate) {
+    rb_thread_schedule();
+}
+else rb_thread_pending = 1;
+
+

There’s a required condition that is doing rb_thread_schedule() only when +it is rb_trap_immediate. This is the point. rb_trap_immediate is, as the +name suggests, expressing “whether or not immediately process signals”, +and it is usually false. +It becomes true only while the limited time such as while doing I/O on a single +thread. In the source code, it is the part between TRAP_BEG and TRAP_END.

+

On the other hand, since rb_thread_pending is set when it is false, +let’s follow this. +This variable is used in the following place.

+

CHECK_INTSHAVE_SETITIMER

+ +
+  73  #if defined(HAVE_SETITIMER) && !defined(__BOW__)
+  74  EXTERN int rb_thread_pending;
+  75  # define CHECK_INTS do {\
+  76      if (!rb_prohibit_interrupt) {\
+  77          if (rb_trap_pending) rb_trap_exec();\
+  78          if (rb_thread_pending && !rb_thread_critical)\
+  79              rb_thread_schedule();\
+  80      }\
+  81  } while (0)
+
+(rubysig.h)
+
+

This way, inside of CHECK_INTS, rb_thread_pending is checked and +rb_thread_schedule() is done. +It means, when receiving SIGVTALRM, rb_thread_pending becomes true, +then the thread will be switched at the next time going through CHECK_INTS.

+

This CHECK_INTS has appeared at various places by now. +For example, rb_eval() and rb_call0() and rb_yeild_0. +CHECK_INTS would be meaningless if it was not located where the place +frequently being passed. +Therefore, it is natural to exist in the important functions.

+

tick

+

We understood the case when there’s setitimer. +But what if setitimer does not exist? +Actually, the answer is in CHECK_INTS, which we’ve just seen. +It is the definition of the #else side.

+

CHECK_INTSnot HAVE_SETITIMER

+ +
+  84  EXTERN int rb_thread_tick;
+  85  #define THREAD_TICK 500
+  86  #define CHECK_INTS do {\
+  87      if (!rb_prohibit_interrupt) {\
+  88          if (rb_trap_pending) rb_trap_exec();\
+  89          if (!rb_thread_critical) {\
+  90              if (rb_thread_tick-- <= 0) {\
+  91                  rb_thread_tick = THREAD_TICK;\
+  92                  rb_thread_schedule();\
+  93              }\
+  94          }\
+  95      }\
+  96  } while (0)
+
+(rubysig.h)
+
+

Every time going through CHECK_INTS, decrement rb_thread_tick. +When it becomes 0, do rb_thread_schedule(). +In other words, the mechanism is that the thread will be switched +after THREAD_TICK (=500) times going through CHECK_INTS.

+

Scheduling

+

The second point is to which thread to switch. +What solely responsible for this decision is rb_thread_schedule().

+

rb_thread_schedule()

+

The important functions of ruby are always huge. +This rb_thread_schedule() has more than 220 lines. +Let’s exhaustively divide it into portions.

+

rb_thread_schedule() (outline)

+ +
+7819  void
+7820  rb_thread_schedule()
+7821  {
+7822      rb_thread_t next;           /* OK */
+7823      rb_thread_t th;
+7824      rb_thread_t curr;
+7825      int found = 0;
+7826
+7827      fd_set readfds;
+7828      fd_set writefds;
+7829      fd_set exceptfds;
+7830      struct timeval delay_tv, *delay_ptr;
+7831      double delay, now;  /* OK */
+7832      int n, max;
+7833      int need_select = 0;
+7834      int select_timeout = 0;
+7835
+7836      rb_thread_pending = 0;
+7837      if (curr_thread == curr_thread->next
+7838          && curr_thread->status == THREAD_RUNNABLE)
+7839          return;
+7840
+7841      next = 0;
+7842      curr = curr_thread;         /* starting thread */
+7843
+7844      while (curr->status == THREAD_KILLED) {
+7845          curr = curr->prev;
+7846      }
+
+          /* ……prepare the variables used at select …… */
+          /* ……select if necessary        …… */
+          /* ……decide the thread to invoke next …… */
+          /* ……context-switch     …… */
+8045  }
+
+(eval.c)
+
+

(A) When there’s only one thread, this does not do anything and returns immediately. +Therefore, the talks after this can be thought based on the assumption that +there are always multiple threads.

+

(B) Subsequently, the initialization of the variables. +We can consider the part until and including the while is the initialization. +Since cur is following prev, +the last alive thread (status != THREAD_KILLED) will be set. +It is not “the first” one +because there are a lot of loops that “start with the next of curr then +deal with curr and end”.

+

After that, we can see the sentences about select. +Since the thread switch of ruby is considerably depending on select, +let’s first study about select in advance here.

+

select

+

select is a system call to wait until the preparation for reading or writing a +certain file will be completed. +Its prototype is this:

+
+int select(int max,
+           fd_set *readset, fd_set *writeset, fd_set *exceptset,
+           struct timeval *timeout);
+
+

In the variable of type fd_set, a set of fd that we want to check is stored. +The first argument max is “(the maximum value of fd in fd_set) + 1”. +The timeout is the maximum waiting time of select. +If timeout is NULL, it would wait eternally. +If timeout is 0, without waiting for even just a second, +it would only check and return immediately. +As for the return value, I’ll talk about it at the moment when using it.

+

I’ll talk about fd_set in detail. +fd_set can be manipulated by using the below macros:

+

fd_set maipulation

+ +
+fd_set set;
+
+FD_ZERO(&set)       /* initialize */
+FD_SET(fd, &set)    /* add a file descriptor fd to the set */
+FD_ISSET(fd, &set)  /* true if fd is in the set */
+
+

fd_set is typically a bit array, +and when we want to check n-th file descriptor, the n-th bit is set (Figure 2).

+
+

(fdset)
+Figure 2: fd_set

+
    +
  • インデックス index +
+ +

I’ll show a simple usage example of select.

+

▼ a usage exmple of select

+ +
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+    char *buf[1024];
+    fd_set readset;
+
+    FD_ZERO(&readset);              /* initialize readset */
+    FD_SET(STDIN_FILENO, &readset); /* put stdin into the set */
+    select(STDIN_FILENO + 1, &readset, NULL, NULL,  NULL);
+    read(STDIN_FILENO, buf, 1024);  /* success without delay */
+    exit(0);
+}
+
+

This code assume the system call is always success, +thus there are not any error checks at all. +I’d like you to see only the flow that is FD_ZEROFD_SETselect. +Since here the fifth argument timeout of select is NULL, +this select call waits eternally for reading stdin. +And since this select is completed, +the next read does not have to wait to read at all. +By putting print in the middle, +you will get further understandings about its behavior. +And a little more detailed example code is put in the attached CD-ROM +{see also doc/select.html}.

+

Preparations for select

+

Now, we’ll go back to the code of rb_thread_schedule(). +Since this code branches based on the reason why threads are waiting. +I’ll show the content in shortened form.

+

rb_thread_schedule() − preparations for select

+ +
+7848    again:
+          /* initialize the variables relating to select */
+7849      max = -1;
+7850      FD_ZERO(&readfds);
+7851      FD_ZERO(&writefds);
+7852      FD_ZERO(&exceptfds);
+7853      delay = DELAY_INFTY;
+7854      now = -1.0;
+7855
+7856      FOREACH_THREAD_FROM(curr, th) {
+7857          if (!found && th->status <= THREAD_RUNNABLE) {
+7858              found = 1;
+7859          }
+7860          if (th->status != THREAD_STOPPED) continue;
+7861          if (th->wait_for & WAIT_JOIN) {
+                  /* ……join wait…… */
+7866          }
+7867          if (th->wait_for & WAIT_FD) {
+                  /* ……I/O wait…… */
+7871          }
+7872          if (th->wait_for & WAIT_SELECT) {
+                  /* ……select wait…… */
+7882          }
+7883          if (th->wait_for & WAIT_TIME) {
+                  /* ……time wait…… */
+7899          }
+7900      }
+7901      END_FOREACH_FROM(curr, th);
+
+(eval.c)
+
+

Whether it is supposed to be or not, +what stand out are the macros named FOREACH-some. +These two are defined as follows:

+

FOREACH_THREAD_FROM

+ +
+7360  #define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
+7361  #define END_FOREACH_FROM(f,x) } while (x != f)
+
+(eval.c)
+
+

Let’s extract them for better understandability.

+
+th = curr;
+do {
+    th = th->next;
+    {
+        .....
+    }
+} while (th != curr);
+
+

This means: follow the circular list of threads from the next of curr +and process curr at last and end, +and meanwhile the th variable is used. +This makes me think about the Ruby’s iterators +… is this my too much imagination?

+

Here, we’ll go back to the subsequence of the code, it uses +this a bit strange loop and checks if there’s any thread which needs select. +As we’ve seen previously, since select can wait for +reading/writing/exception/time all at once, +you can probably understand I/O waits and time waits can be centralized by single select. +And though I didn’t describe about it in the previous section, +select waits are also possible. +There’s also a method named IO.select in the Ruby’s library, +and you can use rb_thread_select() at C level. +Therefore, we need to execute that select at the same time. +By merging fd_set, multiple select can be done at once.

+

The rest is only join wait. +As for its code, let’s see it just in case.

+

rb_thread_schedule()select preparation − join wait

+ +
+7861          if (th->wait_for & WAIT_JOIN) {
+7862              if (rb_thread_dead(th->join)) {
+7863                  th->status = THREAD_RUNNABLE;
+7864                  found = 1;
+7865              }
+7866          }
+
+(eval.c)
+
+

The meaning of rb_thread_dead() is obvious because of its name. +It determines whether or not the thread of the argument has finished.

+

Calling select

+

By now, we’ve figured out whether select is necessary or not, +and if it is necessary, its fd_set has already prepared. +Even if there’s a immediately invocable thread (THREAD_RUNNABLE), +we need to call select beforehand. +It’s possible that there’s actually a thread that it has already been while +since its I/O wait finished and has the higher priority. +But in that case, tell select to immediately return +and let it only check if I/O was completed.

+

rb_thread_schedule()select

+ +
+7904      if (need_select) {
+7905          /* convert delay into timeval */
+7906          /* if theres immediately invocable threads, do only I/O checks */
+7907          if (found) {
+7908              delay_tv.tv_sec = 0;
+7909              delay_tv.tv_usec = 0;
+7910              delay_ptr = &delay_tv;
+7911          }
+7912          else if (delay == DELAY_INFTY) {
+7913              delay_ptr = 0;
+7914          }
+7915          else {
+7916              delay_tv.tv_sec = delay;
+7917              delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec)*1e6;
+7918              delay_ptr = &delay_tv;
+7919          }
+7920
+7921          n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr);
+7922          if (n < 0) {
+                  /* …… being cut in by signal or something …… */
+7944          }
+7945          if (select_timeout && n == 0) {
+                  /* …… timeout …… */
+7960          }
+7961          if (n > 0) {
+                  /* …… properly finished …… */
+7989          }
+7990          /* In a somewhere thread, its I/O wait has finished.
+7991             roll the loop again to detect the thread */
+7992          if (!found && delay != DELAY_INFTY)
+7993              goto again;
+7994      }
+
+(eval.c)
+
+

The first half of the block is as written in the comment. +Since delay is the usec until the any thread will be next invocable, +it is converted into timeval form.

+

In the last half, it actually calls select and branches based on its result. +Since this code is long, I divided it again. +When being cut in by a signal, it either goes back to the beginning +then processes again or becomes an error. +What are meaningful are the rest two.

+

Timeout

+

When select is timeout, a thread of time wait or select wait may become +invocable. Check about it and search runnable threads. +If it is found, set THREAD_RUNNABLE to it.

+

Completing normally

+

If select is normally completed, +it means either the preparation for I/O is completed or select wait ends. +Search the threads that are no longer waiting by checking fd_set. +If it is found, set THREAD_RUNNABLE to it.

+

Decide the next thread

+

Taking all the information into considerations, +eventually decide the next thread to invoke. +Since all what was invocable and all what had finished waiting and so on became +RUNNABLE, you can arbitrary pick up one of them.

+

rb_thread_schedule() − decide the next thread

+ +
+7996      FOREACH_THREAD_FROM(curr, th) {
+7997          if (th->status == THREAD_TO_KILL) {              /*(A)*/
+7998              next = th;
+7999              break;
+8000          }
+8001          if (th->status == THREAD_RUNNABLE && th->stk_ptr) {
+8002              if (!next || next->priority < th->priority)  /*(B)*/
+8003                 next = th;
+8004          }
+8005      }
+8006      END_FOREACH_FROM(curr, th);
+
+(eval.c)
+
+

(A) if there’s a thread that is about to finish, +give it the high priority and let it finish.

+

(B) find out what seems runnable. +However it seems to consider the value of priority. +This member can also be modified from Ruby level +by using Tread#priority Thread#priority=. +ruby itself does not especially modify it.

+

If these are done but the next thread could not be found, +in other words if the next was not set, what happen? +Since select has already been done, +at least one of threads of time wait or I/O wait should have finished waiting. +If it was missing, the rest is only the waits for the other threads, +and moreover there’s no runnable threads, +thus this wait will never end. +This is a dead lock.

+

Of course, for the other reasons, a dead lock can happen, +but generally it’s very hard to detect a dead lock. +Especially in the case of ruby, Mutex and such are implemented at Ruby +level, the perfect detection is nearly impossible.

+

Switching Threads

+

The next thread to invoke has been determined. +I/O and select checks has also been done. +The rest is transferring the control to the target thread. +However, for the last of rb_thread_schedule() and the code to switch threads, +I’ll start a new section.

+

Context Switch

+

The last third point is thread-switch, +and it is context-switch. +This is the most interesting part of threads of ruby.

+

The Base Line

+

Then we’ll start with the tail of rb_thread_schedule(). +Since the story of this section is very complex, +I’ll go with a significantly simplified version.

+

rb_thread_schedule() (context switch)

+ +
+if (THREAD_SAVE_CONTEXT(curr)) {
+    return;
+}
+rb_thread_restore_context(next, RESTORE_NORMAL);
+
+

As for the part of THREAD_SAVE_CONTEXT(), +we need to extract the content at several places in order to understand.

+

THREAD_SAVE_CONTEXT()

+ +
+7619  #define THREAD_SAVE_CONTEXT(th) \
+7620      (rb_thread_save_context(th),thread_switch(setjmp((th)->context)))
+
+7587  static int
+7588  thread_switch(n)
+7589      int n;
+7590  {
+7591      switch (n) {
+7592        case 0:
+7593          return 0;
+7594        case RESTORE_FATAL:
+7595          JUMP_TAG(TAG_FATAL);
+7596          break;
+7597        case RESTORE_INTERRUPT:
+7598          rb_interrupt();
+7599          break;
+            /* …… process various abnormal things …… */
+7612        case RESTORE_NORMAL:
+7613        default:
+7614          break;
+7615      }
+7616      return 1;
+7617  }
+
+(eval.c)
+
+

If I merge the three then extract it, here is the result:

+
+rb_thread_save_context(curr);
+switch (setjmp(curr->context)) {
+  case 0:
+    break;
+  case RESTORE_FATAL:
+    ....
+  case RESTORE_INTERRUPT:
+    ....
+  /* ……process abnormals…… */
+  case RESTORE_NORMAL:
+  default:
+    return;
+}
+rb_thread_restore_context(next, RESTORE_NORMAL);
+
+

At both of the return value of setjmp() and rb_thread_restore_context(), +RESTORE_NORMAL appears, +this is clearly suspicious. +Since it does longjmp() in rb_thread_restore_context(), +we can expect the correspondence between setjmp() and longjmp(). +And if we will imagine the meaning also from the function names,

+
+save the context of the current thread
+setjmp
+restore the context of the next thread
+longjmp
+
+

The rough main flow would probably look like this. +However what we have to be careful about here is, +this pair of setjmp() and longjmp() is not completed in this thread. +setjmp() is used to save the context of this thread, +longjmp() is used to restore the context of the next thread. +In other words, there’s a chain of setjmp/longjmp() as follows. (Figure 3)

+
+

(setjmploop)
+Figure 3: the backstitch by chaining of setjmp

+
    +
  • 外側 outside
  • +
  • 退避 set aside
  • +
  • 復元 restore
  • +
  • スレッド thread +
+ +

We can restore around the CPU registers with setjmp()/longjmp(), +so the remaining context is the Ruby stacks in addition to the machine stack. +rb_thread_save_context() is to save it, +and rb_thread_restore_context() is to restore it. +Let’s look at each of them in sequential order.

+

rb_thread_save_context()

+

Now, we’ll start with rb_thread_save_context(), which saves a context.

+

rb_thread_save_context() (simplified)

+ +
+7539  static void
+7540  rb_thread_save_context(th)
+7541      rb_thread_t th;
+7542  {
+7543      VALUE *pos;
+7544      int len;
+7545      static VALUE tval;
+7546
+7547      len = ruby_stack_length(&pos);
+7548      th->stk_len = 0;
+7549      th->stk_pos = (rb_gc_stack_start<pos)?rb_gc_stack_start
+7550                                           :rb_gc_stack_start - len;
+7551      if (len > th->stk_max) {
+7552          REALLOC_N(th->stk_ptr, VALUE, len);
+7553          th->stk_max = len;
+7554      }
+7555      th->stk_len = len;
+7556      FLUSH_REGISTER_WINDOWS;
+7557      MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
+
+          /* …………omission………… */
+      }
+
+(eval.c)
+
+

The last half is just keep assigning the global variables such as ruby_scope +into th, so it is omitted because it is not interesting. +The rest, in the part shown above, it attempts to copy the entire machine stack +into the place where th->stk_ptr points to.

+

First, it is ruby_stack_length() which writes the head address of the stack +into the parameter pos and returns its length. +The range of the stack is determined by using this value +and the address of the bottom-end side is set to th->stk_ptr. +We can see some branches, +it is because both a stack extending higher and a stack extending lower are +possible. (Figure 4)

+
+

(twodirection)
+Fig.4: a stack extending higher and a stack extending lower

+
    +
  • 下にのびるスタック a stack extending lower
  • +
  • 上にのびるスタック a stack extending higher +
+ +

After that, the rest is allocating a memory in where th->stkptr points to and +copying the stack: allocate the memory whose size is th->stk_max then copy the +stack by the len length.

+

FLUSH_REGISTER_WINDOWS was described in Chapter 5: Garbage collection, +so its explanation might no longer be necessary. +This is a macro (whose substance is written in Assembler) +to write down the cache of the stack space to the memory. +It must be called when the target is the entire stack.

+

rb_thread_restore_context()

+

And finally, +it is rb_thread_restore_context(), +which is the function to restore a thread.

+

rb_thread_restore_context()

+ +
+7635  static void
+7636  rb_thread_restore_context(th, exit)
+7637      rb_thread_t th;
+7638      int exit;
+7639  {
+7640      VALUE v;
+7641      static rb_thread_t tmp;
+7642      static int ex;
+7643      static VALUE tval;
+7644
+7645      if (!th->stk_ptr) rb_bug("unsaved context");
+7646
+7647      if (&v < rb_gc_stack_start) {
+7648          /* the machine stack extending lower */
+7649          if (&v > th->stk_pos) stack_extend(th, exit);
+7650      }
+7651      else {
+7652          /* the machine stack extending higher */
+7653          if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
+7654      }
+
+          /* omission …… back the global variables */
+
+7677      tmp = th;
+7678      ex = exit;
+7679      FLUSH_REGISTER_WINDOWS;
+7680      MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
+7681
+7682      tval = rb_lastline_get();
+7683      rb_lastline_set(tmp->last_line);
+7684      tmp->last_line = tval;
+7685      tval = rb_backref_get();
+7686      rb_backref_set(tmp->last_match);
+7687      tmp->last_match = tval;
+7688
+7689      longjmp(tmp->context, ex);
+7690  }
+
+(eval.c)
+
+

The th parameter is the target to give the execution back. +MEMCPY() and longjmp() in the last half are at the heart. +The closer MEMCPY() to the last, the better it is, because +after this manipulation, the stack is in a destroyed state until longjmp().

+

Nevertheless, there are rb_lastline_set() and rb_backref_set(). +They are the restorations of $_ and $~. +Since these two variables are not only local variables but also thread local variables, +even if it is only a single local variable slot, +there are its as many slots as the number of threads. +This must be here because the place actually being written back is the stack. +Because they are local variables, their slot spaces are allocated with alloca().

+

That’s it for the basics. But if we merely write the stack back, +in the case when the stack of the current thread is shorter than the stack of +the thread to switch to, +the stack frame of the very currently executing function +(it is rb_thread_restore_context) would be overwritten. +It means the content of the th parameter will be destroyed. +Therefore, in order to prevent this from occurring, +we first need to extend the stack. +This is done by the stack_extend() in the first half.

+

stack_extend()

+ +
+7624  static void
+7625  stack_extend(th, exit)
+7626      rb_thread_t th;
+7627      int exit;
+7628  {
+7629      VALUE space[1024];
+7630
+7631      memset(space, 0, 1);        /* prevent array from optimization */
+7632      rb_thread_restore_context(th, exit);
+7633  }
+
+(eval.c)
+
+

By allocating a local variable (which will be put at the machine stack space) +whose size is 1K, forcibly extend the stack. +However, though this is a matter of course, doing return from stack_extend() +means the extended stack will shrink immediately. +This is why rb_thread_restore_context() is called again immediately in the +place.

+

By the way, the completion of the task of rb_thread_restore_context() +means it has reached the call of longjmp(), +and once it is called it will never return back. +Obviously, the call of stack_extend() will also never return. +Therefore, rb_thread_restore_context() does not have to think about +such as possible procedures after returning from stack_extend().

+

Issues

+

This is the implementation of the ruby thread switch. +We can’t think it is lightweight. +Plenty of malloc() realloc() and plenty of memcpy() and doing setjmp() longjmp() +then furthermore calling functions to extend the stack. +There’s no problem to express “It is deadly heavy”. +But instead, there’s not any system call depending on a particular OS, +and there are just a few assembly only for the register windows of Sparc. +Indeed, this seems to be highly portable.

+

There’s another problem. It is, because the stacks of all threads are allocated to the +same address, there’s the possibility that the code using the pointer to the +stack space is not runnable. Actually, Tcl/Tk excellently matches this +situation, in order to bypass, Ruby’s Tcl/Tk interface reluctantly choses +to access only from the main thread.

+

Of course, this does not go along with native threads. +It would be necessary to restrict ruby threads to run only on a particular +native thread in order to let them work properly. +In UNIX, there are still a few libraries that use a lot of threads. +But in Win32, because threads are running every now and then, +we need to be careful about it.

+ + + +
+ + diff --git a/htmls/variable.html b/htmls/variable.html new file mode 100644 index 0000000..99e66fa --- /dev/null +++ b/htmls/variable.html @@ -0,0 +1,589 @@ + + + + + Variables and constants | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Vincent ISAMBART

+

Chapter 6: Variables and constants

+

Outline of this chapter

+

Ruby variables

+

In Ruby there are quite a lot of different types of variables and +constants. Let’s line them up, starting from the largest scope.

+
    +
  • Global variables
  • +
  • Constants
  • +
  • Class variables
  • +
  • Instance variables
  • +
  • Local variables
  • +
+

Instance variables were already explained in chapter 2 “Objects”. In +this chapter we’ll talk about:

+
    +
  • Global variables
  • +
  • Class variables
  • +
  • Constants
  • +
+

We will talk about local variables in the third part of the book.

+

API for variables

+

The object of this chapter’s analysis is variable.c. Let’s first +look at the available API.

+
+VALUE rb_iv_get(VALUE obj, char *name)
+VALUE rb_ivar_get(VALUE obj, ID name)
+VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
+VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
+
+

We’ve already spoken about those functions, but must mention them again +as they are in variable.c. They are of course used for accessing instance +variables.

+
+VALUE rb_cv_get(VALUE klass, char *name)
+VALUE rb_cvar_get(VALUE klass, ID name)
+VALUE rb_cv_set(VALUE klass, char *name, VALUE val)
+VALUE rb_cvar_set(VALUE klass, ID name, VALUE val)
+
+

These functions are the API for accessing class variables. Class +variables belong directly to classes so the functions take a class as +parameter. There are in two groups, depending if their name starts +with rb_Xv or rb_Xvar. The difference lies in the type of the +variable “name”. The ones with a shorter name are generally easier to +use because they take a char*. The ones with a longer name are more +for internal use as they take a ID.

+
+VALUE rb_const_get(VALUE klass, ID name)
+VALUE rb_const_get_at(VALUE klass, ID name)
+VALUE rb_const_set(VALUE klass, ID name, VALUE val)
+
+

These functions are for accessing constants. Constants also belong to +classes so they take classes as parameter. rb_const_get() follows +the superclass chain, whereas rb_const_get_at() does not (it just +looks in klass).

+
+struct global_entry *rb_global_entry(ID name)
+VALUE rb_gv_get(char *name)
+VALUE rb_gvar_get(struct global_entry *ent)
+VALUE rb_gv_set(char *name, VALUE val)
+VALUE rb_gvar_set(struct global_entry *ent, VALUE val)
+
+

These last functions are for accessing global variables. They are a +little different from the others due to the use of `struct +global_entry`. We’ll explain this while describing the implementation.

+

Important points

+

The most important topic of this chapter is “Where and how are variables +stored?”, in other words: data structures.

+

The second most important matter is how we search for the values. The scopes +of Ruby variables and constants are quite complicated because +variables and constants are sometimes inherited, sometimes looked for +outside of the local scope… To have a better understanding, you +should first try to guess from the behavior how it could be +implemented, then compare that with what is really done.

+

Class variables

+

Class variables are variables that belong to classes. In Java or C++ +they are called static variables. They can be accessed from both the +class or its instances. But “from an instance” or “from the class” is +information only available in the evaluator, and we do not have one +for the moment. So from the C level it’s like having no access +range. We’ll just focus on the way these variables are stored.

+

Reading

+

The functions to get a class variable are rb_cvar_get() and +rb_cv_get(). The function with the longer name takes ID as +parameter and the one with the shorter one takes char*. Because the +one taking an ID seems closer to the internals, we’ll look at it.

+

rb_cvar_get() +

+1508  VALUE
+1509  rb_cvar_get(klass, id)
+1510      VALUE klass;
+1511      ID id;
+1512  {
+1513      VALUE value;
+1514      VALUE tmp;
+1515
+1516      tmp = klass;
+1517      while (tmp) {
+1518          if (RCLASS→iv_tbl) {
+1519              if (st_lookup(RCLASS→iv_tbl,id,&value)) {
+1520                  if (RTEST) {
+1521                      cvar_override_check(id, tmp);
+1522                  }
+1523                  return value;
+1524              }
+1525          }
+1526          tmp = RCLASS→super;
+1527      }
+1528
+1529      rb_name_error(id,“uninitialized class variable %s in %s”,
+1530                    rb_id2name(id), rb_class2name(klass));
+1531      return Qnil;                /* not reached */
+1532  }

+

(variable.c) +

+

This function reads a class variable in klass.

+

Error management functions like rb_raise() can be simply ignored +like I said before. The rb_name_error() that appears this time is a +function for raising an exception, so it can be ignored for the same +reasons. In ruby, you can assume that all functions ending with +_error raise an exception.

+

After removing all this, we can see that while following the klass‘s +superclass chain we only search in iv_tbl. At this point you should +say "What? iv_tbl is the instance variables table, isn’t it?" As a +matter of fact, class variables are stored in the instance variable +table.

+

We can do this because when creating IDs, the whole name of the +variables is taken into account, including the prefix: rb_intern() +will return different IDs for “@var” and “@@var”. At the Ruby +level, the variable type is determined only by the prefix so there’s +no way to access a class variable called @var from Ruby.

+

Constants

+

It’s a little abrupt but I’d like you to remember the members of +struct RClass. If we exclude the basic member, struct RClass +contains:

+
    +
  • VALUE super
  • +
  • struct st_table *iv_tbl
  • +
  • struct st_table *m_tbl
  • +
+

Then, considering that:

+
    +
  1. constants belong to a class
  2. +
  3. we can’t see any table dedicated to constants in struct RClass
  4. +
  5. class variables and instance variables are both in iv_tbl
  6. +
+

Could it mean that the constants are also…

+

Assignment

+

rb_const_set() is a function to set the value of constants: it sets +the constant id in the class klass to the value val.

+

rb_const_set() +

+1377  void
+1378  rb_const_set(klass, id, val)
+1379      VALUE klass;
+1380      ID id;
+1381      VALUE val;
+1382  {
+1383      mod_av_set(klass, id, val, Qtrue);
+1384  }

+

(variable.c) +

+

mod_av_set() does all the hard work:

+

mod_av_set() +

+1352  static void
+1353  mod_av_set(klass, id, val, isconst)
+1354      VALUE klass;
+1355      ID id;
+1356      VALUE val;
+1357      int isconst;
+1358  {
+1359      char *dest = isconst ? “constant” : “class variable”;
+1360
+1361      if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
+1362          rb_raise(rb_eSecurityError, “Insecure: can’t set %s”, dest);
+1363      if (OBJ_FROZEN(klass)) rb_error_frozen(“class/module”);
+1364      if (!RCLASS→iv_tbl) {
+1365          RCLASS→iv_tbl = st_init_numtable();
+1366      }
+1367      else if (isconst) {
+1368          if (st_lookup(RCLASS→iv_tbl, id, 0) ||
+1369              (klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) {
+1370              rb_warn(“already initialized %s %s”, dest, rb_id2name(id));
+1371          }
+1372      }
+1373
+1374      st_insert(RCLASS→iv_tbl, id, val);
+1375  }

+

(variable.c) +

+

You can this time again ignore the warning checks (rb_raise(), +rb_error_frozen() and rb_warn()). Here’s what’s left:

+

mod_av_set() (only the important part) +

+    if (!RCLASS→iv_tbl) {
+        RCLASS→iv_tbl = st_init_numtable();
+    }
+    st_insert(RCLASS→iv_tbl, id, val);
+

+

We’re now sure constants also reside in the instance table. It means +in the iv_tbl of struct RClass, the following are mixed together:

+
    +
  1. the class’s own instance variables
  2. +
  3. class variables
  4. +
  5. constants
  6. +
+

Reading

+

We now know how the constants are stored. We’ll now check how they +really work.

+

rb_const_get()

+

We’ll now look at rconst_get(), the function to read a +constant. This functions returns the constant referred to by id from the class +klass.

+

rb_const_get() +

+1156  VALUE
+1157  rb_const_get(klass, id)
+1158      VALUE klass;
+1159      ID id;
+1160  {
+1161      VALUE value, tmp;
+1162      int mod_retry = 0;
+1163
+1164      tmp = klass;
+1165    retry:
+1166      while (tmp) {
+1167          if (RCLASS→iv_tbl &&
+                  st_lookup(RCLASS→iv_tbl,id,&value)) {
+1168              return value;
+1169          }
+1170          if (tmp == rb_cObject && top_const_get(id, &value))
+                  return value;
+1171          tmp = RCLASS→super;
+1172      }
+1173      if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
+1174          mod_retry = 1;
+1175          tmp = rb_cObject;
+1176          goto retry;
+1177      }
+1178
+1179      /* Uninitialized constant /
+1180      if (klass && klass != rb_cObject) {
+1181          rb_name_error(id, “uninitialized constant %s at %s”,
+1182                        rb_id2name(id),
+1183                        RSTRING)→ptr);
+1184      }
+1185      else { / global_uninitialized /
+1186          rb_name_error(id, “uninitialized constant %s”,rb_id2name(id));
+1187      }
+1188      return Qnil;                / not reached */
+1189  }

+

(variable.c) +

+

There’s a lot of code in the way. First, we should at least remove the +rb_name_error() in the second half. In the middle, what’s around +mod_entry seems to be a special handling for modules. Let’s also +remove that for the time being. The function gets reduced to this:

+

rb_const_get (simplified) +

+VALUE
+rb_const_get(klass, id)
+    VALUE klass;
+    ID id;
+{
+    VALUE value, tmp;

+tmp = klass; +while (tmp) { +if (RCLASS→iv_tbl && st_lookup(RCLASS→iv_tbl,id,&value)) { +return value; +} +if (tmp == rb_cObject && top_const_get(id, &value)) return value; +tmp = RCLASS→super; +} +

} +

+

Now it should be pretty easy to understand. The function searches for the +constant in iv_tbl while climbing klass’s superclass chain. That +means:

+
+class A
+  Const = "ok"
+end
+class B < A
+  p(Const)    # can be accessed
+end
+
+

The only problem remaining is top_const_get(). This function is only +called for rb_cObject so top must mean “top-level”. If you don’t +remember, at the top-level, the class is Object. This means the same +as “in the class statement defining C, the class becomes C”, +meaning that “the top-level’s class is Object”.

+
+# the class of the top-level is Object
+class A
+  # the class is A
+  class B
+    # the class is B
+  end
+end
+
+

So top_const_get() probably does something specific to the top +level.

+

top_const_get()

+

Let’s look at this top_const_get function. It looks up the id +constant writes the value in klassp and returns.

+

top_const_get() +

+1102  static int
+1103  top_const_get(id, klassp)
+1104      ID id;
+1105      VALUE klassp;
+1106  {
+1107      / pre-defined class /
+1108      if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue;
+1109
+1110      / autoload */
+1111      if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
+1112          rb_autoload_load(id);
+1113          *klassp = rb_const_get(rb_cObject, id);
+1114          return Qtrue;
+1115      }
+1116      return Qfalse;
+1117  }

+

(variable.c) +

+

rb_class_tbl was already mentioned in chapter 4 “Classes and +modules”. It’s the table for storing the classes defined at the +top-level. Built-in classes like String or Array have for example +an entry in it. That’s why we should not forget to search in this +table when looking for top-level constants.

+

The next block is related to autoloading. This allows us to automatically +load a library when accessing a top-level constant for the first +time. This can be used like this:

+
+autoload(:VeryBigClass, "verybigclass")   # VeryBigClass is defined in it
+
+

After this, when VeryBigClass is accessed for the first time, the +verybigclass library is loaded (with require). As long as +VeryBigClass is defined in the library, execution can continue smoothly. It’s +an efficient approach, when a library is too big and a lot of time is spent on loading.

+

This autoload is processed by rb_autoload_xxxx(). We won’t discuss +autoload further in this chapter because there will probably be a big +change in how it works soon (The way autoload works did change in +1.8: autoloaded constants do not need to be defined at top-level +anymore).

+

Other classes?

+

But where did the code for looking up constants in other classes end up? +After all, constants are first looked up in the outside classes, then +in the superclasses.

+

In fact, we do not yet have enough knowledge to look at that. The +outside classes change depending on the location in the program. In +other words it depends of the program context. So we need first to +understand how the internal state of the +evaluator is handled. Specifically, this search in other classes is done in the +ev_const_get() function of eval.c. We’ll look at it and finish +with the constants in the third part of the book.

+

Global variables

+

General remarks

+

Global variables can be accessed from anywhere. Or put the other way +around, there is no need to restrict access to them. Because they are +not attached to any context, the table only has to be at one place, and +there’s no need to do any check. Therefore implementation is very +simple.

+

But there is still quite a lot of code. The reason for this is that global +variables are quite different from normal variables. Functions like +the following are only available for global variables:

+
    +
  • you can “hook” access of global variables
  • +
  • you can alias them with alias
  • +
+

Let’s explain this simply.

+

Aliases of variables

+
+alias $newname $oldname
+
+

After this, you can use $newname instead of $oldname. alias for +variables is mainly a counter-measure for “symbol variables”. “symbol +variables” are variables inherited from Perl like $= or $0. $= +decides if during string comparison upper and lower case letters +should be differentiated. $0 shows the name of the main Ruby +program. There are some other symbol variables but anyway as their +name is only one character long, they are difficult to remember for +people who don’t know Perl. So, aliases were created to make them a little +easier to understand.

+

That said, currently symbol variables are not recommended, and are +moved one by one in singleton methods of suitable modules. The current +school of thought is that $= and others will be abolished in 2.0.

+

Hooks

+

You can “hook” read and write of global variables.

+

Hooks can be also be set at the Ruby level, but I was thinking: why not +instead look at C level special variables for system use like +$KCODE? $KCODE is the variable containing the encoding the +interpreter currently uses to handle strings. It can only be set to +special values like "EUC" or "UTF8". But this is too bothersome so +it can also be set it to "e" or "u".

+
+p($KCODE)      # "NONE" (default)
+$KCODE = "e"
+p($KCODE)      # "EUC"
+$KCODE = "u"
+p($KCODE)      # "UTF8"
+
+

Knowing that you can hook assignment of global variables, you should +understand easily how this can be done. By the way, $KCODE’s K comes +from “kanji” (the name of Chinese characters in Japanese).

+

You might say that even with alias or hooks, +global variables just aren’t used much, so it’s functionality that doesn’t +really mater. It’s adequate not to talk much about unused +functions, and I need some pages for the analysis of the parser and +evaluator. That’s why I’ll proceed with the explanation below throwing +away what’s not really important.

+

Data structure

+

When we were looking at how variables work, I said that the way they +are stored is important. That’s why I’d like you to firmly grasp the +structure used by global variables.

+

▼ Data structure for global variables +

+  21  static st_table *rb_global_tbl;

+334 struct global_entry { +335 struct global_variable *var; +336 ID id; +337 }; +324 struct global_variable { +325 int counter; /* reference counter */ +326 void data; / value of the variable */ +327 VALUE (getter)(); / function to get the variable */ +328 void (setter)(); / function to set the variable */ +329 void (marker)(); / function to mark the variable */ +330 int block_trace; +331 struct trace_var *trace; +332 }; +

(variable.c) +

+

rb_global_tbl is the main table. All global variables are stored in +this table. The keys of this table are of course variable names +(ID). A value is expressed by a struct global_entry and a `struct +global_variable` (figure 1).

+

+

(gvar)
+Figure 1: Global variables table at execution time

+

+

The structure representing the variables is split in two to be able to +create aliases. When an alias is established, two global_entrys +point to the same struct global_variable.

+

It’s at this time that the reference counter (the counter member of +struct global_variable) is necessary. I explained the general idea of +a reference counter in the previous section “Garbage +collection”. Reviewing it briefly, when a new reference to the +structure is made, the counter in incremented by 1. When the reference +is not used anymore, the counter is decreased by 1. When the counter +reaches 0, the structure is no longer useful so free() can be +called.

+

When hooks are set at the Ruby level, a list of struct trace_vars is +stored in the trace member of struct global_variable, but I won’t +talk about it, and omit struct trace_var.

+

Reading

+

You can have a general understanding of global variables just by looking at how +they are read. The functions for reading them are rb_gv_get() and +rb_gvar_get().

+

rb_gv_get() rb_gvar_get() +

+ 716  VALUE
+ 717  rb_gv_get(name)
+ 718      const char *name;
+ 719  {
+ 720      struct global_entry *entry;
+ 721
+ 722      entry = rb_global_entry(global_id(name));
+ 723      return rb_gvar_get(entry);
+ 724  }

+649 VALUE +650 rb_gvar_get(entry) +651 struct global_entry *entry; +652 { +653 struct global_variable *var = entry→var; +654 return (*var→getter)(entry→id, var→data, var); +655 } +

(variable.c) +

+

A substantial part of the content seems to turn around the +rb_global_entry() function, but that does not prevent us +understanding what’s going on. global_id is a function that converts a +char* to ID and checks if it’s the ID of a global +variable. (*var->getter)(...) is of course a function call using the +function pointer var->getter. If p is a function pointer, +(*p)(arg) calls the function.

+

But the main part is still rb_global_entry().

+

rb_global_entry() +

+ 351  struct global_entry*
+ 352  rb_global_entry(id)
+ 353      ID id;
+ 354  {
+ 355      struct global_entry *entry;
+ 356
+ 357      if (!st_lookup(rb_global_tbl, id, &entry)) {
+ 358          struct global_variable *var;
+ 359          entry = ALLOC;
+ 360          st_add_direct(rb_global_tbl, id, entry);
+ 361          var = ALLOC;
+ 362          entry→id = id;
+ 363          entry→var = var;
+ 364          var→counter = 1;
+ 365          var→data = 0;
+ 366          var→getter = undef_getter;
+ 367          var→setter = undef_setter;
+ 368          var→marker = undef_marker;
+ 369
+ 370          var→block_trace = 0;
+ 371          var→trace = 0;
+ 372      }
+ 373      return entry;
+ 374  }

+

(variable.c) +

+

The main treatment is only done by the st_lookup() at the beginning. +What’s done afterwards is just creating (and storing) a new entry. As, when +accessing a non existing global variable, an entry is automatically +created, rb_global_entry() will never return NULL.

+

This was mainly done for speed. When the parser finds a global +variable, it gets the corresponding struct global_entry. When +reading the value of the variable, the parser just has to get the +value from the entry (using rb_gv_get()), and has no need to do any +check.

+

Let’s now continue a little with the code that follows. var->getter +and others are set to undef_xxxx. undef means that the global +setter/getter/marker for the variable are currently undefined.

+

undef_getter() just shows a warning and returns nil, as even +undefined global variables can be read. undef_setter() is quite +interesting so let’s look at it.

+

undef_setter() +

+ 385  static void
+ 386  undef_setter(val, id, data, var)
+ 387      VALUE val;
+ 388      ID id;
+ 389      void data;
+ 390      struct global_variable *var;
+ 391  {
+ 392      var→getter = val_getter;
+ 393      var→setter = val_setter;
+ 394      var→marker = val_marker;
+ 395
+ 396      var→data = (void)val;
+ 397  }

+

(variable.c) +

+

val_getter() takes the value from entry->data and returns +it. val_getter() just puts a value in entry->data. Setting +handlers this way allows us not to need special handling for undefined +variables (figure 2). Skillfully done, isn’t it?

+

+

(gaccess)
+Figure 2: Setting and consultation of global variables

+

+ + + +
+ + diff --git a/htmls/yacc.html b/htmls/yacc.html new file mode 100644 index 0000000..7feb6e9 --- /dev/null +++ b/htmls/yacc.html @@ -0,0 +1,1013 @@ + + + + + YACC crash course | Ruby Hacking Guide + + + + +
+ +
+

Ruby Hacking Guide

+
+ + + +

Translated by Vincent ISAMBART & ocha-

+

Chapter 9: yacc crash course

+

Outline

+

Parser and scanner

+

How to write parsers for programming languages has been an active area +of research for a long time, and there is a quite firm established +tactic for doing it. If we limit ourselves to a grammar not too +strange (or ambiguous), we can solve this problem by following this +method.

+

The first part consists in splitting a string in a list of words (or +tokens). This is called a scanner or lexer. The term “lexical +analyzer” is also used, but is too complicated to say so we’ll use the +name scanner.

+

When speaking about scanners, the common sense first says “there are +generally spaces at the end of a word”. And in practice, it was made +like this in most programming languages, because it’s the easiest way.

+

There can also be exceptions. For example, in the old Fortran, white +spaces did not have any meaning. This means a white space did not end +a word, and you could put spaces in the name of a variable. However +that made the parsing very complicated so the compiler vendors, one by +one, started ignoring that standard. Finally Fortran 90 followed this +trend and made the fact that white spaces have an impact the standard.

+

By the way, it seems the reason white spaces had not meaning in +Fortran 77 was that when writing programs on punch cards it was easy +to make errors in the number of spaces.

+

List of symbols

+

I said that the scanner spits out a list of words (tokens), but, to be +exact, what the scanner creates is a list of “symbols”, not words.

+

What are symbols? Let’s take numbers as an example. In a programming +language, 1, 2, 3, 99 are all “numbers”. They can all be handled the +same way by the grammar. Where we can write 1, we can also write 2 or +3. That’s why the parser does not need to handle them in different +ways. For numbers, “number” is enough.

+

“number”, “identifier” and others can be grouped together as +“symbol”. But be careful not to mix this with the Symbol class.

+

The scanner first splits the string into words and determines what +these symbols are. For example, NUMBER or DIGIT for numbers, +IDENTIFIER for names like “name”, IF for the reserved word +if. These symbols are then given to the next phase.

+

Parser generator

+

The list of words and symbols spitted out by the scanner are going to +be used to form a tree. This tree is called a syntax tree.

+

The name “parser” is also sometimes used to include both the scanner +and the creation of the syntax tree. However, we will use the narrow +sense of “parser”, the creation of the syntax tree. How does this +parser make a tree from the list of symbols? In other words, on what +should we focus to find the tree corresponding to a piece of code?

+

The first way is to focus on the meaning of the words. For example, +let’s suppose we find the word var. If the definition of the local +variable var has been found before this, we’ll understand it’s the +reading of a local variable.

+

An other ways is to only focus on what we see. For example, if after +an identified comes a ‘=’, we’ll understand it’s an assignment. If +the reserved word if appears, we’ll understand it’s the start of an +if statement.

+

The later method, focusing only on what we see, is the current +trend. In other words the language must be designed to be analyzed +just by looking at the list of symbols. The choice was because +this way is simpler, can be more easily generalized and can therefore +be automatized using tools. These tools are called parser generators.

+

The most used parser generator under UNIX is yacc. Like many others, +ruby‘s parser is written using yacc. The input file for this tool +is parser.y. That’s why to be able to read ruby’s parser, we need +to understand yacc to some extent. (Note: Starting from 1.9, ruby +requires bison instead of yacc. However, bison is mainly yacc +with additional functionality, so this does not diminish the interest +of this chapter.)

+

This chapter will be a simple presentation of yacc to be able to +understand parse.y, and therefore we will limit ourselves to what’s +needed to read parse.y. If you want to know more about parsers and +parser generators, I recommend you a book I wrote called “Rubyを256倍使 +うための本 無道編” (The book to use 256 times more of Ruby - +Unreasonable book). I do not recommend it because I wrote it, but +because in this field it’s the easiest book to understand. And besides +it’s cheap so stakes will be low.

+

Nevertheless, if you would like a book from someone else (or can’t +read Japanese), I recommend O’Reilly’s “lex & yacc programming” by +John R. Levine, Tony Mason and Doug Brown. And if your are still not +satisfied, you can also read “Compilers” (also known as the “dragon +book” because of the dragon on its cover) by Alfred V. Aho, Ravi Sethi +and Jeffrey D. Ullman.

+

Grammar

+

Grammar file

+

The input file for yacc is called “grammar file”, as it’s the file +where the grammar is written. The convention is to name this grammar +file *.y. It will be given to yacc who will generate C source +code. This file can then be compiled as usual (figure 1 shows the full +process).

+

+

(build)
+Figure 1: File dependencies

+

+

The output file name is always y.tab.c and can’t be changed. The +recent versions of yacc usually allow to change it on the command +line, but for compatibility it was safer to keep y.tab.c. By the +way, it seems the tab of y.tab.c comes from table, as lots of +huge tables are defined in it. +It’s good to have a look at the file once.

+

The grammar file’s content has the following form:

+

▼ General form of the grammar file +

+%{
+Header
+%}
+%union ….
+%token ….
+%type ….

+

% +Rules part +% +User defined part +

+

yacc‘s input file is first divided in 3 parts by %%. The first +part if called the definition part, has a lot of definitions and +setups. Between %{ and %} we can write anything we want in C, like +for example necessary macros. After that, the instructions starting +with % are special yacc instructions. Every time we use one, we’ll +explain it.

+

The middle part of the file is called the rules part, and is the most +essential part for yacc. It’s where is written the grammar we want +to parse. We’ll explain it in details in the next section.

+

The last part of the file, the user defined part, can be used freely +by the user. yacc just copies this part verbatim in the output +file. It’s used for example to put auxiliary routines needed by the +parser.

+

What does yacc do.

+

What yacc takes care of is mainly this rules part in the +middle. yacc takes the grammar written there and use it to make a +function called yyparse(). It’s the parser, in the narrow sense of +the word.

+

In the narrow sense, so it means a scanner is needed. However, yacc +won’t take care of it, it must be done by the user. +The scanner is the function named yylex().

+

Even if yacc creates yyparse(), it only takes care of its core +part. The “actions” we’ll mention later is out of its scope. You can +think the part done by yacc is too small, but that’s not the +case. That’s because this “core part” is overly important that yacc +survived to this day even though we keep complaining about it.

+

But what on earth is this core part? That’s what we’re going to see.

+

BNF

+

When we want to write a parser in C, its code will be “cut the string +this way, make this an if statement…” When using parser +generators, we say the opposite, that is “I would like to parse this +grammar.” Doing this creates for us a parser to handle the +grammar. This means telling the specification gives us the +implementation. That’s the convenient point of yacc.

+

But how can we tell the specification? With yacc, the method of +description used is the BNF (Backus-Naur Form). Let’s look at a very +simple example.

+
+if_stmt: IF expr THEN stmt END
+
+

Let’s see separately what’s at the left and at the right of the +“:”. The part on the left side, if_stmt, is equal to the right +part… is what I mean here. In other words, I’m saying that:

+

if_stmt and IF expr THEN stmt END are equivalent.

+

Here, if_stmt, IF, expr… are all “symbols”. expr is the +abbreviation of expression, stmt of statement. It must be for +sure the declaration of the if statement.

+

One definition is called a rule. The part at the left of “:” is +called the left side and the right part called the right side. This is +quite easy to remember.

+

But something is missing. We do not want an if statement without +being able to use else. And even if we could write else, having +to always write the else even when it’s useless would be +cumbersome. In this case we could do the following:

+
+if_stmt: IF expr THEN stmt END
+       | IF expr THEN stmt ELSE stmt END
+
+

|” means “or”.

+

if_stmt is either “IF expr THEN stmt END” or “`IF expr THEN stmt +ELSE stmt END`”.

+

That’s it.

+

Here I would like you to pay attention to the split done with +|. With just this, one more rule is added. In fact, punctuating with +| is just a shorter way to repeat the left side. The previous +example has exactly the same meaning as the following:

+
+if_stmt: IF expr THEN stmt END
+if_stmt: IF expr THEN stmt ELSE stmt END
+
+

This means two rules are defined in the example.

+

This is not enough to complete the definition of the if +statement. That’s because the symbols expr and stmt are not sent +by the scanner, their rules must be defined. To be closer to Ruby, let’s +boldly add some rules.

+
+stmt   : if_stmt
+       | IDENTIFIER '=' expr   /* assignment */
+       | expr
+
+if_stmt: IF expr THEN stmt END
+       | IF expr THEN stmt ELSE stmt END
+
+expr   : IDENTIFIER       /* reading a variable */
+       | NUMBER           /* integer constant */
+       | funcall          /* FUNction CALL */
+
+funcall: IDENTIFIER '(' args ')'
+
+args   : expr             /* only one parameter */
+
+

I used two new elements. First, comments of the same form as in C, and +character expressed using '='. This '=' is also of course a +symbol. Symbols like “=” are different from numbers as there is only +one variety for them. That’s why for symbols where can also use '='. +It would be great to be able to use for strings for, for example, +reserved words, but due to limitations of the C language this cannot +be done.

+

We add rules like this, to the point we complete writing all the +grammar. With yacc, the left side of the first written rule is “the +whole grammar we want to express”. So in this example, stmt +expresses the whole program.

+

It was a little too abstract. Let’s explain this a little more +concretely. By “stmt expresses the whole program”, I mean stmt and +the rows of symbols expressed as equivalent by the rules, are all +recognized as grammar. For example, stmt and stmt are +equivalent. Of course. Then expr is equivalent to stmt. That’s +expressed like this in the rule. Then, NUMBER and stmt are +equivalent. That’s because NUMBER is expr and expr is stmt.

+

We can also say that more complicated things are equivalent.

+
+              stmt
+               ↓
+             if_stmt
+               ↓
+      IF expr THEN stmt END
+          ↓        ↓
+IF IDENTIFIER THEN expr END
+                    ↓
+IF IDENTIFIER THEN NUMBER END
+
+

When it has expanded until here, +all elements become the symbols sent by the scanner. +It means such sequence of symbols is correct as a program. +Or putting it the other way around, if this sequence of symbols is sent +by the scanner, the parser can understand it in the opposite order of expanding.

+
+IF IDENTIFIER THEN NUMBER END
+                    ↓
+IF IDENTIFIER THEN expr END
+          ↓        ↓
+      IF expr THEN stmt END
+               ↓
+             if_stmt
+               ↓
+              stmt
+
+

And stmt is a symbol expressing the whole program. That’s why this +sequence of symbols is a correct program for the parser. When it’s the +case, the parsing routine yyparse() ends returning 0.

+

By the way, the technical term expressing that the parser succeeded is +that it “accepted” the input. The parser is like a government office: +if you do not fill the documents in the boxes exactly like he asked +you to, he’ll refuse them. The accepted sequences of symbols are the +ones for which the boxes where filled correctly. Parser and government +office are strangely similar for instance in the fact that they care +about details in specification and that they use complicated terms.

+

Terminal symbols and nonterminal symbols

+

Well, in the confusion of the moment I used without explaining it the +expression “symbols coming from the scanner”. So let’s explain this. I +use one word “symbol” but there are two types.

+

The first type of the symbols are the ones sent by the scanner. They +are for example, IF, THEN, END, '=', … They are called +terminal symbols. That’s because like before when we did the quick +expansion we find them aligned at the end. In this chapter terminal +symbols are always written in capital letters. However, symbols like +'=' between quotes are special. Symbols like this are all terminal +symbols, without exception.

+

The other type of symbols are the ones that never come from the +scanner, for example if_stmt, expr or stmt. They are called +nonterminal symbols. As they don’t come from the scanner, they only +exist in the parser. Nonterminal symbols also always appear at one +moment or the other as the left side of a rule. In this chapter, +nonterminal symbols are always written in lower case letters.

+

How to test

+

I’m now going to tell you the way to process the grammar file with +yacc.

+
+%token A B C D E
+%%
+list: A B C
+    | de
+
+de  : D E
+
+

First, put all terminal symbols used after %token. However, you do +not have to type the symbols with quotes (like '='). Then, put %% +to mark a change of section and write the grammar. That’s all.

+

Let’s now process this.

+
+% yacc first.y
+% ls
+first.y  y.tab.c
+%
+
+

Like most Unix tools, “silence means success”.

+

There’s also implementations of yacc that need semicolons at the end +of (groups of) rules. When it’s the case we need to do the following:

+
+%token A B C D E
+%%
+list: A B C
+    | de
+    ;
+
+de  : D E
+    ;
+
+

I hate these semicolons so in this book I’ll never use them.

+

Void rules

+

Let’s now look a little more at some of the established ways of +grammar description. I’ll first introduce void rules.

+
+void:
+
+

There’s nothing on the right side, this rule is “void”. For example, +the two following targets means exactly the same thing.

+
+target: A B C
+
+target: A void B void C
+void  :
+
+

What is the use of such a thing? It’s very useful. For example in the +following case.

+
+if_stmt : IF expr THEN stmts opt_else END
+
+opt_else:
+        | ELSE stmts
+
+

Using void rules, we can express cleverly the fact that “the else +section may be omitted”. Compared to the rules made previously using +two definitions, this way is shorter and we do not have to disperse +the burden.

+

Recursive definitions

+

The following example is still a little hard to understand.

+
+list: ITEM         /* rule 1 */
+    | list ITEM    /* rule 2 */
+
+

This expresses a list of one or more items, in other words any of the +following lists of symbols:

+
+ITEM
+ITEM ITEM
+ITEM ITEM ITEM
+ITEM ITEM ITEM ITEM
+      :
+
+

Do you understand why? First, according to rule 1 list can be read +ITEM. If you merge this with rule 2, list can be ITEM ITEM.

+
+list: list ITEM
+    = ITEM ITEM
+
+

We now understand that the list of symbols ITEM ITEM is similar to +list. By applying again rule 2 to list, we can say that 3 ITEM +are also similar to list. By quickly continuing this process, the +list can grow to any size. +This is something like mathematical induction.

+

I’ll now show you the next example. The following example expresses +the lists with 0 or more ITEM.

+
+list:
+    | list ITEM
+
+

First the first line means “list is equivalent to (void)”. By void I +mean the list with 0 ITEM. Then, by looking at rule 2 we can say +that “list ITEM” is equivalent to 1 ITEM. That’s because list is +equivalent to void.

+
+list: list   ITEM
+    = (void) ITEM
+    =        ITEM
+
+

By applying the same operations of replacement multiple times, we can +understand that list is the expression a list of 0 or more items.

+

With this knowledge, “lists of 2 or more ITEM” or “lists of 3 or +more ITEM” are easy, and we can even create “lists of an even number +of elements”.

+
+list:
+    | list ITEM ITEM
+
+

Construction of values

+

This abstract talk lasted long enough so in this section I’d really +like to go on with a more concrete talk.

+

Shift and reduce

+

Up until now, various ways to write grammars have been explained, +but what we want is being able to build a syntax tree. +However, I’m afraid to say, only telling it the rules is not enough to be able +to let it build a syntax tree, as might be expected. +Therefore, this time, I’ll tell you the way to build a syntax tree by adding +something to the rules.

+

We’ll first see what the parser does during the execution. We’ll use +the following simple grammar as an example.

+
+%token A B C
+%%
+program: A B C
+
+

In the parser there is a stack called the semantic stack. The parser +pushes on it all the symbols coming from the scanner. This move is +called “shifting the symbols”.

+
+[ A B ] ← C   shift
+
+

And when any of the right side of a rule is equal to the end of the +stack, it is “interpreted”. When this happens, +the sequence of the right-hand side is replaced by the symbol of the left-hand +side.

+
+[ A B C ]
+    ↓         reduction
+[ program ]
+
+

This move is called “reduce A B C” to program". This term +is a little presumptuous, but in short it is like, +when you have enough number of tiles of haku and hatsu and chu respectively, +it becomes “Big three dragons” in Japanese Mahjong, +… this might be irrelevant.

+

And since program expresses the whole program, +if there’s only a program on the stack, it probably means the whole program is +found out. Therefore, if the input is just finished here, it is accepted.

+

Let’s try with a little more complicated grammar.

+
+%token IF E S THEN END
+%%
+program : if
+
+if      : IF expr THEN stmts END
+
+expr    : E
+
+stmts   : S
+        | stmts S
+
+

The input from the scanner is this.

+
+IF  E  THEN  S  S  S  END
+
+

The transitions of the semantic stack in this case are shown below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Stack Move
empty at first
IF shift IF
IF E shift E
IF expr reduce E to expr
IF expr THEN shift THEN
IF expr THEN S shift S
IF expr THEN stmts reduce S to stmts
IF expr THEN stmts S shift S
IF expr THEN stmts reduce stmts S to stmts
IF expr THEN stmts S shift S
IF expr THEN stmts reduce stmts S to stmts
IF expr THEN stmts END shift END
if reduce IF expr THEN stmts END to if
program reduce if to program
accept.
+

As the end of this section, there’s one thing to be cautious with. +a reduction does not always means decreasing the symbols. +If there’s a void rule, it’s possible that a symbol is generated out of “void”.

+

Action

+

Now, I’ll start to describe the important parts. +Whichever shifting or reducing, +doing several things only inside of the semantic stack is not meaningful. +Since our ultimate goal was building a syntax tree, +it cannot be sufficient without leading to it. +How does yacc do it for us? +The answer yacc made is that “we shall enable to hook the moment when the +parser performing a reduction.” The hooks are called actions of the parser. +An action can be written at the last of the rule as follows.

+
+program: A B C { /* Here is an action */ }
+
+

The part between { and } is the action. If you write like this, +at the moment reducing A B C to program this action will be executed. +Whatever you do as an action is free. +If it is a C code, almost all things can be written.

+

The value of a symbol

+

This is further more important but, +each symbol has “its value”. +Both terminal and nonterminal symbols do. +As for terminal symbols, since they come from the scanner, +their values are also given by the scanner. +For example, 1 or 9 or maybe 108 for a NUMBER symbol. +For an IDENTIFIER symbol, it might be "attr" or "name" or "sym". +Anything is fine. +Each symbol and its value are pushed together on the semantic stack. +The next figure shows the state just the moment S is shifted with its value.

+
+IF     expr    THEN    stmts   S
+value  value   value   value   value
+
+

According to the previous rule, stmts S can be reduced to stmts. +If an action is written at the rule, it would be executed, +but at that moment, the values of the symbols corresponding to the right-hand +side are passed to the action.

+
+IF    expr   THEN   stmts  S      /* Stack */
+v1    v2     v3     v4     v5
+                    ↓     ↓
+            stmts:  stmts  S      /* Rule */
+                    ↓     ↓
+                  { $1  +  $2; }  /* Action */
+
+

This way an action can take the value of each symbol corresponding to the +right-hand side of a rule through $1, $2, $3, … +yacc will rewrite the kinds of $1 and $2 to the notation to point to the stack. +However because it is written in C language it needs to handle, for instance, +types, but because it is tiresome, let’s assume their types are of int for the moment.

+

Next, instead it will push the symbol of the left-hand side, but because all +symbols have their values the left-hand side symbol must also have its value. +It is expressed as $$ in actions, the value of $$ when leaving an action +will be the value of the left-hand side symbol.

+
+IF    expr   THEN   stmts  S      /* the stack just before reducing */
+v1    v2     v3     v4     v5
+                    ↓     ↓
+            stmts:  stmts  S      /* the rule that the right-hand side matches the end */
+              ↑    ↓     ↓
+            { $$  = $1  +  $2; }  /* its action */
+
+
+IF    expr   THEN   stmts         /* the stack after reducing */
+v1    v2     v3     (v4+v5)
+
+

As the end of this section, this is just an extra. +The value of a symbol is sometimes called “semantic value”. +Therefore the stack to put them is the “semantic value stack”, +and it is called “semantic stack” for short.

+

yacc and types

+

It’s really cumbersome but without talking about types we cannot finish this +talk. What is the type of the value of a symbol? +To say the bottom line first, it will be the type named YYSTYPE. +This must be the abbreviation of either YY Stack TYPE or Semantic value TYPE. +And YYSTYPE is obviously the typedef of somewhat another type. +The type is the union defined with the instruction named %union in the definition part.

+

We have not written %union before but it did not cause an error. Why? +This is because yacc considerately process with the default value without asking. +The default value in C should naturally be int. +Therefore, YYSTYPE is int by default.

+

As for an example of a yacc book or a calculator, int can be used unchanged. +But in order to build a syntax tree, +we want to use structs and pointers and the other various things. +Therefore for instance, we use %union as follows.

+
+%union {
+    struct node {
+        int type;
+        struct node *left;
+        struct node *right;
+    } *node;
+    int num;
+    char *str;
+}
+
+

Because this is not for practical use, +the arbitrary names are used for types and members. +Notice that it is different from the ordinal C but there’s no semicolon at the +end of the %unicon block.

+

And, if this is written, it would look like the following in y.tab.c.

+
+typedef union {
+    struct node {
+        int type;
+        struct node *left;
+        struct node *right;
+    } *node;
+    int num;
+    char *str;
+} YYSTYPE;
+
+

And, as for the semantic stack,

+
+YYSTYPE yyvs[256];       /* the substance of the stack(yyvs = YY Value Stack) */
+YYSTYPE *yyvsp = yyvs;   /* the pointer to the end of the stack */
+
+

we can expect something like this. +Therefore, the values of the symbols appear in actions would be

+
+/* the action before processed by yacc */
+target: A B C { func($1, $2, $3); }
+
+/* after converted, its appearance in y.tab.c */
+{ func(yyvsp[-2], yyvsp[-1], yyvsp[0]); ;
+
+

naturally like this.

+

In this case, because the default value int is used, +it can be accessed just by referring to the stack. +If YYSTYPE is a union, it is necessary to also specify one of its members. +There are two ways to do that, one way is associating with each symbol, +another way is specifying every time.

+

Generally, the way of associating with each type is used. +By using %token for terminal symbols and +using %type for nonterminal symbols, +it is written as follows.

+
+%token<num> A B C    /* All of the values of A B C is of type int */
+%type<str> target    /* All of the values of target is of type char* */
+
+

On the other hand, if you’d like to specify everytime, +you can write a member name into next to $ as follows.

+
+%union { char *str; }
+%%
+target: { $<str>$ = "In short, this is like typecasting"; }
+
+

You’d better avoid using this method if possible.
+Defining a member for each symbol is basic.

+

Coupling the parser and the scanner together

+

After all, I’ve finished to talk all about this and that of the values inside the parser. +For the rest, I’ll talking about the connecting protocol with the scanner, +then the heart of this story will be all finished.

+

First, we’d like to make sure that I mentioned that the scanner was the yylex() function. +each (terminal) symbol itself is returned (as int) as a return value of the function. +Since the constants with the same names of symbols are defined (#define) by +yacc, we can write NUMBER for a NUMBER. +And its value is passed by putting it into a global variable named yylval. +This yylval is also of type YYSTYPE, +and the exactly same things as the parser can be said. +In other words, if it is defined in %union it would become a union. +But this time the member is not automatically selected, +its member name has to be manually written. +The very simple examples would look like the following.

+
+static int
+yylex()
+{
+    yylval.str = next_token();
+    return STRING;
+}
+
+

Figure 2 summarizes the relationships described by now. +I’d like you to check one by one. +yylval, $$, $1, $2 … +all of these variables that become the interfaces are of type YYSTYPE.

+
+

(yaccvars)
+Figure 2: Relationships among yacc related variables & functions

+
+

Embedded Action

+

An action is written at the last of a rule, is how it was explained. +However, actually it can be written in the middle of a rule.

+
+target: A B { puts("embedded action"); } C D
+
+

This is called “embedded action”.
+An embedded action is merely a syntactic sugar of the following definition:

+
+target: A B dummy C D
+
+dummy :     /* void rule */
+        {
+            puts("embedded action");
+        }
+
+

From this example, you might be able to tell everything including +when it is executed. +The value of a symbol can also be taken. +In other words, in this example, +the value of the embedded action will come out as $3.

+

Practical Topics

+

Conflicts

+

I’m not afraid of yacc anymore.

+

If you thought so, it is too naive. +Why everyone is afraid so much about yacc, +the reason is going to be revealed.

+

Up until now, I wrote not so carefully “when the right-hand side of the rule +matches the end of the stack”, +but what happens if there’s a rule like this:

+
+target  : A B C
+        | A B C
+
+

When the sequence of symbols A B C actually comes out, +it would be hard to determine which is the rule to match. +Such thing cannot be interpreted even by humans. +Therefore yacc also cannot understand this. +When yacc find out an odd grammar like this, +it would complain that a reduce/reduce conflict occurs. +It means multiple rules are possible to reduce at the same time.

+
+% yacc rrconf.y
+conflicts:  1 reduce/reduce
+
+

But usually, I think you won’t do such things except as an accident.
+But how about the next example? +The described symbol sequence is completely the same.

+
+target  : abc
+        | A bc
+
+abc     : A B C
+
+bc      :   B C
+
+

This is relatively possible. Especially when each part is complicatedly moved +while developing rules, it is often the case that this kind of rules are made +without noticing.

+

There’s also a similar pattern, as follows:

+
+target  : abc
+        | ab C
+
+abc     : A B C
+
+ab      : A B
+
+

When the symbol sequence A B C comes out, +it’s hard to determine whether +it should choose one abc or the combination of ab and C. +In this case, yacc will complain that a shift/reduce conflict occurs. +This means there’re both a shift-able rule and a reduce-able rule +at the same time.

+
+% yacc srconf.y
+conflicts:  1 shift/reduce
+
+

The famous example of shift/reduce conflicts is “the hanging else problem”. +For example, the if statement of C language causes this problem. +I’ll describe it by simplifying the case:

+
+stmt     : expr ';'
+         | if
+
+expr     : IDENTIFIER
+
+if       : IF '(' expr ')' stmt
+         | IF '(' expr ')' stmt  ELSE stmt
+
+

In this rule, +the expression is only IDENTIFIER (variable), +the substance of if is only one statement. +Now, what happens if the next program is parsed with this grammar?

+
+if (cond)
+    if (cond)
+        true_stmt;
+    else
+        false_stmt;
+
+

If it is written this way, we might feel like it’s quite obvious. +But actually, this can be interpreted as follows.

+
+if (cond) {
+    if (cond)
+        true_stmt;
+}
+else {
+    false_stmt;
+}
+
+

The question is +“between the two ifs, inside one or outside oue, +which is the one to which the else should be attached?”.

+

However shift/reduce conflicts are relatively less harmful than reduce/reduce +conflicts, because usually they can be solved by choosing shift. +Choosing shift is almost equivalent to “connecting the elements closer to each +other” and it is easy to match human instincts. +In fact, the hanging else can also be solved by shifting it. +Hence, the yacc follows this trend, +it choses shift by default when a shift/reduce conflict occurs.

+

Look-ahead

+

As an experiment, +I’d like you to process the next grammar with yacc.

+
+%token A B C
+%%
+target  : A B C   /* rule 1 */
+        | A B     /* rule 2 */
+
+

We can’t help expecting there should be a conflict. +At the time when it has read until A B, +the rule 1 would attempt to shift, +the rule 2 would attempt to reduce. +In other words, this should cause a shift/reduce conflict. However, ….

+
+% yacc conf.y
+%
+
+

It’s odd, there’s no conflict. Why?

+

In fact, the parser created with yacc can look ahead only one symbol. +Before actually doing shift or reduce, +it can decide what to do by peeking the next symbol.

+

Therefore, it is also considered for us when generating the parser, +if the rule can be determined by a single look-ahead, +conflicts would be avoided. +In the previous rules, for instance, if C comes right after A B, +only the rule 1 is possible and it would be chose (shift). +If the input has finished, the rule 2 would be chose (reduce).

+

Notice that the word “look-ahead” has two meanings: +one thing is the look-ahead while processing *.y with yacc. +The other thing is the look-ahead while actually executing the generated parser. +The look-ahead during the execution is not so difficult, +but the look-ahead of yacc itself is pretty complicated. +That’s because +it needs to predict all possible input patterns and decides its behaviors +from only the grammar rules.

+

However, because “all possible” is actually impossible, +it handles “most of” patterns. +How broad range over all patterns it can cover up shows +the strength of a look-ahead algorithm. +The look-ahead algorithm that yacc uses when processing grammar files is +LALR, which is relatively powerful among +currently existing algorithms to resolve conflicts.

+

A lot things have been introduced, +but you don’t have to so worry because what to do in this book is only reading +and not writing. What I wanted to explain here is not the look-ahead of grammars +but the look-ahead during executions.

+

Operator Precedence

+

Since abstract talks have lasted for long, I’ll talk more concretely. +Let’s try to define the rules for infix operators such as + or *. +There are also established tactics for this, we’d better tamely follow it. +Something like a calculator for arithmetic operations is defined below:

+
+expr    : expr '+' expr
+        | expr '-' expr
+        | expr '*' expr
+        | expr '/' expr
+        | primary
+
+primary : NUMBER
+        | '(' expr ')'
+
+

primary is the smallest grammar unit. +The point is that expr between parentheses becomes a primary.

+

Then, if this grammar is written to an arbitrary file and compiled, +the result would be this.

+
+% yacc infix.y
+16 shift/reduce conflicts
+
+

They conflict aggressively. Thinking for 5 minutes is enough to see that +this rule causes a problem in the following and simialr cases:

+
+1 - 1 - 1
+
+

This can be interpreted in both of the next two ways.

+
+(1 - 1) - 1
+1 - (1 - 1)
+
+

The former is natural as an numerical expression. +But what yacc does is the process of their appearances, +there does not contain any meanings. +As for the things such as the meaning the - symbol has, +it is absolutely not considered at all. +In order to correctly reflect a human intention, +we have to specify what we want step by step.

+

Then, what we can do is +writing this in the definition part.

+
+%left '+' '-'
+%left '*' '/'
+
+

These instructions specifies both the precedence and the associativity +at the same time.
+I’ll explain them in order.

+

I think that the term “precedence” often appears when talking about the grammar +of a programming language. +Describing it logically is complicated, so if I put it instinctively, +it is about to which operator parentheses are attached +in the following and similar cases.

+
+1 + 2 * 3
+
+

If * has higher precedence, it would be this.

+
+1 + (2 * 3)
+
+

If + has higher precedence, it would be this.

+
+(1 + 2) * 3
+
+

As shown above, resolving shift/reduce conflicts +by defining the stronger ones and weaker ones among operators +is operator precedence.

+

However, if the operators has the same precedence, how can it be resolved? +Like this, for instance,

+
+1 - 2 - 3
+
+

because both operators are -, their precedences are the completely same. +In this case, it is resolved by using the associativity. +Associativity has three types: left right nonassoc, +they will be interpreted as follows:

+ + + + + + + + + + + + + + + + + +
Associativity Interpretation
left (left-associative) (1 – 2) – 3
right (right-associative) 1 – (2 – 3)
nonassoc (non-associative) parse error
+

Most of the operators for numerical expressions are left-associative. +The right-associative is used mainly for = of assignment and not of denial.

+
+a = b = 1    # (a = (b = 1))
+not not a    # (not (not a))
+
+

The representatives of non-associative are probably the comparison operators.

+
+a == b == c   # parse error
+a <= b <= c   # parse error
+
+

However, this is not the only possibility. +In Python, for instance, comparisons between three terms are possible.

+

Then, the previous instructions named %left %right %noassoc are used to +specify the associativities of their names. +And, precedence is specified as the order of the instructions. +The lower the operators written, the higher the precedences they have. +If they are written in the same line, they have the same level of precedence.

+
+%left  '+' '-'    /* left-associative and third precedence  */
+%left  '*' '/'    /* left-associative and second precedence */
+%right '!'        /* right-associative and first precedence */
+
+ + + +
+ + From 82abf742e19cd98b1de709c717150433e035acd0 Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 19 Aug 2013 03:55:33 +0900 Subject: [PATCH 009/121] remove the generated files under ./htmls --- htmls/anyeval.html | 675 -------------- htmls/class.html | 1422 ----------------------------- htmls/contextual.html | 1755 ----------------------------------- htmls/css/styles.css | 173 ---- htmls/evaluator.html | 1236 ------------------------- htmls/fin.html | 364 -------- htmls/gc.html | 1652 --------------------------------- htmls/index.html | 129 --- htmls/intro.html | 1021 --------------------- htmls/iterator.html | 1094 ---------------------- htmls/load.html | 906 ------------------ htmls/method.html | 921 ------------------- htmls/minimum.html | 1251 ------------------------- htmls/module.html | 1560 ------------------------------- htmls/name.html | 591 ------------ htmls/object.html | 1011 --------------------- htmls/parser.html | 2014 ----------------------------------------- htmls/preface.html | 247 ----- htmls/security.html | 208 ----- htmls/spec.html | 1675 ---------------------------------- htmls/syntree.html | 1615 --------------------------------- htmls/thread.html | 1153 ----------------------- htmls/variable.html | 589 ------------ htmls/yacc.html | 1013 --------------------- 24 files changed, 24275 deletions(-) delete mode 100644 htmls/anyeval.html delete mode 100644 htmls/class.html delete mode 100644 htmls/contextual.html delete mode 100644 htmls/css/styles.css delete mode 100644 htmls/evaluator.html delete mode 100644 htmls/fin.html delete mode 100644 htmls/gc.html delete mode 100644 htmls/index.html delete mode 100644 htmls/intro.html delete mode 100644 htmls/iterator.html delete mode 100644 htmls/load.html delete mode 100644 htmls/method.html delete mode 100644 htmls/minimum.html delete mode 100644 htmls/module.html delete mode 100644 htmls/name.html delete mode 100644 htmls/object.html delete mode 100644 htmls/parser.html delete mode 100644 htmls/preface.html delete mode 100644 htmls/security.html delete mode 100644 htmls/spec.html delete mode 100644 htmls/syntree.html delete mode 100644 htmls/thread.html delete mode 100644 htmls/variable.html delete mode 100644 htmls/yacc.html diff --git a/htmls/anyeval.html b/htmls/anyeval.html deleted file mode 100644 index e7998da..0000000 --- a/htmls/anyeval.html +++ /dev/null @@ -1,675 +0,0 @@ - - - - - Chapter 17: Dynamic evaluation | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 17: Dynamic evaluation

-

Overview

-

I have already finished to describe about the mechanism of the evaluator by the -previous chapter. -In this chapter, by including the parser in addition to it, -let’s examine the big picture as “the evaluator in a broad sense”. -There are three targets: eval, Module#module_eval and -Object#instance_eval.

-

eval

-

I’ve already described about eval, -but I’ll introduce more tiny things about it here.

-

By using eval, you can compile and evaluate a string at runtime in the place. -Its return value is the value of the last expression of the program.

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

You can also refer to a variable in its scope from inside of a string to eval.

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

Readers who have been reading until here cannot simply read and pass over the -word “its scope”. For instance, you are curious about how is its “scope” of -constants, aren’t you? I am. To put the bottom line first, basically you -can think it directly inherits the environment of outside of eval.

-

And you can also define methods and define classes.

-
-def a
-  eval('class C;  def test() puts("ok") end   end')
-end
-
-a()          # define class C and C#test
-C.new.test   # shows ok
-
-

Moreover, as mentioned a little in the previous chapter, -when you pass a Proc as the second argument, the string can be evaluated in -its environment.

-
-def new_env
-  n = 5
-  Proc.new { nil }   # turn the environment of this method into an object and return it
-end
-
-p eval('n * 3', new_env())   # 15
-
-

module_eval and instance_eval

-

When a Proc is passed as the second argument of eval, the evaluations can be -done in its environment. module_eval and instance_eval is its limited (or -shortcut) version. With module_eval, you can evaluate in an environment that -is as if in a module statement or a class statement.

-
-lvar = "toplevel lvar"   # a local variable to confirm this scope
-
-module M
-end
-M.module_eval(<<'EOS')   # a suitable situation to use here-document
-    p lvar   # referable
-    p self   # shows M
-    def ok   # define M#ok
-      puts 'ok'
-    end
-EOS
-
-

With instance_eval, you can evaluate in an environment whose self of the -singleton class statement is the object.

-
-lvar = "toplevel lvar"   # a local variable to confirm this scope
-
-obj = Object.new
-obj.instance_eval(<<'EOS')
-    p lvar   # referable
-    p self   # shows #<Object:0x40274f5c>
-    def ok   # define obj.ok
-      puts 'ok'
-    end
-EOS
-
-

Additionally, these module_eval and instance_eval can also be used as -iterators, a block is evaluated in each environment in that case. -For instance,

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

Like this.

-

However, between the case when using a string and the case when using a block, -the behavior around local variables is different each other. -For example, when creating a block in the a method then doing instance_eval -it in the b method, the block would refer to the local variables of a. -When creating a string in the a method then doing instance_eval it in the -b method, from inside of the string, it would refer to the local variables of b. -The scope of local variables is decided “at compile time”, -the consequence differs because a string is compiled every time but a block is -compiled when loading files.

-

eval

-

eval()

-

The eval of Ruby branches many times based on the presence and absence of the -parameters. Let’s assume the form of call is limited to the below:

-
-eval(prog_string, some_block)
-
-

Then, since this makes the actual interface function rb_f_eval() almost -meaningless, we’ll start with the function eval() which is one step lower. -The function prototype of eval() is:

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

scope is the Proc of the second parameter. -file and line is the file name and line number of where a string to eval -is supposed to be located. Then, let’s see the content:

-

eval() (simplified)

- -
-4984  static VALUE
-4985  eval(self, src, scope, file, line)
-4986      VALUE self, src, scope;
-4987      char *file;
-4988      int line;
-4989  {
-4990      struct BLOCK *data = NULL;
-4991      volatile VALUE result = Qnil;
-4992      struct SCOPE * volatile old_scope;
-4993      struct BLOCK * volatile old_block;
-4994      struct RVarmap * volatile old_dyna_vars;
-4995      VALUE volatile old_cref;
-4996      int volatile old_vmode;
-4997      volatile VALUE old_wrapper;
-4998      struct FRAME frame;
-4999      NODE *nodesave = ruby_current_node;
-5000      volatile int iter = ruby_frame->iter;
-5001      int state;
-5002
-5003      if (!NIL_P(scope)) {  /* always true now */
-5009          Data_Get_Struct(scope, struct BLOCK, data);
-5010          /* push BLOCK from data */
-5011          frame = data->frame;
-5012          frame.tmp = ruby_frame; /* to prevent from GC */
-5013          ruby_frame = &(frame);
-5014          old_scope = ruby_scope;
-5015          ruby_scope = data->scope;
-5016          old_block = ruby_block;
-5017          ruby_block = data->prev;
-5018          old_dyna_vars = ruby_dyna_vars;
-5019          ruby_dyna_vars = data->dyna_vars;
-5020          old_vmode = scope_vmode;
-5021          scope_vmode = data->vmode;
-5022          old_cref = (VALUE)ruby_cref;
-5023          ruby_cref = (NODE*)ruby_frame->cbase;
-5024          old_wrapper = ruby_wrapper;
-5025          ruby_wrapper = data->wrapper;
-5032          self = data->self;
-5033          ruby_frame->iter = data->iter;
-5034      }
-5045      PUSH_CLASS();
-5046      ruby_class = ruby_cbase;  /* == ruby_frame->cbase */
-5047
-5048      ruby_in_eval++;
-5049      if (TYPE(ruby_class) == T_ICLASS) {
-5050          ruby_class = RBASIC(ruby_class)->klass;
-5051      }
-5052      PUSH_TAG(PROT_NONE);
-5053      if ((state = EXEC_TAG()) == 0) {
-5054          NODE *node;
-5055
-5056          result = ruby_errinfo;
-5057          ruby_errinfo = Qnil;
-5058          node = compile(src, file, line);
-5059          if (ruby_nerrs > 0) {
-5060              compile_error(0);
-5061          }
-5062          if (!NIL_P(result)) ruby_errinfo = result;
-5063          result = eval_node(self, node);
-5064      }
-5065      POP_TAG();
-5066      POP_CLASS();
-5067      ruby_in_eval--;
-5068      if (!NIL_P(scope)) {  /* always true now */
-5069          int dont_recycle = ruby_scope->flags & SCOPE_DONT_RECYCLE;
-5070
-5071          ruby_wrapper = old_wrapper;
-5072          ruby_cref  = (NODE*)old_cref;
-5073          ruby_frame = frame.tmp;
-5074          ruby_scope = old_scope;
-5075          ruby_block = old_block;
-5076          ruby_dyna_vars = old_dyna_vars;
-5077          data->vmode = scope_vmode; /* save the modification of the visibility scope */
-5078          scope_vmode = old_vmode;
-5079          if (dont_recycle) {
-                  /* ……copy SCOPE BLOCK VARS…… */
-5097          }
-5098      }
-5104      if (state) {
-5105          if (state == TAG_RAISE) {
-                  /* ……prepare an exception object…… */
-5121              rb_exc_raise(ruby_errinfo);
-5122          }
-5123          JUMP_TAG(state);
-5124      }
-5125
-5126      return result;
-5127  }
-
-(eval.c)
-
-

If this function is shown without any preamble, you probably feel “oww!”. -But we’ve defeated many functions of eval.c until here, -so this is not enough to be an enemy of us. -This function is just continuously saving/restoring the stacks. -The points we need to care about are only the below three:

-
    -
  • unusually FRAME is also replaced (not copied and pushed)
  • -
  • ruby_cref is substituted (?) by ruby_frame->cbase
  • -
  • only scope_vmode is not simply restored but influences data.
  • -
-

And the main parts are the compile() and eval_node() located around the -middle. Though it’s possible that eval_node() has already been forgotten, -it is the function to start the evaluation of the parameter node. -It was also used in ruby_run().

-

Here is compile().

-

compile()

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

ruby_nerrs is the variable incremented in yyerror(). -In other words, if this variable is non-zero, it indicates more than one parse -error happened. And, rb_compile_string() was already discussed in Part 2. -It was a function to compile a Ruby string into a syntax tree.

-

One thing becomes a problem here is local variable. -As we’ve seen in Chapter 12: Syntax tree construction, -local variables are managed by using lvtbl. -However, since a SCOPE (and possibly also VARS) already exists, -we need to parse in the way of writing over and adding to it. -This is in fact the heart of eval(), -and is the worst difficult part. -Let’s go back to parse.y again and complete this investigation.

-

top_local

-

I’ve mentioned that the functions named local_push() local_pop() are used -when pushing struct local_vars, which is the management table of local -variables, -but actually there’s one more pair of functions to push the management table. -It is the pair of top_local_init() and top_local_setup(). -They are called in this sort of way.

-

▼ How top_local_init() is called

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

Of course, in actuality various other things are also done, -but all of them are cut here because it’s not important. -And this is the content of it:

-

top_local_init()

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

This means that local_tbl is copied from ruby_scope to lvtbl. -As for block local variables, since it’s better to see them all at once later, -we’ll focus on ordinary local variables for the time being. -Next, here is top_local_setup().

-

top_local_setup()

- -
-5291  static void
-5292  top_local_setup()
-5293  {
-5294      int len = lvtbl->cnt;  /* the number of local variables after parsing */
-5295      int i;                 /* the number of local varaibles before parsing */
-5296
-5297      if (len > 0) {
-5298          i = ruby_scope->local_tbl ? ruby_scope->local_tbl[0] : 0;
-5299
-5300          if (i < len) {
-5301              if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
-5302                  VALUE *vars = ALLOC_N(VALUE, len+1);
-5303                  if (ruby_scope->local_vars) {
-5304                      *vars++ = ruby_scope->local_vars[-1];
-5305                      MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
-5306                      rb_mem_clear(vars+i, len-i);
-5307                  }
-5308                  else {
-5309                      *vars++ = 0;
-5310                      rb_mem_clear(vars, len);
-5311                  }
-5312                  ruby_scope->local_vars = vars;
-5313                  ruby_scope->flags |= SCOPE_MALLOC;
-5314              }
-5315              else {
-5316                  VALUE *vars = ruby_scope->local_vars-1;
-5317                  REALLOC_N(vars, VALUE, len+1);
-5318                  ruby_scope->local_vars = vars+1;
-5319                  rb_mem_clear(ruby_scope->local_vars+i, len-i);
-5320              }
-5321              if (ruby_scope->local_tbl &&
-                      ruby_scope->local_vars[-1] == 0) {
-5322                  free(ruby_scope->local_tbl);
-5323              }
-5324              ruby_scope->local_vars[-1] = 0;  /* NODE is not necessary anymore */
-5325              ruby_scope->local_tbl = local_tbl();
-5326          }
-5327      }
-5328      local_pop();
-5329  }
-
-(parse.y)
-
-

Since local_vars can be either in the stack or in the heap, it makes the code -complex to some extent. However, this is just updating local_tbl and -local_vars of ruby_scope. (When SCOPE_MALLOC was set, local_vars was -allocated by malloc()). And here, because there’s no meaning of using alloca(), -it is forced to change its allocation method to malloc.

-

Block Local Variable

-

By the way, how about block local variables? -To think about this, we have to go back to the entry point of the parser first, -it is yycompile().

-

▼ setting ruby_dyna_vars aside

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

This looks like a mere save-restore, but the point is that this does not clear -the ruby_dyna_vars. This means that also in the parser it directly adds -elements to the link of RVarmap created in the evaluator.

-

However, according to the previous description, the structure of -ruby_dyna_vars differs between the parser and the evalutor. -How does it deal with the difference in the way of attaching the header -(RVarmap whose id=0)?

-

What is helpful here is the “1” of local_push(1) in top_local_init(). -When the argument of local_push() becomes true, -it does not attach the first header of ruby_dyna_vars. -It means, it would look like Figure 1. Now, it is assured that -we can refer to the block local variables of the outside scope -from inside of a string to eval.

-
-

(dynavars)
-Figure 1: ruby_dyna_vars inside eval

-
    -
  • パーサで追加 added in the parser
  • -
  • 評価機で作成 created in the evaluator -
- -

Well, it’s sure we can refer to, -but didn’t you say that ruby_dyna_vars is entirely freed in the parser? -What can we do if the link created at the evaluator will be freed? -… -I’d like the readers who noticed this to be relieved by reading the next part.

-

yycompile() − freeing ruby_dyna_vars

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

It is designed so that the loop would stop -when it reaches the link created at the evaluator (vars).

-

instance_eval

-

The Whole Picture

-

The substance of Module#module_eval is rb_mod_module_eval(), -and the substance of Object#instance_eval is rb_obj_instance_eval().

-

rb_mod_module_eval() rb_obj_instance_eval()

- -
-5316  VALUE
-5317  rb_mod_module_eval(argc, argv, mod)
-5318      int argc;
-5319      VALUE *argv;
-5320      VALUE mod;
-5321  {
-5322      return specific_eval(argc, argv, mod, mod);
-5323  }
-
-5298  VALUE
-5299  rb_obj_instance_eval(argc, argv, self)
-5300      int argc;
-5301      VALUE *argv;
-5302      VALUE self;
-5303  {
-5304      VALUE klass;
-5305
-5306      if (rb_special_const_p(self)) {
-5307          klass = Qnil;
-5308      }
-5309      else {
-5310          klass = rb_singleton_class(self);
-5311      }
-5312
-5313      return specific_eval(argc, argv, klass, self);
-5314  }
-
-(eval.c)
-
-

These two methods have a common part as “a method to replace self with class”, -that part is defined as specific_eval(). -Figure 2 shows it and also what will be described. -What with parentheses are calls by function pointers.

-

-

(speceval)
-Figure 2: Call Graph

-

-

Whichever instance_eval or module_eval, -it can accept both a block and a string, -thus it branches for each particular process to yield and eval respectively. -However, most of them are also common again, -this part is extracted as exec_under().

-

But for those who reading, one have to simultaneously face at 2 times 2 = 4 ways, -it is not a good plan. Therefore, here we assume only the case when

-
    -
  1. it is an instance_eval
  2. -
  3. which takes a string as its argument
  4. -
-

. And extracting all functions under rb_obj_instance_eval() in-line, -folding constants, we’ll read the result.

-

After Absorbed

-

After all, -it becomes very comprehensible in comparison to the one before being absorbed.

-

specific_eval()instance_eval, eval, string

- -
-static VALUE
-instance_eval_string(self, src, file, line)
-    VALUE self, src;
-    const char *file;
-    int line;
-{
-    VALUE sclass;
-    VALUE result;
-    int state;
-    int mode;
-
-    sclass = rb_singleton_class(self);
-
-    PUSH_CLASS();
-    ruby_class = sclass;
-    PUSH_FRAME();
-    ruby_frame->self       = ruby_frame->prev->self;
-    ruby_frame->last_func  = ruby_frame->prev->last_func;
-    ruby_frame->last_class = ruby_frame->prev->last_class;
-    ruby_frame->argc       = ruby_frame->prev->argc;
-    ruby_frame->argv       = ruby_frame->prev->argv;
-    if (ruby_frame->cbase != sclass) {
-        ruby_frame->cbase = rb_node_newnode(NODE_CREF, sclass, 0,
-                                            ruby_frame->cbase);
-    }
-    PUSH_CREF(sclass);
-
-    mode = scope_vmode;
-    SCOPE_SET(SCOPE_PUBLIC);
-    PUSH_TAG(PROT_NONE);
-    if ((state = EXEC_TAG()) == 0) {
-        result = eval(self, src, Qnil, file, line);
-    }
-    POP_TAG();
-    SCOPE_SET(mode);
-
-    POP_CREF();
-    POP_FRAME();
-    POP_CLASS();
-    if (state) JUMP_TAG(state);
-
-    return result;
-}
-
-

It seems that this pushes the singleton class of the object to CLASS and -CREF and ruby_frame->cbase. -The main process is one-shot of eval(). -It is unusual that things such as initializing FRAME by a struct-copy are -missing, but this is also not create so much difference.

-

Before being absorbed

-

Though the author said it becomes more friendly to read, -it’s possible it has been already simple since it was not absorbed, -let’s check where is simplified in comparison to the before-absorbed one.

-

The first one is specific_eval(). Since this function is to share the code of -the interface to Ruby, almost all parts of it is to parse the parameters. -Here is the result of cutting them all.

-

specific_eval() (simplified)

- -
-5258  static VALUE
-5259  specific_eval(argc, argv, klass, self)
-5260      int argc;
-5261      VALUE *argv;
-5262      VALUE klass, self;
-5263  {
-5264      if (rb_block_given_p()) {
-
-5268          return yield_under(klass, self);
-5269      }
-5270      else {
-
-5294          return eval_under(klass, self, argv[0], file, line);
-5295      }
-5296  }
-
-(eval.c)
-
-

As you can see, this is perfectly branches in two ways based on whether there’s -a block or not, and each route would never influence the other. -Therefore, when reading, we should read one by one. -To begin with, the absorbed version is enhanced in this point.

-

And file and line are irrelevant when reading yield_under(), -thus in the case when the route of yield is absorbed by the main body, -it might become obvious that we don’t have to think about the parse of these -parameters at all.

-

Next, we’ll look at eval_under() and eval_under_i().

-

eval_under()

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

In this function, in order to make its arguments single, -it stores them into the args array and passes it. -We can imagine that this args exists as a temporary container to pass from -eval_under() to eval_under_i(), -but not sure that it is truly so. -It’s possible that args is modified inside evec_under().

-

As a way to share a code, this is a very right way to do. -But for those who read it, this kind of indirect passing is incomprehensible. -Particularly, because there are extra castings for file and line to fool -the compiler, it is hard to imagine what were their actual types. -The parts around this entirely disappeared in the absorbed version, -so you don’t have to worry about getting lost.

-

However, it’s too much to say that absorbing and extracting always makes things -easier to understand. -For example, when calling exec_under(), under is passed as both the second -and third arguments, but is it all right if the exec_under() side extracts -the both parameter variables into under? -That is to say, the second and third arguments of exec_under() are, in fact, -indicating CLASS and CREF that should be pushed. -CLASS and CREF are “different things”, -it might be better to use different variables. -Also in the previous absorbed version, for only this point,

-
-VALUE sclass = .....;
-VALUE cbase = sclass;
-
-

I thought that I would write this way, -but also thought it could give the strange impression -if abruptly only these variables are left, -thus it was extracted as sclass. -It means that this is only because of the flow of the texts.

-

By now, so many times, I’ve extracted arguments and functions, -and for each time I repeatedly explained the reason to extract. -They are

-
    -
  • there are only a few possible patterns
  • -
  • the behavior can slightly change
  • -
-

Definitely, I’m not saying -“In whatever ways extracting various things always makes things simpler”.

-

In whatever case, what of the first priority is the comprehensibility for -ourself and not keep complying the methodology. -When extracting makes things simpler, extract it. -When we feel that not extracting or conversely bundling as a procedure makes -things easier to understand, let us do it. -As for ruby, I often extracted them because the original is written properly, -but if a source code was written by a poor programmer, -aggressively bundling to functions should often become a good choice.

- - - -
- - diff --git a/htmls/class.html b/htmls/class.html deleted file mode 100644 index 14f0036..0000000 --- a/htmls/class.html +++ /dev/null @@ -1,1422 +0,0 @@ - - - - - Classes and modules | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Vincent ISAMBART

-

Chapter 4: Classes and modules

-

In this chapter, we’ll see the details of the data structures created -for classes and modules.

-

Classes and methods definition

-

First, I’d like to have a look at how Ruby classes are defined at the -C level. This chapter investigates almost only particular -cases, so I’d like you to know first the way used most often.

-

The main API to define classes and modules consists of the following 6 -functions:

-
    -
  • rb_define_class()
  • -
  • rb_define_class_under()
  • -
  • rb_define_module()
  • -
  • rb_define_module_under()
  • -
  • rb_define_method()
  • -
  • rb_define_singleton_method()
  • -
-

There are a few other versions of these functions, but the extension -libraries and even most of the core library is defined using just this -API. I’ll introduce to you these functions one by one.

-

Class definition

-

rb_define_class() defines a class at the top-level. Let’s take the -Ruby array class, Array, as an example.

-

Array class definition -

-  19  VALUE rb_cArray;

-

1809 void -1810 Init_Array() -1811 { -1812 rb_cArray = rb_define_class(“Array”, rb_cObject);

-

(array.c) -

-

rb_cObject and rb_cArray correspond respectively to Object and -Array at the Ruby level. The added prefix rb shows that it belongs -to ruby and the c that it is a class object. These naming rules -are used everywhere in ruby.

-

This call to rb_define_class() defines a class called Array, which -inherits from Object. At the same time as rb_define_class() creates -the class object, it also defines the constant. That means that after this -you can already access Array from a Ruby program. It corresponds to -the following Ruby program:

-
-class Array < Object
-
-

I’d like you to note the fact that there is no end. It was -written like this on purpose. It is because with rb_define_class() -the body of the class has not been executed.

-

Nested class definition

-

After that, there’s rb_define_class_under(). This function defines a -class nested in an other class or module. This time the example is -what is returned by stat(2), File::Stat.

-

▼ Definition of File::Stat -

-  78  VALUE rb_cFile;
-  80  static VALUE rb_cStat;

-

2581 rb_cFile = rb_define_class(“File”, rb_cIO); -2674 rb_cStat = rb_define_class_under(rb_cFile, “Stat”, rb_cObject);

-

(file.c) -

-

This code corresponds to the following Ruby program;

-
-class File < IO
-  class Stat < Object
-
-

This time again I omitted the end on purpose.

-

Module definition

-

rb_define_module() is simple so let’s end this quickly.

-

▼ Definition of Enumerable -

-  17  VALUE rb_mEnumerable;

-492 rb_mEnumerable = rb_define_module(“Enumerable”); -

(enum.c) -

-

The m in the beginning of rb_mEnumerable is similar to the c for -classes: it shows that it is a module. The corresponding Ruby program -is:

-
-module Enumerable
-
-

rb_define_module_under() is not used much so we’ll skip it.

-

Method definition

-

This time the function is the one for defining methods, -rb_define_method(). It’s used very often. We’ll take once again an -example from Array.

-

▼ Definition of Array#to_s -

-1818  rb_define_method(rb_cArray, “to_s”, rb_ary_to_s, 0);

-

(array.c) -

-

With this the to_s method is defined in Array. The method body is -given by a function pointer (rb_ary_to_s). The fourth parameter is -the number of parameters taken by the method. As to_s does not take -any parameters, it’s 0. If we write the corresponding Ruby program, -we’ll have this:

-
-class Array < Object
-  def to_s
-    # content of rb_ary_to_s()
-  end
-end
-
-

Of course the class part is not included in rb_define_method() and -only the def part is accurate. But if there is no class part, it -will look like the method is defined like a function, so I also wrote -the enclosing class part.

-

One more example, this time taking a parameter:

-

▼ Definition of Array#concat -

-1835  rb_define_method(rb_cArray, “concat”, rb_ary_concat, 1);

-

(array.c) -

-

The class for the definition is rb_cArray -(Array), the method name is concat, its body -is rb_ary_concat() and the number of parameters is 1. It -corresponds to writing the corresponding Ruby program:

-
-class Array < Object
-  def concat( str )
-    # content of rb_ary_concat()
-  end
-end
-
-

Singleton methods definition

-

We can define methods that are specific to a single object instance. -They are called singleton methods. As I used File.unlink as -an example in chapter 1 “Ruby language minimum”, I first wanted to -show it here, but for a particular reason we’ll look at File.link -instead.

-

▼ Definition of File.link -

-2624  rb_define_singleton_method(rb_cFile, “link”, rb_file_s_link, 2);

-

(file.c) -

-

It’s used like rb_define_method(). The only difference is that here -the first parameter is just the object where the method is -defined. In this case, it’s defined in rb_cFile.

-

Entry point

-

Being able to make definitions like before is great, but where -are these functions called from, and by what means are they executed? -These definitions are grouped in functions named Init_xxxx(). For -instance, for Array a function Init_Array() like this has been -made:

-

Init_Array -

-1809  void
-1810  Init_Array()
-1811  {
-1812      rb_cArray  = rb_define_class(“Array”, rb_cObject);
-1813      rb_include_module(rb_cArray, rb_mEnumerable);
-1814
-1815      rb_define_singleton_method(rb_cArray, “allocate”,
-                                     rb_ary_s_alloc, 0);
-1816      rb_define_singleton_method(rb_cArray, “[]”, rb_ary_s_create, -1);
-1817      rb_define_method(rb_cArray, “initialize”, rb_ary_initialize, -1);
-1818      rb_define_method(rb_cArray, “to_s”, rb_ary_to_s, 0);
-1819      rb_define_method(rb_cArray, “inspect”, rb_ary_inspect, 0);
-1820      rb_define_method(rb_cArray, “to_a”, rb_ary_to_a, 0);
-1821      rb_define_method(rb_cArray, “to_ary”, rb_ary_to_a, 0);
-1822      rb_define_method(rb_cArray, “frozen?”,  rb_ary_frozen_p, 0);

-

(array.c) -

-

The Init for the built-in functions are explicitly called during -the startup of ruby. This is done in inits.c.

-

rb_call_inits() -

-  47  void
-  48  rb_call_inits()
-  49  {
-  50      Init_sym();
-  51      Init_var_tables();
-  52      Init_Object();
-  53      Init_Comparable();
-  54      Init_Enumerable();
-  55      Init_Precision();
-  56      Init_eval();
-  57      Init_String();
-  58      Init_Exception();
-  59      Init_Thread();
-  60      Init_Numeric();
-  61      Init_Bignum();
-  62      Init_Array();

-

(inits.c) -

-

This way, Init_Array() is called properly.

-

That explains it for the built-in libraries, but what about extension -libraries? In fact, for extension libraries the convention is the -same. Take the following code:

-
-require "myextension"
-
-

With this, if the loaded extension library is myextension.so, at -load time, the (extern) function named Init_myextension() is -called. How they are called is beyond the scope of this chapter. For -that, you should read chapter 18, “Load”. Here we’ll just end this -with an example of Init.

-

The following example is from stringio, an extension library -provided with ruby, that is to say not from a built-in library.

-

Init_stringio() (beginning) -

- 895  void
- 896  Init_stringio()
- 897  {
- 898      VALUE StringIO = rb_define_class(“StringIO”, rb_cData);
- 899      rb_define_singleton_method(StringIO, “allocate”,
-                                     strio_s_allocate, 0);
- 900      rb_define_singleton_method(StringIO, “open”, strio_s_open, -1);
- 901      rb_define_method(StringIO, “initialize”, strio_initialize, -1);
- 902      rb_enable_super(StringIO, “initialize”);
- 903      rb_define_method(StringIO, “become”, strio_become, 1);
- 904      rb_define_method(StringIO, “reopen”, strio_reopen, -1);

-

(ext/stringio/stringio.c) -

-

Singleton classes

-

rb_define_singleton_method()

-

You should now be able to more or less understand how normal methods are -defined. Somehow making the body of the method, then registering it -in m_tbl will do. But what about singleton methods? We’ll now look -into the way singleton methods are defined.

-

rb_define_singleton_method() -

- 721  void
- 722  rb_define_singleton_method(obj, name, func, argc)
- 723      VALUE obj;
- 724      const char name;
- 725      VALUE (func)();
- 726      int argc;
- 727  {
- 728      rb_define_method(rb_singleton_class(obj), name, func, argc);
- 729  }

-

(class.c) -

-

As I explained, rb_define_method() is a function used to define -normal methods, so the difference from normal methods is only -rb_singleton_class(). But what on earth are singleton classes?

-

In brief, singleton classes are virtual classes that are only used -to execute singleton methods. Singleton methods are functions defined -in singleton classes. Classes themselves are in the first place (in a -way) the “implementation” to link objects and methods, but singleton -classes are even more on the implementation side. In the Ruby language -way, they are not formally included, and don’t appear much at the Ruby -level.

-

rb_singleton_class()

-

Well, let’s confirm what the singleton classes are made of. It’s too -simple to just show you the code of a function each time so this time -I’ll use a new weapon, a call graph.

-
-rb_define_singleton_method
-    rb_define_method
-    rb_singleton_class
-        SPECIAL_SINGLETON
-        rb_make_metaclass
-            rb_class_boot
-            rb_singleton_class_attached
-
-

Call graphs are graphs showing calling relationships among functions -(or more generally procedures). The call graphs showing all the calls -written in the source code are called static call graphs. The ones -expressing only the calls done during an execution are called dynamic -call graphs.

-

This diagram is a static call graph and the indentation expresses -which function calls which one. For instance, -rb_define_singleton_method() calls rb_define_method() and -rb_singleton_class(). And this rb_singleton_class() itself calls -SPECIAL_SINGLETON() and rb_make_metaclass().

-

Let’s go back to the code. When looking at the call graph, you can see -that the calls made by rb_singleton_class() go very deep. Until now -all call levels were shallow, so we could simply look at the functions -without getting too lost. But at this depth, I easily forget -what is going on in the code. That’s why in those situations I check -the call graph to have a better understanding. This time, we’ll decode -in parallel what the procedures below rb_singleton_class() do. The -two points to look out for are the following ones:

-
    -
  • What exactly are singleton classes?
  • -
  • What is the purpose of singleton classes?
  • -
-

Normal classes and singleton classes

-

Singleton classes are special classes: they’re basically the same as -normal classes, but there are a few differences. We can say that -finding these differences is explaining concretely singleton classes.

-

What should we do to find them? We should find the differences between -the function creating normal classes and the one creating singleton -classes. For this, we have to find the function for creating normal -classes. That is as normal classes can be defined by -rb_define_class(), it must call in a way or another a function to -create normal classes. For the moment, we’ll not look at the content -of rb_define_class() itself. I have some reasons to be interested in -something that’s deeper. That’s why we will first look at the call -graph of rb_define_class().

-
-rb_define_class
-    rb_class_inherited
-    rb_define_class_id
-        rb_class_new
-            rb_class_boot
-        rb_make_metaclass
-            rb_class_boot
-            rb_singleton_class_attached
-
-

I’m interested by rb_class_new(). Doesn’t this name means it creates -a new class? Let’s confirm that.

-

rb_class_new() -

-  37  VALUE
-  38  rb_class_new(super)
-  39      VALUE super;
-  40  {
-  41      Check_Type(super, T_CLASS);
-  42      if (super == rb_cClass) {
-  43          rb_raise(rb_eTypeError, “can’t make subclass of Class”);
-  44      }
-  45      if (FL_TEST(super, FL_SINGLETON)) {
-  46          rb_raise(rb_eTypeError, “can’t make subclass of virtual class”);
-  47      }
-  48      return rb_class_boot(super);
-  49  }

-

(class.c) -

-

Check_Type() is checks the type of object structure, so we can -ignore it. rb_raise() is error handling so we can ignore it. Only -rb_class_boot() remains. So let’s look at it.

-

rb_class_boot() -

-  21  VALUE
-  22  rb_class_boot(super)
-  23      VALUE super;
-  24  {
-  25      NEWOBJ;        /* allocates struct RClass /
-  26      OBJSETUP; / initialization of the RBasic part /
-  27
-  28      klass→super = super;       / (A) */
-  29      klass→iv_tbl = 0;
-  30      klass→m_tbl = 0;
-  31      klass→m_tbl = st_init_numtable();
-  32
-  33      OBJ_INFECT(klass, super);
-  34      return (VALUE)klass;
-  35  }

-

(class.c) -

-

NEWOBJ() and OBJSETUP() are fixed expressions used when creating -Ruby objects that possess one of the internal structure types (`struct -Rxxxx). They are both macros. In NEWOBJ, the struct RBasic member of the RClass (and thus -basic.klass and basic.flags) is initialized.

-

OBJ_INFECT() is a macro related to security. From now on, we’ll -ignore it.

-

At (A), the super member of klassis set to the super -parameter. It looks like rb_class_boot() is a function that creates -a class inheriting from super.

-

So, as rb_class_boot() is a function that creates a class, -what does rb_class_new() is very similar.

-

Then, let’s once more look at rb_singleton_class()’s call graph:

-
-rb_singleton_class
-    SPECIAL_SINGLETON
-    rb_make_metaclass
-        rb_class_boot
-        rb_singleton_class_attached
-
-

Here also rb_class_boot() is called. So up to that point, it’s the -same as in normal classes. What’s going on after is what’s different -between normal classes and singleton classes, in other words the -characteristics of singleton classes. If everything’s clear so -far, we just need to read rb_singleton_class() and -rb_make_metaclass().

-

Compressed rb_singleton_class()

-

rb_singleton_class() is a little long so we’ll first remove its -non-essential parts.

-

rb_singleton_class() -

- 678  #define SPECIAL_SINGLETON(x,c) do {\
- 679      if (obj == (x)) {\
- 680          return c;\
- 681      }\
- 682  } while (0)

-684 VALUE -685 rb_singleton_class(obj) -686 VALUE obj; -687 { -688 VALUE klass; -689 -690 if (FIXNUM_P(obj) || SYMBOL_P(obj)) { -691 rb_raise(rb_eTypeError, “can’t define singleton”); -692 } -693 if (rb_special_const_p(obj)) { -694 SPECIAL_SINGLETON(Qnil, rb_cNilClass); -695 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass); -696 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass); -697 rb_bug(“unknown immediate %ld”, obj); -698 } -699 -700 DEFER_INTS; -701 if (FL_TEST(RBASIC→klass, FL_SINGLETON) && -702 (BUILTIN_TYPE(obj) == T_CLASS || -703 rb_iv_get(RBASIC→klass, “attached”) == obj)) { -704 klass = RBASIC→klass; -705 } -706 else { -707 klass = rb_make_metaclass(obj, RBASIC→klass); -708 } -709 if (OBJ_TAINTED(obj)) { -710 OBJ_TAINT(klass); -711 } -712 else { -713 FL_UNSET(klass, FL_TAINT); -714 } -715 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); -716 ALLOW_INTS; -717 -718 return klass; -719 } -

(class.c) -

-

The first and the second half are separated by a blank line. The first -half handles a special case and the second half handles the general -case. In other words, the second half is the trunk of the -function. That’s why we’ll keep it for later and talk about the first -half.

-

Everything that is handled in the first half are non-pointer VALUEs, -in other words objects without an existing C structure. First, -Fixnum and Symbol are explicitly picked. Then, -rb_special_const_p() is a function that returns true for non-pointer -VALUEs, so there only Qtrue, Qfalse and Qnil should get -caught. Other than that, there are no valid non-pointer value so a bug -is reported with rb_bug().

-

DEFER_INTS() and ALLOW_INTS() both end with the same INTS so you -should see a pair in them. That’s the case, and they are macros -related to signals. Because they are defined in rubysig.h, you can -guess that INTS is the abbreviation of interrupts. You can ignore -them.

-

Compressed rb_make_metaclass()

-

rb_make_metaclass() -

- 142  VALUE
- 143  rb_make_metaclass(obj, super)
- 144      VALUE obj, super;
- 145  {
- 146      VALUE klass = rb_class_boot(super);
- 147      FL_SET(klass, FL_SINGLETON);
- 148      RBASIC→klass = klass;
- 149      rb_singleton_class_attached(klass, obj);
- 150      if (BUILTIN_TYPE(obj) == T_CLASS) {
- 151          RBASIC→klass = klass;
- 152          if (FL_TEST(obj, FL_SINGLETON)) {
- 153              RCLASS→super =
-                          RBASIC→super))→klass;
- 154          }
- 155      }
- 156
- 157      return klass;
- 158  }

-

(class.c) -

-

We already saw rb_class_boot(). It creates a (normal) class using -the super parameter as its superclass. After that, the -FL_SINGLETON of this class is set. This is clearly suspicious. The -name of the function makes us think that it is not the indication of -a singleton class.

-

What are singleton classes?

-

Continuing the simplification process, furthermore as parameters, -return values, local variables are all VALUE, we can throw away the -declarations. That makes us able to compress to the following:

-

rb_singleton_class() rb_make_metaclass() (after compression) -

-rb_singleton_class(obj)
-{
-    if (FL_TEST(RBASIC→klass, FL_SINGLETON) &&
-        (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) &&
-        rb_iv_get(RBASIC→klass, “attached”) == obj) {
-        klass = RBASIC→klass;
-    }
-    else {
-        klass = rb_make_metaclass(obj, RBASIC→klass);
-    }
-    return klass;
-}

-

rb_make_metaclass(obj, super) -{ - klass = create a class with super as superclass; - FL_SET(klass, FL_SINGLETON); - RBASIC→klass = klass; - rb_singleton_class_attached(klass, obj); - if (BUILTIN_TYPE(obj) == T_CLASS) { - RBASIC→klass = klass; - if (FL_TEST(obj, FL_SINGLETON)) { - RCLASS→super = - RBASIC→super))→klass; - } - }

-return klass; -

} -

-

The condition of the if statement of rb_singleton_class() seems -quite complicated. However, this condition is not connected to the -mainstream of rb_make_metaclass() so we’ll see it later. Let’s first -think about what happens on the false branch of the if.

-

The BUILTIN_TYPE() of rb_make_metaclass() is similar to TYPE() -as it is a macro to get the structure type flag (T_xxxx). That means -this check in rb_make_metaclass means “if obj is a class”. For the -moment it’s better not to limit ourselves to obj being a class, so -we’ll remove it.

-

With these simplifications, we get the the following:

-

rb_singleton_class() rb_make_metaclass() (after recompression) -

-rb_singleton_class(obj)
-{
-    klass = create a class with RBASIC→klass as superclass;
-    FL_SET(klass, FL_SINGLETON);
-    RBASIC→klass = klass;
-    return klass;
-}
-

-

But there is still a quite hard to understand side to it. That’s -because klass is used too often. So let’s rename the klass -variable to sclass.

-

rb_singleton_class() rb_make_metaclass() (variable substitution) -

-rb_singleton_class(obj)
-{
-    sclass = create a class with RBASIC→klass as superclass;
-    FL_SET(sclass, FL_SINGLETON);
-    RBASIC→klass = sclass;
-    return sclass;
-}
-

-

Now it should be very easy to understand. To make it even simpler, -I’ve represented what is done with a diagram (figure 1). In the -horizontal direction is the “instance – class” relation, and in the -vertical direction is inheritance (the superclasses are above).

-

-

(addsclass)
-Figure 1: rb_singleton_class

-

-

When comparing the first and last part of this diagram, you can -understand that sclass is inserted without changing the -structure. That’s all there is to singleton classes. In other words -the inheritance is increased one step. If a method is defined in a -singleton class, this construction allows the other instances of -klass to define completely different methods.

-

Singleton classes and instances

-

By the way, you must have seen that during the compression process, -the call to rb_singleton_class_attached() was stealthily -removed. Here:

-
-rb_make_metaclass(obj, super)
-{
-    klass = create a class with super as superclass;
-    FL_SET(klass, FL_SINGLETON);
-    RBASIC(obj)->klass = klass;
-    rb_singleton_class_attached(klass, obj);   /* THIS */
-
-

Let’s have a look at what it does.

-

rb_singleton_class_attached() -

- 130  void
- 131  rb_singleton_class_attached(klass, obj)
- 132      VALUE klass, obj;
- 133  {
- 134      if (FL_TEST(klass, FL_SINGLETON)) {
- 135          if (!RCLASS→iv_tbl) {
- 136              RCLASS→iv_tbl = st_init_numtable();
- 137          }
- 138          st_insert(RCLASS→iv_tbl,
-                        rb_intern(“attached”), obj);
- 139      }
- 140  }

-

(class.c) -

-

If the FL_SINGLETON flag of klass is set… in other words if it’s a -singleton class, put the __attached__obj relation in the -instance variable table of klass (iv_tbl). That’s how it looks -like (in our case klass is always a singleton class… in other -words its FL_SINGLETON flag is always set).

-

__attached__ does not have the @ prefix, but it’s stored in the -instance variables table so it’s still an instance variable. Such an -instance variable can never be read at the Ruby level so it can be -used to keep values for the system’s exclusive use.

-

Let’s now think about the relationship between klass and -obj. klass is the singleton class of obj. In other words, this -“invisible” instance variable allows the singleton class to remember -the instance it was created from. Its value is used when the singleton -class is changed, notably to call hook methods on the instance -(i.e. obj). For example, when a method is added to a singleton -class, the obj‘s singleton_method_added method is called. There is -no logical necessity to doing it, it was done because that’s how it -was defined in the language.

-

But is it really all right? Storing the instance in __attached__ -will force one singleton class to have only one attached instance. For -example, by getting (in some way or an other) the singleton class and -calling new on it, won’t a singleton class end up having multiple -instances?

-

This cannot be done because the proper checks are done to prevent the -creation of an instance of a singleton class.

-

Singleton classes are in the first place for singleton -methods. Singleton methods are methods existing only on a particular -object. If singleton classes could have multiple instances, there -would the same as normal classes. That’s why they are forced to only -have one instance.

-

Summary

-

We’ve done a lot, maybe made a real mayhem, so let’s finish and put -everything in order with a summary.

-

What are singleton classes? They are classes that have the -FL_SINGLETON flag set and that can only have one instance.

-

What are singleton methods? They are methods defined in the singleton -class of an object.

-

Metaclasses

-

Inheritance of singleton methods

-

Infinite chain of classes

-

Even a class has a class, and it’s Class. And the class of Class -is again Class. We find ourselves in an infinite loop (figure 2).

-

-

(infloop)
-Figure 2: Infinite loop of classes

-

-

Up to here it’s something we’ve already gone through. What’s going -after that is the theme of this chapter. Why do classes have to make a -loop?

-

First, in Ruby all data are objects. And classes are data so in Ruby -they have to be objects.

-

As they are objects, they must answer to methods. And setting the rule -“to answer to methods you must belong to a class” made processing -easier. That’s where comes the need for a class to also have a class.

-

Let’s base ourselves on this and think about the way to implement it. -First, we can try first with the most naïve way, Class‘s class is -ClassClass, ClassClass’s class is ClassClassClass…, chaining -classes of classes one by one. But whichever the way you look at it, -this can’t be implemented effectively. That’s why it’s common in -object oriented languages where classes are objects that Class’s -class is to Class itself, creating an endless virtual instance-class -relationship.

-

I’m repeating myself, but the fact that Class‘s class is Class is -only to make the implementation easier, there’s nothing important in -this logic.

-

“Class is also an object”

-

“Everything is an object” is often used as advertising statement when -speaking about Ruby. And as a part of that, “Classes are also objects!” -also appears. But these expressions often go too far. When thinking -about these sayings, we have to split them in two:

-
    -
  • all data are objects
  • -
  • classes are data
  • -
-

Talking about data or code makes a discussion much harder to -understand. That’s why here we’ll restrict the meaning of “data” to -“what can be put in variables in programs”.

-

Being able to manipulate classes from programs gives programs the -ability to manipulate themselves. This is called reflection. It fits -object oriented languages, and even more Ruby with the classes it has, -to be able to directly manipulate classes.

-

Nevertheless, classes could be made available in a form that is not an -object. For example, classes could be manipulated with function-style -methods (functions defined at the top-level). However, as inside the -interpreter there are data structures to represent the classes, it’s -more natural in object oriented languages to make them available -directly. And Ruby did this choice.

-

Furthermore, an objective in Ruby is for all data to be -objects. That’s why it’s appropriate to make them objects.

-

By the way, there is a reason not linked to reflection why in Ruby -classes had to be made objects. That is to be able to define methods -independently from instances (what is called static methods in Java in -C++).

-

And to implement static methods, another thing was necessary: -singleton methods. By chain reaction, that also makes singleton -classes necessary. Figure 3 shows these dependency relationships.

-

-

(reqlink)
-Figure 3: Requirements dependencies

-

-

Class methods inheritance

-

In Ruby, singleton methods defined in a class are called class -methods. However, their specification is a little strange. Why are -class methods inherited?

-
-class A
-  def A.test    # defines a singleton method in A
-    puts("ok")
-  end
-end
-
-class B < A
-end
-
-B.test()  # calls it
-
-

This can’t occur with singleton methods from objects that are not -classes. In other words, classes are the only ones handled -specially. In the following section we’ll see how class methods are -inherited.

-

Singleton class of a class

-

Assuming that class methods are inherited, where is this operation -done? At class definition (creation)? At singleton method definition? -Then let’s look at the code defining classes.

-

Class definition means of course rb_define_class(). Now -let’s take the call graph of this function.

-
-rb_define_class
-    rb_class_inherited
-    rb_define_class_id
-        rb_class_new
-            rb_class_boot
-        rb_make_metaclass
-            rb_class_boot
-            rb_singleton_class_attached
-
-

If you’re wondering where you’ve seen it before, we looked at it in -the previous section. At that time you did not see it but if you look -closely, why does rb_make_metaclass() appear? As we saw before, this -function introduces a singleton class. This is very suspicious. Why is -this called even if we are not defining a singleton function? -Furthermore, why is the lower level rb_make_metaclass() used instead -of rb_singleton_class()? It looks like we have to check these -surroundings again.

-

rb_define_class_id()

-

Let’s first start our reading with its caller, rb_define_class_id().

-

rb_define_class_id() -

- 160  VALUE
- 161  rb_define_class_id(id, super)
- 162      ID id;
- 163      VALUE super;
- 164  {
- 165      VALUE klass;
- 166
- 167      if (!super) super = rb_cObject;
- 168      klass = rb_class_new(super);
- 169      rb_name_class(klass, id);
- 170      rb_make_metaclass(klass, RBASIC→klass);
- 171
- 172      return klass;
- 173  }

-

(class.c) -

-

rb_class_new() was a function that creates a class with super as -its superclass. rb_name_class()‘s name means it names a class, but -for the moment we do note care about names so we’ll skip it. After -that there’s the rb_make_metaclass() in question. I’m concerned by -the fact that when called from rb_singleton_class(), the parameters -were different. Last time was like this:

-
-rb_make_metaclass(obj, RBASIC(obj)->klass);
-
-

But this time is like this:

-
-rb_make_metaclass(klass, RBASIC(super)->klass);
-
-

So as you can see it’s slightly different. How do the results change -depending on that? Let’s have once again a look at a simplified -rb_make_metaclass().

-

rb_make_metaclass (once more)

-

rb_make_metaclass (after first compression) -

-rb_make_metaclass(obj, super)
-{
-    klass = create a class with super as superclass;
-    FL_SET(klass, FL_SINGLETON);
-    RBASIC→klass = klass;
-    rb_singleton_class_attached(klass, obj);
-    if (BUILTIN_TYPE(obj) == T_CLASS) {
-        RBASIC→klass = klass;
-        if (FL_TEST(obj, FL_SINGLETON)) {
-            RCLASS→super =
-                    RBASIC→super))→klass;
-        }
-    }

-return klass; -

} -

-

Last time, the if statement was skillfully skipped, but looking once -again, something is done only for T_CLASS, in other words -classes. This clearly looks important. In rb_define_class_id(), as -it’s called like this:

-
-rb_make_metaclass(klass, RBASIC(super)->klass);
-
-

Let’s expand rb_make_metaclass()’s parameter variables with this -values.

-

rb_make_metaclass (recompression) -

-rb_make_metaclass(klass, super_klass /* == RBASIC→klass */)
-{
-    sclass = create a class with super_class as superclass;
-    RBASIC→klass = sclass;
-    RBASIC→klass = sclass;
-    return sclass;
-}
-

-

Doing this as a diagram gives something like figure 4. In it, the -names between parentheses are singleton classes. This notation is -often used in this book so I’d like you to remember it. This means -that obj‘s singleton class is written as (obj). And (klass) is -the singleton class for klass. It looks like the singleton class is -caught between a class and this class’s superclass’s class.

-

-

(metaclass)
-Figure 4: Introduction of a class’s singleton class

-

-

From this result, and moreover when thinking more deeply, we can think -that the superclass’s class must again be the superclass’s singleton -class. You’ll understand with one more inheritance level (figure 5).

-

-

(multi)
-Figure 5: Hierarchy of multi-level inheritance

-

-

As the relationship between super and klass is the same as the one -between klass and klass2, c must be the singleton class -(super). If you continue like this, finally you’ll arrive at the -conclusion that Object‘s class must be (Object). And that’s the -case in practice. For example, by inheriting like in the following -program :

-
-class A < Object
-end
-class B < A
-end
-
-

internally, a structure like figure 6 is created.

-

-

(metatree)
-Figure 6: Class hierarchy and metaclasses

-

-

As classes and their metaclasses are linked and inherit like this, -class methods are inherited.

-

Class of a class of a class

-

You’ve understood the working of class methods inheritance, but by -doing that, in the opposite some questions have appeared. What is the -class of a class’s singleton class? To do this we can try -debugging. I’ve made the figure 7 from the results of this -investigation.

-

-

(mmm)
-Figure 7: Class of a class’s singleton class

-

-

A class’s singleton class puts itself as its own class. Quite -complicated.

-

The second question: the class of Object must be Class. Didn’t I -properly confirm this in chapter 1: Ruby language minimum?

-
-p(Object.class())   # Class
-
-

Certainly, that’s the case “at the Ruby level”. But “at the C level”, -it’s the singleton class (Object). If (Object) does not appear at -the Ruby level, it’s because Object#class skips the singleton -classes. Let’s look at the body of the method, rb_obj_class() to -confirm that.

-

rb_obj_class() -

-  86  VALUE
-  87  rb_obj_class(obj)
-  88      VALUE obj;
-  89  {
-  90      return rb_class_real(CLASS_OF(obj));
-  91  }

-76 VALUE -77 rb_class_real(cl) -78 VALUE cl; -79 { -80 while (FL_TEST(cl, FL_SINGLETON) || TYPE == T_ICLASS) { -81 cl = RCLASS→super; -82 } -83 return cl; -84 } -

(object.c) -

-

CLASS_OF(obj) returns the basic.klass of obj. While in -rb_class_real(), all singleton classes are skipped (advancing -towards the superclass). In the first place, singleton class are -caught between a class and its superclass, like a proxy. That’s why -when a “real” class is necessary, we have to follow the superclass -chain (figure 8).

-

I_CLASS will appear later when we will talk about include.

-

-

(real)
-Figure 8: Singleton class and real class

-

-

Singleton class and metaclass

-

Well, the singleton classes that were introduced in classes is also -one type of class, it’s a class’s class. So it can be called -metaclass.

-

However, you should be wary of the fact that singleton class are -not metaclasses. It’s the singleton classes introduced in classes that -are metaclasses. The important fact is not that they are singleton -classes, but that they are the classes of classes. I was stuck on this -point when I started learning Ruby. As I may not be the only one, I -would like to make this clear.

-

Thinking about this, the rb_make_metaclass() function name is not -very good. When used in classes, it does indeed create a metaclass, -but not in the other cases, when using objects.

-

Then finally, even if you understood that some class are metaclasses, -it’s not as if there was any concrete gain. I’d like you not to care -too much about it.

-

Bootstrap

-

We have nearly finished our talk about classes and metaclasses. But -there is still one problem left. It’s about the 3 metaobjects -Object, Module and Class. These 3 cannot be created with the -common use API. To make a class, its metaclass must be built, but like -we saw some time ago, the metaclass’s superclass is Class. However, -as Class has not been created yet, the metaclass cannot be build. So -in ruby, only these 3 classes’s creation is handled specially.

-

Then let’s look at the code:

-

Object, Module and Class creation -

-1243  rb_cObject = boot_defclass(“Object”, 0);
-1244  rb_cModule = boot_defclass(“Module”, rb_cObject);
-1245  rb_cClass =  boot_defclass(“Class”,  rb_cModule);
-1246
-1247  metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
-1248  metaclass = rb_make_metaclass(rb_cModule, metaclass);
-1249  metaclass = rb_make_metaclass(rb_cClass, metaclass);

-

(object.c) -

-

First, in the first half, boot_defclass() is similar to -rb_class_boot(), it just creates a class with its given superclass -set. These links give us something like the left part of figure 9.

-

And in the three lines of the second half, (Object), (Module) and -(Class) are created and set (right figure 9). (Object) and -(Module)‘s classes… that is themselves… is already set in -rb_make_metaclass() so there is no problem. With this, the -metaobjects’ bootstrap is finished.

-

-

(boot1)
-Figure 9: Metaobjects creation

-

-

After taking everything into account, it gives us a the final shape -like figure 10.

-

-

(metaobj)
-Figure 10: Ruby metaobjects

-

-

Class names

-

In this section, we will analyse how’s formed the reciprocal -conversion between class and class names, in other words -constants. Concretely, we will target rb_define_class() and -rb_define_class_under().

-

Name → class

-

First we’ll read rb_defined_class(). After the end of this function, -the class can be found from the constant.

-

rb_define_class() -

- 183  VALUE
- 184  rb_define_class(name, super)
- 185      const char name;
- 186      VALUE super;
- 187  {
- 188      VALUE klass;
- 189      ID id;
- 190
- 191      id = rb_intern(name);
- 192      if (rb_autoload_defined(id)) {             / (A) autoload /
- 193          rb_autoload_load(id);
- 194      }
- 195      if (rb_const_defined(rb_cObject, id)) {    / (B) rb_const_defined /
- 196          klass = rb_const_get(rb_cObject, id);  / © rb_const_get /
- 197          if (TYPE != T_CLASS) {
- 198              rb_raise(rb_eTypeError, “%s is not a class”, name);
- 199          }                                      / (D) rb_class_real */
- 200          if (rb_class_real(RCLASS→super) != super) {
- 201              rb_name_error(id, “%s is already defined”, name);
- 202          }
- 203          return klass;
- 204      }
- 205      if (!super) {
- 206          rb_warn(“no super class for ‘%s’, Object assumed”, name);
- 207      }
- 208      klass = rb_define_class_id(id, super);
- 209      rb_class_inherited(super, klass);
- 210      st_add_direct(rb_class_tbl, id, klass);
- 211
- 212      return klass;
- 213  }

-

(class.c) -

-

Many things can be understood with what’s before and after -rb_define_class_id()… Before we acquire or create the class. After -we set the constant. We will look at it in more detail below.

-

(A) In Ruby, there is an autoload function that automatically loads -libraries when some constants are accessed. This is done in the -rb_autoload_xxxx() function. You can ignore it without any problem.

-

(B) We determine whether the name constant has been defined or not -in Object.

-

© Get the value of the name constant. This will be explained in -detail in chapter 6.

-

(D) We’ve seen rb_class_real() some time ago. If the class c is a -singleton class or an ICLASS, it climbs the super hierarchy up to -a class that is not and returns it. In short, this function skips the -virtual classes that should not appear at the Ruby level.

-

That’s what we can read nearby.

-

As around constants are involved, it is very troublesome. However, we -will talk about class definition in the constants chapter so for the -moment we will content ourselves with a partial description.

-

After rb_define_class_id, we can find the following:

-
-st_add_direct(rb_class_tbl, id, klass);
-
-

This part assigns the class to the constant. However, whichever -way you look at it you do not see that. In fact, top-level classes are -separated from the other constants and regrouped in -rb_class_tbl(). The split is slightly related to the GC. It’s not -essential.

-

Class → name

-

We understood how the class can be obtained from the class name, but -how to do the opposite? By doing things like calling p or -Class#name, we can get the name of the class, but how is it -implemented?

-

In fact this was already done a long time ago by -rb_name_class(). The call is around the following:

-
-rb_define_class
-    rb_define_class_id
-        rb_name_class
-
-

Let’s look at its content:

-

rb_name_class() -

- 269  void
- 270  rb_name_class(klass, id)
- 271      VALUE klass;
- 272      ID id;
- 273  {
- 274      rb_iv_set(klass, “classid”, ID2SYM);
- 275  }

-

(variable.c) -

-

__classid__ is another instance variable that can’t be seen from -Ruby. As only VALUEs can be put in the instance variable table, the -ID is converted to Symbol using ID2SYM().

-

That’s how we are able to find the constant name from the class.

-

Nested classes

-

So, in the case of classes defined at the top-level, we know how works -the reciprocal link between name and class. What’s left is the case of -classes defined in modules or other classes, and for that it’s a -little more complicated. The function to define these nested classes -is rb_define_class_under().

-

rb_define_class_under() -

- 215  VALUE
- 216  rb_define_class_under(outer, name, super)
- 217      VALUE outer;
- 218      const char *name;
- 219      VALUE super;
- 220  {
- 221      VALUE klass;
- 222      ID id;
- 223
- 224      id = rb_intern(name);
- 225      if (rb_const_defined_at(outer, id)) {
- 226          klass = rb_const_get(outer, id);
- 227          if (TYPE != T_CLASS) {
- 228              rb_raise(rb_eTypeError, “%s is not a class”, name);
- 229          }
- 230          if (rb_class_real(RCLASS→super) != super) {
- 231              rb_name_error(id, “%s is already defined”, name);
- 232          }
- 233          return klass;
- 234      }
- 235      if (!super) {
- 236          rb_warn(“no super class for ‘%s::%s’, Object assumed”,
- 237                  rb_class2name(outer), name);
- 238      }
- 239      klass = rb_define_class_id(id, super);
- 240      rb_set_class_path(klass, outer, name);
- 241      rb_class_inherited(super, klass);
- 242      rb_const_set(outer, id, klass);
- 243
- 244      return klass;
- 245  }

-

(class.c) -

-

The structure is like the one of rb_define_class(): before the call -to rb_define_class_id() is the redefinition check, after is the -creation of the reciprocal link between constant and class. The first -half is pretty boringly similar to rb_define_class() so we’ll skip -it. In the second half, rb_set_class() is new. We’re going to look -at it.

-

rb_set_class_path()

-

This function gives the name name to the class klass nested in the -class under. “class path” means a name including all the nesting -information starting from top-level, for example -“Net::NetPrivate::Socket”.

-

rb_set_class_path() -

- 210  void
- 211  rb_set_class_path(klass, under, name)
- 212      VALUE klass, under;
- 213      const char name;
- 214  {
- 215      VALUE str;
- 216
- 217      if (under == rb_cObject) {
-              / defined at top-level /
- 218          str = rb_str_new2(name);    / create a Ruby string from name /
- 219      }
- 220      else {
-              / nested constant /
- 221          str = rb_str_dup(rb_class_path(under));  / copy the return value /
- 222          rb_str_cat2(str, “::”);     / concatenate “::” /
- 223          rb_str_cat2(str, name);     / concatenate name */
- 224      }
- 225      rb_iv_set(klass, “classpath”, str);
- 226  }

-

(variable.c) -

-

Everything except the last line is the construction of the class path, -and the last line makes the class remember its own -name. __classpath__ is of course another instance variable that -can’t be seen from a Ruby program. In rb_name_class() there was -__classid__, but id is different because it does not include -nesting information (look at the table below).

-
-__classpath__    Net::NetPrivate::Socket
-__classid__                       Socket
-
-

It means classes defined for example in rb_defined_class() all have -__classid__ or __classpath__ defined. So to find under‘s -classpath we can look up in these instance variables. This is done by -rb_class_path(). We’ll omit its content.

-

Nameless classes

-

Contrary to what I have just said, there are in fact cases in which -neither __classpath__ nor __classid__ are set. That is because in -Ruby you can use a method like the following to create a class.

-
-c = Class.new()
-
-

If you create a class like this, we won’t go through -rb_define_class_id() and the classpath won’t be set. In this case, -c does not have any name, which is to say we get an unnamed class.

-

However, if later it’s assigned to a constant, the name of this -constant will be attached to the class.

-
-SomeClass = c   # the class name is SomeClass
-
-

Strictly speaking, the name is attached after the assignment, the -first time it is requested. For instance, when calling p on this -SomeClass class or when calling the Class#name method. When doing -this, a value equal to the class is searched in rb_class_tbl, and a -name has to be chosen. The following case can also happen:

-
-class A
-  class B
-    C = tmp = Class.new()
-    p(tmp)   # here we search for the name
-  end
-end
-
-

so in the worst case we have to search for the whole constant -space. However, generally, there aren’t many constants so searching -all constants does not take too much time.

-

Include

-

We only talked about classes so let’s finish this chapter with -something else and talk about module inclusion.

-

rb_include_module (1)

-

Includes are done by the ordinary method Module#include. Its -corresponding function in C is rb_include_module(). In fact, to be -precise, its body is rb_mod_include(), and there -Module#append_feature is called, and this function’s default -implementation finally calls rb_include_module(). Mixing what’s -happening in Ruby and C gives us the following call graph.

-
-Module#include (rb_mod_include)
-    Module#append_features (rb_mod_append_features)
-        rb_include_module
-
-

All usual includes are done by rb_include_module(). This function is -a little long so we’ll look at it a half at a time.

-

rb_include_module (first half) -

-      /* include module in class */
- 347  void
- 348  rb_include_module(klass, module)
- 349      VALUE klass, module;
- 350  {
- 351      VALUE p, c;
- 352      int changed = 0;
- 353
- 354      rb_frozen_class_p(klass);
- 355      if (!OBJ_TAINTED(klass)) {
- 356          rb_secure(4);
- 357      }
- 358
- 359      if (NIL_P(module)) return;
- 360      if (klass == module) return;
- 361
- 362      switch (TYPE) {
- 363        case T_MODULE:
- 364        case T_CLASS:
- 365        case T_ICLASS:
- 366          break;
- 367        default:
- 368          Check_Type(module, T_MODULE);
- 369      }

-

(class.c) -

-

For the moment it’s only security and type checking, therefore we can -ignore it. The process itself is below:

-

rb_include_module (second half) -

- 371      OBJ_INFECT(klass, module);
- 372      c = klass;
- 373      while (module) {
- 374          int superclass_seen = Qfalse;
- 375
- 376          if (RCLASS→m_tbl == RCLASS→m_tbl)
- 377              rb_raise(rb_eArgError, “cyclic include detected”);
- 378          /* (A) skip if the superclass already includes module /
- 379          for (p = RCLASS→super; p; p = RCLASS→super) {
- 380              switch (BUILTIN_TYPE(p)) {
- 381                case T_ICLASS:
- 382                  if (RCLASS→m_tbl == RCLASS→m_tbl) {
- 383                      if (!superclass_seen) {
- 384                          c = p;  / move the insertion point */
- 385                      }
- 386                      goto skip;
- 387                  }
- 388                  break;
- 389                case T_CLASS:
- 390                  superclass_seen = Qtrue;
- 391                  break;
- 392              }
- 393          }
- 394          c = RCLASS→super =
-                          include_class_new(module, RCLASS→super);
- 395          changed = 1;
- 396        skip:
- 397          module = RCLASS→super;
- 398      }
- 399      if (changed) rb_clear_cache();
- 400  }

-

(class.c) -

-

First, what the (A) block does is written in the comment. It seems to -be a special condition so let’s first skip reading it for now. By -extracting the important parts from the rest we get the following:

-
-c = klass;
-while (module) {
-    c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
-    module = RCLASS(module)->super;
-}
-
-

In other words, it’s a repetition of module‘s super. What is in -module’s super must be a module included by module (because our -intuition tells us so). Then the superclass of the class where the -inclusion occurs is replaced with something. We do not understand much -what, but at the moment I saw that I felt “Ah, doesn’t this look the -addition of elements to a list (like LISP’s cons)?” and it suddenly -make the story faster. In other words it’s the following form:

-
-list = new(item, list)
-
-

Thinking about this, it seems we can expect that module is inserted -between c and c->super. If it’s like this, it fits module’s -specification.

-

But to be sure of this we have to look at include_class_new().

-

include_class_new()

-

include_class_new() -

- 319  static VALUE
- 320  include_class_new(module, super)
- 321      VALUE module, super;
- 322  {
- 323      NEWOBJ;               /* (A) /
- 324      OBJSETUP;
- 325
- 326      if (BUILTIN_TYPE(module) == T_ICLASS) {
- 327          module = RBASIC→klass;
- 328      }
- 329      if (!RCLASS→iv_tbl) {
- 330          RCLASS→iv_tbl = st_init_numtable();
- 331      }
- 332      klass→iv_tbl = RCLASS→iv_tbl;     / (B) /
- 333      klass→m_tbl = RCLASS→m_tbl;
- 334      klass→super = super;                       / © /
- 335      if (TYPE == T_ICLASS) {             / (D) /
- 336          RBASIC→klass = RBASIC→klass;   / (D-1) /
- 337      }
- 338      else {
- 339          RBASIC→klass = module;                  / (D-2) */
- 340      }
- 341      OBJ_INFECT(klass, module);
- 342      OBJ_INFECT(klass, super);
- 343
- 344      return (VALUE)klass;
- 345  }

-

(class.c) -

-

We’re lucky there’s nothing we do not know.

-

(A) First create a new class.

-

(B) Transplant module’s instance variable and method tables into -this class.

-

© Make the including class’s superclass (super) the super class of -this new class.

-

In other words, this function creates an include class for the -module. The important point is that at (B) only the pointer is moved -on, without duplicating the table. Later, if a method is added, the -module’s body and the include class will still have exactly the -same methods (figure 11).

-

-

(symbolic)
-Figure 11: Include class

-

-

If you look closely at (A), the structure type flag is set to -T_ICLASS. This seems to be the mark of an include class. This -function’s name is include_class_new() so ICLASS’s I must be -include.

-

And if you think about joining what this function and -rb_include_module() do, we know that our previous expectations were not -wrong. In brief, including is inserting the include class of a -module between a class and its superclass (figure 12).

-

-

(include)
-Figure 12: Include

-

-

At (D-2) the module is stored in the include class’s klass. At -(D-1), the module’s body is taken out… at least that’s what I’d like -to say, but in fact this check does not have any use. The T_ICLASS -check is already done at the beginning of this function, so when -arriving here there can’t still be a T_ICLASS. Modification to -ruby piled up at a fast pace during quite a long period of time so -there are quite a few small overlooks.

-

There is one more thing to consider. Somehow the include class’s -basic.klass is only used to point to the module’s body, so for -example calling a method on the include class would be very bad. So -include classes must not be seen from Ruby programs. And in -practice all methods skip include classes, with no exception.

-

Simulation

-

It was complicated so let’s look at a concrete example. I’d like you -to look at figure 13 (1). We have the c1 class and the m1 module -that includes m2. From there, the changes made to include m1 in -c1 are (2) and (3). ims are of course include classes.

-

-

(simulate)
-Figure 13: Include

-

-

rb_include_module (2)

-

Well, now we can explain the part of rb_include_module() we skipped.

-

rb_include_module (avoiding double inclusion) -

- 378  /* (A) skip if the superclass already includes module /
- 379  for (p = RCLASS→super; p; p = RCLASS→super) {
- 380      switch (BUILTIN_TYPE(p)) {
- 381        case T_ICLASS:
- 382          if (RCLASS→m_tbl == RCLASS→m_tbl) {
- 383              if (!superclass_seen) {
- 384                  c = p;  / the inserting point is moved */
- 385              }
- 386              goto skip;
- 387          }
- 388          break;
- 389        case T_CLASS:
- 390          superclass_seen = Qtrue;
- 391          break;
- 392      }
- 393  }

-

(class.c) -

-

If one of the T_ICLASSes (include classes) that are in klass‘s -superclasses (p) has the same table as one of the modules we want to -include (module), it’s an include class for module. That’s why we -skip the inclusion to not include the module twice. If this module -includes an other module (module->super), we check this once more.

-

However, when we skip an inclusion, p is a module that has been -included once, so its included modules must already be -included… that’s what I thought for a moment, but we can have the -following context:

-
-module M
-end
-module M2
-end
-class C
-  include M   # M2 is not yet included in M
-end           # therefore M2 is not in C's superclasses
-
-module M
-  include M2  # as there M2 is included in M,
-end
-class C
-  include M   # I would like here to only add M2
-end
-
-

So on the contrary, there are cases for which include does not have -real-time repercussions.

-

For class inheritance, the class’s singleton methods were inherited -but in the case of module there is no such thing. Therefore the -singleton methods of the module are not inherited by the including -class (or module). When you want to also inherit singleton methods, -the usual way is to override Module#append_features.

- - - -
- - diff --git a/htmls/contextual.html b/htmls/contextual.html deleted file mode 100644 index 58a65ac..0000000 --- a/htmls/contextual.html +++ /dev/null @@ -1,1755 +0,0 @@ - - - - - Finite-state scanner | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Peter Zotov
-I’m very grateful to my employer Evil Martians , who sponsored -the work, and Nikolay Konovalenko , who put -more effort in this translation than I could ever wish for. Without them, -I would be still figuring out what COND_LEXPOP() actually does.

-

Chapter 11 Finite-state scanner

-

Outline

-

In theory, the scanner and the parser are completely independent of each other -– the scanner is supposed to recognize tokens, while the parser is supposed to -process the resulting series of tokens. It would be nice if things were that -simple, but in reality it rarely is. Depending on the context of the program it -is often necessary to alter the way tokens are recognized or their symbols. In -this chapter we will take a look at the way the scanner and the parser -cooperate.

-

Practical examples

-

In most programming languages, spaces don’t have any specific meaning unless -they are used to separate words. However, Ruby is not an ordinary language and -meanings can change significantly depending on the presence of spaces. -Here is an example

-
-a[i] = 1      # a[i] = (1)
-a [i]         # a([i])
-
-

The former is an example of assigning an index. The latter is an example of -omitting the method call parentheses and passing a member of an array to a -parameter.

-

Here is another example.

-
-a  +  1    # (a) + (1)
-a  +1      # a(+1)
-
-

This seems to be really disliked by some.

-

However, the above examples might give one the impression that only omitting -the method call parentheses can be a source of trouble. Let’s look at a -different example.

-
-`cvs diff parse.y`          # command call string
-obj.`("cvs diff parse.y")   # normal method call
-
-

Here, the former is a method call using a literal. In contrast, the latter is a -normal method call (with ‘’’ being the method name). Depending on the context, -they could be handled quite differently.

-

Below is another example where the functioning changes dramatically

-
-print(<<EOS)   # here-document
-......
-EOS
-
-list = []
-list << nil    # list.push(nil)
-
-

The former is a method call using a here-document. The latter is a method call -using an operator.

-

As demonstrated, Ruby’s grammar contains many parts which are difficult to -implement in practice. I couldn’t realistically give a thorough description of -all in just one chapter, so in this one I will look at the basic principles and -those parts which present the most difficulty.

-

lex_state

-

There is a variable called “lex_state”. “lex”, obviously, stands for “lexer”. -Thus, it is a variable which shows the scanner’s state.

-

What states are there? Let’s look at the definitions.

-

enum lex_state

-
  61  static enum lex_state {
-  62      EXPR_BEG,      /* ignore newline, +/- is a sign. */
-  63      EXPR_END,      /* newline significant, +/- is a operator. */
-  64      EXPR_ARG,      /* newline significant, +/- is a operator. */
-  65      EXPR_CMDARG,   /* newline significant, +/- is a operator. */
-  66      EXPR_ENDARG,   /* newline significant, +/- is a operator. */
-  67      EXPR_MID,      /* newline significant, +/- is a operator. */
-  68      EXPR_FNAME,    /* ignore newline, no reserved words. */
-  69      EXPR_DOT,      /* right after `.' or `::', no reserved words. */
-  70      EXPR_CLASS,    /* immediate after `class', no here document. */
-  71  } lex_state;
-(parse.y)
-

The EXPR prefix stands for “expression”. EXPR_BEG is “Beginning of -expression” and EXPR_DOT is “inside the expression, after the dot”.

-

To elaborate, EXPR_BEG denotes “Located at the head of the expression”. -EXPR_END denotes “Located at the end of the expression”. EXPR_ARG denotes -“Before the method parameter”. EXPR_FNAME denotes “Before the method name -(such as def)”. The ones not covered here will be analyzed in detail below.

-

Incidentally, I am led to believe that lex_state actually denotes “after -parentheses”, “head of statement”, so it shows the state of the parser rather -than the scanner. However, it’s still conventionally referred to as the -scanner’s state and here’s why.

-

The meaning of “state” here is actually subtly different from how it’s usually -understood. The “state” of lex_state is “a state under which the scanner does -x”. For example an accurate description of EXPR_BEG would be “A state under -which the scanner, if run, will react as if this is at the head of the -expression”

-

Technically, this “state” can be described as the state of the scanner if we -look at the scanner as a state machine. However, delving there would be veering -off topic and too tedious. I would refer any interested readers to any textbook -on data structures.

-

Understanding the finite-state scanner

-

The trick to reading a finite-state scanner is to not try to grasp everything -at once. Someone writing a parser would prefer not to use a finite-state -scanner. That is to say, they would prefer not to make it the main part of the -process. Scanner state management often ends up being an extra part attached to -the main part. In other words, there is no such thing as a clean and concise -diagram for state transitions.

-

What one should do is think toward specific goals: “This part is needed to -solve this task” “This code is for overcoming this problem”. Basically, put out -code in accordance with the task at hand. If you start thinking about the -mutual relationship between tasks, you’ll invariably end up stuck. Like I said, -there is simply no such thing.

-

However, there still needs to be an overreaching objective. When reading a -finite-state scanner, that objective would undoubtedly be to understand every -state. For example, what kind of state is EXPR_BEG? It is a state where the -parser is at the head of the expression.

-

The static approach

-

So, how can we understand what a state does? There are three basic approaches

-
    -
  • Look at the name of the state
  • -
-

The simplest and most obvious approach. For example, the name EXPR_BEG -obviously refers to the head (beginning) of something.

-
    -
  • Observe what changes under this state
  • -
-

Look at the way token recognition changes under the state, then test it in -comparison to previous examples.

-
    -
  • Look at the state from which it transitions
  • -
-

Look at which state it transitions from and which token causes it. For example, -if '\n' is always followed by a transition to a HEAD state, it must denote -the head of the line.

-

Let us take EXPR_BEG as an example. -In Ruby, all state transitions are expressed as assignments to lex_state, so -first we need to grep EXPR_BEG assignments to find them. Then we need to -export their location, for example, such as '#' and '*' and '!' of -yylex() Then we need to recall the state prior to the transition and consider -which case suits best (see image 1)

-

-

(transittobeg)
-Figure 1: Transition to EXPR_BEG

-

-

This does indeed look like the head of statement. Especially the '\n' and the -';' The open parentheses and the comma also suggest that it’s the head not -just of the statement, but of the expression as well.

-

The dynamic approach

-

There are other easy methods to observe the functioning. For example, you can -use a debugger to “hook” the yylex() and look at the lex_state

-

Another way is to rewrite the source code to output state transitions. In the -case of lex_state we only have numerical patterns for assignment and -comparison, so the solution would be to treat them as text patterns and rewrite -the code to output state transitions. The CD that comes with this book contains -the rubylex-analyser tool. When necessary, I will refer to it in this text.

-

The overall process looks like this: use a debugger or the aforementioned tool -to observe the functioning of the program. Then look at the source code to -confirm the acquired data and use it.

-

Description of states

-

Here I will give simple descriptions of lex_state states.

-
    -
  • EXPR_BEG
  • -
-

Head of expression. Comes immediately after \n ( { [ ! ? : , or the operator -op= The most general state.

-
    -
  • EXPR_MID
  • -
-

Comes immediately after the reserved words return break next rescue. -Invalidates binary operators such as * or & -Generally similar in function to EXPR_BEG

-
    -
  • EXPR_ARG
  • -
-

Comes immediately after elements which are likely to be the method name in a -method call. -Also comes immediately after '[' -Except for cases where EXPR_CMDARG is used.

-
    -
  • EXPR_CMDARG
  • -
-

Comes before the first parameter of a normal method call. -For more information, see the section “The do conflict”

-
    -
  • EXPR_END
  • -
-

Used when there is a possibility that the statement is terminal. For example, -after a literal or brackets. Except for cases when EXPR_ENDARG is used

-
    -
  • EXPR_ENDARG
  • -
-

Special iteration of EXPR_END Comes immediately after the closing parenthesis -corresponding to tLPAREN_ARG -Refer to the section “First parameter enclosed in parentheses”

-
    -
  • EXPR_FNAME
  • -
-

Comes before the method name, usually after def, alias, undef or the -symbol ':' In an independent position ` is the method name.

-
    -
  • EXPR_DOT
  • -
-

Comes after the dot in a method call. Handled similarly to EXPR_FNAME -Various reserved words are treated as simple identifiers. -In an independent position '`' is the name.

-
    -
  • EXPR_CLASS
  • -
-

Comes after the reserved word class This is a very limited state.

-

The following states can be grouped together

-
    -
  • BEG MID
  • -
  • END ENDARG
  • -
  • ARG CMDARG
  • -
  • FNAME DOT
  • -
-

They all express similar conditions. EXPR_CLASS is a little different, but -only appears in a limited number of places, not warranting any special -attention.

-

Line-break handling

-

The problem

-

In Ruby, a statement does not necessarily require a terminator. In C or Java a -statement must always end with a semicolon, but Ruby has no such requirement. -Statements usually take up only one line, and thus end at the end of the line.

-

On the other hand, when a statement is clearly continued, this happens -automatically. Some conditions for “This statement is clearly continued” are as -follows:

-
    -
  • After a comma
  • -
  • After an infix operator
  • -
  • Parentheses or brackets are not balanced
  • -
  • Immediately after the reserved word if
  • -
-

Etc.

-

Implementation

-

So, what do we need to implement this grammar? Simply having the scanner ignore -line-breaks is not sufficient. In a grammar like Ruby’s, where statements are -delimited by reserved words on both ends, conflicts don’t happen as frequently -as in C languages, but when I tried a simple experiment, I couldn’t get it to -work until I got rid of return -next break and returned the method call parentheses wherever they were -omitted. To retain those features we need some kind of terminal symbol for -statements’ ends. It doesn’t matter whether it’s \n or ';' but it is -necessary.

-

Two solutions exist – parser-based and scanner-based. For the former, you can -just optionally put \n in every place that allows it. For the latter, have -the \n passed to the parser only when it has some meaning (ignoring it -otherwise).

-

Which solution to use is up to your preferences, but usually the scanner-based -one is used. That way produces a more compact code. Moreover, if the rules are -overloaded with meaningless symbols, it defeats the purpose of the -parser-generator.

-

To sum up, in Ruby, line-breaks are best handled using the scanner. When a line -needs to continued, the \n will be ignored, and when it needs to be -terminated, the \n is passed as a token. In the yylex() this is found here:

-

yylex()-'\n' -

-3155        case ‘\n’:
-3156          switch (lex_state) {
-3157            case EXPR_BEG:
-3158            case EXPR_FNAME:
-3159            case EXPR_DOT:
-3160            case EXPR_CLASS:
-3161              goto retry;
-3162            default:
-3163              break;
-3164          }
-3165          command_start = Qtrue;
-3166          lex_state = EXPR_BEG;
-3167          return ‘\n’;

-

(parse.y) -

-

With EXPR_BEG, EXPR_FNAME, EXPR_DOT, EXPR_CLASS it will be goto retry. -That is to say, it’s meaningless and shall be ignored. The label retry is -found in front of the large switch in the yylex()

-

In all other instances, line-breaks are meaningful and shall be passed to the -parser, after which lex_state is restored to EXPR_BEG Basically, whenever a -line-break is meaningful, it will be the end of expr

-

I recommend leaving command_start alone for the time being. To reiterate, -trying to grasp too many things at once will only end in needless confusion.

-

Let us now take a look at some examples using the rubylex-analyser tool.

-
-% rubylex-analyser -e '
-m(a,
-  b, c) unless i
-'
-+EXPR_BEG
-EXPR_BEG     C      "\nm"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG           "("  '('                  EXPR_BEG
-                                              0:cond push
-                                              0:cmd push
-EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG           ","  ','                  EXPR_BEG
-EXPR_BEG    S     "\n  b"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ","  ','                  EXPR_BEG
-EXPR_BEG    S         "c"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ")"  ')'                  EXPR_END
-                                              0:cond lexpop
-                                              0:cmd lexpop
-EXPR_END    S    "unless"  kUNLESS_MOD          EXPR_BEG
-EXPR_BEG    S         "i"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG             "\n"  \n                   EXPR_BEG
-EXPR_BEG     C       "\n"  '                    EXPR_BEG
-
-

As you can see, there is a lot of output here, but we only need the left and -middle columns. The left column displays the lex_state before it enters the -yylex() while the middle column displays the tokens and their symbols.

-

The first token m and the second parameter b are preceded by a line-break -but a \n is appended in front of them and it is not treated as a terminal -symbol. That is because the lex_state is EXPR_BEG.

-

However, in the second to last line \n is used as a terminal symbol. -That is because the state is EXPR_ARG

-

And that is how it should be used. Let us have another example.

-
-% rubylex-analyser -e 'class
-C < Object
-end'
-+EXPR_BEG
-EXPR_BEG     C    "class"  kCLASS               EXPR_CLASS
-EXPR_CLASS          "\nC"  tCONSTANT            EXPR_END
-EXPR_END    S         "<"  '<'                  EXPR_BEG
-+EXPR_BEG
-EXPR_BEG    S    "Object"  tCONSTANT            EXPR_ARG
-EXPR_ARG             "\n"  \n                   EXPR_BEG
-EXPR_BEG     C      "end"  kEND                 EXPR_END
-EXPR_END             "\n"  \n                   EXPR_BEG
-
-

The reserved word class is followed by EXPR_CLASS so the line-break is ignored. -However, the superclass Object is followed by EXPR_ARG, so the \n appears.

-
-% rubylex-analyser -e 'obj.
-class'
-+EXPR_BEG
-EXPR_BEG     C      "obj"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG           "."  '.'                  EXPR_DOT
-EXPR_DOT        "\nclass"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG             "\n"  \n                   EXPR_BEG
-
-

'.' is followed by EXPR_DOT so the \n is ignored.

-

Note that class becomes tIDENTIFIER despite being a reserved word. -This is discussed in the next section.

-

Reserved words and identical method names

-

The problem

-

In Ruby, reserved words can used as method names. However, in actuality it’s -not as simple as “it can be used” – there exist three possible contexts:

-
    -
  • Method definition (def xxxx)
  • -
  • Call (obj.xxxx)
  • -
  • Symbol literal (:xxxx)
  • -
-

All three are possible in Ruby. Below we will take a closer look at each.

-

First, the method definition. -It is preceded by the reserved word def so it should work.

-

In case of the method call, omitting the receiver can be a source of difficulty. -However, the scope of use here is even more limited, and omitting the receiver -is actually forbidden. That is, when the method name is a reserved word, the -receiver absolutely cannot be omitted. Perhaps it would be more accurate to say -that it is forbidden in order to guarantee that parsing is always possible.

-

Finally, in case of the symbol, it is preceded by the terminal symbol ':' so -it also should work. However, regardless of reserved words, the ':' here -conflicts with the colon in a?b:c If this is avoided, there should be no -further trouble.

-

For each of these cases, similarly to before, a scanner-based solution and a -parser-based solution exist. For the former use tIDENTIFIER (for example) as -the reserved word that comes after def or . or : For the latter, make -that into a rule. Ruby allows for both solutions to be used in each of the -three cases.

-

Method definition

-

The name part of the method definition. This is handled by the parser.

-

▼ Method definition rule -

-                | kDEF fname
-                  f_arglist
-                  bodystmt
-                  kEND
-                | kDEF singleton dot_or_colon  fname
-                  f_arglist
-                  bodystmt
-                  kEND
-

-

There exist only two rules for method definition – one for normal methods and -one for singleton methods. For both, the name part is fname and it is defined -as follows.

-

fname -

-fname           : tIDENTIFIER
-                | tCONSTANT
-                | tFID
-                | op
-                | reswords
-

-

reswords is a reserved word and op is a binary operator. Both rules consist -of simply all terminal symbols lined up, so I won’t go into detail here. -Finally, for tFID the end contains symbols similarly to gsub! and include?

-

Method call

-

Method calls with names identical to reserved words are handled by the scanner. -The scan code for reserved words is shown below.

-
-Scanning the identifier
-result = (tIDENTIFIER or tCONSTANT)
-
-if (lex_state != EXPR_DOT) {
-    struct kwtable *kw;
-
-    /* See if it is a reserved word.  */
-    kw = rb_reserved_word(tok(), toklen());
-    Reserved word is processed
-}
-
-

EXPR_DOT expresses what comes after the method call dot. Under EXPR_DOT -reserved words are universally not processed. The symbol for reserved words -after the dot becomes either tIDENTIFIER or tCONSTANT.

-

Symbols

-

Reserved word symbols are handled by both the scanner and the parser. -First, the rule.

-

symbol -

-symbol          : tSYMBEG sym

-

sym : fname -                | tIVAR -                | tGVAR -                | tCVAR

-

fname : tIDENTIFIER -                | tCONSTANT -                | tFID -                | op -                | reswords -

-

Reserved words (reswords) are explicitly passed through the parser. This is -only possible because the special terminal symbol tSYMBEG is present at the -start. If the symbol were, for example, ':' it would conflict with the -conditional operator (a?b:c) and stall. Thus, the trick is to recognize -tSYMBEG on the scanner level.

-

But how to cause that recognition? Let’s look at the implementation of the -scanner.

-

yylex-':' -

-3761        case ‘:’:
-3762          c = nextc();
-3763          if (c == ‘:’) {
-3764              if (lex_state == EXPR_BEG ||  lex_state == EXPR_MID ||
-3765                  (IS_ARG() && space_seen)) {
-3766                  lex_state = EXPR_BEG;
-3767                  return tCOLON3;
-3768              }
-3769              lex_state = EXPR_DOT;
-3770              return tCOLON2;
-3771          }
-3772          pushback©;
-3773          if (lex_state == EXPR_END ||
-                  lex_state == EXPR_ENDARG ||
-                  ISSPACE©) {
-3774              lex_state = EXPR_BEG;
-3775              return ‘:’;
-3776          }
-3777          lex_state = EXPR_FNAME;
-3778          return tSYMBEG;

-

(parse.y) -

-

This is a situation when the if in the first half has two consecutive ':' -In this situation, the '::'is scanned in accordance with the leftmost longest -match basic rule.

-

For the next if , the ':' is the aforementioned conditional operator. Both -EXPR_END and EXPR_ENDARG come at the end of the expression, so a parameter -does not appear. That is to say, since there can’t be a symbol, the ':' is a -conditional operator. -Similarly, if the next letter is a space (ISSPACE(c)) , a symbol is unlikely -so it is again a conditional operator.

-

When none of the above applies, it’s all symbols. In that case, a transition to -EXPR_FNAME occurs to prepare for all method names. There is no particular -danger to parsing here, but if this is forgotten, the scanner will not pass -values to reserved words and value calculation will be disrupted.

-

Modifiers

-

The problem

-

For example, for if if there exists a normal notation and one for postfix -modification.

-
-# Normal notation
-if cond then
-  expr
-end
-
-# Postfix
-expr if cond
-
-

This could cause a conflict. The reason can be guessed – again, it’s because -method parentheses have been omitted previously. Observe this example

-
-call if cond then a else b end
-
-

Reading this expression up to the if gives us two possible interpretations.

-
-call((if ....))
-call() if ....
-
-

When unsure, I recommend simply using trial and error and seeing if a conflict -occurs. Let us try to handle it with yacc after changing kIF_MOD to kIF -in the grammar.

-
-% yacc parse.y
-parse.y contains 4 shift/reduce conflicts and 13 reduce/reduce conflicts.
-
-

As expected, conflicts are aplenty. If you are interested, you add the option --v to yacc and build a log. The nature of the conflicts should be shown -there in great detail.

-

Implementation

-

So, what is there to do? In Ruby, on the symbol level (that is, on the scanner -level) the normal if is distinguished from the postfix if by them being -kIF and kIF_MOD respectively. This also applies to all other postfix -operators. In all, there are five – kUNLESS_MOD kUNTIL_MOD kWHILE_MOD -kRESCUE_MOD and kIF_MOD The distinction is made here:

-

yylex-Reserved word

-
4173                  struct kwtable *kw;
-4174
-4175                  /* See if it is a reserved word.  */
-4176                  kw = rb_reserved_word(tok(), toklen());
-4177                  if (kw) {
-4178                      enum lex_state state = lex_state;
-4179                      lex_state = kw->state;
-4180                      if (state == EXPR_FNAME) {
-4181                          yylval.id = rb_intern(kw->name);
-4182                      }
-4183                      if (kw->id[0] == kDO) {
-4184                          if (COND_P()) return kDO_COND;
-4185                          if (CMDARG_P() && state != EXPR_CMDARG)
-4186                              return kDO_BLOCK;
-4187                          if (state == EXPR_ENDARG)
-4188                              return kDO_BLOCK;
-4189                          return kDO;
-4190                      }
-4191                      if (state == EXPR_BEG)  /*** Here ***/
-4192                          return kw->id[0];
-4193                      else {
-4194                          if (kw->id[0] != kw->id[1])
-4195                              lex_state = EXPR_BEG;
-4196                          return kw->id[1];
-4197                      }
-4198                  }
-(parse.y)
-

This is located at the end of yylex after the identifiers are scanned. -The part that handles modifiers is the last (innermost) ifelse Whether -the return value is altered can be determined by whether or not the state is -EXPR_BEG. This is where a modifier is identified. Basically, the variable kw -is the key and if you look far above you will find that it is struct kwtable

-

I’ve already described in the previous chapter how struct kwtable is a -structure defined in keywords and the hash function rb_reserved_word() is -created by gperf. I’ll show the structure here again.

-

keywordsstruct kwtable

-
   1  struct kwtable {char *name; int id[2]; enum lex_state state;};
-(keywords)
-

I’ve already explained about name and id[0] – they are the reserved word -name and its symbol. Here I will speak about the remaining members.

-

First, id[1] is a symbol to deal with modifiers. For example, in case of if -that would be kIF_MOD. -When a reserved word does not have a modifier equivalent, id[0] and id[1] -contain the same things.

-

Because state is enum lex_state it is the state to which a transition -should occur after the reserved word is read. -Below is a list created in the kwstat.rb tool which I made. The tool can be -found on the CD.

-
-% kwstat.rb ruby/keywords
----- EXPR_ARG
-defined?  super     yield
-
----- EXPR_BEG
-and     case    else    ensure  if      module  or      unless  when
-begin   do      elsif   for     in      not     then    until   while
-
----- EXPR_CLASS
-class
-
----- EXPR_END
-BEGIN     __FILE__  end       nil       retry     true
-END       __LINE__  false     redo      self
-
----- EXPR_FNAME
-alias  def    undef
-
----- EXPR_MID
-break   next    rescue  return
-
----- modifiers
-if      rescue  unless  until   while
-
-

The do conflict

-

The problem

-

There are two iterator forms – doend and {} Their difference is in -priority – {} has a much higher priority. A higher priority means that as -part of the grammar a unit is “small” which means it can be put into a smaller -rule. For example, it can be put not into stmt but expr or primary. In -the past {} iterators were in primary while doend iterators were -in stmt

-

By the way, there has been a request for an expression like this:

-
-m do .... end + m do .... end
-
-

To allow for this, put the doend iterator in arg or primary. -Incidentally, the condition for while is expr, meaning it contains arg -and primary, so the do will cause a conflict here. Basically, it looks like -this:

-
-while m do
-  ....
-end
-
-

At first glance, the do looks like the do of while. However, a closer -look reveals that it could be a m doend bundling. Something that’s not -obvious even to a person will definitely cause yacc to conflict. Let’s try it -in practice.

-
-/* do conflict experiment */
-%token kWHILE kDO tIDENTIFIER kEND
-%%
-expr: kWHILE expr kDO expr kEND
-    | tIDENTIFIER
-    | tIDENTIFIER kDO expr kEND
-
-

I simplified the example to only include while, variable referencing and -iterators. This rule causes a shift/reduce conflict if the head of the -conditional contains tIDENTIFIER. If tIDENTIFIER is used for variable -referencing and do is appended to while, then it’s reduction. If it’s made -an iterator do, then it’s a shift.

-

Unfortunately, in a shift/reduce conflict the shift is prioritized, so if left -unchecked, do will become an iterator do. That said, even if a reduction -is forced through operator priorities or some other method, do won’t shift at -all, becoming unusable. Thus, to solve the problem without any contradictions, -we need to either deal with on the scanner level or write a rule that allows to -use operators without putting the doend iterator into expr.

-

However, not putting doend into expr is not a realistic goal. That -would require all rules for expr (as well as for arg and primary) to be -repeated. This leaves us only the scanner solution.

-

Rule-level solution

-

Below is a simplified example of a relevant rule.

-

do symbol -

-primary         : kWHILE expr_value do compstmt kEND

-

do : term -                | kDO_COND

-

primary : operation brace_block -                | method_call brace_block

-

brace_block : ‘{’ opt_block_var compstmt ‘}’ -                | kDO opt_block_var compstmt kEND -

-

As you can see, the terminal symbols for the do of while and for the -iterator do are different. For the former it’s kDO_COND while for the -latter it’s kDO Then it’s simply a matter of pointing that distinction out to -the scanner.

-

Symbol-level solution

-

Below is a partial view of the yylex section that processes reserved words. -It’s the only part tasked with processing do so looking at this code should -be enough to understand the criteria for making the distinction.

-

yylex-Identifier-Reserved word

-
4183                      if (kw->id[0] == kDO) {
-4184                          if (COND_P()) return kDO_COND;
-4185                          if (CMDARG_P() && state != EXPR_CMDARG)
-4186                              return kDO_BLOCK;
-4187                          if (state == EXPR_ENDARG)
-4188                              return kDO_BLOCK;
-4189                          return kDO;
-4190                      }
-(parse.y)
-

It’s a little messy, but you only need the part associated with kDO_COND. -That is because only two comparisons are meaningful. -The first is the comparison between kDO_COND and kDO/kDO_BLOCK -The second is the comparison between kDO and kDO_BLOCK. -The rest are meaningless. -Right now we only need to distinguish the conditional do – leave all the -other conditions alone.

-

Basically, COND_P() is the key.

-

COND_P()

-

cond_stack

-

COND_P() is defined close to the head of parse.y

-

cond_stack -

-  75  #ifdef HAVE_LONG_LONG
-  76  typedef unsigned LONG_LONG stack_type;
-  77  #else
-  78  typedef unsigned long stack_type;
-  79  #endif
-  80
-  81  static stack_type cond_stack = 0;
-  82  #define COND_PUSH(n) (cond_stack = (cond_stack<<1)|((n)&1))
-  83  #define COND_POP() (cond_stack >>= 1)
-  84  #define COND_LEXPOP() do {\
-  85      int last = COND_P();\
-  86      cond_stack >>= 1;\
-  87      if (last) cond_stack |= 1;\
-  88  } while (0)
-  89  #define COND_P() (cond_stack&1)

-

(parse.y) -

-

The type stack_type is either long (over 32 bit) or long long (over 64 -bit). cond_stack is initialized by yycompile() at the start of parsing and -after that is handled only through macros. All you need, then, is to understand -those macros.

-

If you look at COND_PUSH/POP you will see that these macros use integers as -stacks consisting of bits.

-
-MSB←   →LSB
-...0000000000         Initial value 0
-...0000000001         COND_PUSH(1)
-...0000000010         COND_PUSH(0)
-...0000000101         COND_PUSH(1)
-...0000000010         COND_POP()
-...0000000100         COND_PUSH(0)
-...0000000010         COND_POP()
-
-

As for COND_P(), since it determines whether or not the least significant bit -(LSB) is a 1, it effectively determines whether the head of the stack is a 1.

-

The remaining COND_LEXPOP() is a little weird. It leaves COND_P() at the -head of the stack and executes a right shift. Basically, it “crushes” the -second bit from the bottom with the lowermost bit.

-
-MSB←   →LSB
-...0000000000         Initial value 0
-...0000000001         COND_PUSH(1)
-...0000000010         COND_PUSH(0)
-...0000000101         COND_PUSH(1)
-...0000000011         COND_LEXPOP()
-...0000000100         COND_PUSH(0)
-...0000000010         COND_LEXPOP()
-
-

Now I will explain what that means.

-

Investigating the function

-

Let us investigate the function of this stack. To do that I will list up all -the parts where COND_PUSH() COND_POP() are used.

-
-        | kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
---
-        | kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();}
---
-        | kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
---
-      case '(':
-                :
-                :
-        COND_PUSH(0);
-        CMDARG_PUSH(0);
---
-      case '[':
-                :
-                :
-        COND_PUSH(0);
-        CMDARG_PUSH(0);
---
-      case '{':
-                :
-                :
-        COND_PUSH(0);
-        CMDARG_PUSH(0);
---
-      case ']':
-      case '}':
-      case ')':
-        COND_LEXPOP();
-        CMDARG_LEXPOP();
-
-

From this we can derive the following general rules

-
    -
  • At the start of a conditional expression PUSH(1)
  • -
  • At opening parenthesis PUSH(0)
  • -
  • At the end of a conditional expression POP()
  • -
  • At closing parenthesisLEXPOP()
  • -
-

With this, you should see how to use it. If you think about it for a minute, -the name cond_stack itself is clearly the name for a macro that determines -whether or not it’s on the same level as the conditional expression (see image 2)

-

-

(condp)
-Figure 2: Changes of COND_P()

-

-

Using this trick should also make situations like the one shown below easy to -deal with.

-
-while (m do .... end)   # do is an iterator do(kDO)
-  ....
-end
-
-

This means that on a 32-bit machine in the absence of long long if -conditional expressions or parentheses are nested at 32 levels, things could -get strange. Of course, in reality you won’t need to nest so deep so there’s no -actual risk.

-

Finally, the definition of COND_LEXPOP() looks a bit strange – that seems to -be a way of dealing with lookahead. However, the rules now do not allow for -lookahead to occur, so there’s no purpose to make the distinction between POP -and LEXPOP. Basically, at this time it would be correct to say that -COND_LEXPOP() has no meaning.

-

tLPAREN_ARG(1)

-

The problem

-

This one is very complicated. It only became workable in in Ruby 1.7 and only -fairly recently. The core of the issue is interpreting this:

-
-call (expr) + 1
-
-

As one of the following

-
-(call(expr)) + 1
-call((expr) + 1)
-
-

In the past, it was always interpreted as the former. That is, the parentheses -were always treated as “Method parameter parentheses”. But since Ruby 1.7 it -became possible to interpret it as the latter – basically, if a space is added, -the parentheses become “Parentheses of expr

-

I will also provide an example to explain why the interpretation changed. -First, I wrote a statement as follows

-
-p m() + 1
-
-

So far so good. But let’s assume the value returned by m is a fraction and -there are too many digits. Then we will have it displayed as an integer.

-
-p m() + 1 .to_i   # ??
-
-

Uh-oh, we need parentheses.

-
-p (m() + 1).to_i
-
-

How to interpret this? Up to 1.6 it will be this

-
-(p(m() + 1)).to_i
-
-

The much-needed to_i is rendered meaningless, which is unacceptable. -To counter that, adding a space between it and the parentheses will cause the -parentheses to be treated specially as expr parentheses.

-

For those eager to test this, this feature was implemented in parse.y -revision 1.100(2001-05-31). Thus, it should be relatively prominent when -looking at the differences between it and 1.99. This is the command to find the -difference.

-
-~/src/ruby % cvs diff -r1.99 -r1.100 parse.y
-
-

Investigation

-

First let us look at how the set-up works in reality. Using the ruby-lexer -tool{ruby-lexer: located in tools/ruby-lexer.tar.gz on the CD} we can look -at the list of symbols corresponding to the program.

-
-% ruby-lexer -e 'm(a)'
-tIDENTIFIER '(' tIDENTIFIER ')' '\n'
-
-

Similarly to Ruby, -e is the option to pass the program directly from the -command line. With this we can try all kinds of things. Let’s start with the -problem at hand – the case where the first parameter is enclosed in parentheses.

-
-% ruby-lexer -e 'm (a)'
-tIDENTIFIER tLPAREN_ARG tIDENTIFIER ')' '\n'
-
-

After adding a space, the symbol of the opening parenthesis became tLPAREN_ARG. -Now let’s look at normal expression parentheses.

-
-% ruby-lexer -e '(a)'
-tLPAREN tIDENTIFIER ')' '\n'
-
-

For normal expression parentheses it seems to be tLPAREN. To sum up:

- - - - - - - - - - - - - - - - - -
Input Symbol of opening parenthesis
m(a) '('
m (a) tLPAREN_ARG
(a) tLPAREN
-

Thus the focus is distinguishing between the three. For now tLPAREN_ARG is -the most important.

-

The case of one parameter

-

We’ll start by looking at the yylex() section for '('

-

yylex-'(' -

-3841        case ‘(’:
-3842          command_start = Qtrue;
-3843          if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
-3844              c = tLPAREN;
-3845          }
-3846          else if (space_seen) {
-3847              if (lex_state == EXPR_CMDARG) {
-3848                  c = tLPAREN_ARG;
-3849              }
-3850              else if (lex_state == EXPR_ARG) {
-3851                  c = tLPAREN_ARG;
-3852                  yylval.id = last_id;
-3853              }
-3854          }
-3855          COND_PUSH(0);
-3856          CMDARG_PUSH(0);
-3857          lex_state = EXPR_BEG;
-3858          return c;

-

(parse.y) -

-

Since the first if is tLPAREN we’re looking at a normal expression -parenthesis. The distinguishing feature is that lex_state is either BEG or -MID – that is, it’s clearly at the beginning of the expression.

-

The following space_seen shows whether the parenthesis is preceded by a space. -If there is a space and lex_state is either ARG or CMDARG, basically if -it’s before the first parameter, the symbol is not '(' but tLPAREN_ARG. -This way, for example, the following situation can be avoided

-
-m(              # Parenthesis not preceded by a space. Method parenthesis ('(')
-m arg, (        # Unless first parameter, expression parenthesis (tLPAREN)
-
-

When it is neither tLPAREN nor tLPAREN_ARG, the input character c is used -as is and becomes '('. This will definitely be a method call parenthesis.

-

If such a clear distinction is made on the symbol level, no conflict should -occur even if rules are written as usual. Simplified, it becomes something like -this:

-
-stmt         : command_call
-
-method_call  : tIDENTIFIER '(' args ')'    /* Normal method */
-
-command_call : tIDENTIFIER command_args    /* Method with parentheses omitted */
-
-command_args : args
-
-args         : arg
-             : args ',' arg
-
-arg          : primary
-
-primary      : tLPAREN compstmt ')'        /* Normal expression parenthesis */
-             | tLPAREN_ARG expr ')'        /* First parameter enclosed in parentheses */
-             | method_call
-
-

Now I need you to focus on method_call and command_call If you leave the -'(' without introducing tLPAREN_ARG, then command_args will produce -args, args will produce arg, arg will produce primary. Then, '(' -will appear from tLPAREN_ARG and conflict with method_call (see image 3)

-

-

(trees)
-Figure 3: method_call and command_call

-

-

The case of two parameters and more

-

One might think that if the parenthesis becomes tLPAREN_ARG all will be well. -That is not so. For example, consider the following

-
-m (a, a, a)
-
-

Before now, expressions like this one were treated as method calls and did not -produce errors. However, if tLPAREN_ARG is introduced, the opening -parenthesis becomes an expr parenthesis, and if two or more parameters are -present, that will cause a parse error. This needs to be resolved for the sake -of compatibility.

-

Unfortunately, rushing ahead and just adding a rule like

-
-command_args : tLPAREN_ARG args ')'
-
-

will just cause a conflict. Let’s look at the bigger picture and think carefully.

-
-stmt         : command_call
-             | expr
-
-expr         : arg
-
-command_call : tIDENTIFIER command_args
-
-command_args : args
-             | tLPAREN_ARG args ')'
-
-args         : arg
-             : args ',' arg
-
-arg          : primary
-
-primary      : tLPAREN compstmt ')'
-             | tLPAREN_ARG expr ')'
-             | method_call
-
-method_call  : tIDENTIFIER '(' args ')'
-
-

Look at the first rule of command_args Here, args produces arg Then arg -produces primary and out of there comes the tLPAREN_ARG rule. And since -expr contains arg and as it is expanded, it becomes like this:

-
-command_args : tLPAREN_ARG arg ')'
-             | tLPAREN_ARG arg ')'
-
-

This is a reduce/reduce conflict, which is very bad.

-

So, how can we deal with only 2+ parameters without causing a conflict? We’ll -have to write to accommodate for that situation specifically. In practice, it’s -solved like this:

-

command_args -

-command_args    : open_args

-

open_args : call_args -                | tLPAREN_ARG ‘)’ -                | tLPAREN_ARG call_args2 ‘)’

-

call_args : command -                | args opt_block_arg -                | args ‘,’ tSTAR arg_value opt_block_arg -                | assocs opt_block_arg -                | assocs ‘,’ tSTAR arg_value opt_block_arg -                | args ‘,’ assocs opt_block_arg -                | args ‘,’ assocs ‘,’ tSTAR arg opt_block_arg -                | tSTAR arg_value opt_block_arg -                | block_arg

-

call_args2 : arg_value ‘,’ args opt_block_arg -                | arg_value ‘,’ block_arg -                | arg_value ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ args ‘,’ tSTAR arg_value opt_block_arg -                | assocs opt_block_arg -                | assocs ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ assocs opt_block_arg -                | arg_value ‘,’ args ‘,’ assocs opt_block_arg -                | arg_value ‘,’ assocs ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ args ‘,’ assocs ‘,’ -                                  tSTAR arg_value opt_block_arg -                | tSTAR arg_value opt_block_arg -                | block_arg

-

primary : literal -                | strings -                | xstring -                       : -                | tLPAREN_ARG expr ‘)’ -

-

Here command_args is followed by another level – open_args which may not be -reflected in the rules without consequence. The key is the second and third -rules of this open_args This form is similar to the recent example, but is -actually subtly different. The difference is that call_args2 has been -introduced. The defining characteristic of this call_args2 is that the number -of parameters is always two or more. This is evidenced by the fact that most -rules contain ',' The only exception is assocs, but since assocs does not -come out of expr it cannot conflict anyway.

-

That wasn’t a very good explanation. To put it simply, in a grammar where this:

-
-command_args    : call_args
-
-

doesn’t work, and only in such a grammar, the next rule is used to make an -addition. Thus, the best way to think here is “In what kind of grammar would -this rule not work?” Furthermore, since a conflict only occurs when the -primary of tLPAREN_ARG appears at the head of call_args, the scope can be -limited further and the best way to think is “In what kind of grammar does this -rule not work when a tIDENTIFIER tLPAREN_ARG line appears?” Below are a few -examples.

-
-m (a, a)
-
-

This is a situation when the tLPAREN_ARG list contains two or more items.

-
-m ()
-
-

Conversely, this is a situation when the tLPAREN_ARG list is empty.

-
-m (*args)
-m (&block)
-m (k => v)
-
-

This is a situation when the tLPAREN_ARG list contains a special expression -(one not present in expr).

-

This should be sufficient for most cases. Now let’s compare the above with a -practical implementation.

-

open_args(1) -

-open_args       : call_args
-                | tLPAREN_ARG   ‘)’
-

-

First, the rule deals with empty lists

-

open_args(2) -

-                | tLPAREN_ARG call_args2  ‘)’

-

call_args2 : arg_value ‘,’ args opt_block_arg -                | arg_value ‘,’ block_arg -                | arg_value ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ args ‘,’ tSTAR arg_value opt_block_arg -                | assocs opt_block_arg -                | assocs ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ assocs opt_block_arg -                | arg_value ‘,’ args ‘,’ assocs opt_block_arg -                | arg_value ‘,’ assocs ‘,’ tSTAR arg_value opt_block_arg -                | arg_value ‘,’ args ‘,’ assocs ‘,’ -                                  tSTAR arg_value opt_block_arg -                | tSTAR arg_value opt_block_arg -                | block_arg -

-

And call_args2 deals with elements containing special types such as assocs, -passing of arrays or passing of blocks. With this, the scope is now -sufficiently broad.

-

tLPAREN_ARG(2)

-

The problem

-

In the previous section I said that the examples provided should be sufficient -for “most” special method call expressions. I said “most” because iterators are -still not covered. For example, the below statement will not work:

-
-m (a) {....}
-m (a) do .... end
-
-

In this section we will once again look at the previously introduced parts with -solving this problem in mind.

-

Rule-level solution

-

Let us start with the rules. The first part here is all familiar rules, -so focus on the do_block part

-

command_call -

-command_call    : command
-                | block_command

-

command : operation command_args

-

command_args : open_args

-

open_args : call_args -                | tLPAREN_ARG ‘)’ -                | tLPAREN_ARG call_args2 ‘)’

-

block_command : block_call

-

block_call : command do_block

-

do_block : kDO_BLOCK opt_block_var compstmt ‘}’ -                | tLBRACE_ARG opt_block_var compstmt ‘}’ -

-

Both do and { are completely new symbols kDO_BLOCK and tLBRACE_ARG. -Why isn’t it kDO or '{' you ask? In this kind of situation the best answer -is an experiment, so we will try replacing kDO_BLOCK with kDO and -tLBRACE_ARG with '{' and processing that with yacc

-
-% yacc parse.y
-conflicts:  2 shift/reduce, 6 reduce/reduce
-
-

It conflicts badly. A further investigation reveals that this statement is the -cause.

-
-m (a), b {....}
-
-

That is because this kind of statement is already supposed to work. b{....} -becomes primary. And now a rule has been added that concatenates the block -with m That results in two possible interpretations:

-
-m((a), b) {....}
-m((a), (b {....}))
-
-

This is the cause of the conflict – namely, a 2 shift/reduce conflict.

-

The other conflict has to do with doend

-
-m((a)) do .... end     # Add do〜end using block_call
-m((a)) do .... end     # Add do〜end using primary
-
-

These two conflict. This is 6 reduce/reduce conflict.

-

{} iterator

-

This is the important part. As shown previously, you can avoid a conflict by -changing the do and '{' symbols.

-

yylex-'{'

-
3884        case '{':
-3885          if (IS_ARG() || lex_state == EXPR_END)
-3886              c = '{';          /* block (primary) */
-3887          else if (lex_state == EXPR_ENDARG)
-3888              c = tLBRACE_ARG;  /* block (expr) */
-3889          else
-3890              c = tLBRACE;      /* hash */
-3891          COND_PUSH(0);
-3892          CMDARG_PUSH(0);
-3893          lex_state = EXPR_BEG;
-3894          return c;
-(parse.y)
-

IS_ARG() is defined as

-

IS_ARG -

-3104  #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)

-

(parse.y) -

-

Thus, when the state is EXPR_ENDARG it will always be false. In other words, -when lex_state is EXPR_ENDARG, it will always become tLBRACE_ARG, so the -key to everything is the transition to EXPR_ENDARG.

-

EXPR_ENDARG

-

Now we need to know how to set EXPR_ENDARG I used grep to find where it is -assigned.

-

▼ Transition toEXPR_ENDARG -

-open_args       : call_args
-                | tLPAREN_ARG  {lex_state = EXPR_ENDARG;} ‘)’
-                | tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ‘)’

-

primary : tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ‘)’ -

-

That’s strange. One would expect the transition to EXPR_ENDARG to occur after -the closing parenthesis corresponding to tLPAREN_ARG, but it’s actually -assigned before ')' I ran grep a few more times thinking there might be -other parts setting the EXPR_ENDARG but found nothing.

-

Maybe there’s some mistake. Maybe lex_state is being changed some other way. -Let’s use rubylex-analyser to visualize the lex_state transition.

-
-% rubylex-analyser -e 'm (a) { nil }'
-+EXPR_BEG
-EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG S         "("  tLPAREN_ARG          EXPR_BEG
-                                              0:cond push
-                                              0:cmd push
-                                              1:cmd push-
-EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG           ")"  ')'                  EXPR_END
-                                              0:cond lexpop
-                                              1:cmd lexpop
-+EXPR_ENDARG
-EXPR_ENDARG S         "{"  tLBRACE_ARG          EXPR_BEG
-                                              0:cond push
-                                             10:cmd push
-                                              0:cmd resume
-EXPR_BEG    S       "nil"  kNIL                 EXPR_END
-EXPR_END    S         "}"  '}'                  EXPR_END
-                                              0:cond lexpop
-                                              0:cmd lexpop
-EXPR_END             "\n"  \n                   EXPR_BEG
-
-

The three big branching lines show the state transition caused by yylex(). -On the left is the state before yylex() The middle two are the word text and -its symbols. Finally, on the right is the lex_state after yylex()

-

The problem here are parts of single lines that come out as +EXPR_ENDARG. -This indicates a transition occurring during parser action. According to this, -for some reason an action is executed after reading the ')' a transition to -EXPR_ENDARG occurs and '{' is nicely changed into tLBRACE_ARG This is -actually a pretty high-level technique – indiscriminately (ab)using -the LALR up to the (1).

-

Abusing the lookahead

-

ruby -y can bring up a detailed display of the yacc parser engine. -This time we will use it to more closely trace the parser.

-
-% ruby -yce 'm (a) {nil}' 2>&1 | egrep '^Reading|Reducing'
-Reducing via rule 1 (line 303),  -> @1
-Reading a token: Next token is 304 (tIDENTIFIER)
-Reading a token: Next token is 340 (tLPAREN_ARG)
-Reducing via rule 446 (line 2234), tIDENTIFIER  -> operation
-Reducing via rule 233 (line 1222),  -> @6
-Reading a token: Next token is 304 (tIDENTIFIER)
-Reading a token: Next token is 41 (')')
-Reducing via rule 392 (line 1993), tIDENTIFIER  -> variable
-Reducing via rule 403 (line 2006), variable  -> var_ref
-Reducing via rule 256 (line 1305), var_ref  -> primary
-Reducing via rule 198 (line 1062), primary  -> arg
-Reducing via rule 42 (line 593), arg  -> expr
-Reducing via rule 260 (line 1317),  -> @9
-Reducing via rule 261 (line 1317), tLPAREN_ARG expr @9 ')'  -> primary
-Reading a token: Next token is 344 (tLBRACE_ARG)
-                         :
-                         :
-
-

Here we’re using the option -c which stops the process at just compiling and --e which allows to give a program from the command line. And we’re using -grep to single out token read and reduction reports.

-

Start by looking at the middle of the list. ')' is read. Now look at the end -– the reduction (execution) of embedding action (@9) finally happens. Indeed, -this would allow EXPR_ENDARG to be set after the ')' before the '{' -But is this always the case? Let’s take another look at the part where it’s set.

-
-Rule 1    tLPAREN_ARG  {lex_state = EXPR_ENDARG;} ')'
-Rule 2    tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ')'
-Rule 3    tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ')'
-
-

The embedding action can be substituted with an empty rule. For example, -we can rewrite this using rule 1 with no change in meaning whatsoever.

-
-target  : tLPAREN_ARG tmp ')'
-tmp     :
-            {
-                lex_state = EXPR_ENDARG;
-            }
-
-

Assuming that this is before tmp, it’s possible that one terminal symbol will -be read by lookahead. Thus we can skip the (empty) tmp and read the next. -And if we are certain that lookahead will occur, the assignment to lex_state -is guaranteed to change to EXPR_ENDARG after ')' -But is ')' certain to be read by lookahead in this rule?

-

Ascertaining lookahead

-

This is actually pretty clear. Think about the following input.

-
-m () { nil }        # A
-m (a) { nil }       # B
-m (a,b,c) { nil }   # C
-
-

I also took the opportunity to rewrite the rule to make it easier to understand -(with no actual changes).

-
-rule1: tLPAREN_ARG             e1  ')'
-rule2: tLPAREN_ARG  one_arg    e2  ')'
-rule3: tLPAREN_ARG  more_args  e3  ')'
-
-e1:   /* empty */
-e2:   /* empty */
-e3:   /* empty */
-
-

First, the case of input A. Reading up to

-
-m (         # ... tLPAREN_ARG
-
-

we arrive before the e1. If e1 is reduced here, another rule cannot be -chosen anymore. Thus, a lookahead occurs to confirm whether to reduce e1 and -continue with rule1 to the bitter end or to choose a different rule. -Accordingly, if the input matches rule1 it is certain that ')' will be read -by lookahead.

-

On to input B. First, reading up to here

-
-m (         # ... tLPAREN_ARG
-
-

Here a lookahead occurs for the same reason as described above. -Further reading up to here

-
-m (a        # ... tLPAREN_ARG '(' tIDENTIFIER
-
-

Another lookahead occurs. It occurs because depending on whether what follows -is a ',' or a ')' a decision is made between rule2 and rule3 If what -follows is a ',' then it can only be a comma to separate parameters, thus -rule3 the rule for two or more parameters, is chosen. This is also true if -the input is not a simple a but something like an if or literal. When the -input is complete, a lookahead occurs to choose between rule2 and rule3 - -the rules for one parameter and two or more parameters respectively.

-

The presence of a separate embedding action is present before ')' in every -rule. There’s no going back after an action is executed, so the parser will try -to postpone executing an action until it is as certain as possible. For that -reason, situations when this certainty cannot be gained with a single lookahead -should be excluded when building a parser as it is a conflict.

-

Proceeding to input C.

-
-m (a, b, c
-
-

At this point anything other than rule3 is unlikely so we’re not expecting a -lookahead. And yet, that is wrong. If the following is '(' then it’s a method -call, but if the following is ',' or ')' it needs to be a variable -reference. Basically, this time a lookahead is needed to confirm parameter -elements instead of embedding action reduction.

-

But what about the other inputs? For example, what if the third parameter is a -method call?

-
-m (a, b, c(....)    # ... ',' method_call
-
-

Once again a lookahead is necessary because a choice needs to be made between -shift and reduction depending on whether what follows is ',' or ')'. Thus, -in this rule in all instances the ')' is read before the embedding action is -executed. This is quite complicated and more than a little impressive.

-

But would it be possible to set lex_state using a normal action instead of an -embedding action? For example, like this:

-
-                | tLPAREN_ARG ')' { lex_state = EXPR_ENDARG; }
-
-

This won’t do because another lookahead is likely to occur before the action is -reduced. This time the lookahead works to our disadvantage. With this it should -be clear that abusing the lookahead of a LALR parser is pretty tricky and not -something a novice should be doing.

-

doend iterator

-

So far we’ve dealt with the {} iterator, but we still have doend -left. Since they’re both iterators, one would expect the same solutions to work, -but it isn’t so. The priorities are different. For example,

-
-m a, b {....}          # m(a, (b{....}))
-m a, b do .... end     # m(a, b) do....end
-
-

Thus it’s only appropriate to deal with them differently.

-

That said, in some situations the same solutions do apply. -The example below is one such situation

-
-m (a) {....}
-m (a) do .... end
-
-

In the end, our only option is to look at the real thing. -Since we’re dealing with do here, we should look in the part of yylex() -that handles reserved words.

-

yylex-Identifiers-Reserved words-do -

-4183                      if (kw→id0 == kDO) {
-4184                          if (COND_P()) return kDO_COND;
-4185                          if (CMDARG_P() && state != EXPR_CMDARG)
-4186                              return kDO_BLOCK;
-4187                          if (state == EXPR_ENDARG)
-4188                              return kDO_BLOCK;
-4189                          return kDO;
-4190                      }

-

(parse.y) -

-

This time we only need the part that distinguishes between kDO_BLOCK and kDO. -Ignore kDO_COND Only look at what’s always relevant in a finite-state scanner.

-

The decision-making part using EXPR_ENDARG is the same as tLBRACE_ARG so -priorities shouldn’t be an issue here. Similarly to '{' the right course of -action is probably to make it kDO_BLOCK

-

The problem lies with CMDARG_P() and EXPR_CMDARG. Let’s look at both.

-

CMDARG_P()

-

cmdarg_stack -

-  91  static stack_type cmdarg_stack = 0;
-  92  #define CMDARG_PUSH(n) (cmdarg_stack = (cmdarg_stack<<1)|((n)&1))
-  93  #define CMDARG_POP() (cmdarg_stack >>= 1)
-  94  #define CMDARG_LEXPOP() do {\
-  95      int last = CMDARG_P();\
-  96      cmdarg_stack >>= 1;\
-  97      if (last) cmdarg_stack |= 1;\
-  98  } while (0)
-  99  #define CMDARG_P() (cmdarg_stack&1)

-

(parse.y) -

-

The structure and interface (macro) of cmdarg_stack is completely identical -to cond_stack. It’s a stack of bits. Since it’s the same, we can use the same -means to investigate it. Let’s list up the places which use it. -First, during the action we have this:

-
-command_args    :  {
-                        $<num>$ = cmdarg_stack;
-                        CMDARG_PUSH(1);
-                    }
-                  open_args
-                    {
-                        /* CMDARG_POP() */
-                        cmdarg_stack = $<num>1;
-                        $$ = $2;
-                    }
-
-

$<num>$ represents the left value with a forced casting. In this case it -comes out as the value of the embedding action itself, so it can be produced in -the next action with $<num>1. Basically, it’s a structure where cmdarg_stack -is hidden in $$ before open_args and then restored in the next action.

-

But why use a hide-restore system instead of a simple push-pop? That will be -explained at the end of this section.

-

Searching yylex() for more CMDARG relations, I found this.

- - - - - - - - - - - - - -
Token Relation
'(' '[' '{' CMDARG_PUSH(0)
')' ']' '}' CMDARG_LEXPOP()
-

Basically, as long as it is enclosed in parentheses, CMDARG_P() is false.

-

Consider both, and it can be said that when command_args , a parameter for a -method call with parentheses omitted, is not enclosed in parentheses -CMDARG_P() is true.

-

EXPR_CMDARG

-

Now let’s take a look at one more condition – EXPR_CMDARG -Like before, let us look for place where a transition to EXPR_CMDARG occurs.

-

yylex-Identifiers-State Transitions -

-4201              if (lex_state == EXPR_BEG ||
-4202                  lex_state == EXPR_MID ||
-4203                  lex_state == EXPR_DOT ||
-4204                  lex_state == EXPR_ARG ||
-4205                  lex_state == EXPR_CMDARG) {
-4206                  if (cmd_state)
-4207                      lex_state = EXPR_CMDARG;
-4208                  else
-4209                      lex_state = EXPR_ARG;
-4210              }
-4211              else {
-4212                  lex_state = EXPR_END;
-4213              }

-

(parse.y) -

-

This is code that handles identifiers inside yylex() -Leaving aside that there are a bunch of lex_state tests in here, let’s look -first at cmd_state -And what is this?

-

cmd_state -

-3106  static int
-3107  yylex()
-3108  {
-3109      static ID last_id = 0;
-3110      register int c;
-3111      int space_seen = 0;
-3112      int cmd_state;
-3113
-3114      if (lex_strterm) {
-              /* ……omitted…… */
-3132      }
-3133      cmd_state = command_start;
-3134      command_start = Qfalse;

-

(parse.y) -

-

Turns out it’s an yylex local variable. Furthermore, an investigation using -grep revealed that here is the only place where its value is altered. This -means it’s just a temporary variable for storing command_start during a -single run of yylex

-

When does command_start become true, then?

-

command_start -

-2327  static int command_start = Qtrue;

-

2334 static NODE* -2335 yycompile(f, line) -2336 char *f; -2337 int line; -2338 { -                   : -2380 command_start = 1;

-

      static int -      yylex() -      { -                   : -            case ‘\n’: -              /* ……omitted…… */ -3165 command_start = Qtrue; -3166 lex_state = EXPR_BEG; -3167 return ‘\n’;

-

3821 case ‘;’: -3822 command_start = Qtrue;

-

3841 case ‘(’: -3842 command_start = Qtrue;

-

(parse.y) -

-

From this we understand that command_start becomes true when one of the -parse.y static variables \n ; ( is scanned.

-

Summing up what we’ve covered up to now, first, when \n ; ( is read, -command_start becomes true and during the next yylex() run cmd_state -becomes true.

-

And here is the code in yylex() that uses cmd_state

-

yylex-Identifiers-State transitions -

-4201              if (lex_state == EXPR_BEG ||
-4202                  lex_state == EXPR_MID ||
-4203                  lex_state == EXPR_DOT ||
-4204                  lex_state == EXPR_ARG ||
-4205                  lex_state == EXPR_CMDARG) {
-4206                  if (cmd_state)
-4207                      lex_state = EXPR_CMDARG;
-4208                  else
-4209                      lex_state = EXPR_ARG;
-4210              }
-4211              else {
-4212                  lex_state = EXPR_END;
-4213              }

-

(parse.y) -

-

From this we understand the following: when after \n ; ( the state is -EXPR_BEG MID DOT ARG CMDARG and an identifier is read, a transition to -EXPR_CMDARG occurs. However, lex_state can only become EXPR_BEG following -a \n ; ( so when a transition occurs to EXPR_CMDARG the lex_state loses -its meaning. The lex_state restriction is only important to transitions -dealing with EXPR_ARG

-

Based on the above we can now think of a situation where the state is -EXPR_CMDARG. For example, see the one below. The underscore is the current -position.

-
-m _
-m(m _
-m m _
-
-

Conclusion

-

Let us now return to the do decision code.

-

yylex-Identifiers-Reserved words-kDO-kDO_BLOCK -

-4185                          if (CMDARG_P() && state != EXPR_CMDARG)
-4186                              return kDO_BLOCK;

-

(parse.y) -

-

Inside the parameter of a method call with parentheses omitted but not before -the first parameter. That means from the second parameter of command_call -onward. Basically, like this:

-
-m arg, arg do .... end
-m (arg), arg do .... end
-
-

Why is the case of EXPR_CMDARG excluded? This example should clear It up

-
-m do .... end
-
-

This pattern can already be handled using the doend iterator which uses -kDO and is defined in primary Thus, including that case would cause another -conflict.

-

Reality and truth

-

Did you think we’re done? Not yet. -Certainly, the theory is now complete, but only if everything that has been -written is correct. -As a matter of fact, there is one falsehood in this section. -Well, more accurately, it isn’t a falsehood but an inexact statement. -It’s in the part about CMDARG_P()

-
-

Actually, CMDARG_P() becomes true when inside command_args , that is to say, -inside the parameter of a method call with parentheses omitted.

-
-

But where exactly is “inside the parameter of a method call with parentheses -omitted”? Once again, let us use rubylex-analyser to inspect in detail.

-
-% rubylex-analyser -e  'm a,a,a,a;'
-+EXPR_BEG
-EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG S         "a"  tIDENTIFIER          EXPR_ARG
-                                              1:cmd push-
-EXPR_ARG              ","  ','                  EXPR_BEG
-EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ","  ','                  EXPR_BEG
-EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ","  ','                  EXPR_BEG
-EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ";"  ';'                  EXPR_BEG
-                                              0:cmd resume
-EXPR_BEG     C       "\n"  '                    EXPR_BEG
-
-

The 1:cmd push- in the right column is the push to cmd_stack. When the -rightmost digit in that line is 1 CMDARG_P() become true. To sum up, the -period of CMDARG_P() can be described as:

-
-

From immediately after the first parameter of a method call with parentheses omitted -To the terminal symbol following the final parameter

-
-

But, very strictly speaking, even this is still not entirely accurate.

-
-% rubylex-analyser -e  'm a(),a,a;'
-+EXPR_BEG
-EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG S         "a"  tIDENTIFIER          EXPR_ARG
-                                              1:cmd push-
-EXPR_ARG              "("  '('                  EXPR_BEG
-                                              0:cond push
-                                             10:cmd push
-EXPR_BEG     C        ")"  ')'                  EXPR_END
-                                              0:cond lexpop
-                                              1:cmd lexpop
-EXPR_END              ","  ','                  EXPR_BEG
-EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ","  ','                  EXPR_BEG
-EXPR_BEG              "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG              ";"  ';'                  EXPR_BEG
-                                              0:cmd resume
-EXPR_BEG     C       "\n"  '                    EXPR_BEG
-
-

When the first terminal symbol of the first parameter has been read, -CMDARG_P() is true. Therefore, the complete answer would be:

-
-

From the first terminal symbol of the first parameter of a method call with parentheses omitted -To the terminal symbol following the final parameter

-
-

What repercussions does this fact have? Recall the code that uses CMDARG_P()

-

yylex-Identifiers-Reserved words-kDO-kDO_BLOCK -

-4185                          if (CMDARG_P() && state != EXPR_CMDARG)
-4186                              return kDO_BLOCK;

-

(parse.y) -

-

EXPR_CMDARG stands for “Before the first parameter of command_call” and is -excluded. But wait, this meaning is also included in CMDARG_P(). -Thus, the final conclusion of this section:

-
-

EXPR_CMDARG is completely useless

-
-

Truth be told, when I realized this, I almost broke down crying. I was sure it -had to mean SOMETHING and spent enormous effort analyzing the source, but -couldn’t understand anything. Finally, I ran all kind of tests on the code -using rubylex-analyser and arrived at the conclusion that it has no meaning -whatsoever.

-

I didn’t spend so much time doing something meaningless just to fill up more -pages. It was an attempt to simulate a situation likely to happen in reality. -No program is perfect, all programs contain their own mistakes. Complicated -situations like the one discussed here are where mistakes occur most easily, -and when they do, reading the source material with the assumption that it’s -flawless can really backfire. In the end, when reading the source code, you can -only trust the what actually happens.

-

Hopefully, this will teach you the importance of dynamic analysis. When -investigating something, focus on what really happens. The source code will not -tell you everything. It can’t tell anything other than what the reader infers.

-

And with this very useful sermon, I close the chapter.

-

Still not the end

-

Another thing I forgot. I can’t end the chapter without explaining why -CMDARG_P() takes that value. Here’s the problematic part:

-

command_args -

-1209  command_args    :  {
-1210                          $$ = cmdarg_stack;
-1211                          CMDARG_PUSH(1);
-1212                      }
-1213                    open_args
-1214                      {
-1215                          /* CMDARG_POP() */
-1216                          cmdarg_stack = $1;
-1217                          $$ = $2;
-1218                      }

-

1221 open_args : call_args

-

(parse.y) -

-

All things considered, this looks like another influence from lookahead. -command_args is always in the following context:

-
-tIDENTIFIER _
-
-

Thus, this looks like a variable reference or a method call. If it’s a variable -reference, it needs to be reduced to variable and if it’s a method call it -needs to be reduced to operation We cannot decide how to proceed without -employing lookahead. Thus a lookahead always occurs at the head of -command_args and after the first terminal symbol of the first parameter is -read, CMDARG_PUSH() is executed.

-

The reason why POP and LEXPOP exist separately in cmdarg_stack is also -here. Observe the following example:

-
-% rubylex-analyser -e 'm m (a), a'
--e:1: warning: parenthesize argument(s) for future version
-+EXPR_BEG
-EXPR_BEG     C        "m"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG S         "m"  tIDENTIFIER          EXPR_ARG
-                                              1:cmd push-
-EXPR_ARG    S         "("  tLPAREN_ARG          EXPR_BEG
-                                              0:cond push
-                                             10:cmd push
-                                            101:cmd push-
-EXPR_BEG     C        "a"  tIDENTIFIER          EXPR_CMDARG
-EXPR_CMDARG           ")"  ')'                  EXPR_END
-                                              0:cond lexpop
-                                             11:cmd lexpop
-+EXPR_ENDARG
-EXPR_ENDARG           ","  ','                  EXPR_BEG
-EXPR_BEG    S         "a"  tIDENTIFIER          EXPR_ARG
-EXPR_ARG             "\n"  \n                   EXPR_BEG
-                                             10:cmd resume
-                                              0:cmd resume
-
-

Looking only at the parts related to cmd and how they correspond to each other…

-
-  1:cmd push-       parserpush(1)
- 10:cmd push        scannerpush
-101:cmd push-       parserpush(2)
- 11:cmd lexpop      scannerpop
- 10:cmd resume      parserpop(2)
-  0:cmd resume      parserpop(1)
-
-

The cmd push- with a minus sign at the end is a parser push. Basically, -push and pop do not correspond. Originally there were supposed to be two -consecutive push- and the stack would become 110, but due to the lookahead -the stack became 101 instead. CMDARG_LEXPOP() is a last-resort measure to -deal with this. The scanner always pushes 0 so normally what it pops should -also always be 0. When it isn’t 0, we can only assume that it’s 1 due to the -parser push being late. Thus, the value is left.

-

Conversely, at the time of the parser pop the stack is supposed to be back in -normal state and usually pop shouldn’t cause any trouble. When it doesn’t do -that, the reason is basically that it should work right. Whether popping or -hiding in $$ and restoring, the process is the same. When you consider all -the following alterations, it’s really impossible to tell how lookahead’s -behavior will change. Moreover, this problem appears in a grammar that’s going -to be forbidden in the future (that’s why there is a warning). To make -something like this work, the trick is to consider numerous possible situations -and respond them. And that is why I think this kind of implementation is right -for Ruby. Therein lies the real solution.

- - - -
- - diff --git a/htmls/css/styles.css b/htmls/css/styles.css deleted file mode 100644 index 93e4f9c..0000000 --- a/htmls/css/styles.css +++ /dev/null @@ -1,173 +0,0 @@ -body { - background-color: white; - color: black; - text-align: left; - line-height: 140%; - margin-top: 5%; - margin-left: 2em; - width: 40em; -} - -h1 { - text-align: left; - font-size: 200%; - margin-top: 0em; - margin-bottom: 1em; - padding-left: 12px; - border-left: 80px solid #33a; - line-height: 80px; -} - -h2 { - text-align: left; - font-size: 150%; - margin-top: 3em; - margin-bottom: 1em; - border-bottom: 2px solid #33a; -} - -h3 { - text-align: left; - font-size: 150%; - margin-top: 1em; - margin-bottom: 0.1em; - padding-left: 8px; - border-left: 12px solid #33a; -} - -h4 { - text-align: left; - font-size: 150%; - margin-top: 1em; - margin-bottom: 0.1em; -} - -ul { - padding-left: 1em; -} - -li { - padding-left: 0em; -} - -dl { - margin-top: 0em; - margin-bottom: 0em; - margin-left: 0em; - margin-right: 0em; -} - -dt { - margin-top: 0.5em; - margin-bottom: 0.2em; - margin-left: 0em; - margin-right: 0em; -} - -dd { - margin-top: 0em; - margin-bottom: 0em; - margin-left: 4em; - margin-right: 0em; -} - -p.caption { - margin-botton: 0px; -} - -pre { - line-height: 110%; - padding: 8px; - background: #eee; -} - -span.ami { - color: black; - background-color: #ccc; -} - -.image { - align: center; - margin-top: 2em; - margin-bottom: 2em; -} - -address { - font-style: normal; - line-height: 110%; - text-align: right; -} - -a:link, a:visited { - color: #33a; - text-decoration: none; -} - -a:active, a:visited { - color: #666; - text-decoration: none; -} - -a:hover, a:focus { - text-decoration: underline; -} - -/* -- */ -footer { - margin-top: 2em; -} - -body { - font-family: Georgia, serif; -} - -h1 code, h2 code, h3 code, h4 code, h5 code{ - font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; - font-weight: normal; -} - - -pre { - font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; - font-size: .8em; -} - -code { - font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; - font-size: .8em; -} - -h1#chapter { font-size: 150%; } - -th { padding-right: .5em } - -pre.longlist, pre.screen { - padding: 8px; - background: #eee; -} - -pre.emlist { - background: white; - padding-left: 2em; -} - -p { width: 35em } - -.image ul { - list-style-type: none; - padding-left: 0; - font-size: .8em; - margin: 0 -} - -.image p { margin: 0 } - -/* for chapter 16 */ -div.longlist { - padding: 8px; - background: #eee; - font-size: .8em; - font-family: Menlo, Monaco, "Andale Mono", "Lucida console", "courier New", monospace; -} - -div.longlist p { margin: 0 } diff --git a/htmls/evaluator.html b/htmls/evaluator.html deleted file mode 100644 index 4506dbe..0000000 --- a/htmls/evaluator.html +++ /dev/null @@ -1,1236 +0,0 @@ - - - - - Chapter 13: Structure of the evaluator | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 13: Structure of the evaluator

-

Outline

-

Interface

-

We are not familiar with the word “Hyo-ka-ki” (evaluator). Literally, it must -be a “-ki” (device) to “hyo-ka” (evaluating). Then, what is “hyo-ka”?

-

“Hyo-ka” is the definitive translation of “evaluate”. However, if the premise -is describing about programing languages, it can be considered as an error in -translation. It’s hard to avoid that the word “hyo-ka” gives the impression -of “whether it is good or bad”.

-

“Evaluate” in the context of programing languages has nothing to do with -“good or bad”, and its meaning is more close to “speculating” or “executing”. -The origin of “evaluate” is a Latin word “ex+value+ate”. -If I translate it directly, -it is “turn it into a value”. This may be the simplest way to understand: -to determine the value from an expression expressed in text.

-

Very frankly speaking, the bottom line is that evaluating is executing a -written expression and getting the result of it. Then why is it not called just -“execute”? It’s because evaluating is not only executing.

-

For example, in an ordinary programming language, when we write “3”, -it will be dealt with as an integer 3. -This situation is sometimes described as “the result of evaluating -”3" is 3". It’s hard to say an expression of a constant is executed, -but it is certainly an evaluation. -It’s all right if there exist a programming language in which the letter “3”, -when it is evaluated, will be dealt with (evaluated) as an integer 6.

-

I’ll introduce another example. -When an expression consists of multiple constants, -sometimes the constants are calculated during the compiling process (constant folding). - We usually don’t call it “executing” because executing indicates the process -that the created binary is working. However, no matter when it is calculated -you’ll get the same result from the same program.

-

In other words, “evaluating” is usually equals to “executing”, but essentially -“evaluating” is different from “executing”. For now, only this point is what -I’d like you to remember.

-

The characteristics of ruby's evaluator.

-

The biggest characteristic of ruby ’s evaluator is that, as this is also of -the whole ruby ’s interpretor, the difference in expressions between -the C-level code (extension libraries) and the Ruby-level code is small. -In ordinary programming languages, -the amount of the features of its interpretor we can use from extension -libraries is usually very limited, but there are awfully few limits in ruby . -Defining classes, defining methods and calling a method without limitation, -these can be taken for granted. We can also use exception handling, iterators. -Furthermore, threads.

-

But we have to compensate for the conveniences somewhere. -Some codes are weirdly hard to implement, some codes have a lot overhead, -and there are a lot of places implementing the almost same thing twice both for -C and Ruby.

-

Additionally, ruby is a dynamic language, -it means that you can construct and evaluate a string at runtime. -That is eval which is a function-like method. As you expected, -it is named after “evaluate”. By using it, you can even do something like this:

-
-lvar = 1
-answer = eval("lvar + lvar")    # the answer is 2
-
-

There are also Module#module_eval and Object#instance_eval , each method -behaves slightly differently. I’ll describe about them in detail in Chapter 17: Dynamic evaluation.

-

eval.c

-

The evaluator is implemented in eval.c . However, this eval.c is a -really huge file: it has 9000 lines, its size is 200K bytes, -and the number of the functions in it is 309. It is hard to fight against. -When the size becomes this amount, -it’s impossible to figure out its structure by just looking over it.

-

So how can we do? -First, the bigger the file, the less possibility of its content not separated at all. -In other words, the inside of it must be modularized into small portions. -Then, how can we find the modules? -I’ll list up some ways.

-

The first way is to print the list of the defined functions and look at the -prefixes of them. rb_dvar_ , rb_mod_ , rb_thread — there are plenty of -functions with these prefixes. -Each prefix clearly indicate a group of the same type of functions.

-

Alternatively, as we can tell when looking at the code of the class libraries, -Init_xxxx() is always put at the end of a block in ruby . -Therefore, Init_xxxx() also indicates a break between modules.

-

Additionally, the names are obviously important, too. -Since eval() and rb_eval() and eval_node() appear close to each other, -we naturally think there should be a deep relationship among them.

-

Finally, in the source code of ruby , the definitions of types or variables -and the declarations of prototypes often indicate a break between modules.

-

Being aware of these points when looking, -it seems that eval.c can be mainly divided into these modules listed below:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Safe Level already explained in Chapter 7: Security
Method Entry Manipulations finding or deleting syntax trees which are actual method bodies
Evaluator Core the heart of the evaluator that rb_eval() is at its center.
Exception generations of exceptions and creations of backtraces
Method the implementation of method call
Iterator the implementation of functions that are related to blocks
Load loading and evaluating external files
Proc the implementation of Proc
Thread the implementation of Ruby threads
-

Among them, “Load” and “Thread” are the parts that essentially should not be in eval.c . -They are in eval.c merely because of the restrictions of C language. -To put it more precisely, they need the macros such as PUSH_TAG defined in eval.c . -So, I decided to exclude the two topics from Part 3 and deal with them -at Part 4. And, it’s probably all right if I don’t explain the safe level here -because I’ve already done in Part 1.

-

Excluding the above three, the six items are left to be described. -The below table shows the corresponding chapter of each of them:

- - - - - - - - - - - - - - - - - - - - - - - - - -
Method Entry Manipulations the next chapter: Context
Evaluator Core the entire part of Part 3
Exception this chapter
Method Chapter 15: Methods
Iterator Chapter 16: Blocks
Proc Chapter 16: Blocks
-

From main by way of ruby_run to rb_eval

-

Call Graph

-

The true core of the evaluator is a function called rb_eval() . -In this chapter, we will follow the path from main() to that rb_eval() . -First of all, here is a rough call graph around rb_eval :

-
-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
-
-

I put the file names on the right side when moving to another file. -Gazing this carefully, the first thing we’ll notice is that the functions of -eval.c call the functions of ruby.c back.

-

I wrote it as “calling back” because main.c and ruby.c are relatively for -the implementation of ruby command. eval.c is the implementation of the -evaluator itself which keeps a little distance from ruby command. -In other words, eval.c is supposed to be used by ruby.c and calling the -functions of ruby.c from eval.c makes eval.c less independent.

-

Then, why is this in this way? It’s mainly because of the restrictions of C language. -Because the functions such as ruby_prog_init() and ruby_process_options() -start to use the API of the ruby world, it’s possible an exception occurs. -However, in order to stop an exception of Ruby, it’s necessary to use the macro -named PUSH_TAG() which can only be used in eval.c . In other words, essentially, -ruby_init() and ruby_run() should have been defined in ruby.c .

-

Then, why isn’t PUSH_TAG an extern function or something which is available -to other files? -Actually, PUSH_TAG can only be used as a pair with POP_TAG as follows:

-
-PUSH_TAG();
-/* do lots of things */
-POP_TAG();
-
-

Because of its implementation, the two macros should be put into the same function. -It’s possible to implement in a way to be able to divide them into different functions, -but not in such way because it’s slower.

-

The next thing we notice is, the fact that it sequentially calls the functions -named ruby_xxxx from main() seems very meaningful. -Since they are really obviously symmetric, it’s odd if there’s not any relationship.

-

Actually, these three functions have deep relationships. Simply speaking, all of -these three are “built-in Ruby interfaces”. That is, they are used only when -creating a command with built-in ruby interpretor and not when writing -extension libraries. Since ruby command itself can be considered as one of -programs with built-in Ruby in theory, to use these interfaces is natural.

-

What is the ruby_ prefix ? So far, the all of ruby ’s functions are prefixed -with rb_ . Why are there the two types: rb_ and ruby_ ? I investigated but -could not understand the difference, so I asked directly. The answer was, -“ruby_ is for the auxiliary functions of ruby command and rb_ is for the -official interfaces”

-

“Then, why are the variables like ruby_scope are ruby_ ?”, I asked further. -It seems this is just a coincidence. The variables like ruby_scope -are originally named as the_xxxx , but in the middle of the version 1.3 there’s -a change to add prefixes to all interfaces. At that time ruby_ was added to -the “may-be-internals-for-some-reasons” variables.

-

The bottom line is that what ruby_ is attached to are either what to support -ruby command or the internal variables and what rb_ is attached to are the -official interfaces of ruby interpretor.

-

main()

-

First, straightforwardly, I’ll start with main() . -It is nice that this is very short.

-

main()

- -
-  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)
-
-

#if def NT is obviously the NT of Windows NT. But somehow NT is also -defined in Win9x. So, it means Win32 environment. -NtInitialize() initializes argc argv and the socket system (WinSock) for -Win32. Because this function is only doing the initialization, it’s not -interesting and not related to the main topic. Thus, I omit this.

-

And, __MACOS__ is not “Ma-Ko-Su” but Mac OS. In this case, it means -Mac OS 9 and before, and it does not include Mac OS X. Even though such -#ifdef remains, as I wrote at the beginning of this book, the current version -can not run on Mac OS 9 and before. It’s just a legacy from when ruby was -able to run on it. Therefore, I also omit this code.

-

By the way, as it is probably known by the readers who are familiar with C language, -the identifiers starting with an under bar are reserved for the system libraries or OS. -However, although they are called “reserved”, using it is almost never result in an error, -but if using a little weird cc it could result in an error. -For example, it is the cc of HP-US. HP-US is an UNIX which HP is creating. -If there’s any opinion such as HP-UX is not weird, I would deny it out loud.

-

Anyway, conventionally, we don’t define such identifiers in user applications.

-

Now, I’ll start to briefly explain about the built-in Ruby interfaces.

-

ruby_init()

-

ruby_init() initializes the Ruby interpretor. -Since only a single interpretor of the current Ruby can exist in a process, -it does not need neither arguments or a return value. -This point is generally considered as “lack of features”.

-

When there’s only a single interpretor, -what have difficulty most is probably around the development environment of Ruby. -Concretely, they are the applications such as irb , RubyWin, and RDE. -Although loading a rewritten program, the classes which are supposed to be -deleted would remain. To counter this with the reflection API is not impossible -but requires a lot of effort.

-

However, it seems that Mr. Matsumoto (Matz) purposefully limits the number of -interpretors to one. “it’s impossible to initialize completely” appears to be -its reason. For example, “the loaded extension libraries could not be removed” -is taken as an example.

-

The code of ruby_init() is omitted because it’s unnecessary to read.

-

ruby_options()

-

What to parse command-line options for the Ruby interpreter is ruby_options() . -Of course, depending on the command, we do not have to use this.

-

Inside this function, -r (load a library) and --e (pass a program from command-line) are processed. -This is also where the file passed as a command-line argument is parsed as -a Ruby program.

-

ruby command reads the main program from a file if it was given, otherwise from stdin . -After that, using rb_compile_string() or rb_compile_file() introduced at Part 2, -it compiles the text into a syntax tree. -The result will be set into the global variable ruby_eval_tree .

-

I also omit the code of ruby_options() because it’s just doing necessary -things one by one and not interesting.

-

ruby_run()

-

Finally, ruby_run() starts to evaluate the syntax tree which was set to ruby_eval_tree . -We also don’t always need to call this function. Other than ruby_run() , -for instance, we can evaluate a string by using a function named rb_eval_string() .

-

ruby_run()

- -
-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)
-
-

We can see the macros PUSH_xxxx() , but we can ignore them for now. I’ll -explain about around them later when the time comes. The important thing here -is only eval_node() . Its content is:

-

eval_node()

- -
-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)
-
-

This calls rb_eval() on ruby_eval_tree . The ruby_eval_tree_begin is -storing the statements registered by BEGIN . But, this is also not important.

-

And, ruby_stop() inside of ruby_run() terminates all threads and -finalizes all objects and checks exceptions and, in the end, calls exit() . -This is also not important, so we won’t see this.

-

rb_eval()

-

Outline

-

Now, rb_eval() . This function is exactly the real core of ruby . -One rb_eval() call processes a single NODE , and the whole syntax tree will -be processed by calling recursively. (Fig.1)

-

-

(rbeval)
-Fig.1: rb_eval

-

-

rb_eval is, as the same as yylex() , made of a huge switch statement and -branching by each type of the nodes. First, let’s look at the outline.

-

rb_eval() Outline

- -
-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:
-                   :
-              (plenty of case statements)
-                   :
-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)
-
-

In the omitted part, plenty of the codes to process all nodes are listed. -By branching like this, it processes each node. When the code is only a few, -it will be processed in rb_eval() . But when it becoming many, it will be a -separated function. Most of functions in eval.c are created in this way.

-

When returning a value from rb_eval() , it uses the macro RETURN() instead -of return , in order to always pass through CHECK_INTS . Since this macro is -related to threads, you can ignore this until the chapter about it.

-

And finally, the local variables result and node are volatile for GC.

-

NODE_IF

-

Now, taking the if statement as an example, let’s look at the process of -the rb_eval() evaluation concretely. -From here, in the description of rb_eval() ,

-
    -
  • The source code (a Ruby program)
  • -
  • Its corresponding syntax tree
  • -
  • The partial code of rb_eval() to process the node.
  • -
-

these three will be listed at the beginning.

-

▼source program

- -
-if true
-  'true expr'
-else
-  'false expr'
-end
-
-

▼ its corresponding syntax tree ( nodedump )

- -
-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
-
-

As we’ve seen in Part 2, elsif and unless can be, by contriving the ways to assemble, -bundled to a single NODE_IF type, so we don’t have to treat them specially.

-

rb_eval()NODE_IF

- -
-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)
-
-

What is important is only the last if statement. -If rewriting it without any change in its meaning, it becomes this:

-
-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, at (A), evaluating (the node of) the Ruby’s condition statement and -testing its value with RTEST() . -I’ve mentioned that RTEST() is a macro to test whether or not -a VALUE is true of Ruby. -If that was true, evaluating the then side clause at (B). -If false, evaluating the else side clause at ©.

-

In addition, I’ve mentioned that if statement of Ruby also has its own value, -so it’s necessary to return a value. -Since the value of an if is the value of either the then side or the else -side which is the one executed, returning it by using the macro RETURN() .

-

In the original list, it does not call rb_eval() recursively but just does goto . -This is the "conversion from tail recursion to goto " which has also appeared -in the previous chapter “Syntax tree construction”.

-

NODE_NEW_LINE

-

Since there was NODE_NEWLINE at the node for a if statement, -let’s look at the code for it.

-

rb_eval()NODE_NEWLINE

- -
-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)
-
-

There’s nothing particularly difficult.

-

call_trace_func() has already appeared at NODE_IF . Here is a simple -explanation of what kind of thing it is. This is a feature to trace a Ruby -program from Ruby level. The debugger ( debug.rb ) and the tracer ( tracer.rb ) -and the profiler ( profile.rb ) and irb (interactive ruby command) and more -are using this feature.

-

By using the function-like method set_trace_func you can register a Proc -object to trace, and that Proc object is stored into trace_func . If -trace_func is not 0, it means not QFalse , it will be considered as a Proc -object and executed (at call_trace_func() ).

-

This call_trace_func() has nothing to do with the main topic and not so -interesting as well. Therefore in this book, from now on, -I’ll completely ignore it. If you are interested in it, I’d like you to -challenge after finishing the Chapter 16: Blocks.

-

Pseudo-local Variables

-

NODE_IF and such are interior nodes in a syntax tree. -Let’s look at the leaves, too.

-

rb_eval() Ppseudo-Local Variable Nodes

- -
-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)
-
-

We’ve seen self as the argument of rb_eval() . I’d like you to make sure it -by going back a little. -The others are probably not needed to be explained.

-

Jump Tag

-

Next, I’d like to explain NODE_WHILE which is corresponding to while , -but to implement break or next only with recursive calls of a function is difficult. -Since ruby enables these syntaxes by using what named “jump tag”, -I’ll start with describing it first.

-

Simply put, “jump tag” is a wrapper of setjmp() and longjump() which are -library functions of C language. Do you know about setjmp() ? -This function has already appeared at gc.c , -but it is used in very abnormal way there. -setjmp() is usually used to jump over functions. -I’ll explain by taking the below code as an example. -The entry point is parent() .

-

setjmp() and longjmp()

- -
-jmp_buf buf;
-
-void child2(void) {
-    longjmp(buf, 34);   /* go back straight to parent
-                           the return value of setjmp becomes 34 */
-    puts("This message will never be printed.");
-}
-
-void child1(void) {
-    child2();
-    puts("This message will never be printed.");
-}
-
-void parent(void) {
-    int result;
-    if ((result = setjmp(buf)) == 0) {
-        /* normally returned from setjmp */
-        child1();
-    } else {
-        /* returned from child2 via longjmp */
-        printf("%d\n", result);   /* shows 34 */
-    }
-}
-
-

First, when setjmp() is called at parent() , -the executing state at the time is saved to the argument buf . -To put it a little more directly, the address of the top of the machine -stack and the CPU registers are saved. -If the return value of setjmp() was 0, it means it normally returned from setjmp() , -thus you can write the subsequent code as usual. -This is the if side. Here, it calls child1() .

-

Next, the control moves to child2() and calls longjump , -then it can go back straight to the place where the argument buf was setjmp ed. -So in this case, it goes back to the setjmp at parent() . -When coming back via longjmp , the return value of setjmp becomes -the value of the second argument of longjmp , so the else side is executed. -And, even if we pass 0 to longjmp , -it will be forced to be another value. Thus it’s fruitless.

-

Fig.2 shows the state of the machine stack. -The ordinary functions return only once for each call. -However, it’s possible setjmp() returns twice. -Is it helpful to grasp the concept if I say that it is something like fork() ?

-

-

(setjmp)
-Fig.2: setjmp() longjmp() Image

-

-

Now, we’ve learned about setjmp() as a preparation. -In eval.c , EXEC_TAG corresponds to setjmp() and JUMP_TAG() corresponds -to longjmp() respectively. (Fig.3)

-

-

(jumptag)
-Fig.3: “tag jump” image

-

-

Take a look at this image, it seems that EXEC_TAG() does not have any arguments. -Where has jmp_buf gone? -Actually, in ruby , jmp_buf is wrapped by the struct struct tag. -Let’s look at it.

-

struct tag

- -
- 783  struct tag {
- 784      jmp_buf buf;
- 785      struct FRAME *frame;   /* FRAME when PUSH_TAG */
- 786      struct iter *iter;     /* ITER  when PUSH_TAG */
- 787      ID tag;                /* tag type */
- 788      VALUE retval;          /* the return value of this jump */
- 789      struct SCOPE *scope;   /* SCOPE when PUSH_TAG */
- 790      int dst;               /* the destination ID */
- 791      struct tag *prev;
- 792  };
-
-(eval.c)
-
-

Because there’s the member prev , we can infer that struct tag is probably -a stack structure using a linked list. Moreover, by looking around it, we can -find the macros PUSH_TAG() and POP_TAG , thus it definitely seems a stack.

-

PUSH_TAG() POP_TAG()

- -
- 793  static struct tag *prot_tag;   /* the pointer to the head of the machine stack */
-
- 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)
-
-

I’d like you to be flabbergasted here because the actual tag is fully allocated -at the machine stack as a local variable. (Fig.4). Moreover, do ~ while is -divided between the two macros. -This might be one of the most awful usages of the C preprocessor. -Here is the macros PUSH / POP coupled and extracted to make it easy to read.

-
-do {
-    struct tag _tag;
-    _tag.prev = prot_tag;   /* save the previous tag */
-    prot_tag = &_tag;       /* push a new tag on the stack */
-    /* do several things */
-    prot_tag = _tag.prev;   /* restore the previous tag */
-} while (0);
-
-

This method does not have any overhead of function calls, -and its cost of the memory allocation is next to nothing. -This technique is only possible because the ruby evaluator is made of -recursive calls of rb_eval() .

-

-

(tagstack)
-Fig.4: the tag stack is embedded in the machine stack

-

-

Because of this implementation, it’s necessary that PUSH_TAG and POP_TAG -are in the same one function as a pair. Plus, since it’s not supposed to be -carelessly used at the outside of the evaluator, -we can’t make them available to other files.

-

Additionally, let’s also take a look at EXEC_TAG() and JUMP_TAG() .

-

EXEC_TAG() JUMP_TAG()

- -
- 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 are wrapped by EXEC_TAG() and JUMP_TAG() respectively. -The name EXEC_TAG() can look like a wrapper of longjmp() at first sight, -but this one is to execute setjmp() .

-

Based on all of the above, I’ll explain the mechanism of while . -First, when starting while it does EXEC_TAG() ( setjmp ). -After that, it executes the main body by calling rb_eval() -recursively. If there’s break or next , it does JUMP_TAG() ( longjmp ). -Then, it can go back to the start point of the while loop. (Fig.5)

-

-

(whilejmp)
-Fig.5: the implementation of while by using “tag jump”

-

-

Though break was taken as an example here, what cannot be implemented without -jumping is not only break . Even if we limit the case to while , -there are next and redo . -Additionally, return from a method and exceptions also should have to -climb over the wall of rb_eval() . -And since it’s cumbersome to use a different tag stack for each case, -we want for only one stack to handle all cases in one way or another.

-

What we need to make it possible is just attaching information about -“what the purpose of this jump is”. -Conveniently, the return value of setjmp() could be specified as the argument -of longjmp() , thus we can use this. The types are expressed by the following flags:

-

▼tag type

- -
- 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 exceptions */
- 834  #define TAG_THROW       0x7    /* throw(won't be explained in this boook)*/
- 835  #define TAG_FATAL       0x8    /* fatal : exceptions which are not catchable */
- 836  #define TAG_MASK        0xf
-
-(eval.c)
-
-

The meanings are written as each comment. The last TAG_MASK is the bitmask to -take out these flags from a return value of setjmp() . This is because the -return value of setjmp() can also include information which is not about a -“type of jump”.

-

NODE_WHILE

-

Now, by examining the code of NODE_WHILE , let’s check the actual usage of tags.

-

▼ The Source Program

- -
-while true
-  'true_expr'
-end
-
-

▼ Its corresponding syntax tree( nodedump-short

- -
-NODE_WHILE
-nd_state = 1 (while)
-nd_cond:
-    NODE_TRUE
-nd_body:
-    NODE_STR
-    nd_lit = "true_expr":String
-
-

rb_evalNODE_WHILE

- -
-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)
-
-

The idiom which will appear over and over again appeared in the above code.

-
-PUSH_TAG(PROT_NONE);
-switch (state = EXEC_TAG()) {
-  case 0:
-    /* process normally */
-    break;
-  case TAG_a:
-    state = 0;    /* clear state because the jump waited for comes */
-    /* do the process of when jumped with TAG_a */
-    break;
-  case TAG_b:
-    state = 0;    /* clear state because the jump waited for comes */
-    /* do the process of when jumped with TAG_b */
-    break;
-  default
-    break;        /* this jump is not waited for, then ... */
-}
-POP_TAG();
-if (state) JUMP_TAG(state);   /* .. jump again here */
-
-

First, as PUSH_TAG() and POP_TAG() are the previously described mechanism, -it’s necessary to be used always as a pair. Also, they need to be written -outside of EXEC_TAG() . And, apply EXEC_TAG() to the just pushed jmp_buf . -This means doing setjmp() . -If the return value is 0, since it means immediately returning from setjmp() , -it does the normal processing (this usually contains rb_eval() ). -If the return value of EXEC_TAG() is not 0, since it means returning via longjmp() , -it filters only the own necessary jumps by using case and -lets the rest ( default ) pass.

-

It might be helpful to see also the code of the jumping side. -The below code is the handler of the node of redo .

-

rb_eval()NODE_REDO

- -
-2560  case NODE_REDO:
-2561    CHECK_INTS;
-2562    JUMP_TAG(TAG_REDO);
-2563    break;
-
-(eval.c)
-
-

As a result of jumping via JUMP_TAG() , it goes back to the last EXEC_TAG() . -The return value at the time is the argument TAG_REDO . Being aware of this, -I’d like you to look at the code of NODE_WHILE and check what route is taken.

-

The idiom has enough explained, now I’ll explain about the code of NODE_WHILE -a little more in detail. As mentioned, since the inside of case 0: is the main -process, I extracted only that part. -Additionally, I moved some labels to enhance readability.

-
-  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:
-
-

There are the two places calling rb_eval() on node->nd_state which -corresponds to the conditional statement. It seems that only the first test of -the condition is separated. This is to deal with both do ~ while and while -at once. When node->nd_state is 0 it is a do ~ while , when 1 it is an -ordinary while . The rest might be understood by following step-by-step, -I won’t particularly explain.

-

By the way, I feel like it easily becomes an infinite loop if there is next -or redo in the condition statement. Since it is of course exactly what the -code means, it’s the fault of who wrote it, but I’m a little curious about it. -So, I’ve actually tried it.

-
-% ruby -e 'while next do nil end'
--e:1: void value expression
-
-

It’s simply rejected at the time of parsing. -It’s safe but not an interesting result. -What produces this error is value_expr() of parse.y .

-

The value of an evaluation of while

-

while had not had its value for a long time, but it has been able to return -a value by using break since ruby 1.7. -This time, let’s focus on the flow of the value of an evaluation. -Keeping in mind that the value of the local variable result becomes the -return value of rb_eval() , I’d like you to look at the following code:

-
-        result = Qnil;
-        switch (state = EXEC_TAG()) {
-          case 0:
-            /* the main process */
-          case TAG_REDO:
-          case TAG_NEXT:
-            /* each jump */
-
-          case TAG_BREAK:
-            state = 0;
-            result = prot_tag->retval;     (A)
-          default:
-            break;
-        }
-        RETURN(result);
-
-

What we should focus on is only (A). The return value of the jump seems to be -passed via prot_tag->retval which is a struct tag. -Here is the passing side:

-

rb_eval()NODE_BREAK

- -
-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, by using the macro return_value() , it assigns the value to the -struct of the top of the tag stack.

-

The basic flow is this, but in practice there could be another EXEC_TAG -between EXEC_TAG() of NODE_WHILE and JUMP_TAG() of NODE_BREAK . -For example, rescue of an exception handling can exist between them.

-
-while cond       # EXEC_TAG() for NODE_WHILE
-  begin          # EXEC_TAG() again for rescue
-    break 1
-  rescue
-  end
-end
-
-

Therefore, it’s hard to determine whether or not the strict tag of when doing -JUMP_TAG() at NODE_BREAK is the one which was pushed at NODE_WHILE . -In this case, because retval is propagated in POP_TAG() as shown below, -the return value can be passed to the next tag without particular thought.

-

POP_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)
-
-

This can probably be depicted as Fig.6.

-

-

(usetag)
-Fig.6: the return value propagation

-

-

Exception

-

As the second example of the usage of “tag jump”, we’ll look at how exceptions -are dealt with.

-

raise

-

When I explained while , we looked at the setjmp() side first. This time, -we’ll look at the longjmp() side first for a change. It’s rb_exc_raise() -which is the substance of raise .

-

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 (an instance of Exception or one of its subclass). -Notice that It seems to jump with TAG_RAISE this time. -And the below code is very simplified rb_longjmp() .

-

rb_longjmp() (simplified)

- -
-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);
-}
-
-

Well, though this can be considered as a matter of course, this is just to jump -as usual by using JUMP_TAG() .

-

What is ruby_errinfo ? By doing grep a few times, I figured out that this -variable is the substance of the global variable $! of Ruby. -Since this variable indicates the exception which is currently occurring, -naturally its substance ruby_errinfo should have the same meaning as well.

-

The Big Picture

-

▼the source program

- -
-begin
-  raise('exception raised')
-rescue
-  'rescue clause'
-ensure
-  'ensure clause'
-end
-
-

▼the syntax tree( nodedump-short

- -
-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
-
-

As the right order of rescue and ensure is decided at parser level, -the right order is -strictly decided at syntax tree as well. NODE_ENSURE is always at the “top”, -NODE_RESCUE comes next, the main body (where raise exist) is the last. -Since NODE_BEGIN is a node to do nothing, you can consider NODE_ENSURE is -virtually on the top.

-

This means, since NODE_ENSURE and NODE_RESCUE are above the main body which -we want to protect, we can stop raise by merely doing EXEC_TAG() . Or rather, -the two nodes are put above in syntax tree for this purpose, is probably more -accurate to say.

-

ensure

-

We are going to look at the handler of NODE_ENSURE which is the node of ensure .

-

rb_eval()NODE_ENSURE

- -
-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 branch using if is another idiom to deal with tag. -It interrupts a jump by doing EXEC_TAG() then evaluates the ensure clause ( -( node->nd_ensr ). As for the flow of the process, it’s probably straightforward.

-

Again, we’ll try to think about the value of an evaluation. -To check the specification first,

-
-begin
-  expr0
-ensure
-  expr1
-end
-
-

for the above statement, the value of the whole begin will be the value of -expr0 regardless of whether or not ensure exists. -This behavior is reflected to the code (A-1,2), -so the value of the evaluation of an ensure clause is completely discarded.

-

At (B-1,3), it deals with the evaluated value of when a jump occurred at the main body. -I mentioned that the value of this case is stored in prot_tag->retval , -so it saves the value to a local variable to prevent from being carelessly -overwritten during the execution of the ensure clause (B-1). -After the evaluation of the ensure clause, it restores the value by using -return_value() (B-2). -When any jump has not occurred, state==0 in this case, -prot_tag->retval is not used in the first place.

-

rescue

-

It’s been a little while, I’ll show the syntax tree of rescue again just in case.

-

▼Source Program

- -
-begin
-  raise()
-rescue ArgumentError, TypeError
-  'error raised'
-end
-
-

▼ Its Syntax Tree ( nodedump-short )

- -
-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)
-
-

I’d like you to make sure that (the syntax tree of) the statement to be -rescue ed is “under” NODE_RESCUE .

-

rb_eval()NODE_RESCUE

- -
-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); /* evaluate the body */
-2598        }
-2599        POP_TAG();
-2600        if (state == TAG_RAISE) { /* an exception occurred at the body */
-2601            NODE * volatile resq = node->nd_resq;
-2602
-2603            while (resq) { /* deal with the rescue clause one by one */
-2604                ruby_current_node = resq;
-2605                if (handle_rescue(self, resq)) { /* If dealt with by this clause */
-2606                    state = 0;
-2607                    PUSH_TAG(PROT_NONE);
-2608                    if ((state = EXEC_TAG()) == 0) {
-2609                        result = rb_eval(self, resq->nd_body);
-2610                    }                            /* evaluate the rescue clause */
-2611                    POP_TAG();
-2612                    if (state == TAG_RETRY) { /* Since retry occurred, */
-2613                        state = 0;
-2614                        ruby_errinfo = Qnil;  /* the exception is stopped */
-2615                        goto retry_entry;     /* convert to goto */
-2616                    }
-2617                    if (state != TAG_RAISE) {  /* Also by rescue and such */
-2618                        ruby_errinfo = e_info; /* the exception is stopped  */
-2619                    }
-2620                    break;
-2621                }
-2622                resq = resq->nd_head; /* move on to the next rescue clause */
-2623            }
-2624        }
-2625        else if (node->nd_else) { /* when there is an else clause, */
-2626            if (!state) { /* evaluate it only when any exception has not occurred. */
-2627                result = rb_eval(self, node->nd_else);
-2628            }
-2629        }
-2630        if (state) JUMP_TAG(state); /* the jump was not waited for */
-2631    }
-2632    break;
-
-(eval.c)
-
-

Even though the size is not small, it’s not difficult because it only simply -deal with the nodes one by one. -This is the first time handle_rescue() appeared, -but for some reasons we cannot look at this function now. -I’ll explain only its effects here. Its prototype is this,

-
-static int handle_rescue(VALUE self, NODE *resq)
-
-

and it determines whether the currently occurring exception ( ruby_errinfo ) is -a subclass of the class that is expressed by resq ( TypeError , for instance). -The reason why passing self is that it’s necessary to call rb_eval() inside -this function in order to evaluate resq .

- - - -
- - diff --git a/htmls/fin.html b/htmls/fin.html deleted file mode 100644 index 801b11f..0000000 --- a/htmls/fin.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - - Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

第20章 Rubyの未来

-

第20章 Rubyの未来 -h2. 解決すべき課題

-

@ruby@は「完成してしまったソフトウェア」ではない。まだまだ発展途上で -あり、多くの課題を抱えている。まずは現在のインタプリタに内在する -問題を摘出してみよう。話題の順番はだいたい本書の章の順番に沿っている。

-

GCの性能

-

現在のGCの性能は「特に悪くないが、特に良くもない」と言ったところだろう -か。「特に悪くない」というのは「日常生活で困ることはない」ということで、 -「特に良くもない」というのは「高負荷になると弱点が露呈する」という意味 -である。例えば大量にオブジェクトを作ってそのまま保持し続けるアプリケー -ションだと速度が急激に低下してしまう。GCのたびに全オブジェクトをマーク -することになるうえ、オブジェクトが回収できないものでさらにGCの回数まで -増えてしまうからである。この問題には第5章で触れた世代別GCが効 -果的なはずだ(少なくとも理論的にはそういうことになっている)。

-

また反応速度の点でも改善の余地がある。現在のGCの実行中はインタプリタ全 -体が停止するので、エディタだとかGUIアプリケーションだと時々「ぐっ」と -固まって反応が中断することになる。例えそれが0.1秒程度だろうとも、 -文字をタイプしている途中に止まられたりすると非常に印象が悪い。今はそ -ういうアプリケーションはあまり作られていないか、あってもさほど大きくな -いためこの点があまり問題にならないのだろう。だがいずれそういうものが出 -てくればインクリメンタルGCの導入を考える必要もあるかもしれない。

-

パーサの実装

-

第二部で見たように@ruby@のパーサの実装は -既に@yacc@を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな -い。拡張の予定がないのならいいが、この後には「キーワード引数」という -大物の導入が予定されているし、@yacc@の制限のせいで欲しい文法が表現でき -ない、なんてことになったら悲しい。

-

パーサの再利用

-

Rubyのパーサは非常に複雑だ。特に@lex_state@のあたりを真面目に扱う -のがとても大変である。そのせいで、Rubyプログラムを埋め込んだり、 -Rubyプログラム自体を扱うプログラムを作るのが非常に難しくなっている。

-

例えば筆者が開発しているツールで@racc@というものがある。@yacc@のRuby版 -なのでRを付けて@racc@だ。その@racc@では文法ファイルの構文などはほとんど -@yacc@と同じで、 -アクションの部分だけがRubyのコードになっている。そのためにはRubyのコー -ドをちゃんとパースしないとアクションの終わりを判定できないが、「ちゃん -と」パースするのがとても難しい。仕方がないので今は「だいたい」パースで -きるというレベルで妥協している。

-

他にRubyプログラムの解析が必要になる例としては -@indent@や@lint@のようなツールが -挙げられるが、こういうものを作るのにも非常に苦労する。リファクタリング -ツールのような複雑なものになるともはや絶望的である。

-

ではどうしようか。同じものを作り直すのが無理なら、@ruby@のオリジナルの -パーサを部品として使えるようにすればいいのではないだろうか。つまり処理 -系のパーサ自体をライブラリ化するわけだ。これは是非とも欲しい機能である。

-

ただここで問題なのは、@yacc@を使う限りパーサがリエントラントにできない -ということだ。つまり@yyparse()@を再帰呼び出ししたり複数のスレッドから -呼んだりできないのである。だからパース中にRubyに制御が戻らないように実 -装しなければならない。

-

コード隠蔽

-

現在の@ruby@は動かすプログラムのソースコードがないと動かせない。 -つまりソースコードを他人に読ませたくない人達は困るだろう。

-

インタプリタオブジェクト

-

現在の@ruby@インタプリタはプロセスに一つしか持てない、ということは -第13章で話した。複数のインタプリタを持つことが現実に可能 -ならそのほうがよさそうではあるが、果たしてそういうことは実装可能なのだ -ろうか。

-

評価器の構造

-

いまの@eval.c@はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー -ムを埋め込むのも何かと厄介の元だし、@setjmp() longjmp()を使いまくるのも -わかりやすさと速度を下げている。特にレジスタの多いRISCマシンだと -@setjmp()を使いまくると速度が落ちやすい。@setjmp()@ではレジスタを全て -退避するからである。

-

評価器の速度

-

@ruby@は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理 -系は速ければ速いほどいいのは間違いない。速度を上げる、即ち最適化をする -にはどうしたらいいだろう。そういうときはまずプロファイルを採らねばなら -ない。というわけで採った。

-

p(=emlist). - % cumulative self self total - time seconds seconds calls ms/call ms/call name - 20.25 1.64 1.64 2638359 0.00 0.00 rb_eval - 12.47 2.65 1.01 1113947 0.00 0.00 ruby_re_match - 8.89 3.37 0.72 5519249 0.00 0.00 rb_call0 - 6.54 3.90 0.53 2156387 0.00 0.00 st_lookup - 6.30 4.41 0.51 1599096 0.00 0.00 rb_yield_0 - 5.43 4.85 0.44 5519249 0.00 0.00 rb_call - 5.19 5.27 0.42 388066 0.00 0.00 st_foreach - 3.46 5.55 0.28 8605866 0.00 0.00 rb_gc_mark - 2.22 5.73 0.18 3819588 0.00 0.00 call_cfunc -

-

これはとあるアプリケーションを動かしたときのプロファイルなのだが、一般 -的なRubyプログラムのプロファイルにもかなり近い。つまりトップに圧倒的割 -合で@rb_eval()が登場し、そのあとにGCと評価器中枢部、加えて処理に特有 -の関数が混じる。例えばこのアプリケーションの場合は正規表現マッチ -(ruby_re_match@)にかなり時間がかかっているようだ。

-

ただそれがわかったとしてどう解決するかが問題だ。単純に考えれば -rb_eval()を速くすればいい、ということになるだろうが、@ruby@のコアに -関しては小手先の最適化をやる余地はもうほとんどない。@NODE_IF@のところ -で使われていたような「末尾再帰→@goto@変換」もほとんどやり尽くした感が -ある。つまり根本的に考えかたを変えない限り向上の余地がないのだ。

-

スレッドの実装

-

これは第19章でも話した。現在のrubyのスレッドの実装は非常に -問題が多い。特にネイティブスレッドとの相性の悪さはどうしようもない。 -@ruby@スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確 -かに他に代え難い長所なのだが、さすがにあの実装はずっと使い続けるには無 -理があるのではなかろうか。

-

ruby 2

-

続いて今度はこれらの問題点に対するオリジナルの@ruby@の動向を示す。

-

Rite

-

現時点でのrubyの最新バージョンは安定版が1.6.7、開発版が1.7.3だ。 -だがそう遠くないうちに次の安定版1.8が出そうである。そうすると同時に -開発版の1.9.0がスタートする。そしてその次はちょっと変則的に1.9.1が -安定版となる。

-

安定版開発版開始時期 -1.6.×1.7.×2000-09-19に1.6.0リリース -1.8.×1.9.0半年以内には出るだろう -1.9.1〜2.0.0二年後くらいか

-

そして次々世代の開発版が@ruby@ 2、コードネームRite、である。 -この名前はLとRの区別がつけられない日本人へのオマージュらしい。

-

一言で2.0はどこが変わるかと言うと、コアほとんど全部だ。スレッド、評価 -器、パーサ、これが全部変わる。もっとも、コードがカケラも出てきていない -のであくまでここに書くのは全て「予定」である。あまり期待しすぎると失望 -するかもしれない。そういうわけで、軽く期待、ということにしておこう。

-

記述言語

-

まず使う言語。間違いなくCだろう。Rubyの英語メーリングリスト -ruby-talkでのまつもとさんの発言によると

-
-

I hate C++.

-
-

だそうなので、C++を使うというのはまずありえない。いくら全面作り直しと -言ってもオブジェクトシステムはほぼそのまま残ると考えられるので、そのあ -たりでの手間が増えないようする必要もある。ただしCはCでも今度はANSI Cに -なる可能性は高いだろう。

-

GC

-

GCの実装では、 -まず@Boehm GC@footnote{Boehm GC http://www.hpl.hp.com/personal/Hans_Boehm/gc}から -試してみるということだ。Boehm GCは -conservativeかつincrementalかつgenerationalなGCで、しかも -ネイティブスレッドが動いてい -ても全スレッドのスタック領域をマークできるというかなりの優れものGCであ -る。一度導入したとしてそのままBoehm GCをそのまま使い続けるのかどうか -はわからないが、どちらにしてもなんらかの速度向上が期待できる方向に -進むだろう。

-

パーサ

-

仕様の点では、括弧を省略したメソッド呼び出しのネストが一律禁止になりそ -うである。見てきたように@command_call@は文法全域にかなりの影響を与えてい -た。これが簡略化されればパーサもスキャナも随分すっきりするはずだ。 -ただし括弧の省略自体がなくなることはありえない。

-

また実装面では@yacc@を使い続けるかどうかでまだ思案中ということだ。使わ -ないとすれば手書きで、ということだが、あれだけ複雑なものを手で実装でき -るか、不安は残る。どちらを選んでも茨の道には違いない。

-

評価器

-

評価器は完全に作り直しとなる。目的は主に高速化と実装の簡略化であり、 -主眼は二点だ。

-

rb_eval()のような再帰呼び出しをなくす -バイトコードインタプリタへの移行

-

まず@rb_eval()の再帰呼び出しをなくす。なくす方法については「末尾再帰 -→goto@変換」のような感じ、と言うのが一番直感的だろうか。一つの -rb_eval()の中で@goto@を使い、ぐるぐる回るわけだ。するとまず関数呼び -出しが減るし、@return@や@break@のために使っていた@setjmp()も不要にな -る。ただしCで定義されたメソッドの呼び出しが入れば嫌でも関数を呼ばざ -るを得ないので、その区切りではやはりsetjmp()@が必要だ。

-

バイトコード(byte code)というのはようするに機械語のプログラムみたい -なものである。Smalltalk80の仮想マシンで有名になった用語で、命令がバイ -ト単位で構成されているのでバイトコードと呼ばれる。上のレベルばかりいじっ -ている人間からするとバイト単位なんてのはあたりまえに思えてしまうのだが、 -機械語では命令がビット単位になっていることは多い。例えばAlphaだと命令 -コード32ビットのうち先頭6ビットが命令種を表している。

-

バイトコード型にする利点は主に高速化である。理由は二つで、一つめは構文 -木のようにポインタをたぐる必要がないこと。もう一つは局所的な最適化 -(peephole optimization)がやりやすいことだ。

-

またバイトコードを保存しておいて読み込む場合はパースがなくなるのでそ -こでも多少は速くなると考えられる。しかしパースはプログラムの開始時点に -一回しか行われない作業だし、元々パースにはあまり時間がかかっていない -ので、そう大きな影響はない。

-

バイトコードの評価器がどんなふうになるか知りたければ@regex.c@を見てみ -るとよい。あとはPythonがバイトコードインタプリタだ。

-

スレッド

-

スレッドはネイティブスレッド対応。Rubyが誕生した1994年当時に比べると -スレッドを取り巻く環境は格段に良くなっているし、ネイティブスレッドで -いける、と判断されたのだろう。

-

ネイティブスレッドを使うということはCレベルでもプリエンプティブになる -わけだからインタプリタ自体をマルチスレッドセーフにしなければならないが、 -その点はとりあえずグローバルロックをかけて解決するようである。

-

それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。@ruby@の -継続はスレッドの実装に大きく依存しているので、スレッドがネイティブスレッ -ドになれば継続も自然と消滅する。あれが付いているのは「実装できて -しまった」からだし、ほとんど使われていないので問題ないだろう。

-

M17N

-

ついでにクラスライブラリについても少しだけ触れておこう。多言語化 -(Multilingualization、略してM17N)についてだ。プログラミングに -おいてM17Nとは何をすることか有体に言うと、複数の文字コードを扱えるよう -にすることである。

-

似た話題では他に国際化(Internationalization、略してI18N)と -いうのもあ -る。こちらの例を挙げれば、エラーメッセージをユーザの好みの言語で出した -り、日付の表現を国の慣習に合わせたりすることである。この例えでわかると -おり、I18Nを実現するためにはM17Nの実現が必須である。しかし逆は成立しな -い。

-

具体的にRubyを多言語化するためには何が必要か。一つにはパーサの対応、も -う一つは文字列関係のライブラリ、具体的には@String@と@Regexp@の対応、の -二つが必要である。

-

パーサの対応とは、コメントや文字列リテラル、正規表現リテラルに任意言語 -(正確にはエンコーディング)を許すことだ。これが易しそうで難しい。 -まず、@ruby@のパーサに -エンコーディングを伝える方法が必要である。これまで見てきたよ -うにRubyのプログラムは例外なくパーサを抜けたあとに評価される。つまりパー -サにエンコーディングを伝えるのに通常の構文を使うことはできない。だから -エンコーディングを指定するためになんらかの構文を追加する必要がある。

-

ライブラリでの対応はわりと簡単だ。現在ある@mbclen()@という仕組みを -素直に拡張したものになっている。

-

M17N対応@ruby@は既に実装されており、CVSレポジトリの -@ruby_m17n@ブランチから -取得可能だ。実装されたのに取り込まれていないのは仕様が成熟していな -いと判断されたためである。いいインターフェイスさえ設計できれば1.9の途中 -にでも入るのではないだろうか。

-

IO

-

現在のRubyの@IO@クラスは単純な@stdio@のラッパーなのだが、 -このアプローチは

-

プラットフォーム間の微妙な挙動の違いが多すぎる -バッファリングを細かく制御したい

-

という二点で不満があった。そこでRiteでは@stdio@を自前で持つ -ことになりそうである。

-

Ruby Hacking Guide

-

ここまで我々は常に@ruby@を外から観察する者として行動してきた。だがもち -ろん@ruby@は展示ケースに収められた製品とは違う。即ち我々の行動いかんに -よってはこちらから影響を与えることができるのである。本書最後の節はコミュ -ニティから提案された@ruby@に対する働きかけについて話し、現在と未来の -Ruby Hackerたちに対する餞とする。

-

世代別GC

-

まず、第5章でも触れた、木山真人さんによる世代別GC。 -既に述べた通り現在のパッチだと

-

思ったより速度が出ない -最新の@ruby@に合わせてアップデートが必要

-

という点が問題なのだが、この場では初めての大型非公式パッチで -あるという点を何より高評価したい。

-

鬼車

-

いまのRubyが使っている正規表現エンジンはGNU regexの改造版である。その -GNU regexはもともとEmacsのために書かれたもので、それをマルチバイト対応 -にしたものをさらにまつもとさんがPerl互換に改造した。という経緯から容易 -に想像できるように、非常に複雑怪奇な構造になってしまっている。またこの -GNU regexpのライセンスがLGPLであるために@ruby@のライセンスが非常にやや -こしくなっており、かねてからこのエンジンの置き換えが課題になってきた。

-

そこでいきなり登場したのが小迫清美さんの手による正規表現エンジン「鬼車」 -である。これがかなり出来がよいらしく、すぐにでも本体に取りこまれそうだ。

-

鬼車は@ruby@のCVSレポジトリから以下のようにして入手できる。

-

p(=screen). -% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma - -h3. ripper

-

続いて拙作のripper。@parse.y@を改造して拡張ライブラリにしたものだ。 -@ruby@本体に対する変更というわけではないが、パーサのコンポーネント化の -一つの方向性としてここで紹介しておく。

-

ストリーム系のインターフェイスで実装しており、トークンのスキャンだの -パーサでの還元だのをイベント形式で拾うことができる。添付CD-ROMに入れて -おいたfootnote{ripper:添付CD-ROMの@archives/ripper-0.0.5.tar.gz@}ので -使ってみてほしい。なお、このバージョンは半年ほど前の@ruby@ 1.7ベース -なので今の文法とは少し違う。

-

これを作ったのはただ「アイデアを思い付いてしまった」というのが理由だっ -たりするだが、そのわりにはうまくいったと思う。実装時間も三日くらいで実 -にお手軽であった。

-

代替パーサ

-

まだ影も形もないプロダクトではあるが、@ruby@とは全く独立に使える -RubyのパーサをC++で書いている人もいるようだ(@[ruby-talk:50497]@)。

-

JRuby

-

さらに過激に、インタプリタ全体を書き直してしまえー、 -という動きもある。例えばJavaで書いたRuby -「JRubyfootnote{JRuby http://jruby.sourceforge.net}」 -というものが登場している。Jan Arne Petersenさん以下、 -かなりの大所帯で実装しているようだ。

-

ちょっといじってみた感想としては

-

パーサはかなりちゃんとできている。ヒアドキュメントや空白の微妙な挙動まで正確に再現されている。 -@instance_eval@が効かないようだ(これは仕方ないか) -組み込みライブラリはまだ少ない(これも仕方ない) -拡張ライブラリは使えない(あたりまえ) -RubyのUNIX centricなところが全部削られているので既存のスクリプトがそのまま動く可能性は低いと思われる -遅い

-

ということは言えそうだ。ちなみに最後の「遅い」がどのくらいかと言うと、 -オリジナルの@ruby@の20倍くらい(実行時間が)である。ここまで遅いとさす -がに苦しい。やはりJava VMの上でRuby VMが動いているわけだから、遅くない -はずがないのだ。マシンが20倍速になってくれるのを待つしかあるまい。

-

しかし全体としては想像よりずっとよくできている、という印象を受けた。

-

NETRuby

-

Javaで動くならC#でも動くだろう。というわけでC#で書いたRuby、 -「NETRubyfootnote{NETRuby http://sourceforge.jp/projects/netruby/}」 -というのが登場した。作者はartonさんである。

-

筆者の手元には.NET環境がないのでソースコードしか見ていないのだが、 -本人の弁によると

-

何より遅い -クラスライブラリがあまりない -例外処理の互換性がいまいち

-

というあたりが問題らしい。しかし@instance_eval@は動くらしい(驚愕)。

-

@ruby@の開発に参加するには

-

@ruby@の開発者はあくまでまつもとゆきひろさん個人であり、最終的な -@ruby@の方向については絶対的な権限がある。だが同時に@ruby@は -オープンソースソフトウェアであり、誰でも開発に参加できる。参加できる、 -というのは、意見を提案したりパッチを出したりできるということだ。 -以下、具体的な参加方法について話す。

-

@ruby@の場合はメーリングリストを中心に開発が進んでいるので、各メーリン -グリストに参加するのがよい。現在コミュニティの中心となっているメーリ -ングリストは -ruby-list、@ruby-dev@、@ruby-talk@の三つである。@ruby-list@は -「Rubyに関係することならなんでもOK」のメーリングリストで、日本語である。 -ruby-devは開発版@ruby@の話をするメーリングリストで、これも日本語であ -る。@ruby-talk@は英語のメーリングリストだ。参加方法はRubyの -公式サイトfootnote{Rubyの公式サイト:@http://www.ruby-lang.org/ja/@} -の「メーリングリスト」のページに載っている。これらのメーリングリストは -どれも読むだけのメンバーも歓迎なので、とりあえずしばらく参加してみて -議論を眺め、雰囲気を捕むといいのではないだろうか。

-

日本から活動が始まったRubyだが、最近は「主導権は@ruby-talk@に移った」 -と言われてしまったりすることもある。 -だが開発の中心が相変わらず@ruby-dev@であることに変わりはない。なにしろ -@ruby@のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語 -ユーザなのでわざわざ英語で話すのも面倒だし、自然と@ruby-dev@に足が向い -てしまう。将来英語を使うコアメンバーが増えてくれば状況も変わるかもしれ -ないが、当分の間は@ruby@開発のコアは@ruby-dev@だろう。

-

ただ日本語が使えないと開発に参加できないというのも困るので、今は -ruby-devの要約を一週間に一度英訳して@ruby-talk@に流すようになってい -る。筆者もその要約に参加しているのだが、現在は三人の持ち回りで -やっているため非常に厳しい。要約を手伝ってくれるメンバーは常時 -募集中である。我こそはと思うかたは是非@ruby-list@で参加表明して -いただきたい。

-

そして最後に、ソフトウェアはソースコードがあればいいというものでもない。 -各種ドキュメントやウェブサイトの整備も必要である。そしてそういうことを -してくれる人は常に不足ぎみだ。 -ドキュメント関連の活動にもいちおう専用メーリングリストがあるが、とりあえ -ずは@ruby-list@で「何かやりたい」と言ってくれればいい。筆者もできるだ -け答えるようにするし、他のメンバーも反応してくれるだろう。

-

最後に

-

さて、長かった本書もこれで終わりだ。ページ数との兼ね合いもあるのであら -ゆる部分を懇切丁寧にというわけにはいかなかったが、@ruby@の根幹について -は全て語り尽くした。これ以上ウダウダと付け加えるのはよそう。まだわから -ないことがあれば納得するまで自分でソースコードを読んで確かめてほしい。

-

御意見・御感想・誤殖の指摘などは -“青木峰郎 <aamine@loveruby.net>”:mailto:aamine@loveruby.net -までお願いします。

-

『Rubyソースコード完全解説』 -はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。

-

Copyright © 2002-2004 Minero Aoki, All rights reserved.

- - - -
- - diff --git a/htmls/gc.html b/htmls/gc.html deleted file mode 100644 index e803f51..0000000 --- a/htmls/gc.html +++ /dev/null @@ -1,1652 +0,0 @@ - - - - - Garbage Collection | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Sebastian Krause & ocha-

-

Chapter 5: Garbage Collection

-

A conception of an executing program

-

It’s all of a sudden but at the beginning of this chapter, we’ll -learn about the memory space of an executing program. In this chapter -we’ll step inside the lower level parts of a computer quite a bit, so without -preliminary knowledge it’ll be hard to follow. And it’ll be also necessary -for the following chapters. -Once we finish this here, the rest will be easier.

-

Memory Segments

-

A general C program has the following parts in the memory space:

-
    -
  1. the text area
  2. -
  3. a place for static and global variables
  4. -
  5. the machine stack
  6. -
  7. the heap
  8. -
-

The text area is where the code lies. Obviously the second area holds static and global variables. -Arguments and local variables of functions are piling up in the machine stack. -The heap is the place where allocated by malloc().

-

Let’s talk a bit more about number three, the machine stack. -Since it is called the machine “stack”, -obviously it has a stack structure. -In other words, new stuff is piled on top of it one after another. -When we actually pushes values on the stack, each value would be a tiny piece -such as int. But logically, there are a little larger pieces. -They are called stack frames.

-

One stack frame corresponds to one function call. Or in other words when there -is a function call, one stack frame is pushed. -When doing return, one stack frame will be popped. -Figure 1 shows the really simplified appearance of the machine stack.

-
-

(macstack)
-Figure 1: Machine Stack

-
    -
  • 上(先端)above (top)
  • -
  • 下(末端)below (bottom)
  • -
  • スタックフレーム stack frame
  • -
  • 現在実行中の関数フレーム presently executing function frame -
- -

In this picture, “above” is written above the top of the stack, -but this it is not necessarily always the case that the machine stack goes -from low addresses to high addresses. For instance, on the x86 -machine the stack goes from high to low addresses.

-

alloca()

-

By using malloc(), we can get an arbitrarily large memory -area of the heap. alloca() is the machine stack version of it. -But unlike malloc() it’s not necessary to free the memory allocated -with alloca(). Or one should say: -it is freed automatically at the same moment of return of each function. -That’s why it’s not possible to use an allocated value as the return -value. It’s the same as “You must not return the pointer to -a local variable.”

-

There’s been not any difficulty. We can consider it something to locally -allocate an array whose size can be changed at runtime.

-

However there exist environments where there is no native alloca(). -There are still many who would like to use alloca() even if in such -environment, sometimes a function to do the same thing is written in C. -But in that case, only the feature that we don’t have to free it by ourselves -is implemented and it does not necessarily allocate the memory on the machine -stack. In fact, it often does not. -If it were possible, a native -alloca() could have been implemented in the first place.

-

How can one implement alloca() in C? The simplest implementation is: -first allocate memory normally with malloc(). Then remember the pair of the function -which called alloca() and the assigned addresses in a global list. -After that, check this list whenever alloca() is called, -if there are the memories allocated for the functions already finished, -free them by using free().

-
-

(calloca)
-Figure 2: The behavior of an alloca() implemented in C

-
    -
  • D→alloca(8)の対応を記録 record the relation D→ alloca(8)
  • -
  • B→alloca(32)の対応を記録 record the relation B→ alloca(32)
  • -
  • Dで割り当てたメモりを解放 release the memory allocated in D -
- -

The missing/alloca.c of ruby is an example of an emulated alloca() .

-

Overview

-

From here on we can at last talk about the main subject of this chapter: -garbage collection.

-

What is GC?

-

Objects are normally on top of the memory. Naturally, if a lot of objects are created, a lot of memory is used. If memory -were infinite there would be no problem, but in reality there is always a memory -limit. That’s why the memory which is not -used anymore must be collected and recycled. More concretely the memory received through malloc() must be returned with -free().

-

However, it would require a lot of efforts if the management of malloc() and -free() were entirely left to programmers. -Especially in object oriented programs, because objects are referring each other, -it is difficult to tell when to release memory.

-

There garbage collection comes in. -Garbage Collection (GC) is a feature to automatically detect and free the memory -which has become unnecessary. -With garbage collection, -the worry “When should I have to free() ??” has become unnecessary. -Between when it exists and when it does not exist, -the ease of writing programs differs considerably.

-

By the way, in a book about something that I’ve read, -there’s a description “the thing to tidy up the fragmented usable memory is GC”. -This task is called “compaction”. -It is compaction because it makes a thing compact. -Because compaction makes memory cache more often hit, -it has effects for speed-up to some extent, -but it is not the main purpose of GC. -The purpose of GC is to collect memory. There are many GCs which collect -memories but don’t do compaction. -The GC of ruby also does not do compaction.

-

Then, in what kind of system is GC available? -In C and C++, there’s -Boehm GC\footnote{Boehm GC http://www.hpl.hp.com/personal/Hans_Boehm/gc} -which can be used as an add-on. -And, for the recent languages such as Java and Perl, Python, C#, Eiffel, -GC is a standard equipment. And of course, Ruby has its GC. -Let’s follow the details of ruby’s GC in this chapter. -The target file is gc.c.

-

What does GC do?

-

Before explaining the GC algorithm, I should explain “what garbage collection -is”. -In other words, what kind of state of the memory is “the unnecessary memory”?

-

To make descriptions more concrete, -let’s simplify the structure by assuming that there are only objects and links. -This would look as shown in Figure 3.

-

-

(objects)
-Figure 3: Objects

-

-

The objects pointed to by global variables and the objects on the stack of a -language are surely necessary. And objects pointed to by instance variables of -these objects are also necessary. Furthermore, the objects that are reachable by -following links from these objects are also necessary.

-

To put it more logically, the necessary objects are all objects which -can be reached recursively via links from the “surely necessary objects” as -the start points. -This is depicted in figure 4. What are on the left of the line are all “surely necessary objects”, -and the objects which can be reached from them are colored black. -These objects colored black are the -necessary objects. The rest of the objects can be released.

-
-

(gcimage)
-Figure 4: necessary objects and unnecessary objects

-
    -
  • ルートオブジェクト root objects
  • -
  • 不要なオブジェクト unnecessary objects
  • -
  • ルートオブジェクトから参照されているオブジェクト objects referenced by the - root objects -
- -

In technical terms, “the surely necessary objects” are called “the roots of GC”. -That’s because they are the roots of tree structures that emerges as a -consequence of tracing necessary objects.

-

Mark and Sweep

-

GC was first implemented in Lisp. -The GC implemented in Lisp at first, -it means the world’s first GC, -is called mark&sweep GC. -The GC of ruby is one type of it.

-

The image of Mark-and-Sweep GC is pretty close to our definition of “necessary -object”. First, put “marks” on the root objects. Setting them as the start -points, put “marks” on all reachable objects. -This is the mark phase.

-

At the moment when there’s not any reachable object left, -check all objects in the object pool, release (sweep) all objects that have not marked. -“Sweep” is the “sweep” of Minesweeper.

-

There are two advantages.

-
    -
  • There does not need to be any (or almost any) concern for garbage collection -outside the implementation of GC.
  • -
  • Cycles can also be released. (As for cycles, see also the section of “Reference Count”)
  • -
-

There are also two disadvantages.

-
    -
  • In order to sweep every object must be touched at least once.
  • -
  • The load of the GC is concentrated at one point.
  • -
-

When using the emacs editor, there sometimes appears " Garbage collecting... " -and it completely stops reacting. That is an example of the second disadvantage. -But this point can be alleviated by modifying the algorithm (it is called incremental GC).

-

Stop and Copy

-

Stop and Copy is a variation of Mark and Sweep. First, prepare several object -areas. To simplify this description, assume there are two areas A and B here. -And put an “active” mark on the one of the areas. -When creating an object, create it only in the “active” one. (Figure 5)

-

-

(stop2)
-Figure 5: Stop and Copy (1)

-

-

When the GC starts, follow links from the roots in the same manner as -mark-and-sweep. However, move objects to another area instead of marking them -(Figure 6). When all the links have been followed, discard the all elements -which remain in A, and make B active next.

-

-

(stop3)
-Figure 6: Stop and Copy (2)

-

-

Stop and Copy also has two advantages:

-
    -
  • Compaction happens at the same time as collecting the memory
  • -
  • Since objects that reference each other move closer together, - there’s more possibility of hitting the cache.
  • -
-

And also two disadvantages:

-
    -
  • The object area needs to be more than twice as big
  • -
  • The positions of objects will be changed
  • -
-

It seems what exist in this world are not only positive things.

-

Reference counting

-

Reference counting differs a bit from the aforementioned GCs, -the reach-check code is distributed in several places.

-

First, attach an integer count to each element. -When referring via variables or arrays, the counter of the referenced object is -increased. When quitting to refer, decrease the counter. -When the counter of an object becomes zero, release the object. -This is the method called reference counting (Figure 7).

-

-

(refcnt)
-Figure 7: Reference counting

-

-

This method also has two advantages:

-
    -
  • The load of GC is distributed over the entire program.
  • -
  • The object that becomes unnecessary is immediately freed.
  • -
-

And also two disadvantages.

-
    -
  • The counter handling tends to be forgotten.
  • -
  • When doing it naively cycles are not released.
  • -
-

I’ll explain about the second point just in case. A cycle is -a cycle of references as shown in Figure 8. -If this is the case the counters will never decrease -and the objects will never be released.

-

-

(cycle)
-Figure 8: Cycle

-

-

By the way, latest Python(2.2) uses reference counting GC but it can free cycles. -However, it is not because of the reference counting itself, -but because it sometimes invokes mark and sweep GC to check.

-

Object Management

-

Ruby’s garbage collection is only concerned with ruby objects. -Moreover, it only concerned with the objects created and managed by ruby. -Conversely speaking, -if the memory is allocated without following a certain procedure, -it won’t be taken care of. -For instance, the following function will cause a memory leak -even if ruby is running.

-
-void not_ok()
-{
-    malloc(1024);  /* receive memory and discard it */
-}
-
-

However, the following function does not cause a memory leak.

-
-void this_is_ok()
-{
-    rb_ary_new();  /* create a ruby array and discard it */
-}
-
-

Since rb_ary_new() uses Ruby’s proper interface to allocate memory, -the created object is under the management of the GC of ruby, -thus ruby will take care of it.

-

struct RVALUE

-

Since the substance of an object is a struct, -managing objects means managing that structs. -Of course the non-pointer objects like Fixnum Symbol nil true false are -exceptions, but I won’t always describe about it to prevent descriptions -from being redundant.

-

Each struct type has its different size, -but probably in order to keep management simpler, -a union of all the structs of built-in classes is declared and -the union is always used when dealing with memory. -The declaration of that union is as follows.

-

RVALUE

-
- 211  typedef struct RVALUE {
- 212      union {
- 213          struct {
- 214              unsigned long flags;   /* 0 if not used */
- 215              struct RVALUE *next;
- 216          } free;
- 217          struct RBasic  basic;
- 218          struct RObject object;
- 219          struct RClass  klass;
- 220          struct RFloat  flonum;
- 221          struct RString string;
- 222          struct RArray  array;
- 223          struct RRegexp regexp;
- 224          struct RHash   hash;
- 225          struct RData   data;
- 226          struct RStruct rstruct;
- 227          struct RBignum bignum;
- 228          struct RFile   file;
- 229          struct RNode   node;
- 230          struct RMatch  match;
- 231          struct RVarmap varmap;
- 232          struct SCOPE   scope;
- 233      } as;
- 234  } RVALUE;
-
-(gc.c)
-
-

struct RVALUE is a struct that has only one element. -I’ve heard that the reason why union is not directly used is to enable to -easily increase its members when debugging or when extending in the future.

-

First, let’s focus on the first element of the union free.flags. The comment -says “0 if not used”, but is it true? -Is there not any possibility for free.flags to be 0 by chance?

-

As we’ve seen in Chapter 2: Objects, all object structs have struct RBasic as its first -element. Therefore, by whichever element of the union we access, -obj->as.free.flags means the same as it is written as obj->as.basic.flags. -And objects always have the struct-type flag (such as T_STRING), -and the flag is always not 0. Therefore, the flag of an “alive” object will -never coincidentally be 0. -Hence, we can confirm that setting their flags to 0 -is necessity and sufficiency to represent “dead” objects.

-

Object heap

-

The memory for all the object structs has been brought together in global variable heaps. -Hereafter, let’s call this an object heap.

-

▼ Object heap

-
- 239  #define HEAPS_INCREMENT 10
- 240  static RVALUE **heaps;
- 241  static int heaps_length = 0;
- 242  static int heaps_used   = 0;
- 243
- 244  #define HEAP_MIN_SLOTS 10000
- 245  static int *heaps_limits;
- 246  static int heap_slots = HEAP_MIN_SLOTS;
-
-(gc.c)
-
-

heaps is an array of arrays of struct RVALUE. Since it is heapS, -the each contained array is probably each heap. -Each element of heap is each slot (Figure 9).

-

-

(heapitems)
-Figure 9: heaps, heap, slot

-

-

The length of heaps is heap_length and it can be changed. The number of -the slots actually in use is heaps_used. The length of each heap -is in the corresponding heaps_limits[index]. -Figure 10 shows the structure of the object heap.

-

-

(heaps)
-Figure 10: conceptual diagram of heaps in memory

-

-

This structure has a necessity to be this way. -For instance, if all structs are stored in an array, -the memory space would be the most compact, -but we cannot do realloc() because it could change the addresses. -This is because VALUEs are mere pointers.

-

In the case of an implementation of Java, -the counterpart of VALUEs are not addresses but the indexes of objects. -Since they are handled through a pointer table, objects are movable. -However in this case, indexing of the array comes in every time -an object access occurs and it lowers the performance in some degree.

-

On the other hand, what happens if it is an one-dimensional array of pointers -to RVALUEs (it means VALUEs)? -This seems to be able to go well at the first glance, but it does not when GC. -That is, as I’ll describe in detail, the GC of ruby needs to know the -integers "which seems VALUE (the pointers to RVALUE). -If all RVALUE are allocated in addresses which are far from each other, -it needs to compare all address of RVALUE with all integers “which could be -pointers”. -This means the time for GC becomes the order more than O(n^2), -and not acceptable.

-

According to these requirements, it is good that the object heap form a -structure that the addresses are cohesive to some extent -and whose position and total amount are not restricted at the same time.

-

freelist

-

Unused RVALUEs are managed by being linked as a single line which is a linked -list that starts with freelist. -The as.free.next of RVALUE is the link used for this purpose.

-

freelist

-
- 236  static RVALUE *freelist = 0;
-
-(gc.c)
-
-

add_heap()

-

As we understood the data structure, -let’s read the function add_heap() to add a heap. -Because this function contains a lot of lines not part of the main line, -I’ll show the one simplified by omitting error handlings and castings.

-

add_heap() (simplified)

-
-static void
-add_heap()
-{
-    RVALUE *p, *pend;
-
-    /* extend heaps if necessary */
-    if (heaps_used == heaps_length) {
-        heaps_length += HEAPS_INCREMENT;
-        heaps        = realloc(heaps,        heaps_length * sizeof(RVALUE*));
-        heaps_limits = realloc(heaps_limits, heaps_length * sizeof(int));
-    }
-
-    /* increase heaps by 1 */
-    p = heaps[heaps_used] = malloc(sizeof(RVALUE) * heap_slots);
-    heaps_limits[heaps_used] = heap_slots;
-    pend = p + heap_slots;
-    if (lomem == 0 || lomem > p) lomem = p;
-    if (himem < pend) himem = pend;
-    heaps_used++;
-    heap_slots *= 1.8;
-
-    /* link the allocated RVALUE to freelist */
-    while (p < pend) {
-        p->as.free.flags = 0;
-        p->as.free.next = freelist;
-        freelist = p;
-        p++;
-    }
-}
-
-

Please check the following points.

-
    -
  • the length of heap is heap_slots
  • -
  • the heap_slots becomes 1.8 times larger every time when a heap is added
  • -
  • the length of heaps[i] (the value of heap_slots when creating a heap) is - stored in heaps_limits[i].
  • -
-

Plus, since lomem and himem are modified only by this function, -only by this function you can understand the mechanism. -These variables hold the lowest and the highest addresses of the object heap. -These values are used later when determining the integers “which seems VALUE”.

-

rb_newobj()

-

Considering all of the above points, we can tell the way to create an object -in a second. -If there is at least a RVALUE linked from freelist, we can use it. -Otherwise, do GC or increase the heaps. -Let’s confirm this by reading the rb_newobj() function to create an object.

-

rb_newobj()

-
- 297  VALUE
- 298  rb_newobj()
- 299  {
- 300      VALUE obj;
- 301
- 302      if (!freelist) rb_gc();
- 303
- 304      obj = (VALUE)freelist;
- 305      freelist = freelist->as.free.next;
- 306      MEMZERO((void*)obj, RVALUE, 1);
- 307      return obj;
- 308  }
-
-(gc.c)
-
-

If freelest is 0, in other words, if there’s not any unused structs, -invoke GC and create spaces. -Even if we could not collect not any object, -there’s no problem because in this case a new space is allocated in rb_gc(). -And take a struct from freelist, zerofill it by MEMZERO(), and return it.

-

Mark

-

As described, ruby’s GC is Mark & Sweep. -Its “mark” is, concretely speaking, to set a FL_MARK flag: -look for unused VALUE, set FL_MARK flags to found ones, -then look at the object heap after investigating all -and free objects that FL_MARK has not been set.

-

rb_gc_mark()

-

rb_gc_mark() is the function to mark objects recursively.

-

rb_gc_mark()

-
- 573  void
- 574  rb_gc_mark(ptr)
- 575      VALUE ptr;
- 576  {
- 577      int ret;
- 578      register RVALUE *obj = RANY(ptr);
- 579
- 580      if (rb_special_const_p(ptr)) return; /* special const not marked */
- 581      if (obj->as.basic.flags == 0) return;       /* free cell */
- 582      if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
- 583
- 584      obj->as.basic.flags |= FL_MARK;
- 585
- 586      CHECK_STACK(ret);
- 587      if (ret) {
- 588          if (!mark_stack_overflow) {
- 589              if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
- 590                  *mark_stack_ptr = ptr;
- 591                  mark_stack_ptr++;
- 592              }
- 593              else {
- 594                  mark_stack_overflow = 1;
- 595              }
- 596          }
- 597      }
- 598      else {
- 599          rb_gc_mark_children(ptr);
- 600      }
- 601  }
-
-(gc.c)
-
-

The definition of RANY() is as follows. It is not particularly important.

-

RANY()

-
- 295  #define RANY(o) ((RVALUE*)(o))
-
-(gc.c)
-
-

There are the checks for non-pointers or already freed objects and the recursive -checks for marked objects at the beginning,

-
-obj->as.basic.flags |= FL_MARK;
-
-

and obj (this is the ptr parameter of this function) is marked. -Then next, it’s the turn to follow the references from obj and mark. -rb_gc_mark_children() does it.

-

The others, what starts with CHECK_STACK() and is written a lot is a device -to prevent the machine stack overflow. -Since rb_gc_mark() uses recursive calls to mark objects, -if there is a big object cluster, -it is possible to run short of the length of the machine stack. -To counter that, if the machine stack is nearly overflow, -it stops the recursive calls, piles up the objects on a global list, -and later it marks them once again. -This code is omitted because it is not part of the main line.

-

rb_gc_mark_children()

-

Now, as for rb_gc_mark_children(), -it just lists up the internal types and marks one by one, -thus it is not just long but also not interesting. -Here, it is shown but the simple enumerations are omitted:

-

rb_gc_mark_children()

-
- 603  void
- 604  rb_gc_mark_children(ptr)
- 605      VALUE ptr;
- 606  {
- 607      register RVALUE *obj = RANY(ptr);
- 608
- 609      if (FL_TEST(obj, FL_EXIVAR)) {
- 610          rb_mark_generic_ivar((VALUE)obj);
- 611      }
- 612
- 613      switch (obj->as.basic.flags & T_MASK) {
- 614        case T_NIL:
- 615        case T_FIXNUM:
- 616          rb_bug("rb_gc_mark() called for broken object");
- 617          break;
- 618
- 619        case T_NODE:
- 620          mark_source_filename(obj->as.node.nd_file);
- 621          switch (nd_type(obj)) {
- 622            case NODE_IF:         /* 1,2,3 */
- 623            case NODE_FOR:
- 624            case NODE_ITER:
-                /* ………… omitted ………… */
- 749          }
- 750          return;   /* not need to mark basic.klass */
- 751      }
- 752
- 753      rb_gc_mark(obj->as.basic.klass);
- 754      switch (obj->as.basic.flags & T_MASK) {
- 755        case T_ICLASS:
- 756        case T_CLASS:
- 757        case T_MODULE:
- 758          rb_gc_mark(obj->as.klass.super);
- 759          rb_mark_tbl(obj->as.klass.m_tbl);
- 760          rb_mark_tbl(obj->as.klass.iv_tbl);
- 761          break;
- 762
- 763        case T_ARRAY:
- 764          if (FL_TEST(obj, ELTS_SHARED)) {
- 765              rb_gc_mark(obj->as.array.aux.shared);
- 766          }
- 767          else {
- 768              long i, len = obj->as.array.len;
- 769              VALUE *ptr = obj->as.array.ptr;
- 770
- 771              for (i=0; i < len; i++) {
- 772                  rb_gc_mark(*ptr++);
- 773              }
- 774          }
- 775          break;
-
-            /* ………… omitted ………… */
-
- 837        default:
- 838          rb_bug("rb_gc_mark(): unknown data type 0x%x(0x%x) %s",
- 839                 obj->as.basic.flags & T_MASK, obj,
- 840                 is_pointer_to_heap(obj) ? "corrupted object"
-                                             : "non object");
- 841      }
- 842  }
-
-(gc.c)
-
-

It calls rb_gc_mark() recursively, is only what I’d like you to confirm. -In the omitted part, NODE and T_xxxx are enumerated respectively. -NODE will be introduced in Part 2.

-

Additionally, let’s see the part to mark T_DATA (the struct used for extension -libraries) because there’s something we’d like to check. -This code is extracted from the second switch statement.

-

rb_gc_mark_children()T_DATA

-
- 789        case T_DATA:
- 790          if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
- 791          break;
-
-(gc.c)
-
-

Here, it does not use rb_gc_mark() or similar functions, -but the dmark which is given from users. -Inside it, of course, it might use rb_gc_mark() or something, but not using -is also possible. -For example, in an extreme situation, if a user defined object does not -contain VALUE, there’s no need to mark.

-

rb_gc()

-

By now, we’ve finished to talk about each object. -From now on, let’s see the function rb_gc() that presides the whole. -The objects marked here are “objects which are obviously necessary”. -In other words, “the roots of GC”.

-

rb_gc()

-
-1110  void
-1111  rb_gc()
-1112  {
-1113      struct gc_list *list;
-1114      struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
-1115      jmp_buf save_regs_gc_mark;
-1116      SET_STACK_END;
-1117
-1118      if (dont_gc || during_gc) {
-1119          if (!freelist) {
-1120              add_heap();
-1121          }
-1122          return;
-1123      }
-
-          /* …… mark from the all roots …… */
-
-1183      gc_sweep();
-1184  }
-
-(gc.c)
-
-

The roots which should be marked will be shown one by one after this, -but I’d like to mention just one point here.

-

In ruby the CPU registers and the machine stack are also the roots. -It means that the local variables and arguments of C are automatically marked. -For example,

-
-static int
-f(void)
-{
-    VALUE arr = rb_ary_new();
-
-    /* …… do various things …… */
-}
-
-

like this way, we can protect an object just by putting it into a variable. -This is a very significant trait of the GC of ruby. -Because of this feature, ruby’s extension libraries are insanely easy to write.

-

However, what is on the stack is not only VALUE. -There are a lot of totally unrelated values. -How to resolve this is the key when reading the implementation of GC.

-

The Ruby Stack

-

First, it marks the (ruby‘s) stack frames used by the interpretor. -Since you will be able to find out who it is after reaching Part 3, -you don’t have to think so much about it for now.

-

▼ Marking the Ruby Stack

-
-1130      /* mark frame stack */
-1131      for (frame = ruby_frame; frame; frame = frame->prev) {
-1132          rb_gc_mark_frame(frame);
-1133          if (frame->tmp) {
-1134              struct FRAME *tmp = frame->tmp;
-1135              while (tmp) {
-1136                  rb_gc_mark_frame(tmp);
-1137                  tmp = tmp->prev;
-1138              }
-1139          }
-1140      }
-1141      rb_gc_mark((VALUE)ruby_class);
-1142      rb_gc_mark((VALUE)ruby_scope);
-1143      rb_gc_mark((VALUE)ruby_dyna_vars);
-
-(gc.c)
-
-

ruby_frame ruby_class ruby_scope ruby_dyna_vars are the variables to point to -each top of the stacks of the evaluator. These hold the frame, the class scope, -the local variable scope, and the block local variables at that time -respectively.

-

Register

-

Next, it marks the CPU registers.

-

▼ marking the registers

-
-1148      FLUSH_REGISTER_WINDOWS;
-1149      /* Here, all registers must be saved into jmp_buf. */
-1150      setjmp(save_regs_gc_mark);
-1151      mark_locations_array((VALUE*)save_regs_gc_mark,
-                               sizeof(save_regs_gc_mark) / sizeof(VALUE *));
-
-(gc.c)
-
-

FLUSH_REGISTER_WINDOWS is special. We will see it later.

-

setjmp() is essentially a function to remotely jump, -but the content of the registers are saved into the argument (which is a -variable of type jmp_buf) as its side effect. -Making use of this, it attempts to mark the content of the registers. -Things around here really look like secret techniques.

-

However only djgpp and Human68k are specially treated. -djgpp is a gcc environment for DOS. -Human68k is an OS of SHARP X680x0 Series. -In these two environments, the whole registers seem to be not saved only by the -ordinary setjmp(), setjmp() is redefined as follows as an inline-assembler -to explicitly write out the registers.

-

▼ the original version of setjmp

- -
-1072  #ifdef __GNUC__
-1073  #if defined(__human68k__) || defined(DJGPP)
-1074  #if defined(__human68k__)
-1075  typedef unsigned long rb_jmp_buf[8];
-1076  __asm__ (".even\n\                   2-byte alignment
-1077  _rb_setjmp:\n\                       the label of rb_setjmp() function
-1078          move.l  4(sp),a0\n\          load the first argument to the a0 register
-1079          movem.l d3-d7/a3-a5,(a0)\n\  copy the registers to where a0 points to
-1080          moveq.l #0,d0\n\             set 0 to d0 (as the return value)
-1081          rts");                       return
-1082  #ifdef setjmp
-1083  #undef setjmp
-1084  #endif
-1085  #else
-1086  #if defined(DJGPP)
-1087  typedef unsigned long rb_jmp_buf[6];
-1088  __asm__ (".align 4\n\                order 4-byte alignment
-1089  _rb_setjmp:\n\                       the label for rb_setjmp() function
-1090          pushl   %ebp\n\              push ebp to the stack
-1091          movl    %esp,%ebp\n\         set the stack pointer to ebp
-1092          movl    8(%ebp),%ebp\n\      pick up the first argument and set to ebp
-1093          movl    %eax,(%ebp)\n\       in the followings, store each register
-1094          movl    %ebx,4(%ebp)\n\        to where ebp points to
-1095          movl    %ecx,8(%ebp)\n\
-1096          movl    %edx,12(%ebp)\n\
-1097          movl    %esi,16(%ebp)\n\
-1098          movl    %edi,20(%ebp)\n\
-1099          popl    %ebp\n\              restore ebp from the stack
-1100          xorl    %eax,%eax\n\         set 0 to eax (as the return value)
-1101          ret");                       return
-1102  #endif
-1103  #endif
-1104  int rb_setjmp (rb_jmp_buf);
-1105  #define jmp_buf rb_jmp_buf
-1106  #define setjmp rb_setjmp
-1107  #endif /* __human68k__ or DJGPP */
-1108  #endif /* __GNUC__ */
-
-(gc.c)
-
-

Alignment is the constraint when putting variables on memories. -For example, in 32-bit machine int is usually 32 bits, -but we cannot always take 32 bits from anywhere of memories. -Particularly, RISC machine has strict constraints, -it is decided like “from a multiple of 4 byte” or “from even byte”. -When there are such constraints, memory access unit can be more simplified -(thus, it can be faster). When there’s the constraint of “from a multiple of 4 byte”, -it is called “4-byte alignment”.

-

Plus, in cc of djgpp or Human68k, there’s a rule that the compiler put the -underline to the head of each function name. -Therefore, when writing a C function in Assembler, we need to put the underline -(_) to its head by ourselves. -This type of constraints are techniques in order to avoid the conflicts in -names with library functions. -Also in UNIX, it is said that the underline had been attached by some time ago, -but it almost disappears now.

-

Now, the content of the registers has been able to be written out into jmp_buf, -it will be marked in the next code:

-

▼ mark the registers (shown again)

- -
-1151      mark_locations_array((VALUE*)save_regs_gc_mark,
-                               sizeof(save_regs_gc_mark) / sizeof(VALUE *));
-
-(gc.c)
-
-

This is the first time that mark_locations_array() appears. -I’ll describe it in the next section.

-

mark_locations_array()

-

mark_locations_array()

- -
- 500  static void
- 501  mark_locations_array(x, n)
- 502      register VALUE *x;
- 503      register long n;
- 504  {
- 505      while (n--) {
- 506          if (is_pointer_to_heap((void *)*x)) {
- 507              rb_gc_mark(*x);
- 508          }
- 509          x++;
- 510      }
- 511  }
-
-(gc.c)
-
-

This function is to mark the all elements of an array, -but it slightly differs from the previous mark functions. -Until now, each place to be marked is where we know it surely holds a VALUE -(a pointer to an object). -However this time, where it attempts to mark is the register space, -it is enough to expect that there’re also what are not VALUE. -To counter that, it tries to detect whether or not the value is a VALUE (a -pointer), then if it seems, the value will be handled as a pointer. -This kind of methods are called “conservative GC”. -It seems that it is conservative because it “tentatively inclines things to the safe side”

-

Next, we’ll look at the function to check if “it looks like a VALUE”, -it is is_pointer_to_heap().

-

is_pointer_to_heap()

-

is_pointer_to_heap()

- -
- 480  static inline int
- 481  is_pointer_to_heap(ptr)
- 482      void *ptr;
- 483  {
- 484      register RVALUE *p = RANY(ptr);
- 485      register RVALUE *heap_org;
- 486      register long i;
- 487
- 488      if (p < lomem || p > himem) return Qfalse;
- 489
- 490      /* check if there's the possibility that p is a pointer */
- 491      for (i=0; i < heaps_used; i++) {
- 492          heap_org = heaps[i];
- 493          if (heap_org <= p && p < heap_org + heaps_limits[i] &&
- 494              ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0)
- 495              return Qtrue;
- 496      }
- 497      return Qfalse;
- 498  }
-
-(gc.c)
-
-

If I briefly explain it, it would look like the followings:

-
    -
  • check if it is in between the top and the bottom of the addresses where RVALUEs reside.
  • -
  • check if it is in the range of a heap
  • -
  • make sure the value points to the head of a RVALUE.
  • -
-

Since the mechanism is like this, it’s obviously possible that a non-VALUE -value is mistakenly handled as a VALUE. -But at least, it will never fail to find out the used VALUEs. -And, with this amount of tests, it may rarely pick up a non-VALUE value -unless it intentionally does. -Therefore, considering about the benefits we can obtain by GC, it’s sufficient -to compromise.

-

Register Window

-

This section is about FLUSH_REGISTER_WINDOWS() which has been deferred.

-

Register windows are the mechanism to enable to put a part of the machine stack -into inside the CPU. -In short, it is a cache whose purpose of use is narrowed down. -Recently, it exists only in Sparc architecture. -It’s possible that there are also VALUEs in register windows, -and it’s also necessary to get down them into memory.

-

The content of the macro is like this:

-

FLUSH_REGISTER_WINDOWS

- -
- 125  #if defined(sparc) || defined(__sparc__)
- 126  # if defined(linux) || defined(__linux__)
- 127  #define FLUSH_REGISTER_WINDOWS  asm("ta  0x83")
- 128  # else /* Solaris, not sparc linux */
- 129  #define FLUSH_REGISTER_WINDOWS  asm("ta  0x03")
- 130  # endif
- 131  #else /* Not a sparc */
- 132  #define FLUSH_REGISTER_WINDOWS
- 133  #endif
-
-(defines.h)
-
-

asm(...) is a built-in assembler. -However, even though I call it assembler, this instruction named ta is the -call of a privileged instruction. -In other words, the call is not of the CPU but of the OS. -That’s why the instruction is different for each OS. -The comments describe only about Linux and Solaris, -but actually FreeBSD and NetBSD are also works on Sparc, so this comment is wrong.

-

Plus, if it is not Sparc, it is unnecessary to flush, -thus FLUSH_REGISTER_WINDOWS is defined as nothing. -Like this, the method to get a macro back to nothing is very famous technique -that is also convenient when debugging.

-

Machine Stack

-

Then, let’s go back to the rest of rb_gc(). -This time, it marks VALUESs in the machine stack.

-

▼ mark the machine stack

- -
-1152      rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END);
-1153  #if defined(__human68k__)
-1154      rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
-1155                           (VALUE*)((char*)STACK_END + 2));
-1156  #endif
-
-(gc.c)
-
-

rb_gc_stack_start seems the start address (the end of the stack) and -STACK_END seems the end address (the top). -And, rb_gc_mark_locations() practically marks the stack space.

-

There are rb_gc_mark_locations() two times in order to deal with the -architectures which are not 4-byte alignment. -rb_gc_mark_locations() tries to mark for each portion of sizeof(VALUE), so -if it is in 2-byte alignment environment, sometimes not be able to properly mark. -In this case, it moves the range 2 bytes then marks again.

-

Now, rb_gc_stack_start, STACK_END, rb_gc_mark_locations(), -let’s examine these three in this order.

-

Init_stack()

-

The first thing is rb_gc_starck_start. -This variable is set only during Init_stack(). -As the name Init_ might suggest, this function is called at the time when -initializing the ruby interpretor.

-

Init_stack()

- -
-1193  void
-1194  Init_stack(addr)
-1195      VALUE *addr;
-1196  {
-1197  #if defined(__human68k__)
-1198      extern void *_SEND;
-1199      rb_gc_stack_start = _SEND;
-1200  #else
-1201      VALUE start;
-1202
-1203      if (!addr) addr = &start;
-1204      rb_gc_stack_start = addr;
-1205  #endif
-1206  #ifdef HAVE_GETRLIMIT
-1207      {
-1208          struct rlimit rlim;
-1209
-1210          if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
-1211              double space = (double)rlim.rlim_cur*0.2;
-1212
-1213              if (space > 1024*1024) space = 1024*1024;
-1214              STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
-1215          }
-1216      }
-1217  #endif
-1218  }
-
-(gc.c)
-
-

What is important is only the part in the middle. -It defines an arbitrary local variable (it is allocated on the stack) and -it sets its address to rb_gc_stack_start. -The _SEND inside the code for __human68k__ is probably the variable defined -by a library of compiler or system. -Naturally, you can presume that it is the contraction of Stack END.

-

Meanwhile, the code after that bundled by HAVE_GETRLIMIT appears to check the -length of the stack and do mysterious things. -This is also in the same context of what is done at rb_gc_mark_children() to -prevent the stack overflow. -We can ignore this.

-

STACK_END

-

Next, we’ll look at the STACK_END which is the macro to detect the end of the stack.

-

STACK_END

- -
- 345  #ifdef C_ALLOCA
- 346  # define SET_STACK_END VALUE stack_end; alloca(0);
- 347  # define STACK_END (&stack_end)
- 348  #else
- 349  # if defined(__GNUC__) && defined(USE_BUILTIN_FRAME_ADDRESS)
- 350  #  define SET_STACK_END  VALUE *stack_end = __builtin_frame_address(0)
- 351  # else
- 352  #  define SET_STACK_END  VALUE *stack_end = alloca(1)
- 353  # endif
- 354  # define STACK_END (stack_end)
- 355  #endif
-
-(gc.c)
-
-

As there are three variations of SET_STACK_END, let’s start with the bottom one. -alloca() allocates a space at the end of the stack and returns it, -so the return value and the end address of the stack should be very close. -Hence, it considers the return value of alloca() as an approximate value of -the end of the stack.

-

Let’s go back and look at the one at the top. When the macro C_ALLOCA is -defined, alloca() is not natively defined, … in other words, it indicates a -compatible function is defined in C. I mentioned that in this case alloca() -internally allocates memory by using malloc(). -However, it does not help to get the position of the stack at all. -To deal with this situation, it determines that the local variable stack_end -of the currently executing function is close to the end of the stack and uses -its address (&stack_end).

-

Plus, this code contains alloca(0) whose purpose is not easy to see. -This has been a feature of the alloca() defined in C since early times, -and it means “please check and free the unused space”. -Since this is used when doing GC, -it attempts to free the memory allocated with alloca() at the same time. -But I think it’s better to put it in another macro instead of mixing into such -place …

-

And at last, in the middle case, it is about __builtin_frame_address(). -__GNUC__ is a symbol defined in gcc (the compiler of GNU C). -Since this is used to limit, it is a built-in instruction of gcc. -You can get the address of the n-times previous stack frame with __builtin_frame_address(n). -As for __builtin_frame_adress(0), it provides the address of the current frame.

-

rb_gc_mark_locations()

-

The last one is the rb_gc_mark_locations() function that actually marks the stack.

-

rb_gc_mark_locations()

- -
- 513  void
- 514  rb_gc_mark_locations(start, end)
- 515      VALUE *start, *end;
- 516  {
- 517      VALUE *tmp;
- 518      long n;
- 519
- 520      if (start > end) {
- 521          tmp = start;
- 522          start = end;
- 523          end = tmp;
- 524      }
- 525      n = end - start + 1;
- 526      mark_locations_array(start,n);
- 527  }
-
-(gc.c)
-
-

Basically, delegating to the function mark_locations_array() which marks a -space is sufficient. -What this function does is properly adjusting the arguments. -Such adjustment is required because in which direction the machine stack -extends is undecided. -If the machine stack extends to lower addresses, end is smaller, -if it extends to higher addresses, start is smaller. -Therefore, so that the smaller one becomes start, they are adjusted here.

-

The other root objects

-

Finally, it marks the built-in VALUE containers of the interpretor.

-

▼ The other roots

- -
-1159      /* mark the registered global variables */
-1160      for (list = global_List; list; list = list->next) {
-1161          rb_gc_mark(*list->varptr);
-1162      }
-1163      rb_mark_end_proc();
-1164      rb_gc_mark_global_tbl();
-1165
-1166      rb_mark_tbl(rb_class_tbl);
-1167      rb_gc_mark_trap_list();
-1168
-1169      /* mark the instance variables of true, false, etc if exist */
-1170      rb_mark_generic_ivar_tbl();
-1171
-          /* mark the variables used in the ruby parser (only while parsing) */
-1172      rb_gc_mark_parser();
-
-(gc.c)
-
-

When putting a VALUE into a global variable of C, -it is required to register its address by user via rb_gc_register_address(). -As these objects are saved in global_List, all of them are marked.

-

rb_mark_end_proc() is to mark the procedural objects which are registered via -kind of END statement of Ruby and executed when a program finishes. (END -statements will not be described in this book).

-

rb_gc_mark_global_tbl() is to mark the global variable table rb_global_tbl. -(See also the next chapter “Variables and Constants”)

-

rb_mark_tbl(rb_class_tbl) is to mark rb_class_tbl which was discussed in the -previous chapter.

-

rb_gc_mark_trap_list() is to mark the procedural objects which are registered -via the Ruby’s function-like method trap. -(This is related to signals and will also not be described in this book.)

-

rb_mark_generic_ivar_tbl() is to mark the instance variable table prepared -for non-pointer VALUE such as true.

-

rb_gc_mark_parser() is to mark the semantic stack of the parser. -(The semantic stack will be described in Part 2.)

-

Until here, the mark phase has been finished.

-

Sweep

-

The special treatment for NODE

-

The sweep phase is the procedures to find out and free the not-marked objects. -But, for some reason, the objects of type T_NODE are specially treated. -Take a look at the next part:

-

▼ at the beggining of gc_sweep()

- -
- 846  static void
- 847  gc_sweep()
- 848  {
- 849      RVALUE *p, *pend, *final_list;
- 850      int freed = 0;
- 851      int i, used = heaps_used;
- 852
- 853      if (ruby_in_compile && ruby_parser_stack_on_heap()) {
- 854          /* If the yacc stack is not on the machine stack,
- 855             do not collect NODE while parsing */
- 856          for (i = 0; i < used; i++) {
- 857              p = heaps[i]; pend = p + heaps_limits[i];
- 858              while (p < pend) {
- 859                  if (!(p->as.basic.flags & FL_MARK) &&
-                                          BUILTIN_TYPE(p) == T_NODE)
- 860                      rb_gc_mark((VALUE)p);
- 861                  p++;
- 862              }
- 863          }
- 864      }
-
-(gc.c)
-
-

NODE is a object to express a program in the parser. -NODE is put on the stack prepared by a tool named yacc while compiling, -but that stack is not always on the machine stack. -Concretely speaking, when ruby_parser_stack_on_heap() is false, it indicates -it is not on the machine stack. -In this case, a NODE could be accidentally collected in the middle of its -creation, thus the objects of type T_NODE are unconditionally marked and -protected from being collected while compiling (ruby_in_compile) .

-

Finalizer

-

After it has reached here, all not-marked objects can be freed. -However, there’s one thing to do before freeing. -In Ruby the freeing of objects can be hooked, and it is necessary to call them. -This hook is called “finalizer”.

-

gc_sweep() Middle

- -
- 869      freelist = 0;
- 870      final_list = deferred_final_list;
- 871      deferred_final_list = 0;
- 872      for (i = 0; i < used; i++) {
- 873          int n = 0;
- 874
- 875          p = heaps[i]; pend = p + heaps_limits[i];
- 876          while (p < pend) {
- 877              if (!(p->as.basic.flags & FL_MARK)) {
- 878  (A)             if (p->as.basic.flags) {
- 879                      obj_free((VALUE)p);
- 880                  }
- 881  (B)             if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
- 882                      p->as.free.flags = FL_MARK; /* remains marked */
- 883                      p->as.free.next = final_list;
- 884                      final_list = p;
- 885                  }
- 886                  else {
- 887                      p->as.free.flags = 0;
- 888                      p->as.free.next = freelist;
- 889                      freelist = p;
- 890                  }
- 891                  n++;
- 892              }
- 893  (C)         else if (RBASIC(p)->flags == FL_MARK) {
- 894                  /* the objects that need to finalize */
- 895                  /* are left untouched */
- 896              }
- 897              else {
- 898                  RBASIC(p)->flags &= ~FL_MARK;
- 899              }
- 900              p++;
- 901          }
- 902          freed += n;
- 903      }
- 904      if (freed < FREE_MIN) {
- 905          add_heap();
- 906      }
- 907      during_gc = 0;
-
-(gc.c)
-
-

This checks all over the object heap from the edge, -and frees the object on which FL_MARK flag is not set by using obj_free() (A). -obj_free() frees, for instance, only char[] used by String objects or -VALUE[] used by Array objects, -but it does not free the RVALUE struct and does not touch basic.flags at all. -Therefore, if a struct is manipulated after obj_free() is called, -there’s no worry about going down.

-

After it frees the objects, it branches based on FL_FINALIZE flag (B). -If FL_FINALIZE is set on an object, -since it means at least a finalizer is defined on the object, -the object is added to final_list. -Otherwise, the object is immediately added to freelist. -When finalizing, basic.flags becomes FL_MARK. -The struct-type flag (such as T_STRING) is cleared because of this, and -the object can be distinguished from alive objects.

-

Then, this phase completes by executing the all finalizers. -Notice that the hooked objects have already died when calling the finalizers. -It means that while executing the finalizers, one cannot use the hooked objects.

-

gc_sweep() the rest

- -
- 910      if (final_list) {
- 911          RVALUE *tmp;
- 912
- 913          if (rb_prohibit_interrupt || ruby_in_compile) {
- 914              deferred_final_list = final_list;
- 915              return;
- 916          }
- 917
- 918          for (p = final_list; p; p = tmp) {
- 919              tmp = p->as.free.next;
- 920              run_final((VALUE)p);
- 921              p->as.free.flags = 0;
- 922              p->as.free.next = freelist;
- 923              freelist = p;
- 924          }
- 925      }
- 926  }
-
-(gc.c)
-
-

The for in the last half is the main finalizing procedure. -The if in the first half is the case when the execution could not be moved to -the Ruby program for various reasons. -The objects whose finalization is deferred will be appear in the route © of -the previous list.

-

rb_gc_force_recycle()

-

I’ll talk about a little different thing at the end. -Until now, the ruby‘s garbage collector decides whether or not it collects each object, -but there’s also a way that users explicitly let it collect a particular object. -It’s rb_gc_force_recycle().

-

rb_gc_force_recycle()

- -
- 928  void
- 929  rb_gc_force_recycle(p)
- 930      VALUE p;
- 931  {
- 932      RANY(p)->as.free.flags = 0;
- 933      RANY(p)->as.free.next = freelist;
- 934      freelist = RANY(p);
- 935  }
-
-(gc.c)
-
-

Its mechanism is not so special, but I introduced this because you’ll see it -several times in Part 2 and Part 3.

-

Discussions

-

To free spaces

-

The space allocated by an individual object, say, char[] of String, is -freed during the sweep phase, -but the code to free the RVALUE struct itself has not appeared yet. -And, the object heap also does not manage the number of structs in use and such. -This means that if the ruby’s object space is once allocated it would never be freed.

-

For example, the mailer what I’m creating now temporarily uses the space almost -40M bytes when constructing the threads for 500 mails, but if most of the space -becomes unused as the consequence of GC it will keep occupying the 40M bytes. -Because my machine is also kind of modern, -it does not matter if just the 40M bytes are used. -But, if this occurs in a server which keeps running, there’s the possibility of -becoming a problem.

-

However, one also need to consider that free() does not always mean the -decrease of the amount of memory in use. -If it does not return memory to OS, the amount of memory in use of the process -never decrease. And, depending on the implementation of malloc(), -although doing free() it often does not cause returning memory to OS.

-

… I had written so, but just before the deadline of this book, RVALUE became to be freed. -The attached CD-ROM also contains the edge ruby, so please check by diff. -… what a sad ending.

-

Generational GC

-

Mark & Sweep has an weak point, it is “it needs to touch the entire object space -at least once”. There’s the possibility that using the idea of Generational GC -can make up for the weak point.

-

The fundamental of Generational GC is the experiential rule that -“Most objects are lasting for either very long or very short time”. -You may be convinced about this point by thinking for seconds about the -programs you write.

-

Then, thinking based on this rule, one may come up with the idea that -“long-lived objects do not need to be marked or swept each and every time”. -Once an object is thought that it will be long-lived, -it is treated specially and excluded from the GC target. -Then, for both marking and sweeping, it can significantly decrease the number -of target objects. -For example, if half of the objects are long-lived at a particular GC time, -the number of the target objects is half.

-

There’s a problem, though. Generational GC is very difficult to do if objects can’t be moved. -It is because the long-lived objects are, as I just wrote, needed to “be treated specially”. -Since generational GC decreases the number of the objects dealt with and reduces the cost, -if which generation a object belongs to is not clearly categorized, -as a consequence it is equivalent to dealing with both generations. -Furthermore, the ruby’s GC is also a conservative GC, -so it also has to be created so that is_pointer_to_heap() work. -This is particularly difficult.

-

How to solve this problem is … By the hand of Mr. Kiyama Masato, -the implementation of Generational GC for ruby has been published. -I’ll briefly describe how this patch deals with each problem. -And this time, by courtesy of Mr. Kiyama, this Generational GC patch and its -paper are contained in attached CD-ROM. -(See also doc/generational-gc.html)

-

Then, I shall start the explanation. -In order to ease explaining, from now on, -the long-lived objects are called as “old-generation objects”, -the short-lived objects are called as “new-generation objects”,

-

First, about the biggest problem which is the special treatment for the old-generation objects. -This point is resolved by linking only the new-generation objects into a list named newlist. -This list is substantialized by increasing RVALUE’s elements.

-

Second, about the way to detect the old-generation objects. It is very simply -done by just removing the newlist objects which were not garbage collected -from the newlist. -In other words, once an object survives through GC, it will be treated as an -old-generation object.

-

Third, about the way to detect the references from old-generation objects to new-generation objects. -In Generational GC, it’s sort of, the old-generation objects keep being in the marked state. -However, when there are links from old-generation to new-generation, -the new-generation objects will not be marked. (Figure 11)

-
-

(gengc)
-Figure 11: reference over generations

-
    -
  • ルートオブジェクト the root objects
  • -
  • 新世代 new-generation
  • -
  • 旧世代 old-generation -
- -

This is not good, so at the moment when an old-generational object refers to a new-generational object, -the new-generational object must be turned into old-generational. -The patch modifies the libraries and -adds checks to where there’s possibility that this kind of references happens.

-

This is the outline of its mechanism. It was scheduled that this patch is included ruby 1.7, -but it has not been included yet. It is said that the reason is its speed, -There’s an inference that the cost of the third point “check all references” matters, -but the precise cause has not figured out.

-

Compaction

-

Could the ruby’s GC do compaction? -Since VALUE of ruby is a direct pointer to a struct, -if the address of the struct are changed because of compaction, -it is necessary to change the all VALUEs that point to the moved structs.

-

However, since the ruby’s GC is a conservative GC, “the case when it is -impossible to determine whether or not it is really a VALUE” is possible. -Changing the value even though in this situation, -if it was not VALUE something awful will happen. -Compaction and conservative GC are really incompatible.

-

But, let’s contrive countermeasures in one way or another. -The first way is to let VALUE be an object ID instead of a pointer. (Figure 12) -It means sandwiching a indirect layer between VALUE and a struct. -In this way, as it’s not necessary to rewrite VALUE, structs can be safely moved. -But as trade-offs, accessing speed slows down and the compatibility of -extension libraries is lost.

-
-

(objid)
-Figure 12: reference through the object ID

-
    -
  • アドレスを入れる store addresses
  • -
  • インデックスを入れる store indexes
  • -
  • 移動できる can be moved -
- -

Then, the next way is to allow moving the struct only when they are pointed -from only the pointers that “is surely VALUE” (Figure 13). -This method is called Mostly-copying garbage collection. -In the ordinary programs, there are not so many objects that -is_pointer_to_heap() is true, so the probability of being able to move the -object structs is quite high.

-
-

(mostcopy)
-Figure 13: Mostly-copying garbage collection

-
    -
  • (above) Since there’s a possibility of being referred to by non-VALUE, - this object is not moved.
  • -
  • (bottom) Since it is sure that this is referred only VALUEs, - this object can be moved.
  • -
  • 移動 move -
- -

Moreover and moreover, by enabling to move the struct, -the implementation of Generational GC becomes simple at the same time. -It seems to be worth to challenge.

-

volatile to protect from GC

-

I wrote that GC takes care of VALUE on the stack, -therefore if a VALUE is located as a local variable the VALUE should certainly be marked. -But in reality due to the effects of optimization, it’s possible that the -variables disappear. -For example, there’s a possibility of disappearing in the following case:

-
-VALUE str;
-str = rb_str_new2("...");
-printf("%s\n", RSTRING(str)->ptr);
-
-

Because this code does not access the str itself, -some compilers only keeps str->ptr in memory and deletes the str. -If this happened, the str would be collected and the process would be down. -There’s no choice in this case

-
-volatile VALUE str;
-
-

we need to write this way. volatile is a reserved word of C, -and it has an effect of forbidding optimizations that have to do with this variable. -If volatile was attached in the code relates to Ruby, -you could assume almost certainly that its exists for GC. -When I read K & R, I thought “what is the use of this?”, -and totally didn’t expect to see the plenty of them in ruby.

-

Considering these aspects, the promise of the conservative GC “users don’t have -to care about GC” seems not always true. There was once a discussion that “the -Scheme’s GC named KSM does not need volatile”, -but it seems it could not be applied to ruby because its algorithm has a hole.

-

When to invoke

-

Inside gc.c

-

When to invoke GC? -Inside gc.c, there are three places calling rb_gc() -inside of gc.c,

-
    -
  • ruby_xmalloc()
  • -
  • ruby_xrealloc()
  • -
  • rb_newobj()
  • -
-

As for ruby_xmalloc() and ruby_xrealloc(), it is when failing to allocate memory. -Doing GC may free memories and it’s possible that a space becomes available again. -rb_newobj() has a similar situation, it invokes when freelist becomes empty.

-

Inside the interpritor

-

There’s several places except for gc.c where calling rb_gc() in the interpretor.

-

First, in io.c and dir.c, when it runs out of file descriptors and could not open, -it invokes GC. If IO objects are garbage collected, it’s possible that the -files are closed and file descriptors become available.

-

In ruby.c, rb_gc() is sometimes done after loading a file. -As I mentioned in the previous Sweep section, it is to compensate for the fact -that NODE cannot be garbage collected while compiling.

-

Object Creation

-

We’ve finished about GC and come to be able to deal with the Ruby objects from -its creation to its freeing. -So I’d like to describe about object creations here. -This is not so related to GC, rather, it is related a little to the discussion -about classes in the previous chapter.

-

Allocation Framework

-

We’ve created objects many times. For example, in this way:

-
-class C
-end
-C.new()
-
-

At this time, how does C.new create a object?

-

First, C.new is actually Class#new. Its actual body is this:

-

rb_class_new_instance()

- -
- 725  VALUE
- 726  rb_class_new_instance(argc, argv, klass)
- 727      int argc;
- 728      VALUE *argv;
- 729      VALUE klass;
- 730  {
- 731      VALUE obj;
- 732
- 733      obj = rb_obj_alloc(klass);
- 734      rb_obj_call_init(obj, argc, argv);
- 735
- 736      return obj;
- 737  }
-
-(object.c)
-
-

rb_obj_alloc() calles the allocate method against the klass. -In other words, it calls C.allocate in this example currently explained. -It is Class#allocate by default and its actual body is rb_class_allocate_instance().

-

rb_class_allocate_instance()

- -
- 708  static VALUE
- 709  rb_class_allocate_instance(klass)
- 710      VALUE klass;
- 711  {
- 712      if (FL_TEST(klass, FL_SINGLETON)) {
- 713          rb_raise(rb_eTypeError,
-                       "can't create instance of virtual class");
- 714      }
- 715      if (rb_frame_last_func() != alloc) {
- 716          return rb_obj_alloc(klass);
- 717      }
- 718      else {
- 719          NEWOBJ(obj, struct RObject);
- 720          OBJSETUP(obj, klass, T_OBJECT);
- 721          return (VALUE)obj;
- 722      }
- 723  }
-
-(object.c)
-
-

rb_newobj() is a function that returns a RVALUE by taking from the freelist. -NEWOBJ() is just a rb_newobj() with type-casting. -The OBJSETUP() is a macro to initialize the struct RBasic part, -you can think that this exists only in order not to forget to set the FL_TAINT flag.

-

The rest is going back to rb_class_new_instance(), then it calls rb_obj_call_init(). -This function calls initialize on the just created object, -and the initialization completes.

-

This is summarized as follows:

-
-SomeClass.new            = Class#new (rb_class_new_instance)
-    SomeClass.allocate       = Class#allocate (rb_class_allocate_instance)
-    SomeClass#initialize     = Object#initialize (rb_obj_dummy)
-
-

I could say that the allocate class method is to physically initialize, -the initialize is to logically initialize. -The mechanism like this, in other words the mechanism that an object creation -is divided into allocate / initialize and new presides them, is called -the “allocation framework”.

-

Creating User Defined Objects

-

Next, we’ll examine about the instance creations of the classes defined in -extension libraries. -As it is called user-defined, its struct is not decided, without telling -how to allocate it, ruby don’t understand how to create its object. -Let’s look at how to tell it.

-

Data_Wrap_Struct()

-

Whichever it is user-defined or not, its creation mechanism itself can follow -the allocation framework. -It means that when defining a new SomeClass class in C, -we overwrite both SomeClass.allocate and SomeClass#initialize.

-

Let’s look at the allocate side first. Here, it does the physical initialization. -What is necessary to allocate? -I mentioned that the instance of the user-defined class is a pair of -struct RData and a user-prepared struct. -We’ll assume that the struct is of type struct my. -In order to create a VALUE based on the struct my, you can use Data_Wrap_Struct(). -This is how to use:

-
-struct my *ptr = malloc(sizeof(struct my));  /* arbitrarily allocate in the heap */
-VALUE val = Data_Wrap_Struct(data_class, mark_f, free_f, ptr);
-
-

data_class is the class that val belongs to, ptr is the pointer to be wrapped. -mark_f is (the pointer to) the function to mark this struct. -However, this does not mark the ptr itself and is used when the struct -pointed by ptr contains VALUE. -On the other hand, free_f is the function to free the ptr itself. -The argument of the both functions is ptr. -Going back a little and reading the code to mark may help you to understand -things around here in one shot.

-

Let’s also look at the content of Data_Wrap_Struct().

-

Data_Wrap_Struct()

- -
- 369  #define Data_Wrap_Struct(klass, mark, free, sval) \
- 370      rb_data_object_alloc(klass, sval,             \
-                               (RUBY_DATA_FUNC)mark,    \
-                               (RUBY_DATA_FUNC)free)
-
- 365  typedef void (*RUBY_DATA_FUNC) _((void*));
-
-(ruby.h)
-
-

Most of it is delegated to rb_object_alloc().

-

rb_data_object_alloc()

- -
- 310  VALUE
- 311  rb_data_object_alloc(klass, datap, dmark, dfree)
- 312      VALUE klass;
- 313      void *datap;
- 314      RUBY_DATA_FUNC dmark;
- 315      RUBY_DATA_FUNC dfree;
- 316  {
- 317      NEWOBJ(data, struct RData);
- 318      OBJSETUP(data, klass, T_DATA);
- 319      data->data = datap;
- 320      data->dfree = dfree;
- 321      data->dmark = dmark;
- 322
- 323      return (VALUE)data;
- 324  }
-
-(gc.c)
-
-

This is not complicated. As the same as the ordinary objects, it prepares a -RVALUE by using NEWOBJ() OBJSETUP(), -and sets the members.

-

Here, let’s go back to allocate. -We’ve succeeded to create a VALUE by now, -so the rest is putting it in an arbitrary function -and defining the function on a class by rb_define_singleton_method().

-

Data_Get_Struct()

-

The next thing is initialize. Not only for initialize, the methods need a -way to pull out the struct my* from the previously created VALUE. In order -to do it, you can use the Data_Get_Struct() macro.

-

Data_Get_Struct()

- -
- 378  #define Data_Get_Struct(obj,type,sval) do {\
- 379      Check_Type(obj, T_DATA); \
- 380      sval = (type*)DATA_PTR(obj);\
- 381  } while (0)
-
- 360  #define DATA_PTR(dta) (RDATA(dta)->data)
-
-(ruby.h)
-
-

As you see, it just takes the pointer (to struct my) from a member of RData. -This is simple. Check_Type() just checks the struct type.

-

The Issues of the Allocation Framework

-

So, I’ve explained innocently until now, but actually the current allocation -framework has a fatal issue. -I just described that the object created with allocate appears to the -initialize or the other methods, but if the passed object that was created -with allocate is not of the same class, it must be a very serious problem. -For example, if the object created with the default Objct.allocate -(Class#allocate) is passed to the method of String, this cause a serious problem. -That is because even though the methods of String are written -based on the assumption that a struct of type struct RString is given, -the given object is actually a struct RObject. -In order to avoid such situation, -the object created with C.allocate must be passed only to the methods of C -or its subclasses.

-

Of course, this is always true when things are ordinarily done. -As C.allocate creates the instance of the class C, -it is not passed to the methods of the other classes. -As an exception, it is possible that it is passed to the method of Object, -but the methods of Object does not depend on the struct type.

-

However, what if it is not ordinarily done? -Since C.allocate is exposed at the Ruby level, -though I’ve not described about them yet, -by making use of alias or super or something, -the definition of allocate can be moved to another class. -In this way, you can create an object whose class is String but whose actual -struct type is struct RObject. -It means that you can freely let ruby down from the Ruby level. -This is a problem.

-

The source of the issue is that allocate is exposed to the Ruby level as a method. -Conversely speaking, a solution is to define the content of allocate on the -class by using a way that is anything but a method. -So,

-
-rb_define_allocator(rb_cMy, my_allocate);
-
-

an alternative like this is currently in discussion.

- - - -
- - diff --git a/htmls/index.html b/htmls/index.html deleted file mode 100644 index 696c4ac..0000000 --- a/htmls/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Table of contents

-

Some chapters are previews. It means they have not been fully reviewed, -some diagrams may be missing and some sentences may be a little -rough. But it also means they are in open review, so do not hesitate -to address issues on the mailing list.

- -

Part 1: Objects

- -

Part 2: Syntax analysis

- -

Part 3: Evaluation

- -

Part 4: Around the evaluator

- - -

About this Guide

-

This is a new effort to gather efforts to help translate into English the Ruby -Hacking Guide. The RHG is a book -that explains how the ruby interpreter (the official -C implementation of the Ruby language) works -internally.

-

To fully understand it, you need a good knowledge of C and Ruby.

-

Please note that this book was based on the source code of ruby 1.7.3 -so there are a few small differences to the current version of -ruby. However, these differences may make the source code simpler to -understand and the Ruby Hacking Guide is a good starting point before -looking into the ruby source code. The version of the source code used -can be downloaded here: http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz.

-

Many thanks to RubyForge for hosting us and to -Minero AOKI for letting us translate his work.

-

Help us!

-

The original is available here -or hosted within this repo here -(currently with broken formatting)

-

This translation is done during our free time, do not expect too -much. The book is quite big (more than 500 pages) so we need help to -translate it.

-

People who are good at Ruby, C and Japanese or English are -needed. Those good at Japanese (native Japanese speakers are of course -welcome) can help translate and those good at English (preferably -native speakers) can help correct mistakes, and rewrite badly written -parts… Knowing Ruby and C well is really a requirement because it -helps avoiding many mistranslations and misinterpretations.

-

People good at making diagrams would also be helpful because there is -quite a lot to redo and translators would rather spend their time -translating instead of making diagrams.

-

There have been multiple efforts to translate this book, and we want to see if -we can renew efforts by creating an organisation on github. Interested parties -can join in by starting a pull request on this repo -https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com -There is a mostly derelict mailing list at -rhg-discussion mailing list -feel free to introduce yourself (who you are, your skills, how much free time you -have), but I think the best way to propose or send corrections/improvements -is to send a pull request. If you start a feature branch along with a pull -request at the start of your work then people can comment as you work.

-

There is an old SVN repo, that is hosted at -The RubyForge project page is http://rubyforge.org/projects/rhg. -It has been imported here, and I will attempt to give credit and re-write the -SVN/Git history when I can.

-

As for now the contributors to that repo were:

-
    -
  • Vincent ISAMBART
  • -
  • meinrad recheis
  • -
  • Laurent Sansonetti
  • -
  • Clifford Caoile
  • -
  • Jean-Denis Vauguet
  • -
- - - -
- - diff --git a/htmls/intro.html b/htmls/intro.html deleted file mode 100644 index b546577..0000000 --- a/htmls/intro.html +++ /dev/null @@ -1,1021 +0,0 @@ - - - - - Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Preface: Introduction -h2. Characteristics of Ruby

-

Some of the readers may have already been familiar with Ruby, some may be not. -(I wish the latter for this chapter to be most useful) First let’s go though a -rough summary of the characteristics of Ruby for such people.

-

Hereafter capital “Ruby” refers to Ruby as a language scheme, and lowercase -“ruby” refers to the implementation of ruby command.

-

Development pattern

-

Ruby is a personally created language by Yukihiro Matsumoto. That means Ruby -doesn’t have a standard scheme that C or Java have. The specification is merely -shown as an implementation as ruby, and its varying continuously. Whichever -you mention good or bad, it’s unbind.

-

Furthermore ruby itself is a free software – source code being open and -being in public free of charge – this is what I must add in the introduction. -That’s why it allows the approach of this book into publication.

-

Giving the README and LEGAL included in the distribution package the -complete reading of the license, let’s list up what you can do for the time -being:

-

You can redistribute source code of ruby -You can modify source code of ruby -You can redistribute a copy of source code with your modification

-

There is no need for special permission and payment in all these cases.

-

By the way, the original ruby is the version referred to in this book unless -otherwise stated, because our main purpose is to read it. However, I modified -the code without notice at a certain extent such as to remove or add white -spaces, new lines, and comments.

-

It’s conservative

-

Ruby is a very conservative language. It is equipped with only carefully chosen -features that have been tested and washed out in a variety of languages​. -Therefore it doesn’t have plenty of fresh and experimental features very much. -So it has a tendency to appeal to programmers who put importance on practical -functionalities. The dyed-in-the-wool hackers like Scheme and Haskell lovers -don’t seem to find appeal in ruby in a short glance.

-

The library is conservative in the same way. Clear and unabbreviated names are -given for new functions, while names that appears in C and Perl libraries have -been took over from them. For example, printf, getpwent, sub, and tr.

-

It is also conservative in implementation. Assembler is not its option for -seeking speed. Portability is always considered a higher priority when it -conflicts with speed.

-

It is an object-oriented language

-

Ruby is an object-oriented language. It is not possible to forget about it -absolutely, when you talk about the features of Ruby.

-

I will not give a page to this book about what an object-oriented language is. -To tell about an object-oriented feature about Ruby, the expression of the code -that just going to be explained below is the exact sample.

-

It is a script language

-

Ruby is a script language. It is also not possible to forget about it -absolutely, when you talk about the features of Ruby. To gain agreement of -everyone, an introduction of Ruby must include “object-oriented” and “script -language”.

-

However, what is a “script language” for example? I couldn’t figure out the -definition successfully. For example, John K. Ousterhout, the author of Tcl/Tk, -gives a definition as “executable language using #! on UNIX”. There are other -definitions depending on the view points, such as one that can express a useful -program with only one line, or that can execute the code by passing a program -file from the command line, etc.

-

However, I dare to use another definition, because I don’t find much interest -in “what” a script language. To call it a script language, it at least has to -avoid gaining disagreement of calling it so. That’s the definition I suggest. -To fulfill this definition, I would define the meaning of “script language” as -follows.

-

p(=center). -Whether the author of the language calls it “script language” or not.

-

I’m sure this definition will have no failure. And Ruby fulfills this point. -Therefore I call Ruby a “script language”.

-

It’s an interpreter

-

ruby is an interpreter. That’s the fact. But why it’s an interpreter? For -example, couldn’t it be made as a compiler? The answer should be “no”, because -I guess Ruby has at least something better than being an interpreter than a -compiler. Well, what is good about being an interpreter?

-

As a preparation step to investigating into it, let’s start by thinking about -the difference between an interpreter and a compiler. If the matter is to -attempt a comparison with the process how a program is executed theoretically, -there’s no difference between an interpreter language and a compile language. -It may be possible to say that a compiler language involves an interpreter, -because of the fact that CPU “interprets” a code into a machine language using -a compiler. What’s the difference actually? I suppose it’s in a practical -things – in the process of development.

-

I know somebody, as soon as hearing “in the process of development”, would -claim using a stereotypical phrase, that an interpreter reduces effort of -compilation that makes the development procedure easier. But I don’t think it’s -accurate. A language could possibly be planned so that it won’t show the -process of compilation. Actually, Delphi can compile a project by hitting just -F5. A claim about a long time for compilation is derived from the size of the -project or optimization of the codes. Compilation itself doesn’t owe a negative -side.

-

Well, why people perceive an interpreter and compiler so much different like -this? I think that it is because the developers have long distinguished the use -of the implementations of these languages according to the characteristics. In -short, a comparatively small, a daily routine fits well with developing an -interpreter language. On the other hand, a compiler language is a goal for a -large project where a number of people are involved in the development and -accuracy is required. That may be because of the speed, as well as the -readiness of creating a language.

-

Therefore, “it’s handy because it’s an interpreter” is merely an outsized myth. -Being an interpreter doesn’t necessarily contribute the readiness in usage; -seeking readiness in usage naturally makes your path toward building an -interprer language.

-

Anyway, ruby is an interpreter; it has an important fact about where this -book is facing, so I emphasize it here again. It doesn’t matter whether it’s -easy being an interpreter; anyway ruby is implemented as an interpreter.

-

High portability

-

Even with a fundamental problem that the interface is built targeting Unix, I -would insist ruby possesses a high portability. It doesn’t often require an -unfamiliar library. It doesn’t have a part written in assembler gorigorily. -Therefore it’s easy to port to a new platform, comparatively. Namely, it works -on the following platforms currently.

-

Linux -Win32 (Windows 95, 98, Me, NT, 2000, XP) -Cygwin -djgpp -FreeBSD -NetBSD -OpenBSD -BSD/OS -Mac OS X -Solaris -Tru64 UNIX -HP-UX -AIX -VMS -UX/4800 -BeOS -OS/2 (emx) -Psion

-

The main machine of the author Matsumoto is Linux, reportedly. You can assume -that a Linux will not fail to build any version of ruby.

-

Furthermore, a typical Unix environment basically can expect a stable -functionality. Considering the release cycle of packages, the primary option -for the environment to hit around ruby should fall on a branch of PC UNIX, - currently.

-

On the other hand, the Win32 environment tends to cause problems definitely. -The large gaps in the targeting OS model tend to cause problems around the -machine stack and the linker. Yet, recently Windows hackers have contributed to -make better support. I use a native ruby on Windows 2000 and Me. Once it gets -successfully run, it doesn’t seem to show special concerns like frequent -crashing. The main problems on Windows may be the gaps in the specifications.

-

Another type of OS that many people may be interested in should probably be Mac -OS (prior to v9) and handheld OS like Palm.

-

Around ruby 1.2 and before, it supported legacy Mac OS, but the development -seems to be in suspension. Even a compiling can’t get through. The biggest -cause is that the compiler environment of legacy Mac OS and the decrease of -developers. Talking about Mac OS X, there’s no worries because the body is -UNIX.

-

There seem to be discussions the portability to Palm several branches, but I -have never heard of a successful project. I guess the difficulty lies in the -necessity of settling down the specification-level standards such as stdio on -the Palm platform, rather than the processes of actual implementation. Well I -saw a porting to Psion has been done. ([ruby-list:36028]).

-

How about hot stories about VM seen in Java and .NET? I need to mention these -together with implementation in the final chapter.

-

Automatic memory control

-

Functionally it’s called GC, or Garbage Collection. Saying it in C-language, -this feature allows you to skip free() after malloc(). Unused memory is -detected by the system automatically, and will be released. It’s so convenient -that once you get used to GC you will likely be unwilling to do it manual -memory control again.

-

The topics about GC have been common because of its popularity in recent -languages with GC as a standard set, and the GS is fun to talk about because it -has a lot to devise better algorithms.

-

Typeless variables

-

The variables in Ruby don’t have types. The reason is probably typeless -variables conforms more with polymorphism, which is one of the strongest -features of an object-oriented language. Of course a language with variable -type has a way to deal with polymorphism. What I mean here is a typeless -variables have better conformance.

-

The level of “better conformance” in this case refers to synonyms like “handy”. -It’s sometimes corresponds to crucial importance, sometimes it doesn’t matter -practically. Yet, this is certainly an appealing point if a language seeks for -“handy and easy”, and Ruby does.

-

Most of syntactic elements are expressions

-

This topic is probably difficult to understand it instantly without needs -supplemental explanation. For example, the following C-language program -contains a syntactic error.

-

p(=emlist). -result = if (cond) { process(val); } else { 0; } -

-

Because the C-language syntax defines if as a statement. See following rewrite.

-

p(=emlist). -result = cond ? process(val) : 0; -

-

This rewrite is possible because the conditional operator (a?b:c) is defined -as an expression.

-

On the other hand, Ruby acceps a following expression because if is an expression.

-

p(=emlist). -result = if cond then process(val) else nil end -

-

大雑把に言うと、関数やメソッドの引数にできるものは式だと思っていい。

-

もちろん「ほとんどの文法要素が式」という言語は他にもいろいろある。例えば -Lispはその最たるものだ。このあたりの特徴からなんとなく「RubyはLispに似 -てる」と感じる人が多いようである。

-

イテレータ

-

Rubyにはイテレータがある。イテレータとは何か。いやその前にイテレータと -いう言葉は最近嫌われているので別の言葉を使うべきかもしれない。だがい -い言葉を思いつかないので当面イテレータと呼ぶことにする。

-

それでイテレータとは何か。高階の関数を知っているなら、とりあえずはそれ -と似たようなものだと思っておけばいい。Cで言えば関数ポインタを引数 -に渡すやつである。C++で言えばSTLにある@Iterator@の操作部分までをメソッド -に封入したものである。shやPerlを知っているのなら、独自に定義できる -@for@文みたいなもんだと思って見てみるといい。

-

もっともあくまでここに挙げたのは全て「似たようなもの」であって、どれも -Rubyのイテレータと似てはいるが、同じでは、全くない。いずれその時が来た -らもう少し厳密な話をしよう。

-

C言語で書いてある

-

Cで書いたプログラムなどいまどき珍しくもないが、特徴であることは間違い -ない。少なくともHaskellやPL/Iで書いてあるわけではないので一般人にも -読める可能性が高い(本当にそうかどうかはこれから自分で確かめてほしい)。

-

それからC言語と言っても@ruby@が対象としているのは基本的にK&R Cだ。 -少し前まではK&R onlyの環境が、たくさんとは言わないが、それなりにあったからだ。 -しかしさすがに最近はANSI Cが通らない環境はなくなってきており技術的には -ANSI Cに移っても特に問題はない。だが作者のまつもとさん個人の趣味もあっ -てまだK&Rスタイルを通している。

-

そんなわけで関数定義は全てK&Rスタイルだし、プロトタイプ宣言もあまり真面 -目に書かれていない。@gcc@でうっかり@-Wall@を付けると大量に警告が出て -くるとか、 -C++コンパイラでコンパイルするとプロトタイプが合わないと怒られてコンパ -イルできない……なんて話がポロポロとメーリングリストに流れている。

-

拡張ライブラリ

-

RubyのライブラリをCで書くことができ、Rubyを再コンパイルすることなく -実行時にロードできる。このようなライブラリを「Ruby拡張ライブラリ」 -または単に「拡張ライブラリ」と言う。

-

単にCで書けるだけでなくRubyレベルとCレベルでのコードの表現の差が小さい -のも大きな特徴である。Rubyで使える命令はほとんどそのままCでも使うこと -ができる。例えば以下のように。

-

p(=emlist).

-
    -
  1. メソッド呼び出し -obj.method(arg) # Ruby -rb_funcall(obj, rb_intern(“method”), 1, arg); # C
  2. -
  3. ブロック呼び出し -yield arg # Ruby -rb_yield(arg); # C
  4. -
  5. 例外送出 -raise ArgumentError, ‘wrong number of arguments’ # Ruby -rb_raise(rb_eArgError, “wrong number of arguments”); # C
  6. -
  7. オブジェクトの生成 -arr = Array.new # Ruby -VALUE arr = rb_ary_new(); # C -
  8. -
-

拡張ライブラリを書くうえでは非常に楽をできていいし、現実に -このことが代えがたい@ruby@の長所にもなっている。しかしそのぶん -@ruby@の実装にとっては非常に重い足枷となっており、随所にその -影響を見ることができる。特にGCやスレッドへの影響は顕著である。

-

スレッド

-

Rubyにはスレッドがある。さすがに最近はスレッドを知らない人はほとんどい -ないと思うのでスレッド自体に関する説明は省略する。以下はもう少し細かい -話だ。

-

@ruby@のスレッドはオリジナルのユーザレベルスレッドである。この実装の -特徴は、仕様と実装、両方の移植性が非常に高いことである。なにしろDOS上で -さえスレッドが動き、どこでも同じ挙動で使えるのだ。この点を@ruby@の最大の -長所として挙げる人も多い。

-

しかし@ruby@スレッドは凄まじい移植性を実現した反面で速度をおもいきり犠牲 -にしている。どのくらい遅いかというと、世の中に数あるユーザレベルスレッ -ドの実装の中でも一番遅いのではないか、というくらい遅い。これほど@ruby@の -実装の傾向を明確に表しているところもないだろう。

-

ソースコードを読む技術

-

さて。@ruby@の紹介も終わっていよいよソースコード読みに入ろうか、というと -ころだが、ちょっと待ってほしい。

-

ソースコードを読む、というのはプログラマならば誰しもやらなければいけな -いことだが、その具体的な方法を教えてもらえることはあまりないのではない -だろうか。どうしてだろう。プログラムが書けるなら読むのも当然できるとい -うのだろうか。

-

しかし筆者には人の書いたプログラムを読むことがそんなに簡単なことだとは -思えない。プログラムを書くのと同じくらい、読むことにも技術や定石がある -はずだし、必要だと考える。そこで@ruby@を読んでいく前にもう少し一般的に、 -ソースコードを読むにはどういう考えかたをすればいいのか、整理することに -しよう。

-

原則

-

まずは原則について触れる。

-

目的の決定 -bq. -「ソースコードを読むための極意」は『目的をもって読む』ことです。

-

これはRuby作者のまつもとさんの言だ。なるほど、この言葉には非常にうなず -けるものがある。「カーネルくらいは読んどかなきゃいかんかなあ」と思って -ソースコードを展開したり解説本を買ったりしてはみたものの、いったいどう -していいのかわからないまま放ってしまった、という経験のある人は多いので -はないだろうか。その一方で、「このツールのどこかにバグがある、とにかく -これを速攻で直して動かさないと納期に間に合わない」……というときには他 -人のプログラムだろうとなんだろうと瞬く間に直せてしまうこともあるのでは -ないだろうか。

-

この二つのケースで違うのは、意識の持ちかたである。自分が何を知ろうと -しているのかわからなければ「わかる」ことはありえない。だからまず自分が -何を知りたいのか、それを明確に言葉にすることが全ての第一歩である。

-

だがこれだけではもちろん「技術」たりえない。「技術」とは、意識すれば誰に -でもできるものでなければならないからだ。続いて、この第一歩から最終的に -目的を達成するところまで敷衍する方法について延べる。

-

目的の具体化

-

いま「@ruby@全部を理解する」を最終目標に決めたとしよう。これでも「目的を -決めた」とは言えそうだが、しかし実際にソースコードを読む役に立たないこ -とは明らかである。具体的な作業には何にもつながっていないからだ。従って -まずはこの曖昧な目標を具体的なところまで引きずり下ろさなければならない。

-

どうすればいいだろうか。まず第一に、そのプログラムを書いた人間になった -つもりで考えてみることだ。そのときにはプログラムを作るときの知識が流用 -できる。例えば伝統的な「構造化」プログラムを読むとしたら、こちらも -構造化プログラムの手法に則って考えるようにする。即ち目的を徐々に徐々に分割 -していく。あるいはGUIプログラムのようにイベントループに入ってグルグル -するものならば、とりあえず適当にイベントループを眺めてからイベントハン -ドラの役割を調べてみる。あるいはMVC(Model View Controler)のMをまず調 -べてみる。

-

第二に解析の手法を意識することだ。誰しも自分なりの解析方法というのはそ -れなりに持っていると思うが、それは経験と勘に頼って行われていることが多 -い。どうしたらうまくソースコードを読めるのか、そのこと自体を考え、意識 -することが非常に重要である。

-

ではそのような手法にはどんなものがあるだろうか。それを次に説明する。

-

解析の手法

-

ソースコードを読む手法は大雑把に言って静的な手法と動的な手法の二つに分 -類できる。静的な手法とはプログラムを動かさずソースコードを読んだり解析 -したりすること。動的な手法とはデバッガなどのツールを使って実際の動きを -見ることだ。

-

プログラムを調査するときはまず動的な解析から始めたほうがよい。なぜなら -それは「事実」だからだ。静的な解析では現実にプログラムを動かしていない -のでその結果は多かれ少なかれ「予想」になってしまう。真実を知りたいのな -らばまず事実から始めるべきなのだ。

-

もちろん動的な解析の結果が本当に事実であるかどうかはわからない。デバッガがバ -グっているかもしれないし、CPUが熱暴走しているかもしれない。自分が設定 -した条件が間違っているかもしれない。しかし少なくとも静的解析よりは動的 -な解析の結果のほうが事実に近いはずである。

-

動的な解析 -h4. 対象プログラムを使う

-

これがなければ始まらない。そもそもそのプログラムがどういうものなのか、 -どういう動作をすべきなのか、あらかじめ知っておく。

-

デバッガで動きを追う

-

例えば実際にコードがどこを通ってどういうデータ構造を作るか、なんていう -ことは頭の中で考えているよりも実際にプログラムを動かしてみてその結果を -見たほうが早い。それにはデバッガを使うのが簡単だ。

-

実行時のデータ構造を絵にして見られるとさらに嬉しいのだが、そういうツー -ルはなかなかない(特にフリーのものは少ない)。比較的単純な構造のスナッ -プショットくらいならテキストでさらっと書き出し -@graphviz@footnote{@graphviz@……添付CD-ROMの@doc/graphviz.html@参照}の -ようなツールを使って絵にすることもできそうだが、汎用・リアルタイムを -目指すとかなり難しい。

-

トレーサ

-

コードがどの手続きを通っているか調査したければトレーサを使えばいい。 -C言語なら -@ctrace@footnote{@ctrace@……http://www.vicente.org/ctrace}と -いうツールがある。 -またシステムコールのトレースには -@strace@footnote{@strace@……http://www.wi.leidenuniv.nl/~wichert/strace/}、 -@truss@、@ktrace@と言ったツールがある。

-

printしまくる

-

@printf@デバッグという言葉があるが、この手法はデバッグでなくても役に立つ。 -特定の変数の移り変わりなどはデバッガでチマチマ辿ってみるよりもprint文を -埋め込んで結果だけまとめて見るほうがわかりやすい。

-

書き換えて動かす

-

例えば動作のわかりにくいところでパラメータやコードを少しだけ変えて動 -かしてみる。そうすると当然動きが変わるから、コードがどういう意味なのか -類推できる。

-

言うまでもないが、オリジナルのバイナリは残しておいて -同じことを両方にやってみるべきである。

-

静的な解析 -h4. 名前の大切さ

-

静的解析とはつまりソースコードの解析だ。そしてソースコードの解析とは名 -前の調査である。ファイル名・関数名・変数名・型名・メンバ名など、プログ -ラムは名前のかたまりだ。名前はプログラムを抽象化する最大の武器なのであ -たりまえと言えばあたりまえだが、この点を意識して読むとかなり効率が違う。

-

またコーディングルールについてもあたりをつけておきたい。例えばCの関数 -名なら@extern@関数にはプリフィクスを使っていることが多く、関数の種類を見 -分けるのに使える。またオブジェクト指向様式のプログラムだと関数の所属情 -報がプリフィクスに入っていることがあり、貴重な情報になる。 -(例:@rb_str_length@)

-

ドキュメントを読む

-

内部構造を解説したドキュメントが入っていることもある。 -特に「@HACKING@」といった名前のファイルには注意だ。

-

ディレクトリ構造を読む

-

どういう方針でディレクトリが分割されているのか見る。 -そのプログラムがどういう作りになっているのか、 -どういうパートがあるのか、概要を把握する。

-

ファイル構成を読む

-

ファイルの中に入っている関数(名)も合わせて見ながら、 -どういう方針でファイルが分割されているのか見る。ファイル名は -有効期間が非常に長いコメントのようなものであり、注目すべきである。

-

さらに、ファイルの中にまたモジュールがある場合、モジュールを構成する関 -数は近くにまとまっているはずだ。つまり関数の並び順からモジュール構成 -を見付けることができる。

-

略語の調査

-

わかりにくい略語があればリストアップしておいて早めに調べる。 -例えば「GC」と書いてあった場合、それがGarbage Collectionなのか -それともGraphic Contextなのかで随分と話が違ってしまう。

-

プログラム関係の略語はたいてい単語の頭文字を取るとか、単語から母音を落とす、 -という方法で作られる。特に対象プログラムの分野で有名な略語は問答無用で -使われるのであらかじめチェックしておこう。

-

データ構造を知る

-

データとコードが並んでいたら、まずデータ構造から調べるべきである。つま -りCならヘッダファイルから眺めるほうが、たぶんいい。そのときはファイル -名から想像力を最大限に働かせよう。例えば言語処理系で@frame.h@というファ -イルがあったら恐らくスタックフレームの定義だ。

-

また構造体の型とメンバ名だけでも随分といろいろなことがわかる。例え -ば構造体の定義中に自分の型へのポインタで@next@というメンバがあればリンク -リストだろうと想像できる。同様に、@parent@・@children@・@sibling@と言った要 -素があれば十中八九ツリーだ。@prev@ならスタックだろう。

-

関数同士の呼び出し関係を把握する

-

関数同士の関係は名前の次に重要な情報だ。呼び出し関係を表現したものを -特に「コールグラフ」と言うが、これは非常に便利である。このへんは -ツールを活用したい。

-

ツールはテキストベースで十分だが、図にしてくれれば文句無しだ。 -ただそういう便利なものはなかなかない(特にフリーのものは少ない)。 -筆者が本書のために@ruby@を解析したときは、小さなコマンド言語と -パーサを適当にRubyで書き、@graphviz@というツールに渡して半自動生成した。

-

関数を読む

-

動作を読んで、関数のやることを一言で説明できるようにする。関数関連図を -見ながらパートごとに読んでいくのがいい。

-

関数を読むときに重要なのは「何を読むか」ではなく「何を読まないか」であ -る。どれだけコードを削るかで読みやすさが決まると言ってよい。具体的に何 -を削ればいいか、というのは実際に見せてみないとわかりづらいので本文で解 -説する。

-

それとコーディングスタイルが気にいらないときは@indent@のようなツールを -使って変換してしまえばいい。

-

好みに書き換えてみる

-

人間の身体というのは不思議なもので、できるだけ身体のいろんな場所を使い -ながらやったことは記憶に残りやすい。パソコンのキーボードより原稿用紙の -ほうがいい、という人が少なからずいるのは、単なる懐古趣味ではなくそうい -うことも関係しているのではないかと思う。

-

そういうわけで単にモニタで読むというのは非常に身体に残りにくいので、 -書き換えながら読む。そうするとわりと早く身体がコードに馴染んでくること -が多い。気にくわない名前やコードがあったら書き換える。わかりづらい略語 -は置換して省略しないようにしてしまえばよい。

-

ただし当然のことだが書き換えるときはオリジナルのソースは別に残しておき、 -途中で辻褄が合わないと思ったら元のソースを見て確認すること。でないと自 -分の単純ミスで何時間も悩む羽目になる。それに書き換えるのはあくまで馴染 -むためであって書き換えること自体が目的ではないので熱中しすぎないように -注意してほしい。

-

歴史を読む

-

プログラムにはたいてい変更個所の履歴を書いた文書が付いている。例えば -GNUのソフトウェアだと必ず@ChangeLog@というファイルがある。これは -「プログラムがそうなっている理由」を知るのには最高に役に立つ。

-

またCVSやSCCSのようなバージョン管理システムを使っていてしかもそれにア -クセスできる場合は、@ChangeLog@以上に利用価値が高い。CVSを例に取ると、特 -定の行を最後に変更した場所を表示する@cvs annotate@、指定した版からの差分 -を取る@cvs diff@などが便利だ。

-

さらに、開発用のメーリングリストやニュースグループがある場合はその過去 -ログを入手してすぐに検索できるようにしておく。変更の理由がズバリ載って -いることが多いからだ。もちろんWeb上で検索できるならそれでもいい。

-

静的解析用ツール

-

いろいろな目的のためにいろいろなツールがあるので一口には言えないが、筆 -者が一つだけ選ぶとしたら@global@をお勧めする。なんと言っても他の用途に応 -用しやすい作りになっているところがポイントだ。例えば同梱されている -@gctags@は本当はタグファイルを作るためのツールなのだが、 -これを使ってファイルに含まれる関数名のリストを取ることもできる。

-

p(=screen). -~/src/ruby % gctags class.c | awk ‘{print $1}’ -SPECIAL_SINGLETON -SPECIAL_SINGLETON -clone_method -include_class_new -ins_methods_i -ins_methods_priv_i -ins_methods_prot_i -method_list - : - : -

-

とは言えこれはあくまでも筆者のお勧めなので読者は自分の好きなツールを使っ -てもらえばいい。ただその時は最低でも次の機能を備えているものを選ぶように -すべきだ。

-

ファイルに含まれる関数名をリストアップする -関数名や変数名から位置を探す(さらにそこに飛べるとなおよい) -関数クロスリファレンス

-

ビルド -h3. 対象バージョン

-

本書で解説している@ruby@のバージョンは1.7の2002-09-12版である。@ruby@はマ -イナーバージョンが偶数だと安定版で奇数だと開発版だから、1.7は開発版と -いうことになる。しかも9月12日は特に何かの区切りというわけではないの -で、該当バージョンの公式パッケージは配布されていない。従ってこの版を入 -手するには本書添付のCD-ROMまたはサポートサイト -footnote{本書のサポートサイト……http://i.loveruby.net/ja/rhg/} -から入手するか、後述のCVSを使うしかない。

-

安定版の1.6でなく1.7にした理由は、1.7のほうが仕様・実装ともに整理され -ていて扱いやすいことが一つ。次に、開発版先端のほうがCVSが使いやすい。 -さらに、わりと近いうちに次の安定版の1.8が出そうな雰囲気になってきたこと。 -そして最後に、最先端を見ていくほうが気分的に楽しい。

-

ソースコードを入手する

-

添付CD-ROMに解説対象の版のアーカイブを収録した。 -CD-ROMのトップディレクトリに

-

p(=emlist). -ruby-rhg.tar.gz -ruby-rhg.zip -ruby-rhg.lzh -

-

の三種類が置いてあるので、便利なものを選んで使ってほしい。 -もちろん中身はどれも同じだ。例えば@tar.gz@のアーカイブなら -次のように展開すればいいだろう。

-

p(=screen). -~/src % mount /mnt/cdrom -~/src % gzip -dc /mnt/cdrom/ruby-rhg.tar.gz | tar xf - -~/src % umount /mnt/cdrom - -h3. コンパイルする

-

ソースコードを見るだけでも「読む」ことはできる。しかしプログラムを知る -ためには実際にそれを使い、改造し、実験してみることが必要だ。実験をする -なら見ているソースコードと同じものを使わなければ意味がないので、当然自 -分でコンパイルすることになる。

-

そこでここからはコンパイルの方法を説明する。まずはUNIX系OSの場合から話 -を始めよう。Windows上ではいろいろあるので次の項でまとめて話す。ただし -CygwinはWindows上ではあるがほとんどUNIXなので、こちらの話を読んでほし -い。

-

UNIX系OSでのビルド

-

さて、UNIX系OSなら普通Cコンパイラは標準装備なので、次の手順でやれば -たいがい通ってしまう。 -~/src/rubyにソースコードが展開されているとする。

-

p(=screen). -~/src/ruby % ./configure -~/src/ruby % make -~/src/ruby % su -~/src/ruby # make install -

-

以下、いくつか注意すべき点を述べる。

-

Cygwin、UX/4800など一部のプラットフォームでは@configure@の段階で ---enable-sharedオプションを付けないとリンクに失敗する。 ---enable-sharedというのは@ruby@のほとんどを共有ライブラリ -(@libruby.so@)としてコマンドの外に出すオプションである。

-

p(=screen). -~/src/ruby % ./configure —enable-shared -

-

ビルドに関するより詳しいチュートリアルを添付CD-ROMの -doc/build.htmlに入れたので、それを読みながらやってみてほしい。

-

Windowsでのビルド

-

Windowsでのビルドとなるとどうも話がややこしくなる。 -問題の根源はビルド環境が複数あることだ。

-

Visual C++ -MinGW -Cygwin -Borland C++ Compiler

-

まずCygwin環境はWindowsよりもUNIXに条件が近いのでUNIX系のビルド手順に -従えばいい。

-

Visual C++でコンパイルする場合はVisual C++ 5.0以上が -必要である。バージョン6か.NETならまず問題ないだろう。

-

MinGW、Minimalist GNU for WindowsというのはGNUのコンパイル環境(ようするに -@gcc@と@binutils@)をWindowsに移植したものだ。CygwinがUNIX環境全体を移植し -たのに対し、MinGWはあくまでコンパイルのためのツールだけを移植してある。 -またMinGWでコンパイルしたプログラムは実行時に特別なDLLを必要としない。 -つまりMinGWでコンパイルした@ruby@はVisual C++版と全く同じに扱える。

-

また個人利用ならばBorland C++ Compilerのバージョン5.5がBorlandのサイト -footnote{Borlandのサイト:@http://www.borland.co.jp@} -から無料でダウンロードできる。@ruby@がサポートしたのがかなり最近なのが -多少不安だが、本書出版前に行ったビルドテストでは特に問題は出ていない。

-

さて以上四つの環境のうちどれを選べばいいだろうか。まず基本的には -Visual C++版が最も問題が出にくいのでそれをお勧めする。UNIXの経験がある -ならCygwin一式入れてCygwinを使うのもよい。UNIXの経験がなくVisual C++も -持っていない場合はMinGWを使うのがいいだろう。

-

以下ではVisual C++とMinGWでのビルド方法について説明するが、 -あくまで概要だけに留めた。より細かい解説とBorland C++ Compilerでの -ビルド方法は添付CD-ROMの@doc/build.html@に収録したので適宜そちらも -参照してほしい。

-

Visual C++

-

Visual C++と言っても普通はIDEは使わず、DOSプロンプトからビルドする。そ -のときはまずVisual C++自体を動かせるようにするために環境変数の初期化を -しなければいけない。Visual C++にそのためのバッチファイルが付いてくるの -で、まずはそれを実行しよう。

-

p(=screen). -C:> cd “Program FilesMicrosoft Visual Studio .NETVc7bin” -C:Program FilesMicrosoft Visual Studio .NETVc7bin> vcvars32 -

-

これはVisual C++.NETの場合だ。バージョン6なら以下の場所にある。

-

p(=emlist). -C:Program FilesMicrosoft Visual StudioVC98bin -

-

@vcvars32@を実行したらその後は@ruby@のソースツリーの中のフォルダ -@win32@に移動してビルドすればいい。以下、ソースツリーは@C:src@に -あるとしよう。

-

p(=screen). -C:> cd srcruby -C:srcruby> cd win32 -C:srcrubywin32> configure -C:srcrubywin32> nmake -C:srcrubywin32> nmake DESTDIR=“C:Program Filesruby” install -

-

これで@C:Program Filesrubybin@に@ruby@コマンドが、 -C:Program Filesrubylib以下にRubyのライブラリが、 -それぞれインストールされる。@ruby@はレジストリなどは一切使わない -ので、アンインストールするときは@C:ruby@以下を消せばよい。

-

MinGW

-

前述のようにMinGWはコンパイル環境のみなので、一般的なUNIXのツール、 -例えば@sed@や@sh@が存在しない。しかし@ruby@のビルドにはそれが必要なので -それをどこかから調達しなければならない。それにはまた二つの方法が -存在する。CygwinとMSYS(Minimal SYStem)である。

-

だがMSYSのほうは本書の出版前に行ったビルド大会でトラブルが続出してしまっ -たのでお勧めできない。対照的にCygwinを使う方法だと非常に素直に通った。 -従って本書ではCygwinを使う方法を説明する。

-

まずCygwinの@setup.exe@でMinGWと開発ツール一式を入れておく。 -CygwinとMinGWは添付CD-ROMにも収録した -footnote{CygwinとMinGW……添付CD-ROMの@doc/win.html@を参照}。 -あとはCygwinの@bash@プロンプトから以下のように打てばよい。

-

p(=screen). -~/src/ruby % ./configure —with-gcc=‘gcc -mno-cygwin’ - —enable-shared i386-mingw32 -~/src/ruby % make -~/src/ruby % make install -

-

これだけだ。ここでは@configure@の行を折り返しているが実際には一行に -入れる。またバックスラッシュを入れる必要はない。インストール先は -コンパイルしたドライブの@usrlocal@以下になる。このあたりはかなり -ややこしいことが起こっていて説明が長くなるので、 -添付CD-ROMの@doc/build.html@で徹底的に説明しよう。

-

ビルド詳細

-

ここまでが@README@的な解説である。今度はこれまでやったことが具体的に -何をしているのか、つっこんで見ていこう。ただしここの話は部分的に -かなり高度な知識が必要になる。わからない場合はいきなり次の節に -飛んでほしい。本書全体を読んでから戻ってきてもらえばわかるように -なっているはずだ。

-

さて、どのプラットフォームでも@ruby@のビルドは三段階に分かれている。 -即ち@configure@、@make@、@make install@だ。@make install@はいいとして、 -@configure@と@make@の段階について解説しよう。

-

configure

-

まず@configure@である。この中身はシェルスクリプトになっており、これ -でシステムのパラメータを検出する。例えば「ヘッダファイル@setjmp.h@が存 -在するか」とか、「@alloca()@は使えるか」ということを調べてくれる。調べ -る方法は意外と単純である。

-

チェック対象方法 -コマンド実際に実行してみて@$?を見る -ヘッダファイルif [ -f $includedir/stdio.h ]@ -関数小さいプログラムをコンパイルしてみてリンクが成功するかどうか試す

-

違いを検出したら、それをどうにかしてこちらに伝えてもらわないと -いけない。その方法は、まず@Makefile@が一つ。パラメータを@@PARAM@@の -ように埋め込んだ@Makefile.in@を置いておくと、それを実際の値に変換 -した@Makefile@を生成してくれる。例えば次のように。

-

p(=emlist). -Makefile.in: CFLAGS = CFLAGS - ↓ -Makefile : CFLAGS = -g -O2 -

-

もう一つ、関数やヘッダファイルがあるかどうかといった情報を -ヘッダファイルにして出力してくれる。出力ファイルの名前は変更 -できるのでプログラムによって違うが、@ruby@では@config.h@である。 -@configure@を実行した後にこのファイルができていることを確かめてほしい。 -中身はこんな感じだ。

-

p(=caption). ▼@config.h@ -p(=longlist). - : - : -#define HAVE_SYS_STAT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRING_H 1 -#define HAVE_MEMORY_H 1 -#define HAVE_STRINGS_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_UNISTD_H 1 -#define FILE_OFFSET_BITS 64 -#define HAVE_LONG_LONG 1 -#define HAVE_OFF_T 1 -#define SIZEOF_INT 4 -#define SIZEOFSHORT 2 - : - : -

-

どれも意味はわかりやすい。@HAVE_xxxx_H@ならヘッダファイルが存在するか -どうかのチェックだろうし、@SIZEOF_SHORT@ならCの@short@型が何バイトかを -示しているに違いない。同じく@SIZEOF_INT@なら@int@のバイト長だし、 -@HAVE_OFF_T@は@offset_t@型が定義されているかを示している。これに限らず -@configure@では「ある/ない」の情報は@HAVE_xxxx@というマクロで定義される -(する)。

-

以上のことからわかるように、@configure@は違いを検出してはくれるが、 -その違いを自動的に吸収してくれるわけではない。ここで定義された値を -使って差を埋めるのはあくまで各プログラマの仕事である。例えば次の -ように。

-

p(=caption). ▼@HAVE_@マクロの典型的な使いかた -p(=longlist). - 24 #ifdef HAVE_STDLIB_H - 25 # include - 26 #endif -(ruby.h) - -h3. autoconf

-

@configure@は@ruby@の専用ツールではない。関数があるか、ヘッダファイルが -あるか……といったテストには明らかに規則性があるのだから、プログラムを -書く人がみんなでそれぞれに別のものを書くのは無駄だ。

-

そこで登場するのが@autoconf@というツールである。@configure.in@とか -configure.acというファイルに「こういうチェックがしたいんだ」と -書いておき、それを@autoconf@で処理すると適切な@configure@を作ってくれる。 -configure.inの@.in@は@input@の略だろう。@Makefile@と@Makefile.in@の関係と -同じである。@.ac@のほうはもちろん@AutoConf@の略だ。

-

ここまでを絵にすると図1のようになる。

-

p(=image). -

-(build)
-Figure 1: [build]

-

-

図1: @Makefile@ができるまで

-

もっと詳しいことが知りたい読者には『GNU Autoconf/Automake/Libtool』 -footnote{『GNU Autoconf/Automake/Libtool』Gary V.Vaughan, Ben Elliston, Tom Tromey, Ian Lance Taylor共著、でびあんぐる監訳、オーム社} -をお勧めする。

-

ところで@ruby@の@configure@は言ったとおり@autoconf@を使って生成してい -るのだが、世の中にある@configure@が必ずしも@autoconf@で生成されている -とは限らない。手書きだったり、別の自動生成ツールを使っていたりすること -もある。なんにせよ、最終的に@Makefile@や@config.h@やその他いろいろがで -きればそれでいいのだ。

-

make

-

第二段階、@make@では何をするのだろうか。もちろん@ruby@のソースコードを -コンパイルするわけだが、@make@の出力を見ているとどうもその他にいろいろ -やっているように見える。その過程を簡単に説明しておこう。

-

@ruby@自体を構成するソースコードをコンパイルする。 -@ruby@の主要部分を集めたスタティックライブラリ@libruby.a@を作る。 -常にスタティックリンクされる@ruby@「@miniruby@」を作る。 ---enable-sharedのときは共有ライブラリ@libruby.so@を作る。 -@miniruby@を使って拡張ライブラリ(@ext/以下)をコンパイルする。 -最後に、本物のruby@を生成する。

-

@miniruby@と@ruby@の生成が分かれているのには二つ理由がある。一つめは拡張ラ -イブラリのコンパイルに@ruby@が必要になることだ。@—enable-shared@の場合は -@ruby@自身がダイナミックリンクされるので、ライブラリのロードパスの関係で -すぐに動かせないかもしれない。そこでスタティックリンクした@miniruby@を作り、 -ビルドの過程ではそちらを使うようにする。

-

二つめの理由は、共有ライブラリが使えないプラットフォームでは拡張ライブ -ラリを@ruby@自体にスタティックリンクしてしまう場合があるということだ。そ -の場合、@ruby@は拡張ライブラリを全てコンパイルしてからでないと作れないが、 -拡張ライブラリは@ruby@がないとコンパイルできない。そのジレンマを解消する -ために@miniruby@を使うのである。

-

CVS

-

本書の添付CD-ROMに入っている@ruby@のアーカイブにしても公式のリリースパッ -ケージにしても、それは@ruby@という、変化しつづているプログラムのほんの一 -瞬の姿をとらえたスナップショットにすぎない。@ruby@がどう変わってきたか、 -どうしてそうだったのか、ということはここには記述されていない。では過去 -も含めた全体を見るにはどうしたらいいだろうか。CVSを使えばそれができる。

-

CVSとは

-

CVSを一言で言うとエディタのundoリストである。 -ソースコードをCVSの管理下に入れておけばいつでも昔の姿に戻せるし、誰が、 -どこを、いつ、どう変えたのかすぐにわかる。一般にそういうことをしてくれ -るプログラムのことをソースコード管理システムと言うが、オープンソースの -世界で一番有名なソースコード管理システムがCVSである。

-

@ruby@もやはりCVSで管理されているのでCVSの仕組みと使いかたについて少し説 -明しよう。まずCVSの最重要概念はレポジトリとワーキングコピーである。 -CVSはエディタのundoリストのようなものと言ったが、そのためには歴代の変更の -記録を -どこかに残しておかないといけない。それを全部まとめて保存しておく場所が -「CVSレポジトリ」である。

-

ぶっちゃけて言うと、過去のソースコードを全部集めてあるのがレポジトリで -ある。もちろんそれはあくまで概念であって、実際には容量を節約するために、 -最新の姿一つと、そこに至るまでの変更差分(ようするにパッチ)の形で集積 -されている。なんにしてもファイルの過去の姿をどの時点だろうと取り出せる -ようになっていればそれでいいのだ。

-

一方、レポジトリからある一点を選んでファイルを取り出したものが -「ワーキングコピー」だ。レポジトリは一つだけだがワーキングコピーは -いくつあってもいい(図2)。

-

p(=image). -

-(repo)
-Figure 2: [repo]

-

-

図2: レポジトリとワーキングコピー

-

自分がソースコードを変更したいときはまずワーキングコピーを取り出して、 -それをエディタなどで編集してからレポジトリに「戻す」。するとレポジトリ -に変更が記録される。レポジトリからワーキングコピーを取り出すことを -「チェックアウト(checkout)」、戻すことを「チェックイン -(checkin)」 -または「コミット(commit)」と言う(図3)。チェックインするとレ -ポジトリに変更が記録されて、いつでもそれを取り出せるようになる。

-

p(=image). -

-(ci)
-Figure 3: [ci]

-

-

図3: チェックインとチェックアウト

-

そしてCVS最大の特徴はCVSレポジトリにネットワーク越しにアクセスできると -いうところだ。つまりレポジトリを保持するサーバが一つあればインターネッ -ト越しに誰でもどこからでもチェックアウト・チェックインすることができる。 -ただし普通はチェックインにはアクセス制限がかかっているので無制限 -にできるというわけではない。

-

リビジョン

-

レポジトリから特定の版を取り出すにはどうしたらいいだろうか。一つには時 -刻で指定する方法がある。「この当時の最新版をくれ」と要求するとそれを選 -んでくれるわけだ。しかし実際には時刻で指定することはあまりない。普通は -「リビジョン(revision)」というものを使う。

-

「リビジョン」は「バージョン」とほとんど同じ意味である。ただ普通はプロ -ジェクト自体に「バージョン」が付いているので、バージョンという言葉を使 -うと紛らわしい。そこでもうちょっと細かい単位を意図してリビジョンという -言葉を使う。

-

CVSでは、レポジトリに入れたばかりのファイルはリビジョン1.1である。 -チェックアウトして、変更して、チェックインするとリビジョン1.2になる。 -その次は1.3になる。その次は1.4になる。

-

CVSの簡単な使用例

-

以上をふまえてごくごく簡単にCVSの使いかたを話す。まず@cvs@コマンドがな -いとどうにもならないのでインストールしておいてほしい。添付CD-ROMにも -@cvs@のソースコードを収録した -footnote{@cvs@:@archives/cvs-1.11.2.tar.gz@}。 -@cvs@のインストールの方法はあまりにも本筋から外れるのでここでは書かな -い。

-

インストールしたら試しに@ruby@のソースコードをチェックアウトしてみよう。 -インターネットに接続中に次のように打つ。

-

p(=screen). -% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login -CVS Password: anonymous -% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby -

-

何もオプションを付けないと自動的に最新版がチェックアウトされるので、 -ruby/以下に@ruby@の真の最新版が現れているはずだ。

-

また、とある日の版を取り出すには@cvs checkout@に@-D@オプションをつけれ -ばいい。次のように打てば本書が解説しているバージョンのワーキングコピー -が取り出せる。

-

p(=screen). -% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout -D2002-09-12 ruby -

-

このとき、オプションは必ず@checkout@の直後に書かないといけないことに注 -意。先に「@ruby@」を書いてしまうと「モジュールがない」という変なエラー -になる。

-

ちなみにこの例のようなanonymousアクセスだとチェックインはできないようになっている。 -チェックインの練習をするには適当に(ローカルの)レポジトリを作って -Hello, World!プログラムでも入れてみるのがいいだろう。具体的な入れかた -はここには書かない。@cvs@に付いてくるマニュアルが結構親切だ。日本語の書 -籍ならオーム社の『CVSによるオープンソース開発』 -footnote{『CVSによるオープンソース開発』Karl Fogel, Moshe Bar共著、竹内利佳訳、オーム社} -をお勧めする。

-

@ruby@の構成 -h3. 物理構造

-

さてそろそろソースコードを見ていこうと思うのだが、まず最初にしなければ -ならないことはなんだろうか。それはディレクトリ構造を眺めることである。 -たいていの場合ディレクトリ構造すなわちソースツリーはそのままプログラム -のモジュール構造を示している。いきなり@grep@で@main()を探して頭から処理順 -に読んでいく、なんていうのは賢くない。もちろんmain()を探すのも大切だが、 -まずはのんびりとls@したり@head@したりして全体の様子をつかもう。

-

以下はCVSレポジトリからチェックアウトした直後の -トップディレクトリの様子だ。 -スラッシュで終わっているのはサブディレクトリである。

-

p(=emlist). -COPYING compar.c gc.c numeric.c sample/ -COPYING.ja config.guess hash.c object.c signal.c -CVS/ config.sub inits.c pack.c sprintf.c -ChangeLog configure.in install-sh parse.y st.c -GPL cygwin/ instruby.rb prec.c st.h -LEGAL defines.h intern.h process.c string.c -LGPL dir.c io.c random.c struct.c -MANIFEST djgpp/ keywords range.c time.c -Makefile.in dln.c lex.c re.c util.c -README dln.h lib/ re.h util.h -README.EXT dmyext.c main.c regex.c variable.c -README.EXT.ja doc/ marshal.c regex.h version.c -README.ja enum.c math.c ruby.1 version.h -ToDo env.h misc/ ruby.c vms/ -array.c error.c missing/ ruby.h win32/ -bcc32/ eval.c missing.h rubyio.h x68/ -bignum.c ext/ mkconfig.rb rubysig.h -class.c file.c node.h rubytest.rb -

-

最近はプログラム自体が大きくなってきてサブディレクトリが細かく分割され -ているソフトウェアも多いが、@ruby@はかなり長いことトップディレクトリ -一筋である。あまりにファイル数が多いと困るが、この程度なら慣れればな -んでもない。

-

トップレベルのファイルは六つに分類できる。即ち

-

ドキュメント -@ruby@自身のソースコード -@ruby@ビルド用のツール -標準添付拡張ライブラリ -標準添付Rubyライブラリ -その他

-

である。ソースコードとビルドツールが重要なのは当然として、その他に -我々の役に立ちそうなものを挙げておこう。

-

ChangeLog

-

@ruby@への変更の記録。変更の理由を調べるうえでは非常に重要。

-

README.EXT README.EXT.ja

-

拡張ライブラリの作成方法が書いてあるのだが、その一環として -@ruby@自身の実装に関することも書いてある。

-

ソースコードの腑分け

-

ここからは@ruby@自身のソースコードについてさらに細かく分割していく。 -主要なファイルについては@README.EXT@に分類が書いてあったので -それに従う。記載がないものは筆者が分類した。

-

Ruby言語のコア

-

class.cクラス関連API -error.c例外関連API -eval.c評価器 -gc.cガーベージコレクタ -lex.c予約語テーブル -object.cオブジェクトシステム -parse.yパーサ -variable.c定数、グローバル変数、クラス変数 -ruby.h@ruby@の主要マクロとプロトタイプ -intern.h@ruby@のC APIのプロトタイプ。@intern@はinternalの略だと思われるが、ここに載っている関数を拡張ライブラリで使うのは別に構わない。 -rubysig.hシグナル関係のマクロを収めたヘッダファイル -node.h構文木ノード関連の定義 -env.h評価器のコンテキストを表現する構造体の定義

-

@ruby@インタプリタのコアを構成する部分。本書が解説するのは -ここのファイルがほとんどである。@ruby@全体のファイル数と比べれば -非常に少ないが、バイトベースでは全体の50%近くを占める。 -特に@eval.c@は200Kバイト、@parse.y@が100Kバイトと大きい。

-

ユーティリティ

-

dln.c動的ローダ -regex.c正規表現エンジン -st.cハッシュテーブル -util.c基数変換やソートなどのライブラリ

-

@ruby@にとってのユーティリティという意味。ただしユーティリティという -言葉からは想像できないほど大きいものもある。例えば@regex.c@は120Kバイトだ。

-

@ruby@コマンドの実装

-

dmyext.c拡張ライブラリ初期化ルーチンのダミー(DumMY EXTention) -inits.cコアとライブラリの初期化ルーチンのエントリポイント -main.cコマンドのエントリポイント(@libruby@には不要) -ruby.c@ruby@コマンドの主要部分(@libruby@にも必要) -version.c@ruby@のバージョン

-

コマンドラインで@ruby@と打って実行するときの@ruby@コマンドの実装。コマンドライン -オプションの解釈などを行っている部分だ。@ruby@コマンド以外に@ruby@コアを利 -用するコマンドとしては@mod_ruby@や@vim@が挙げられる。これらのコマンドは -ライブラリ@libruby@(@.a@/.so/.dllなど)とリンクして動作する。

-

クラスライブラリ

-

array.cclass Array -bignum.cclass Bignum -compar.cmodule Comparable -dir.cclass Dir -enum.cmodule Enumerable -file.cclass File -hash.cclass Hash(実体は@st.c@) -io.cclass IO -marshal.cmodule Marshal -math.cmodule Math -numeric.cclass Numeric、@Integer@、@Fixnum@、@Float@ -pack.cArray#pack、@String#unpack@ -prec.cmodule Precision -process.cmodule Process -random.cKernel#srand()、@rand()@ -range.cclass Range -re.cclass Regexp(実体は@regex.c@) -signal.cmodule Signal -sprintf.c@ruby@専用の@sprintf()@ -string.cclass String -struct.cclass Struct -time.cclass Time

-

Rubyのクラスライブラリの実装。ここにあるものは基本的に通常の -Ruby拡張ライブラリと全く同じ方法で実装されている。つまりこの -ライブラリが拡張ライブラリの書きかたの例にもなっているということだ。

-

プラットフォーム依存ファイル

-

bcc32/Borland C++(Win32) -beos/BeOS -cygwin/Cygwin(Win32でのUNIXエミュレーションレイヤー) -djgpp/djgpp(DOS用のフリーな開発環境) -vms/VMS(かつてDECがリリースしていたOS) -win32/Visual C++(Win32) -x68/Sharp X680x0系(OSはHuman68k)

-

各プラットフォーム特有のコードが入っている。

-

フォールバック関数 -p(=emlist). -missing/ -

-

各種プラットフォームにない関数を補うためのファイル。 -主に@libc@の関数が多い。

-

論理構造

-

さて、以上四つのグループのうちコアはさらに大きく三つに分けられる。 -一つめはRubyのオブジェクト世界を作りだす「オブジェクト空間(object space)」。 -二つめはRubyプログラム(テキスト)を内部形式に変換する「パーサ(parser)」。 -三つめはRubyプログラムを駆動する「評価器(evaluator)」。 -パーサも評価器もオブジェクト空間の上に成立し、 -パーサがプログラムを内部形式に変換し、 -評価器がプログラムを駆動する。 -順番に解説していこう。

-

オブジェクト空間

-

一つめのオブジェクト空間。これは非常に、理解しやすい。なぜならこれが扱 -うものは基本的にメモリ上のモノが全てであり、関数を使って直接表示したり -操作したりすることができるからだ。従って本書ではまずここから解説を -始める。第2章から -第7章までが第一部である。

-

パーサ

-

二つめのパーサ。これは説明が必要だろう。

-

@ruby@コマンドはRuby言語のインタプリタである。つまり起動時にテキストの入 -力を解析し、それに従って実行する。だから@ruby@はテキストとして書かれたプ -ログラムの意味を解釈できなければいけないのだが、不幸にしてテキストとい -うのはコンピュータにとっては非常に理解しづらいものである。コンピュータ -にとってはテキストファイルはあくまでバイト列であって、それ以上ではない。 -そこからテキストの意味を読みとるには何か特別な仕掛けが必要になる。そ -の仕掛けがパーサだ。このパーサを通すことでRubyプログラム(であるテキス -ト)は@ruby@専用の、プログラムから扱いやすい内部表現に変換される。

-

その内部表現とは具体的には「構文木」というものだ。構文木はプログラムを -ツリー構造で表現したもので、例えば@if@文ならば図4のように -表現される。

-

p(=image). -

-(syntree)
-Figure 4: [syntree]

-

-

図4: @if@文と、それに対応する構文木

-

パーサの解説は第二部『構文解析』で行う。 -第二部は第10章から第12章までだ。 -対象となるファイルは@parse.y@だけである。

-

評価器

-

オブジェクトは実際に触ることができるのでわかりやすい。パーサにしてもやっ -ていること自体はようするにデータ形式の変換なんだから、まあわかる。しか -し三つめの評価器、こいつはつかみどころが全くない。

-

評価器がやるのは構文木に従ってプログラムを「実行」していくことだ。と言 -うと簡単そうに見えるのだが、では「実行する」とはどういうことか、ちゃん -と考えるとこれが結構難しい。@if@文を実行するとはどういうことだろうか。 -@while@文を実行するとはどういうことだろうか。ローカル変数に代入するとは -どういうことだろうか。メソッドを呼ぶとはどういうことだろうか。その -全てにキチンキチンと答えを出していかなければ評価器はわからないのだ。

-

本書では第三部『評価』で評価器を扱う。対象ファイルは@eval.c@だ。 -「評価器」は英語でevaluatorと言うので、それを省略して@eval@である。

-

さて、@ruby@の作りについて簡単に説明してきたが、プログラムの動作なんてい -くら概念を説明してもわかりにくいものだ。次の章ではまず実際に@ruby@を使う -ことから始めるとしよう。

-

御意見・御感想・誤殖の指摘などは -“青木峰郎 ":mailto:aamine@loveruby.net -までお願いします。

-

『Rubyソースコード完全解説』 -はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。

-

Copyright © 2002-2004 Minero Aoki, All rights reserved.

- - - -
- - diff --git a/htmls/iterator.html b/htmls/iterator.html deleted file mode 100644 index a0c5fe8..0000000 --- a/htmls/iterator.html +++ /dev/null @@ -1,1094 +0,0 @@ - - - - - Chapter 16: Blocks | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 16: Blocks

-

Iterator

-

In this chapter, BLOCK, which is the last big name among the seven Ruby stacks, -comes in. -After finishing this, the internal state of the evaluator is virtually understood.

-

The Whole Picture

-

What is the mechanism of iterators? -First, let’s think about a small program as below:

-

▼The Source Program

- -
-iter_method() do
-  9   # a mark to find this block
-end
-
-

Let’s check the terms just in case. -As for this program, iter_method is an iterator method, -do ~ end is an iterator block. -Here is the syntax tree of this program being dumped.

-

▼Its Syntax Tree

- -
-NODE_ITER
-nd_iter:
-    NODE_FCALL
-    nd_mid = 9617 (iter_method)
-    nd_args = (null)
-nd_var = (null)
-nd_body:
-    NODE_LIT
-    nd_lit = 9:Fixnum
-
-

Looking for the block by using the 9 written in the iterator block as a trace, -we can understand that NODE_ITER seems to represent the iterator block. -And NODE_FCALL which calls iter_method is at the “below” of that -NODE_ITER. In other words, the node of iterator block appears earlier than the call -of the iterator method. This means, before calling an iterator method, -a block is pushed at another node.

-

And checking by following the flow of code with debugger, -I found that the invocation of an iterator is separated into 3 steps: -NODE_ITER NODE_CALL and NODE_YIELD. -This means,

-
    -
  1. push a block (NODE_ITER)
  2. -
  3. call the method which is an iterator (NODE_CALL)
  4. -
  5. yield (NODE_YEILD)
  6. -
-

that’s all.

-

Push a block

-

First, let’s start with the first step, that is NODE_ITER, which is the node -to push a block.

-

rb_eval()NODE_ITER (simplified)

- -
-case NODE_ITER:
-  {
-    iter_retry:
-      PUSH_TAG(PROT_FUNC);
-      PUSH_BLOCK(node->nd_var, node->nd_body);
-
-      state = EXEC_TAG();
-      if (state == 0) {
-          PUSH_ITER(ITER_PRE);
-          result = rb_eval(self, node->nd_iter);
-          POP_ITER();
-      }
-      else if (_block.tag->dst == state) {
-          state &= TAG_MASK;
-          if (state == TAG_RETURN || state == TAG_BREAK) {
-              result = prot_tag->retval;
-          }
-      }
-      POP_BLOCK();
-      POP_TAG();
-      switch (state) {
-        case 0:
-          break;
-
-        case TAG_RETRY:
-          goto iter_retry;
-
-        case TAG_BREAK:
-          break;
-
-        case TAG_RETURN:
-          return_value(result);
-          /* fall through */
-        default:
-          JUMP_TAG(state);
-      }
-  }
-  break;
-
-

Since the original code contains the support of the for statement, it is -deleted. After removing the code relating to tags, -there are only push/pop of ITER and BLOCK left. -Because the rest is ordinarily doing rb_eval() with NODE_FCALL, -these ITER and BLOCK are the necessary conditions to turn a method into an iterator.

-

The necessity of pushing BLOCK is fairly reasonable, but what’s ITER for? -Actually, to think about the meaning of ITER, you need to think from the -viewpoint of the side that uses BLOCK.

-

For example, suppose a method is just called. And ruby_block exists. -But since BLOCK is pushed regardless of the break of method calls, -the existence of a block does not mean the block is pushed for that method. -It’s possible that the block is pushed for the previous method. (Figure 1)

-
-

(stacks)
-Figure 1: no one-to-one correspondence between FRAME and BLOCK

-
    -
  • 上が先端 the end is above
  • -
  • FRAMEに対応するBLOCKがあるか? Is there any BLOCK that corresponds to FRAME ?
  • -
  • ある(けどイテレータではない) Yes. (But, this is not an iterator.)
  • -
  • ある(本当にイテレータ) Yes. (this is actually an iterator.)
  • -
  • ない No. -
- -

So, in order to determine for which method the block is pushed, ITER is used. -BLOCK is not pushed for each FRAME -because pushing BLOCK is a little heavy. -How much heavy is, -let’s check it in practice.

-

PUSH_BLOCK()

-

The argument of PUSH_BLOCK() is (the syntax tree of) the block parameter and -the block body.

-

PUSH_BLOCK() POP_BLOCK()

- -
- 592  #define PUSH_BLOCK(v,b) do { \
- 593      struct BLOCK _block;                  \
- 594      _block.tag = new_blktag();            \
- 595      _block.var = v;                       \
- 596      _block.body = b;                      \
- 597      _block.self = self;                   \
- 598      _block.frame = *ruby_frame;           \
- 599      _block.klass = ruby_class;            \
- 600      _block.frame.node = ruby_current_node;\
- 601      _block.scope = ruby_scope;            \
- 602      _block.prev = ruby_block;             \
- 603      _block.iter = ruby_iter->iter;        \
- 604      _block.vmode = scope_vmode;           \
- 605      _block.flags = BLOCK_D_SCOPE;         \
- 606      _block.dyna_vars = ruby_dyna_vars;    \
- 607      _block.wrapper = ruby_wrapper;        \
- 608      ruby_block = &_block
-
- 610  #define POP_BLOCK() \
- 611     if (_block.tag->flags & (BLOCK_DYNAMIC))              \
- 612         _block.tag->flags |= BLOCK_ORPHAN;                \
- 613     else if (!(_block.scope->flags & SCOPE_DONT_RECYCLE)) \
- 614         rb_gc_force_recycle((VALUE)_block.tag);           \
- 615     ruby_block = _block.prev;                             \
- 616  } while (0)
-
-(eval.c)
-
-

Let’s make sure that a BLOCK is “the snapshot of the environment of the moment -of creation”. As a proof of it, except for CREF and BLOCK, the six stack -frames are saved. CREF can be substituted by ruby_frame->cbase, there’s no -need to push.

-

And, I’d like to check the three points about the mechanism of push. -BLOCK is fully allocated on the stack. -BLOCK contains the full copy of FRAME at the moment. -BLOCK is different from the other many stack frame structs in having the -pointer to the previous BLOCK (prev).

-

The flags used in various ways at POP_BLOCK() is not explained now -because it can only be understood after seeing the implementation of Proc -later.

-

And the talk is about “BLOCK is heavy”, certainly it seems a little heavy. -When looking inside of new_blktag(), -we can see it does malloc() and store plenty of members. -But let’s defer the final judge until after looking at and comparing with PUSH_ITER().

-

PUSH_ITER()

-

PUSH_ITER() POP_ITER()

- -
- 773  #define PUSH_ITER(i) do {               \
- 774      struct iter _iter;                  \
- 775      _iter.prev = ruby_iter;             \
- 776      _iter.iter = (i);                   \
- 777      ruby_iter = &_iter
-
- 779  #define POP_ITER()                      \
- 780      ruby_iter = _iter.prev;             \
- 781  } while (0)
-
-(eval.c)
-
-

On the contrary, this is apparently light. -It only uses the stack space and has only two members. -Even if this is pushed for each FRAME, -it would probably matter little.

-

Iterator Method Call

-

After pushing a block, the next thing is to call an iterator method (a method -which is an iterator). There also needs a little machinery. -Do you remember that there’s a code to modify -the value of ruby_iter at the beginning of rb_call0? -Here.

-

rb_call0() − moving to ITER_CUR

- -
-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      }
-
-(eval.c)
-
-

Since ITER_PRE is pushed previously at NODE_TER, this code makes -ruby_iter ITER_CUR. -At this moment, a method finally “becomes” an iterator. -Figure 2 shows the state of the stacks.

-
-

(itertrans)
-Figure 2: the state of the Ruby stacks on an iterator call.

-
    -
  • 上が先端 the end is above
  • -
  • イテレータか?(FRAMEに対応するITERがITER_CURか?) - Is this an iterator? (Is the ITER corresponds to FRAME ITER_CUR ?) -
- -

The possible value of ruby_iter is not the one of two boolean values -(for that method or not), but one of three steps because there’s a little gap -between the timings when pushing a block and invoking an iterator method. -For example, there’s the evaluation of the arguments of an iterator method. -Since it’s possible that it contains method calls inside it, -there’s the possibility that one of that methods mistakenly thinks that the -just pushed block is for itself and uses it during the evaluation. -Therefore, the timing when a method becomes an iterator, -this means turning into ITER_CUR, -has to be the place inside of rb_call() that is just before finishing the invocation.

-

▼ the processing order

-
-

method(arg) { block } # push a block
-method(arg) { block } # evaluate the aruguments
-method(arg) { block } # a method call

-
-

For example, in the last chapter “Method”, there’s a macro named BEGIN_CALLARGS at a handler of NODE_CALL. -This is where making use of the third step ITER. -Let’s go back a little and try to see it.

-

BEGIN_CALLARGS END_CALLARGS

-

BEGIN_CALLARGS END_CALLARGS

- -
-1812  #define BEGIN_CALLARGS do {\
-1813      struct BLOCK *tmp_block = ruby_block;\
-1814      if (ruby_iter->iter == ITER_PRE) {\
-1815          ruby_block = ruby_block->prev;\
-1816      }\
-1817      PUSH_ITER(ITER_NOT)
-
-1819  #define END_CALLARGS \
-1820      ruby_block = tmp_block;\
-1821      POP_ITER();\
-1822  } while (0)
-
-(eval.c)
-
-

When ruby_iter is ITER_PRE, a ruby_block is set aside. -This code is important, for instance, in the below case:

-
-obj.m1 { yield }.m2 { nil }
-
-

The evaluation order of this expression is:

-
    -
  1. push the block of m2
  2. -
  3. push the block of m1
  4. -
  5. call the method m1
  6. -
  7. call the method m2
  8. -
-

Therefore, if there was not BEGIN_CALLARGS, -m1 will call the block of m2.

-

And, if there’s one more iterator connected, -the number of BEGIN_CALLARGS increases at the same time in this case, -so there’s no problem.

-

Block Invocation

-

The third phase of iterator invocation, it means the last phase, -is block invocation.

-

rb_eval()NODE_YIELD

- -
-2579        case NODE_YIELD:
-2580          if (node->nd_stts) {
-2581              result = avalue_to_yvalue(rb_eval(self, node->nd_stts));
-2582          }
-2583          else {
-2584              result = Qundef;    /* no arg */
-2585          }
-2586          SET_CURRENT_SOURCE();
-2587          result = rb_yield_0(result, 0, 0, 0);
-2588          break;
-
-(eval.c)
-
-

nd_stts is the parameter of yield. -avalue_to_yvalue() was mentioned a little at the multiple assignments, -but you can ignore this. -
((errata: actually, it was not mentioned. You can ignore this anyway.))
-The heart of the behavior is not this but rb_yield_0(). -Since this function is also very long, -I show the code after extremely simplifying it. -Most of the methods to simplify are previously used.

-
    -
  • cut the codes relating to trace_func.
  • -
  • cut errors
  • -
  • cut the codes exist only to prevent from GC
  • -
  • As the same as massign(), there’s the parameter pcall. -This parameter is to change the level of restriction of the parameter check, -so not important here. Therefore, assume pcal=0 and perform constant foldings.
  • -
-

And this time, I turn on the “optimize for readability option” as follows.

-
    -
  • when a code branching has equivalent kind of branches, - leave the main one and cut the rest.
  • -
  • if a condition is true/false in the almost all case, assume it is true/false.
  • -
  • assume there’s no tag jump occurs, delete all codes relating to tag.
  • -
-

If things are done until this, -it becomes very shorter.

-

rb_yield_0() (simplified)

- -
-static VALUE
-rb_yield_0(val, self, klass, /* pcall=0 */)
-    VALUE val, self, klass;
-{
-    volatile VALUE result = Qnil;
-    volatile VALUE old_cref;
-    volatile VALUE old_wrapper;
-    struct BLOCK * volatile block;
-    struct SCOPE * volatile old_scope;
-    struct FRAME frame;
-    int state;
-
-    PUSH_VARS();
-    PUSH_CLASS();
-    block = ruby_block;
-    frame = block->frame;
-    frame.prev = ruby_frame;
-    ruby_frame = &(frame);
-    old_cref = (VALUE)ruby_cref;
-    ruby_cref = (NODE*)ruby_frame->cbase;
-    old_wrapper = ruby_wrapper;
-    ruby_wrapper = block->wrapper;
-    old_scope = ruby_scope;
-    ruby_scope = block->scope;
-    ruby_block = block->prev;
-    ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
-    ruby_class = block->klass;
-    self = block->self;
-
-    /* set the block arguments */
-    massign(self, block->var, val, pcall);
-
-    PUSH_ITER(block->iter);
-    /* execute the block body */
-    result = rb_eval(self, block->body);
-    POP_ITER();
-
-    POP_CLASS();
-    /* ……collect ruby_dyna_vars…… */
-    POP_VARS();
-    ruby_block = block;
-    ruby_frame = ruby_frame->prev;
-    ruby_cref = (NODE*)old_cref;
-    ruby_wrapper = old_wrapper;
-    ruby_scope = old_scope;
-
-    return result;
-}
-
-

As you can see, the most stack frames are replaced with what saved at ruby_block. -Things to simple save/restore are easy to understand, -so let’s see the handling of the other frames we need to be careful about.

-

FRAME

-
-struct FRAME frame;
-
-frame = block->frame;     /* copy the entire struct */
-frame.prev = ruby_frame;  /* by these two lines…… */
-ruby_frame = &(frame);    /* ……frame is pushed */
-
-

Differing from the other frames, a FRAME is not used in the saved state, -but a new FRAME is created by duplicating. -This would look like Figure 3.

-
-

(framepush)
-Figure 3: push a copied frame

-
    -
  • コピーして作る creating by copying -
- -

As we’ve seen the code until here, -it seems that FRAME will never be “reused”. -When pushing FRAME, a new FRAME will always be created.

-

BLOCK

-
-block = ruby_block;
-         :
-ruby_block = block->prev;
-         :
-ruby_block = block;
-
-

What is the most mysterious is this behavior of BLOCK. -We can’t easily understand whether it is saving or popping. -It’s comprehensible that the first statement and the third statement are as a pair, -and the state will be eventually back. -However, what is the consequence of the second statement?

-

To put the consequence of I’ve pondered a lot in one phrase, -“going back to the ruby_block of at the moment when pushing the block”. -An iterator is, in short, the syntax to go back to the previous frame. -Therefore, all we have to do is turning the state of the stack frame into what -was at the moment when creating the block. -And, the value of ruby_block at the moment when creating the block is, -it seems certain that it was block->prev. -Therefore, it is contained in prev.

-

Additionally, for the question “is it no problem to assume what invoked is -always the top of ruby_block?”, -there’s no choice but saying “as the rb_yield_0 side, you can assume so”. -To push the block which should be invoked on the top of the ruby_block is the -work of the side to prepare the block, -and not the work of rb_yield_0.

-

An example of it is BEGIN_CALLARGS which was discussed in the previous chapter. -When an iterator call cascades, the two blocks are pushed and the top of the -stack will be the block which should not be used. -Therefore, it is purposefully checked and set aside.

-

VARS

-

Come to think of it, -I think we have not looked the contents of PUSH_VARS() and POP_VARS() yet. -Let’s see them here.

-

PUSH_VARS() POP_VARS()

- -
- 619  #define PUSH_VARS() do { \
- 620      struct RVarmap * volatile _old; \
- 621      _old = ruby_dyna_vars;          \
- 622      ruby_dyna_vars = 0
-
- 624  #define POP_VARS() \
- 625     if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {   \
- 626         if (RBASIC(_old)->flags) /* if were not recycled */ \
- 627             FL_SET(_old, DVAR_DONT_RECYCLE);                  \
- 628      }                                                        \
- 629      ruby_dyna_vars = _old;                                   \
- 630  } while (0)
-
-(eval.c)
-
-

This is also not pushing a new struct, to say “set aside/restore” is closer. -In practice, in rb_yield_0, PUSH_VARS() is used only to set aside the value. -What actually prepares ruby_dyna_vars is this line.

-
-ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
-
-

This takes the dyna_vars saved in BLOCK and sets it. -An entry is attached at the same time. -I’d like you to recall the description of the structure of ruby_dyna_vars in Part 2, -it said the RVarmap whose id is 0 such as the one created here is used as -the break between block scopes.

-

However, in fact, between the parser and the evaluator, the form of the link -stored in ruby_dyna_vars is slightly different. -Let’s look at the dvar_asgn_curr() function, which assigns a block local -variable at the current block.

-

dvar_asgn_curr()

- -
- 737  static inline void
- 738  dvar_asgn_curr(id, value)
- 739      ID id;
- 740      VALUE value;
- 741  {
- 742      dvar_asgn_internal(id, value, 1);
- 743  }
-
- 699  static void
- 700  dvar_asgn_internal(id, value, curr)
- 701      ID id;
- 702      VALUE value;
- 703      int curr;
- 704  {
- 705      int n = 0;
- 706      struct RVarmap *vars = ruby_dyna_vars;
- 707
- 708      while (vars) {
- 709          if (curr && vars->id == 0) {
- 710              /* first null is a dvar header */
- 711              n++;
- 712              if (n == 2) break;
- 713          }
- 714          if (vars->id == id) {
- 715              vars->val = value;
- 716              return;
- 717          }
- 718          vars = vars->next;
- 719      }
- 720      if (!ruby_dyna_vars) {
- 721          ruby_dyna_vars = new_dvar(id, value, 0);
- 722      }
- 723      else {
- 724          vars = new_dvar(id, value, ruby_dyna_vars->next);
- 725          ruby_dyna_vars->next = vars;
- 726      }
- 727  }
-
-(eval.c)
-
-

The last if statement is to add a variable. -If we focus on there, we can see a link is always pushed in at the “next” to -ruby_dyna_vars. This means, it would look like Figure 4.

-
-

(dynavarseval)
-Figure 4: the structure of ruby_dyna_vars

-
    -
  • ブロック起動時に(rb_yield_0で)追加 added (by using rb_yield_0) when invoking a block
  • -
  • ブロック起動直後 immediately after invoking a block
  • -
  • ブロック変数を追加 add block variables
  • -
  • 追加された変数 added variables -
- -

This differs from the case of the parser in one point: -the headers (id=0) to indicate the breaks of scopes are attached before the -links. If a header is attached after the links, the first one of the scope -cannot be inserted properly. (Figure 5)
-((errata: It was described that ruby_dyna_vars of the evaluator always forms -a single straight link. -But according to the errata, it was wrong. That part and relevant descriptions -are removed.))

-
-

(insert)
-Figure 5: cannot properly insert an entry

-
    -
  • ここに挿入しないといけない must be inserted here -
- -

Target Specified Jump

-

The code relates to jump tags are omitted in the previously shown code, -but there’s an effort that we’ve never seen before in the jump of rb_yield_0. -Why is the effort necessary? -I’ll tell the reason in advance. I’d like you to see the below program:

-
-[0].each do
-  break
-end
-# the place to reach by break
-
-

like this way, in the case when doing break from inside of a block, -it is necessary to get out of the block and go to the method that pushed the -block. -What does it actually mean? -Let’s think by looking at the (dynamic) call graph when invoking an iterator.

-
-rb_eval(NODE_ITER)                   .... catch(TAG_BREAK)
-    rb_eval(NODE_CALL)               .... catch(TAG_BREAK)
-        rb_eval(NODE_YIELD)
-            rb_yield_0
-                rb_eval(NODE_BREAK)  .... throw(TAG_BREAK)
-
-

Since what pushed the block is NODE_ITER, -it should go back to a NODE_ITER when doing break. -However, NODE_CALL is waiting for TAG_BREAK before NODE_ITER, -in order to turn a break over methods into an error. -This is a problem. We need to somehow find a way to go straight back to a NODE_ITER.

-

And actually, “going back to a NODE_ITER” will still be a problem. -If iterators are nesting, -there could be multiple NODE_ITERs, -thus the one corresponds to the current block is not always the first NODE_ITER. -In other words, we need to restrict only “the NODE_ITER that pushed the -currently being invoked block”

-

Then, let’s see how this is resolved.

-

rb_yield_0() − the parts relates to tags

- -
-3826      PUSH_TAG(PROT_NONE);
-3827      if ((state = EXEC_TAG()) == 0) {
-              /* ……evaluate the body…… */
-3838      }
-3839      else {
-3840          switch (state) {
-3841            case TAG_REDO:
-3842              state = 0;
-3843              CHECK_INTS;
-3844              goto redo;
-3845            case TAG_NEXT:
-3846              state = 0;
-3847              result = prot_tag->retval;
-3848              break;
-3849            case TAG_BREAK:
-3850            case TAG_RETURN:
-3851              state |= (serial++ << 8);
-3852              state |= 0x10;
-3853              block->tag->dst = state;
-3854              break;
-3855            default:
-3856              break;
-3857          }
-3858      }
-3859      POP_TAG();
-
-(eval.c)
-
-

The parts of TAG_BREAK and TAG_RETURN are crucial.

-

First, serial is a static variable of rb_yield_0(), -its value will be different every time calling rb_yield_0. -“serial” is the serial of “serial number”.

-

The reason why left shifting by 8 bits seems in order to avoid overlapping the -values of TAG_xxxx. -TAG_xxxx is in the range between 0x1 ~ 0x8, 4 bits are enough. -And, the bit-or of 0x10 seems to prevent serial from overflow. -In 32-bit machine, serial can use only 24 bits (only 16 million times), -recent machine can let it overflow within less than 10 seconds. -If this happens, the top 24 bits become all 0 in line. -Therefore, if 0x10 did not exist, state would be the same value as TAG_xxxx -(See also Figure 6).

-
-

(dst)
-Fig.6: block->tag->dst

-
    -
  • 常に1 always 1 -
- -

Now, tag->dst became the value which differs from TAG_xxxx and is unique for each call. -In this situation, because an ordinary switch as previous ones cannot receive it, -the side to stop jumps should need efforts to some extent. -The place where making an effort is this place of rb_eval:NODE_ITER:

-

rb_eval()NODE_ITER (to stop jumps)

- -
-case NODE_ITER:
-  {
-      state = EXEC_TAG();
-      if (state == 0) {
-          /* …… invoke an iterator …… */
-      }
-      else if (_block.tag->dst == state) {
-          state &= TAG_MASK;
-          if (state == TAG_RETURN || state == TAG_BREAK) {
-              result = prot_tag->retval;
-          }
-      }
-  }
-
-

In corresponding NODE_ITER and rb_yield_0, block should point to the same thing, -so tag->dst which was set at rb_yield_0 comes in here. -Because of this, only the corresponding NODE_ITER can properly stop the jump.

-

Check of a block

-

Whether or not a currently being evaluated method is an iterator, -in other words, whether there’s a block, -can be checked by rb_block_given_p(). -After reading the above all, we can tell its implementation.

-

rb_block_given_p()

- -
-3726  int
-3727  rb_block_given_p()
-3728  {
-3729      if (ruby_frame->iter && ruby_block)
-3730          return Qtrue;
-3731      return Qfalse;
-3732  }
-
-(eval.c)
-
-

I think there’s no problem. What I’d like to talk about this time is actually -another function to check, it is rb_f_block_given_p().

-

rb_f_block_given_p()

- -
-3740  static VALUE
-3741  rb_f_block_given_p()
-3742  {
-3743      if (ruby_frame->prev && ruby_frame->prev->iter && ruby_block)
-3744          return Qtrue;
-3745      return Qfalse;
-3746  }
-
-(eval.c)
-
-

This is the substance of Ruby’s block_given?. -In comparison to rb_block_given_p(), -this is different in checking the prev of ruby_frame. -Why is this?

-

Thinking about the mechanism to push a block, -to check the current ruby_frame like rb_block_given_p() is right. -But when calling block_given? from Ruby-level, -since block_given? itself is a method, -an extra FRAME is pushed. -Hence, we need to check the previous one.

-

Proc

-

To describe a Proc object from the viewpoint of implementing, -it is “a BLOCK which can be bring out to Ruby level”. -Being able to bring out to Ruby level means having more latitude, -but it also means when and where it will be used becomes completely unpredictable. -Focusing on how the influence of this fact is, let’s look at the implementation.

-

Proc object creation

-

A Proc object is created with Proc.new. -Its substance is proc_new().

-

proc_new()

- -
-6418  static VALUE
-6419  proc_new(klass)
-6420      VALUE klass;
-6421  {
-6422      volatile VALUE proc;
-6423      struct BLOCK *data, *p;
-6424      struct RVarmap *vars;
-6425
-6426      if (!rb_block_given_p() && !rb_f_block_given_p()) {
-6427          rb_raise(rb_eArgError,
-                "tried to create Proc object without a block");
-6428      }
-6429
-          /* (A)allocate both struct RData and struct BLOCK */
-6430      proc = Data_Make_Struct(klass, struct BLOCK,
-                                  blk_mark, blk_free, data);
-6431      *data = *ruby_block;
-6432
-6433      data->orig_thread = rb_thread_current();
-6434      data->wrapper = ruby_wrapper;
-6435      data->iter = data->prev?Qtrue:Qfalse;
-          /* (B)the essential initialization is finished by here */
-6436      frame_dup(&data->frame);
-6437      if (data->iter) {
-6438          blk_copy_prev(data);
-6439      }
-6440      else {
-6441          data->prev = 0;
-6442      }
-6443      data->flags |= BLOCK_DYNAMIC;
-6444      data->tag->flags |= BLOCK_DYNAMIC;
-6445
-6446      for (p = data; p; p = p->prev) {
-6447          for (vars = p->dyna_vars; vars; vars = vars->next) {
-6448              if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
-6449              FL_SET(vars, DVAR_DONT_RECYCLE);
-6450          }
-6451      }
-6452      scope_dup(data->scope);
-6453      proc_save_safe_level(proc);
-6454
-6455      return proc;
-6456  }
-
-(eval.c)
-
-

The creation of a Proc object itself is unexpectedly simple. -Between (A) and (B), a space for an Proc object is allocated and its -initialization completes. -Data_Make_Struct() is a simple macro that does both malloc() and -Data_Wrap_Struct() at the same time.

-

The problems exist after that:

-
    -
  • frame_dup()
  • -
  • blk_copy_prev()
  • -
  • FL_SET(vars, DVAR_DONT_RECYCLE)
  • -
  • scope_dup()
  • -
-

These four have the same purposes. They are:

-
    -
  • move all of what were put on the machine stack to the heap.
  • -
  • prevent from collecting even if after POP
  • -
-

Here, “all” means the all things including prev. -For the all stack frames pushed there, it duplicates each frame by -doing malloc() and copying. -VARS is usually forced to be collected by rb_gc_force_recycle() at the same moment of POP, -but this behavior is stopped by setting the DVAR_DONT_RECYCLE flag. -And so on. Really extreme things are done.

-

Why are these extreme things necessary? This is because, unlike iterator blocks, -a Proc can persist longer than the method that created it. -And the end of a method means the things allocated on the machine stack such as -FRAME, ITER, and local_vars of SCOPE are invalidated. -It’s easy to predict what the consequence of using the invalidated memories. -(An example answer: it becomes troublesome).

-

I tried to contrive a way to at least use the same FRAME from multiple Proc, -but since there are the places such as old_frame where setting aside the -pointers to the local variables, it does not seem going well. -If it requires a lot efforts in anyway, -another effort, say, allocating all of them with malloc() from the frist place, -seems better to give it a try.

-

Anyway, I sentimentally think that it’s surprising that it runs with that speed -even though doing these extreme things. -Indeed, it has become a good time.

-

Floating Frame

-

Previously, I mentioned it just in one phrase “duplicate all frames”, -but since that was unclear, let’s look at more details. -The points are the next two:

-
    -
  • How to duplicate all
  • -
  • Why all of them are duplicated
  • -
-

Then first, let’s start with the summary of how each stack frame is saved.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Frame location has prev pointer?
FRAME stack yes
SCOPE stack no
local_tbl heap
local_vars stack
VARS heap no
BLOCK stack yes
-

CLASS CREF ITER are not necessary this time. Since CLASS is a general Ruby -object, rb_gc_force_recycle() is not called with it even by mistake (it’s -impossible) and both CREF and ITER becomes unnecessary after storing its -values at the moment in FRAME. -The four frames in the above table are important -because these will be modified or referred to multiple times later. -The rest three will not.

-

Then, this talk moves to how to duplicate all. -I said “how”, but it does not about such as “by malloc()”. -The problem is how to duplicate “all”. -It is because, here I’d like you to see the above table, -there are some frames without any prev pointer. -In other words, we cannot follow links. -In this situation, how can we duplicate all?

-

A fairly clever technique used to counter this. -Let’s take SCOPE as an example. -A function named scope_dup() is used previously in order to duplicate SCOPE, -so let’s see it first.

-

scope_dup() only the beginning

- -
-6187  static void
-6188  scope_dup(scope)
-6189      struct SCOPE *scope;
-6190  {
-6191      ID *tbl;
-6192      VALUE *vars;
-6193
-6194      scope->flags |= SCOPE_DONT_RECYCLE;
-
-(eval.c)
-
-

As you can see, SCOPE_DONT_RECYCLE is set. -Then next, take a look at the definition of POP_SCOPE():

-

POP_SCOPE() only the beginning

- -
- 869  #define POP_SCOPE()                                      \
- 870      if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {        \
- 871         if (_old) scope_dup(_old);                        \
- 872      }                                                    \
-
-(eval.c)
-
-

When it pops, if SCOPE_DONT_RECYCLE flag was set to the current SCOPE (ruby_scope), -it also does scope_dup() of the previous SCOPE (_old). -In other words, SCOPE_DONT_RECYCLE is also set to this one. -In this way, one by one, the flag is propagated at the time when it pops. -(Figure 7)

-

-

(flaginfect)
-Figure 7: flag propagation

-

-

Since VARS also does not have any prev pointer, -the same technique is used to propagate the DVAR_DONT_RECYCLE flag.

-

Next, the second point, try to think about “why all of them are duplicated”. -We can understand that the local variables of SCOPE can be referred to later -if its Proc is created. -However, is it necessary to copy all of them including the previous SCOPE in -order to accomplish that?

-

Honestly speaking, I couldn’t find the answer of this question and has been -worried about how can I write this section for almost three days, -I’ve just got the answer. Take a look at the next program:

-
-def get_proc
-  Proc.new { nil }
-end
-
-env = get_proc { p 'ok' }
-eval("yield", env)
-
-

I have not explained this feature, but by passing a Proc object as the second -argument of eval, you can evaluate the string in that environment.

-

It means, as the readers who have read until here can probably tell, it pushes -the various environments taken from the Proc (meaning BLOCK) and evaluates. -In this case, it naturally also pushes BLOCK and -you can turn the BLOCK into a Proc again. -Then, using the Proc when doing eval … if things are done like this, you -can access almost all information of ruby_block from Ruby level as you like. -This is the reason why the entire stacks need to be fully duplicated. -
((errata: we cannot access ruby_block as we like from Ruby level. -The reason why all SCOPEs are duplicated was not understood. -It seems all we can do is to investigate the mailing list archives of the time -when this change was applied. (It is still not certain whether we can find out -the reason in this way.) -
))

-

Invocation of Proc

-

Next, we’ll look at the invocation of a created Proc. -Since Proc#call can be used from Ruby to invoke, -we can follow the substance of it.

-

The substance of Proc#call is proc_call():

-

proc_call()

- -
-6570  static VALUE
-6571  proc_call(proc, args)
-6572      VALUE proc, args;           /* OK */
-6573  {
-6574      return proc_invoke(proc, args, Qtrue, Qundef);
-6575  }
-
-(eval.c)
-
-

Delegate to proc_invoke(). When I look up invoke in a dictionary, -it was written such as “call on (God, etc.) for help”, -but when it is in the context of programming, -it is often used in the almost same meaning as “activate”.

-

The prototype of the proc_invoke() is,

-
-proc_invoke(VALUE proc, VALUE args, int pcall, VALUE self)
-
-

However, according to the previous code, pcall=Qtrue and self=Qundef in this case, -so these two can be removed by constant foldings.

-

proc_invoke (simplified)

- -
-static VALUE
-proc_invoke(proc, args, /* pcall=Qtrue */, /* self=Qundef */)
-    VALUE proc, args;
-    VALUE self;
-{
-    struct BLOCK * volatile old_block;
-    struct BLOCK _block;
-    struct BLOCK *data;
-    volatile VALUE result = Qnil;
-    int state;
-    volatile int orphan;
-    volatile int safe = ruby_safe_level;
-    volatile VALUE old_wrapper = ruby_wrapper;
-    struct RVarmap * volatile old_dvars = ruby_dyna_vars;
-
-    /*(A)take BLOCK from proc and assign it to data */
-    Data_Get_Struct(proc, struct BLOCK, data);
-    /*(B)blk_orphan */
-    orphan = blk_orphan(data);
-
-    ruby_wrapper = data->wrapper;
-    ruby_dyna_vars = data->dyna_vars;
-    /*(C)push BLOCK from data */
-    old_block = ruby_block;
-    _block = *data;
-    ruby_block = &_block;
-
-    /*(D)transition to ITER_CUR */
-    PUSH_ITER(ITER_CUR);
-    ruby_frame->iter = ITER_CUR;
-
-    PUSH_TAG(PROT_NONE);
-    state = EXEC_TAG();
-    if (state == 0) {
-        proc_set_safe_level(proc);
-        /*(E)invoke the block */
-        result = rb_yield_0(args, self, 0, pcall);
-    }
-    POP_TAG();
-
-    POP_ITER();
-    if (ruby_block->tag->dst == state) {
-        state &= TAG_MASK;      /* target specified jump */
-    }
-    ruby_block = old_block;
-    ruby_wrapper = old_wrapper;
-    ruby_dyna_vars = old_dvars;
-    ruby_safe_level = safe;
-
-    switch (state) {
-      case 0:
-        break;
-      case TAG_BREAK:
-        result = prot_tag->retval;
-        break;
-      case TAG_RETURN:
-        if (orphan) {   /* orphan procedure */
-            localjump_error("return from proc-closure", prot_tag->retval);
-        }
-        /* fall through */
-      default:
-        JUMP_TAG(state);
-    }
-    return result;
-}
-
-

The crucial points are three: C, D, and E.

-

(C) At NODE_ITER a BLOCK is created from the syntax tree and pushed, -but this time, a BLOCK is taken from Proc and pushed.

-

(D) It was ITER_PRE before becoming ITER_CUR at rb_call0(), -but this time it goes directly into ITER_CUR.

-

(E) If the case was an ordinary iterator, -its method call exists before yeild occurs then going to rb_yield_0, -but this time rb_yield_() is directly called and invokes the just pushed block.

-

In other words, in the case of iterator, the procedures are separated into three places, -NODE_ITER ~ rb_call0() ~ NODE_YIELD. But this time, they are done all at once.

-

Finally, I’ll talk about the meaning of blk_orphan(). -As the name suggests, it is a function to determine the state of “the method -which created the Proc has finished”. -For example, the SCOPE used by a BLOCK has already been popped, -you can determine it has finished.

-

Block and Proc

-

In the previous chapter, various things about arguments and parameters of -methods are discussed, but I have not described about block parameters yet. -Although it is brief, here I’ll perform the final part of that series.

-
-def m(&block)
-end
-
-

This is a “block parameter”. The way to enable this is very simple. -If m is an iterator, -it is certain that a BLOCK was already pushed, -turn it into a Proc and assign into (in this case) the local variable block. -How to turn a block into a Proc is just calling proc_new(), which was previously described. -The reason why just calling is enough can be a little incomprehensible. -However whichever Proc.new or m, -the situation “a method is called and a BLOCK is pushed” is the same. -Therefore, from C level, anytime you can turn a block into a Proc -by just calling proc_new().

-

And if m is not an iterator, all we have to do is simply assigning nil.

-

Next, it is the side to pass a block.

-
-m(&block)
-
-

This is a “block argument”. This is also simple, -take a BLOCK from (a Proc object stored in) block and push it. -What differs from PUSH_BLOCK() is only whether a BLOCK has already been -created in advance or not.

-

The function to do this procedure is block_pass(). -If you are curious about, check and confirm around it. -However, it really does just only what was described here, -it’s possible you’ll be disappointed…

- - - -
- - diff --git a/htmls/load.html b/htmls/load.html deleted file mode 100644 index c46c122..0000000 --- a/htmls/load.html +++ /dev/null @@ -1,906 +0,0 @@ - - - - - Loading | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Vincent ISAMBART

-

Chapter 18: Loading

-

Outline

-

Interface

-

At the Ruby level, there are two procedures that can be used for -loading: require and load.

-
-require 'uri'            # load the uri library
-load '/home/foo/.myrc'   # read a resource file
-
-

They are both normal methods, compiled and evaluated exactly like any -other code. It means loading occurs after compilation gave control to -the evaluation stage.

-

These two function each have their own use. ‘require’ is to load -libraries, and load is to load an arbitrary file. Let’s see this in -more details.

-

require

-

require has four features:

-
    -
  • the file is searched for in the load path
  • -
  • it can load extension libraries
  • -
  • the .rb/.so extension can be omitted
  • -
  • a given file is never loaded more than once
  • -
-

Ruby’s load path is in the global variable $:, which contains an -array of strings. For example, displaying the content of the $: in -the environment I usually use would show:

-
-% ruby -e 'puts $:'
-/usr/lib/ruby/site_ruby/1.7
-/usr/lib/ruby/site_ruby/1.7/i686-linux
-/usr/lib/ruby/site_ruby
-/usr/lib/ruby/1.7
-/usr/lib/ruby/1.7/i686-linux
-.
-
-

Calling puts on an array displays one element on each line so it’s easy -to read.

-

As I ran configure using --prefix=/usr, the library path is -/usr/lib/ruby and below, but if you compile it normally from the -source code, the libraries will be in /usr/local/lib/ruby and below. -In a Windows environment, there will also be a drive letter.

-

Then, let’s try to require the standard library nkf.so from the -load path.

-
-require 'nkf'
-
-

If the required name has no extension, require silently -compensates. First, it tries with .rb, then with .so. On some -platforms it also tries the platform’s specific extension for -extension libraries, for example .dll in a Windows environment or -.bundle on Mac OS X.

-

Let’s do a simulation on my environment. ruby checks the following -paths in sequential order.

-
-/usr/lib/ruby/site_ruby/1.7/nkf.rb
-/usr/lib/ruby/site_ruby/1.7/nkf.so
-/usr/lib/ruby/site_ruby/1.7/i686-linux/nkf.rb
-/usr/lib/ruby/site_ruby/1.7/i686-linux/nkf.so
-/usr/lib/ruby/site_ruby/nkf.rb
-/usr/lib/ruby/site_ruby/nkf.so
-/usr/lib/ruby/1.7/nkf.rb
-/usr/lib/ruby/1.7/nkf.so
-/usr/lib/ruby/1.7/i686-linux/nkf.rb
-/usr/lib/ruby/1.7/i686-linux/nkf.so    found!
-
-

nkf.so has been found in /usr/lib/ruby/1.7/i686-linux. Once the -file has been found, require’s last feature (not loading the file -more than once) locks the file. The locks are strings put in the -global variable $". In our case the string "nkf.so" has been put -there. Even if the extension has been omitted when calling require, -the file name in $" has the extension.

-
-require 'nkf'   # after loading nkf...
-p $"            # ["nkf.so"]  the file is locked
-
-require 'nkf'   # nothing happens if we require it again
-p $"            # ["nkf.so"]  the content of the lock array does not change
-
-

The are two reasons for adding the missing extension. The first one is -not to load it twice if the same file is later required with its -extension. The second one is to be able to load both nkf.rb and -nkf.so. In fact the extensions are disparate (.so .dll .bundle -etc.) depending on the platform, but at locking time they all become -.so. That’s why when writing a Ruby program you can ignore the -differences of extensions and consider it’s always so. So you can -say that ruby is quite UNIX oriented.

-

By the way, $" can be freely modified even at the Ruby level so we -cannot say it’s a strong lock. You can for example load an extension -library multiple times if you clear $".

-

load

-

load is a lot easier than require. Like require, it searches the -file in $:. But it can only load Ruby programs. Furthermore, the -extension cannot be omitted: the complete file name must always be -given.

-
-load 'uri.rb'   # load the URI library that is part of the standard library
-
-

In this simple example we try to load a library, but the proper way to -use load is for example to load a resource file giving its full -path.

-

Flow of the whole process

-

If we roughly split it, “loading a file” can be split in:

-
    -
  • finding the file
  • -
  • reading the file and mapping it to an internal form
  • -
  • evaluating it
  • -
-

The only difference between require and load is how to find the -file. The rest is the same in both.

-

We will develop the last evaluation part a little more. Loaded Ruby -programs are basically evaluated at the top-level. It means the -defined constants will be top-level constants and the defined methods -will be function-style methods.

-
-### mylib.rb
-MY_OBJECT = Object.new
-def my_p(obj)
-  p obj
-end
-
-### first.rb
-require 'mylib'
-my_p MY_OBJECT   # we can use the constants and methods defined in an other file
-
-

Only the local variable scope of the top-level changes when the file -changes. In other words, local variables cannot be shared between -different files. You can of course share them using for example Proc -but this has nothing to do with the load mechanism.

-

Some people also misunderstand the loading mechanism. Whatever the -class you are in when you call load, it does not change -anything. Even if, like in the following example, you load a file in -the module statement, it does not serve any purpose, as everything -that is at the top-level of the loaded file is put at the Ruby -top-level.

-
-require 'mylib'     # whatever the place you require from, be it at the top-level
-module SandBox
-  require 'mylib'   # or in a module, the result is the same
-end
-
-

Highlights of this chapter

-

Here the mechanism is a lot about details, so it’s a little difficult -to enumerate it simply. That’s why we will work a little differently -on it, and we are going to reduce the target to 3 points:

-
    -
  • loading serialisation
  • -
  • the repartition of the functions in the different source files
  • -
  • how extension libraries are loaded
  • -
-

Regarding the first point, you will understand it when you see it.

-

For the second point, the functions that appear in this chapter come -from 4 different files, eval.c ruby.c file.c dln.c. We’ll look at -the reason they are stretched in different places.

-

The third point is just like its name says. We will see how the -currently popular trend of execution time loading, more commonly -referred to as plug-ins, works. This is the most important part of this -chapter, so I’d like to use as many pages as possible to talk about it.

-

Searching the library

-

rb_f_require()

-

The body of require is rb_f_require. First, we will only look at -the part concerning the file search. Having many different cases is -bothersome so we will limit ourselves to the case when no file -extension is given.

-

rb_f_require() (simplified version) -

-5527  VALUE
-5528  rb_f_require(obj, fname)
-5529      VALUE obj, fname;
-5530  {
-5531      VALUE feature, tmp;
-5532      char ext, *ftptr; / OK /
-5533      int state;
-5534      volatile int safe = ruby_safe_level;
-5535
-5536      SafeStringValue(fname);
-5537      ext = strrchr(RSTRING→ptr, ‘.’);
-5538      if (ext) {
-              / …if the file extension has been given… /
-5584      }
-5585      tmp = fname;
-5586      switch (rb_find_file_ext(&tmp, loadable_ext)) {
-5587        case 0:
-5588          break;
-5589
-5590        case 1:
-5591          feature = fname = tmp;
-5592          goto load_rb;
-5593
-5594        default:
-5595          feature = tmp;
-5596          fname = rb_find_file(tmp);
-5597          goto load_dyna;
-5598      }
-5599      if (rb_feature_p(RSTRING→ptr, Qfalse))
-5600          return Qfalse;
-5601      rb_raise(rb_eLoadError, “No such file to load — %s”,
-                   RSTRING→ptr);
-5602
-5603    load_dyna:
-          / …load an extension library… /
-5623      return Qtrue;
-5624
-5625    load_rb:
-          / …load a Ruby program… */
-5648      return Qtrue;
-5649  }

-

5491 static const char const loadable_ext[] = { -5492 “.rb”, DLEXT, / DLEXT=“.so”, “.dll”, “.bundle”… / -5493 #ifdef DLEXT2 -5494 DLEXT2, / DLEXT2=“.dll” on Cygwin, MinGW */ -5495 #endif -5496 0 -5497 };

-

(eval.c) -

-

In this function the goto labels load_rb and load_dyna are -actually like subroutines, and the two variables feature and fname -are more or less their parameters. These variables have the following -meaning.

- - - - - - - - - - - - - - - - -
variablemeaningexample
featurethe library file name that will be put in $"uri.rbnkf.so
fnamethe full path to the library/usr/lib/ruby/1.7/uri.rb
-

The name feature can be found in the function rb_feature_p(). This -function checks if a file has been locked (we will look at it just -after).

-

The functions actually searching for the library are rb_find_file() -and rb_find_file_ext(). rb_find_file() searches a file in the load -path $'. rb_find_file_ext() does the same but the difference is -that it takes as a second parameter a list of extensions -(i.e. loadable_ext) and tries them in sequential order.

-

Below we will first look entirely at the file searching code, then we -will look at the code of the require lock in load_rb.

-

rb_find_file()

-

First the file search continues in rb_find_file(). This function -searches the file path in the global load path $' -(rb_load_path). The string contamination check is tiresome so we’ll -only look at the main part.

-

rb_find_file() (simplified version) -

-2494  VALUE
-2495  rb_find_file(path)
-2496      VALUE path;
-2497  {
-2498      VALUE tmp;
-2499      char *f = RSTRING→ptr;
-2500      char *lpath;

-

2530 if (rb_load_path) { -2531 long i; -2532 -2533 Check_Type(rb_load_path, T_ARRAY); -2534 tmp = rb_ary_new(); -2535 for (i=0;i<RARRAY→len;i++) { -2536 VALUE str = RARRAY→ptr[i]; -2537 SafeStringValue(str); -2538 if (RSTRING→len > 0) { -2539 rb_ary_push(tmp, str); -2540 } -2541 } -2542 tmp = rb_ary_join(tmp, rb_str_new2(PATH_SEP)); -2543 if (RSTRING→len == 0) { -2544 lpath = 0; -2545 } -2546 else { -2547 lpath = RSTRING→ptr; -2551 } -2552 }

-

2560 f = dln_find_file(f, lpath); -2561 if (file_load_ok(f)) { -2562 return rb_str_new2(f); -2563 } -2564 return 0; -2565 }

-

(file.c) -

-

If we write what happens in Ruby we get the following:

-
-tmp = []                     # make an array
-$:.each do |path|            # repeat on each element of the load path
-  tmp.push path if path.length > 0 # check the path and push it
-end
-lpath = tmp.join(PATH_SEP)   # concatenate all elements in one string separated by PATH_SEP
-
-dln_find_file(f, lpath)      # main processing
-
-

PATH_SEP is the path separator: ':' under UNIX, ';' under -Windows. rb_ary_join() creates a string by putting it between the -different elements. In other words, the load path that had become an -array is back to a string with a separator.

-

Why? It’s only because dln_find_file() takes the paths as a string -with PATH_SEP as a separator. But why is dln_find_file() -implemented like that? It’s just because dln.c is not a library for -ruby. Even if it has been written by the same author, it’s a general -purpose library. That’s precisely for this reason that when I sorted -the files by category in the Introduction I put this file in the -Utility category. General purpose libraries cannot receive Ruby -objects as parameters or read ruby global variables.

-

dln_find_file() also expands for example ~ to the home directory, -but in fact this is already done in the omitted part of -rb_find_file(). So in ruby‘s case it’s not necessary.

-

Loading wait

-

Here, file search is finished quickly. Then comes is the loading -code. Or more accurately, it is “up to just before the load”. The code -of rb_f_require()’s load_rb has been put below.

-

rb_f_require():load_rb -

-5625    load_rb:
-5626      if (rb_feature_p(RSTRING→ptr, Qtrue))
-5627          return Qfalse;
-5628      ruby_safe_level = 0;
-5629      rb_provide_feature(feature);
-5630      /* the loading of Ruby programs is serialised /
-5631      if (!loading_tbl) {
-5632          loading_tbl = st_init_strtable();
-5633      }
-5634      / partial state /
-5635      ftptr = ruby_strdup(RSTRING→ptr);
-5636      st_insert(loading_tbl, ftptr, curr_thread);
-          / …load the Ruby program and evaluate it… /
-5643      st_delete(loading_tbl, &ftptr, 0); / loading done */
-5644      free(ftptr);
-5645      ruby_safe_level = safe;

-

(eval.c) -

-

Like mentioned above, rb_feature_p() checks if a lock has been put -in $". And rb_provide_feature() pushes a string in $", in other -words locks the file.

-

The problem comes after. Like the comment says “the loading of Ruby -programs is serialised”. In other words, a file can only be loaded -from one thread, and if during the loading another thread tries to load the -same file, that thread will wait for the first loading to be finished. -If it were not the case:

-
-Thread.fork {
-    require 'foo'   # At the beginning of require, foo.rb is added to $"
-}                   # However the thread changes during the evaluation of foo.rb
-require 'foo'   # foo.rb is already in $" so the function returns immediately
-# (A) the classes of foo are used...
-
-

By doing something like this, even though the foo library is not -really loaded, the code at (A) ends up being executed.

-

The process to enter the waiting state is simple. A st_table is -created in loading_tbl, the association “feature=>waiting thread” -is recorded in it. curr_thread is in eval.c’s functions, its value -is the current running thread.

-

The mechanism to enter the waiting state is very simple. A st_table -is created in the loading_tbl global variable, and a -“feature=>loading thread” association is created. curr_thread is -a variable from eval.c, and its value is the currently running -thread. That makes an exclusive lock. And in rb_feature_p(), we -wait for the loading thread to end like the following.

-

rb_feature_p() (second half) -

-5477  rb_thread_t th;
-5478
-5479  while (st_lookup(loading_tbl, f, &th)) {
-5480      if (th == curr_thread) {
-5481          return Qtrue;
-5482      }
-5483      CHECK_INTS;
-5484      rb_thread_schedule();
-5485  }

-

(eval.c) -

-

When rb_thread_schedule() is called, the control is transferred to -an other thread, and this function only returns after the control -returned back to the thread where it was called. When the file name -disappears from loading_tbl, the loading is finished so the function -can end. The curr_thread check is not to lock itself (figure 1).

-

-

(loadwait)
-Figure 1: Serialisation of loads

-

-

Loading of Ruby programs

-

rb_load()

-

We will now look at the loading process itself. Let’s start by the -part inside rb_f_require()’s load_rb loading Ruby programs.

-

rb_f_require()-load_rb- loading -

-5638      PUSH_TAG(PROT_NONE);
-5639      if ((state = EXEC_TAG()) == 0) {
-5640          rb_load(fname, 0);
-5641      }
-5642      POP_TAG();

-

(eval.c) -

-

The rb_load() which is called here is actually the “meat” of the -Ruby-level load. -ということは探索がもう一回必要になるわけで、同じ作業をもう一回見るなん -てやっていられない。そこでその部分は以下では省略してある。

-

And since the second argument (wrap) passed to rb_load in the above code is 0, the call is wrapped in 0. (* What is this supposed to mean??? That the nesting level is 0?) -また第二引数のwrapも、上記の呼び出しコードで0なので、0で畳み込んである。

-

rb_load() (simplified edition) -

-void
-rb_load(fname, /* wrap=0 */)
-    VALUE fname;
-{
-    int state;
-    volatile ID last_func;
-    volatile VALUE wrapper = 0;
-    volatile VALUE self = ruby_top_self;
-    NODE *saved_cref = ruby_cref;

-PUSH_VARS(); -PUSH_CLASS(); -ruby_class = rb_cObject; -ruby_cref = top_cref; /* (A-1) CREFを変える */ -wrapper = ruby_wrapper; -ruby_wrapper = 0; -PUSH_FRAME(); -ruby_frame→last_func = 0; -ruby_frame→last_class = 0; -ruby_frame→self = self; /* (A-2) ruby_frame→cbaseを変える */ -ruby_frame→cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0); -PUSH_SCOPE(); -/* at the top-level the visibility is private by default */ -SCOPE_SET(SCOPE_PRIVATE); -PUSH_TAG(PROT_NONE); -ruby_errinfo = Qnil; /* make sure it’s nil */ -state = EXEC_TAG(); -last_func = ruby_frame→last_func; -if (state == 0) { -NODE *node; -/* (B)なぜかevalと同じ扱い */ -ruby_in_eval++; -rb_load_file(RSTRING→ptr); -ruby_in_eval—; -node = ruby_eval_tree; -if (ruby_nerrs == 0) { /* no parse error occurred */ -eval_node(self, node); -} -} -ruby_frame→last_func = last_func; -POP_TAG(); -ruby_cref = saved_cref; -POP_SCOPE(); -POP_FRAME(); -POP_CLASS(); -POP_VARS(); -ruby_wrapper = wrapper; -if (ruby_nerrs > 0) { /* a parse error occurred */ -ruby_nerrs = 0; -rb_exc_raise(ruby_errinfo); -} -if (state) jump_tag_but_local_jump(state); -if (!NIL_P(ruby_errinfo)) /* an exception was raised during the loading */ -rb_exc_raise(ruby_errinfo); -

} -

-

やっとスタック操作の嵐から抜けられたと思った瞬間また突入するというのも -精神的に苦しいものがあるが、気を取りなおして読んでいこう。

-

長い関数の常で、コードのほとんどがイディオムで占められている。 -PUSH/POP、タグプロテクトと再ジャンプ。その中でも注目したいのは -(A)のCREF関係だ。ロードしたプログラムは常にトップレベル上で -実行されるので、ruby_crefを(プッシュではなく)退避しtop_crefに戻す。 -ruby_frame->cbaseも新しいものにしている。

-

それともう一ヶ所、(B)でなぜかruby_in_evalをオンにしている。そもそも -この変数はいったい何に影響するのか調べてみると、rb_compile_error()とい -う関数だけのようだ。ruby_in_evalが真のときは例外オブジェクトにメッセージを -保存、そうでないときはstderrにメッセージを出力、となっている。つまりコ -マンドのメインプログラムのパースエラーのときはいきなりstderrに出力した -いのだが評価器の中ではそれはまずいので止める、という仕組みらしい。すると -ruby_in_evalのevalはメソッドevalや関数eval()ではなくて一般動詞の -evaluateか、はたまたeval.cのことを指すのかもしれない。

-

rb_load_file()

-

ここでソースファイルは突然ruby.cへと移る。と言うよりも実際のところは -こうではないだろうか。即ち、ロード関係のファイルは本来ruby.cに置きたい。 -しかしrb_load()ではPUSH_TAG()などを使わざるを得ない。だから仕方なく -eval.cに置く。でなければ最初から全部eval.cに置くだろう。

-

それで、rb_load_file()だ。

-

rb_load_file() -

- 865  void
- 866  rb_load_file(fname)
- 867      char *fname;
- 868  {
- 869      load_file(fname, 0);
- 870  }

-

(ruby.c) -

-

まるごと委譲。load_file()の第二引数scriptは真偽値で、rubyコマンドの -引数のファイルをロードしているのかどうかを示す。今はそうではなく -ライブラリのロードと考えたいのでscript=0で疊み込もう。 -さらに以下では意味も考え本質的でないものを削ってある。

-

load_file() (simplified edition) -

-static void
-load_file(fname, /* script=0 */)
-    char *fname;
-{
-    VALUE f;
-    {
-        FILE *fp = fopen(fname, “r”);   (A)
-        if (fp == NULL) {
-            rb_load_fail(fname);
-        }
-        fclose(fp);
-    }
-    f = rb_file_open(fname, “r”);       (B)
-    rb_compile_file(fname, f, 1);       ©
-    rb_io_close(f);
-}
-

-

(A) The call to fopen() is to check if the -file can be opened. If there is no problem, it’s immediately closed. -It may seem a little useless but it’s an extremely simple and yet -highly portable and reliable way to do it.

-

(B) The file is opened once again, this time using the Ruby level -library File.open. The file was not opened with File.open from the -beginning so as not to raise any Ruby exception if the file cannot be -opened. Here if any exception occurred we would like to have a -loading error, but getting the errors related to open, for example -Errno::ENOENT, Errno::EACCESS…, would be problematic. We are in -ruby.c so we cannot stop a tag jump.

-

© Using the parser interface rb_compile_file(), the program is -read from an IO object, and compiled in a syntax tree. The syntax -tree is added to ruby_eval_tree so there is no need to get the -result.

-

That’s all for the loading code. Finally, the calls were quite deep so -let’s look at the callgraph of rb_f_require() bellow.

-
-rb_f_require           ....eval.c
-    rb_find_file            ....file.c
-        dln_find_file           ....dln.c
-            dln_find_file_1
-    rb_load
-        rb_load_file            ....ruby.c
-            load_file
-                rb_compile_file     ....parse.y
-        eval_node
-
-

We’ve seen a lot of callgraphs, they are now common sense.

-

The number of open required for loading

-

Like we’ve seen before, there are open used just to check if a file -can be open, but in fact during the loading process other functions -like for example rb_find_file_ext() also do checks using open. How -many times is open() called in the whole process?

-

If you’re wondering that, it’s just a matter of having the right program available to count and see. You can easily find out using a system call tracer. On Linux, the tool to use would be strace; on Solaris, truss; or on BSD, ktrace or truss.

-

というように -OSによって名前がてんでバラバラなのだが、Googleで検索すればすぐ見付かる

-

If you’re using Windows, probably your IDE will have a tracer built in. Well, as my main environment is Linux, I looked using strace.

-

The output is done on stderr so it was redirected using 2>&1.

-
-% strace ruby -e 'require "rational"' 2>&1 | grep '^open'
-open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT
-open("/etc/ld.so.cache", O_RDONLY)      = 3
-open("/usr/lib/libruby-1.7.so.1.7", O_RDONLY) = 3
-open("/lib/libdl.so.2", O_RDONLY)       = 3
-open("/lib/libcrypt.so.1", O_RDONLY)    = 3
-open("/lib/libc.so.6", O_RDONLY)        = 3
-open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
-open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
-open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
-open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3
-
-

libc.so.6openまではダイナミックリンクの実装で使っているopenなので -残りのopenは計四回。つまり三回は無駄になっているようだ。

-

Loading of extension libraries

-

rb_f_require()-load_dyna

-

This time we will see the loading of extension libraries. We will -start with rb_f_require()’s load_dyna. However, we do not need the -part about locking anymore so it was removed.

-

rb_f_require()-load_dyna -

-5607  {
-5608      int volatile old_vmode = scope_vmode;
-5609
-5610      PUSH_TAG(PROT_NONE);
-5611      if ((state = EXEC_TAG()) == 0) {
-5612          void *handle;
-5613
-5614          SCOPE_SET(SCOPE_PUBLIC);
-5615          handle = dln_load(RSTRING→ptr);
-5616          rb_ary_push(ruby_dln_librefs, LONG2NUMhandle));
-5617      }
-5618      POP_TAG();
-5619      SCOPE_SET(old_vmode);
-5620  }
-5621  if (state) JUMP_TAG(state);

-

(eval.c) -

-

By now, there is very little here which is novel. タグはイディオム通りの使いかた -しかしていないし、可視性スコープの退避・復帰も見慣れた手法だ。 -All that remains is dln_load(). What on earth is that for? For the answer, continue to the next section.

-

リンクについて復習

-

dln_load()は拡張ライブラリをロードしているわけだが、拡張ライブラリを -ロードするとはどういうことなのだろうか。それを話すにはまず話を思い切り -物理世界方向に巻き戻し、リンクのことから始めなければならない。

-

Cのプログラムをコンパイルしたことはもちろんあると思う。筆者は -Linuxでgccを使っているので、次のようにすれば動くプログラムが -作成できる。

-
-% gcc hello.c
-
-

ファイル名からするときっとこれはHello, World!プログラムなんだろう。 -gccはUNIXではデフォルトでa.outというファイルにプログラムを -出力するので続いて次のように実行できる。

-
-% ./a.out
-Hello, World!
-
-

It prints out just as expected.

-

By the way, what is gcc actually doing here? Usually we just say is “compiles”, but actually it…

-
    -
  1. Preprocesses (cpp)
  2. -
  3. Compiles C into assembly (cc)
  4. -
  5. Assembles the assembly language into machine code (as)
  6. -
  7. Links (ld)
  8. -
-

という四つの段階を通っている。このうちプリプロセス・コンパイル・アセン -ブルまではいろいろなところで説明を見掛けるのだが、なぜかリンクの段階だ -けは明文化されずに終わることが多いようだ。学校の歴史の授業では絶対に -「現代」まで行き着かない、というのと同じようなものだろうか。そこで本書 -ではその断絶を埋めるべく、まずリンクとは何なのか簡単にまとめておくこと -にする。

-

アセンブルまでの段階が完了したプログラムはなんらかの形式の -「オブジェクトファイル」 -になっている。そのような形式でメジャーなものには以下のよう -なものがある。

-
    -
  • ELF, Executable and Linking Format(新しめのUNIX)
  • -
  • a.out, assembler output(比較的古いUNIX)
  • -
  • COFF, Common Object File Format(Win32)
  • -
-

念のため言っておくが、オブジェクトファイル形式のa.outccの -デフォルト出力ファイル名のa.outは全然別物である。例えば今時のLinuxで -普通に作ればELF形式のファイルa.outができる。

-

それで、このオブジェクトファイル形式がどう違うのか、という話はこのさい -どうでもいい。今認識しなければならないのは、これらのオブジェクトファイ -ルはどれも「名前の集合」と考えられるということだ。例えばこのファイルに -存在する関数名や変数名など。

-

またオブジェクトファイルに含まれる名前の集合には二種類がある。即ち

-
    -
  • 必要な名前の集合(例えば内部から呼んでいる外部関数。例:printf)
  • -
  • 提供する名前の集合(例えば内部で定義している関数。例:hello)
  • -
-

である。そしてリンクとは、複数のオブジェクトファイルを集めてきたときに -全てのオブジェクトファイルの「必要な名前の集合」が「提供する名前の集合」 -の中に含まれることを確認し、かつ互いに結び付けることだ。つまり全ての -「必要な名前」から線をひっぱって、どこかのオブジェクトファイルが「提供 -する名前」につなげられるようにしなければいけない(図2)。 -このことを用語を使って -言えば、未定義シンボルを解決する(resolving undefined symbol)、となる。

-

-

(link)
-Figure 2: オブジェクトファイルとリンク

-

-

論理的にはそういうことだが、現実にはそれだけではプログラムは走らないわ -けだ。少なくともCのプログラムは走らない。名前をアドレス(数)に変換し -てもらわなければ動けないからだ。

-

そこで論理的な結合の次には物理的な結合が必要になる。オブジェクトファイ -ルを現実のメモリ空間にマップし、全ての名前を数で置き換えないといけない。 -具体的に言えば関数呼び出し時のジャンプ先アドレスを調節したりする。

-

そしてこの二つの結合をいつやるかによってリンクは二種類に分かれる。即ち -スタティックリンクとダイナミックリンクである。スタティックリンクはコン -パイル時に全段階を終了してしまう。一方ダイナミックリンクは結合のうちい -くらかをプログラムの実行時まで遅らせる。そしてプログラムの実行時になっ -て初めてリンクが完了する。

-

もっともここで説明したのは非常に単純な理想的モデルであって現実をかなり -歪曲している面がある。論理結合と物理結合はそんなにキッパリ分かれるもの -ではないし、「オブジェクトファイルは名前の集合」というのもナイーブに過 -ぎる。しかしなにしろこのあたりはプラットフォームによってあまりに動作が -違いすぎるので、真面目に話していたら本がもう一冊書けてしまう。 -現実レベルの知識を得るためにはさらに -『エキスパートCプログラミング』\footnote{『エキスパートCプログラミング』Peter van der Linden著、梅原系訳、アスキー出版局、1996} -『Linkers&Loaders』@footnote{『Linkers&Loaders』John R.Levine著、榊原一矢監訳 ポジティブエッジ訳、オーム社、2001} -あたりも読んでおくとよい。

-

真にダイナミックなリンク

-

And finally we get into our main topic. The “dynamic” in “dynamic linking” naturally means it “occurs at execution time”, but what people usually refer to as “dynamic linking” is pretty much decided already at compile time. For example, the names of the needed functions, and which library they can be found in, are already known. For instance, if you need cos(), you know it’s in libm, so you use gcc -lm. If you didn’t specify the correct library at compile time, you’d get a link error.

-

But extension libraries are different. Neither the names of the needed functions, or the name of the library which defines them are known at compile time. -文字列をプログラムの実 -行中に組み立ててロード・リンクしなければいけないのである。つまり先程の -言葉で言う「論理結合」すらも全て実行時に行わなければならない。そのため -には普通に言うところのダイナミックリンクとはまた少し違う仕組みが必要に -なる。

-

この操作、つまり実行時に全てを決めるリンク、のことを普通は -「動的ロード(dynamic load)」と呼ぶ。本書の用語遣いからいくと -「ダイナミックロード」と片仮名にひらくべきなのだろうが、 -ダイナミックリンクと -ダイナミックロードだと紛らわしいのであえて漢字で「動的ロード」とする。

-

動的ロードAPI

-

概念の説明は以上だ。あとはその動的ロードをどうやればいいかである。とは -言っても難しいことはなくて、普通はシステムに専用APIが用意されているの -でこちらは単にそれを呼べばいい。

-

例えばUNIXならわりと広範囲にあるのがdlopenというAPIである。ただし -「UNIXならある」とまでは言えない。例えばちょっと前のHP-UXには全く違う -インターフェイスがあるしMac OS XだとNeXT風のAPIを使う。また同じ -dlopenでもBSD系だとlibcにあるのにLinuxだとlibdlとして外付けになっ -ている、などなど、壮絶なまでに移植性がない。いちおうUNIX系と並び称され -ていてもこれだけ違うわけだから、他のOSになれば全然違うのもあたりまえで -ある。同じAPIが使われていることはまずありえない。

-

そこでrubyはどうしているかというと、その全然違うインターフェイスを吸収 -するためにdln.cというファイルを用意している。dlnはdynamic linkの略だろ -う。dln_load()はそのdln.cの関数の一つなのである。

-

そんなふうに全くバラバラの動的ロードAPIだが、せめてもの救 -いはAPIの使用パターンが全く同じだということだ。どのプラットフォームだ -ろうと

-
    -
  1. ライブラリをプロセスのアドレス空間にマップする
  2. -
  3. ライブラリに含まれる関数へのポインタを取る
  4. -
  5. ライブラリをアンマップ
  6. -
-

という三段階で構成されている。例えばdlopen系APIならば

-
    -
  1. dlopen
  2. -
  3. dlsym
  4. -
  5. dlclose
  6. -
-

が対応する。Win32 APIならば

-
    -
  1. LoadLibrary(またはLoadLibraryEx)
  2. -
  3. GetProcAddress
  4. -
  5. FreeLibrary
  6. -
-

が対応する。

-

最後に、このAPI群を使ってdln_load()が何をするかを話そう。これが実は、 -Init_xxxx()の呼び出しなのだ。ここに至ってついにruby起動から終了までの全 -過程が欠落なく描けるようになる。即ち、rubyは起動すると評価器を初期化し -なんらかの方法で受け取ったメインプログラムの評価を開始する。その途中で -requireloadが起こるとライブラリをロードし制御を移す。制御を移す、と -は、Rubyライブラリならばパースして評価することであり、拡張ライブラリな -らばロード・リンクしてInit_xxxx()を呼ぶことである。

-

dln_load()

-

ようやくdln_load()の中身にたどりつけた。dln_load()も長い関数だが、これ -また理由があって構造は単純である。まず概形を見てほしい。

-

dln_load()(概形) -

-void*
-dln_load(file)
-    const char file;
-{
-#if defined _WIN32 && !defined CYGWIN
-    Win32 APIでロード
-#else
-    プラットフォーム独立の初期化
-#ifdef 各プラットフォーム
-    ……プラットフォームごとのルーチン……
-#endif
-#endif
-#if !defined(AIX) && !defined(NeXT)
-  failed:
-    rbloaderror(“%s – %s”, error, file);
-#endif
-    return 0;                   / dummy return */
-}
-

-

このようにメインとなる部分がプラットフォームごとに完璧に分離しているため、 -考えるときは一つ一つのプラットフォームのことだけを考えていればいい。 -サポートされているAPIは以下の通りだ。

-
    -
  • dlopen(多くのUNIX)
  • -
  • LoadLibrary(Win32)
  • -
  • shl_load(少し古いHP-UX)
  • -
  • a.out(かなり古いUNIX)
  • -
  • rld_load(NeXT4未満)
  • -
  • dyld(NeXTまたはMac OS X)
  • -
  • get_image_symbol(BeOS)
  • -
  • GetDiskFragment(Mac OS 9以前)
  • -
  • load(少し古いAIX)
  • -
-

dln_load()-dlopen()

-

First, let’s start with the API code for the dlopen series.

-

dln_load()-dlopen() -

-1254  void*
-1255  dln_load(file)
-1256      const char file;
-1257  {
-1259      const char *error = 0;
-1260  #define DLN_ERROR() (error = dln_strerror(),\
-                           strcpy(ALLOCA_N(char, strlen(error) + 1), error))
-1298      char *buf;
-1299      / Init_xxxxという文字列をbufに書き込む(領域はalloca割り当て) */
-1300      init_funcname(&buf, file);

-

1304 { -1305 void handle; -1306 void (init_fct)(); -1307 -1308 #ifndef RTLD_LAZY -1309 # define RTLD_LAZY 1 -1310 #endif -1311 #ifndef RTLD_GLOBAL -1312 # define RTLD_GLOBAL 0 -1313 #endif -1314 -1315 /* (A)ライブラリをロード / -1316 if ((handle = (void)dlopen(file, RTLD_LAZY | RTLD_GLOBAL)) - == NULL) { -1317 error = dln_strerror(); -1318 goto failed; -1319 } -1320 - /* (B)Init_xxxx()へのポインタを取る / -1321 init_fct = (void()())dlsym(handle, buf); -1322 if (init_fct == NULL) { -1323 error = DLN_ERROR(); -1324 dlclose(handle); -1325 goto failed; -1326 } -1327 /* ©Init_xxxx()を呼ぶ / -1328 (init_fct)(); -1329 -1330 return handle; -1331 }

-

1576 failed: -1577 rb_loaderror(“%s – %s”, error, file); -1580 }

-

(dln.c) -

-

(A)dlopen()の引数のRTLD_LAZYは「実際に関数を要求したときに -未解決シンボルを解決する」ことを示す。返り値はライブラリを識別する -ための印(ハンドル)で、dl*()には常にこれを渡さないといけない。

-

(B)dlsym()はハンドルの示すライブラリから関数ポインタを取る。返り値が -NULLなら失敗だ。ここでInit_xxxx()へのポインタを取り、呼ぶ。

-

dlclose()の呼び出しはない。Init_xxxx()の中でロードした -ライブラリの関数ポインタを -返したりしているはずだが、dlclose()するとライブラリ全体が使えなくなって -しまうのでまずいのだ。つまりプロセスが終了するまでdlclose()は呼べない。

-

dln_load()-Win32

-

Win32ではLoadLibrary()GetProcAddress()を使う。 -MSDNにも載っているごく一般的なWin32 APIである。

-

dln_load()-Win32 -

-1254  void*
-1255  dln_load(file)
-1256      const char *file;
-1257  {

-

1264 HINSTANCE handle; -1265 char winfile[MAXPATHLEN]; -1266 void (init_fct)(); -1267 char *buf; -1268 -1269 if (strlen(file) >= MAXPATHLEN) rb_loaderror(“filename too long”); -1270 -1271 / "Init_xxxx"という文字列をbufに書き込む(領域はalloca割り当て) / -1272 init_funcname(&buf, file); -1273 -1274 strcpy(winfile, file); -1275 -1276 / ライブラリをロード / -1277 if ((handle = LoadLibrary(winfile)) == NULL) { -1278 error = dln_strerror(); -1279 goto failed; -1280 } -1281 -1282 if ((init_fct = (void()())GetProcAddress(handle, buf)) == NULL) { -1283 rb_loaderror(“%s – %s\n%s”, dln_strerror(), buf, file); -1284 } -1285 -1286 /* Init_xxxx()を呼ぶ / -1287 (init_fct)(); -1288 return handle;

-

1576 failed: -1577 rb_loaderror(“%s – %s”, error, file); -1580 }

-

(dln.c) -

-

LoadLibrary()してGetProcAddress()。ここまでパターンが同じだと -言うこともないので、終わってしまうことにしよう。

- - - -
- - diff --git a/htmls/method.html b/htmls/method.html deleted file mode 100644 index ac0d3d3..0000000 --- a/htmls/method.html +++ /dev/null @@ -1,921 +0,0 @@ - - - - - Chapter 15: Methods | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 15: Methods

-

In this chapter, I’ll talk about method searching and invoking.

-

Searching methods

-

Terminology

-

In this chapter, both method calls and method definitions are discussed, -and there will appear really various “arguments”. Therefore, to make it not -confusing, let’s strictly define terms here:

-
-m(a)          # a is a "normal argument"
-m(*list)      # list is an "array argument"
-m(&block)     # block is a "block argument"
-
-def m(a)      # a is a "normal parameter"
-def m(a=nil)  # a is an "option parameter", nil is "it default value".
-def m(*rest)  # rest is a "rest parameter"
-def m(&block) # block is a "block parameter"
-
-

In short, they are all “arguments” when passing and “parameters” when receiving, -and each adjective is attached according to its type.

-

However, among the above things, the “block arguments” and the “block -parameters” will be discussed in the next chapter.

-

Investigation

-

▼The Source Program

- -
-obj.method(7,8)
-
-

▼Its 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
-    ]
-
-

The node for a method call is NODE_CALL. -The nd_args holds the arguments as a list of NODE_ARRAY.

-

Additionally, as the nodes for method calls, there are also NODE_FCALL and NODE_VCALL. -NODE_FCALL is for the “method(args)” form, -NODE_VCALL corresponds to method calls in the “method” form that is the same -form as the local variables. -FCALL and VCALL could actually be integrated into one, -but because there’s no need to prepare arguments when it is VCALL, -they are separated from each other only in order to save both times and memories for it.

-

Now, let’s look at the handler of NODE_CALL in rb_eval().

-

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)
-
-

The problems are probably the three macros, BEGIN_CALLARGS SETUP_ARGS() END_CALLARGS. -It seems that rb_eval() is to evaluate the receiver and -rb_call() is to invoke the method, we can roughly imagine that the evaluation -of the arguments might be done in the three macros, but what is actually done? -BEGIN_CALLARGS and END_CALLARGS are difficult to understand before talking -about the iterators, so they are explained in the next chapter “Block”. -Here, let’s investigate only about SETUP_ARGS().

-

SETUP_ARGS()

-

SETUP_ARGS() is the macro to evaluate the arguments of a method. -Inside of this macro, as the comment in the original program says, -the variables named argc and argv are used, -so they must be defined in advance. -And because it uses TMP_ALLOC(), it must use TMP_PROTECT in advance. -Therefore, something like the following is a boilerplate:

-
-int argc; VALUE *argv;   /* used in SETUP_ARGS */
-TMP_PROTECT;
-
-SETUP_ARGS(args_node);
-
-

args_node is (the node represents) the arguments of the method, -turn it into an array of the values obtained by evaluating it, -and store it in argv. -Let’s look at it:

-

SETUP_ARGS()

- -
-1780  #define SETUP_ARGS(anode) do {\
-1781      NODE *n = anode;\
-1782      if (!n) {\                             no arguments
-1783          argc = 0;\
-1784          argv = 0;\
-1785      }\
-1786      else if (nd_type(n) == NODE_ARRAY) {\  only normal arguments
-1787          argc=n->nd_alen;\
-1788          if (argc > 0) {\   arguments present
-1789              int i;\
-1790              n = anode;\
-1791              argv = TMP_ALLOC(argc);\
-1792              for (i=0;i<argc;i++) {\
-1793                  argv[i] = rb_eval(self,n->nd_head);\
-1794                  n=n->nd_next;\
-1795              }\
-1796          }\
-1797          else {\            no arguments
-1798              argc = 0;\
-1799              argv = 0;\
-1800          }\
-1801      }\
-1802      else {\                                 both or one of an array argument
-1803          VALUE args = rb_eval(self,n);\      and a block argument
-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)
-
-

This is a bit long, but since it clearly branches in three ways, not so terrible -actually. The meaning of each branch is written as comments.

-

We don’t have to care about the case with no arguments, the two rest branches -are doing similar things. Roughly speaking, what they are doing consists of -three steps:

-
    -
  • allocate a space to store the arguments
  • -
  • evaluate the expressions of the arguments
  • -
  • copy the value into the variable space
  • -
-

If I write in the code (and tidy up a little), it becomes as follows.

-
-/***** else if clause、argc!=0 *****/
-int i;
-n = anode;
-argv = TMP_ALLOC(argc);                         /* 1 */
-for (i = 0; i < argc; i++) {
-    argv[i] = rb_eval(self, n->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 */
-
-

TMP_ALLOC() is used in the else if side, -but ALLOCA_N(), which is ordinary alloca(), is used in the else side. -Why? -Isn’t it dangerous in the C_ALLOCA environment because alloca() is -equivalent to malloc() ?

-

The point is that “in the else side the values of arguments are also stored in -args”. If I illustrate, it would look like Figure 1.

-
-

(anchor)
-Figure 1: All right if it is in the heap

-
    -
  • パターン case
  • -
  • 側 side
  • -
  • 同じ内容 the same contents
  • -
  • GCのルートとなる(主にスタック) will be the roots of GC (mainly in the stack)
  • -
  • GCのルートとならない(主にヒープ)will not be the roots of GC (mainly in the heap) -
- -

If at least one VALUE is on the stack, others can be successively marked through -it. This kind of VALUE plays a role to tie up the other VALUEs to the stack -like an anchor. Namely, it becomes “anchor VALUE”. -In the else side, args is the anchor VALUE.

-

For your information, “anchor VALUE” is the word just coined now.

-

rb_call()

-

SETUP_ARGS() is relatively off the track. Let’s go back to the main line. The -function to invoke a method, it is rb_call(). In the original there’re codes -like raising exceptions when it could not find anything, as usual I’ll skip all -of them.

-

rb_call() (simplified)

- -
-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;
-
-    /* search over 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 {
-        /* cache miss, searching step-by-step  */
-        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 way of searching methods was discussed in chapter 2: “Object”. -It is following its superclasses and searching m_tbl. This is done by -search_method().

-

The principle is certainly this, but when it comes to the phase to execute -actually, if it searches by looking up its hash many times for each method call, -its speed would be too slow. -To improve this, in ruby, once a method is called, it will be cached. -If a method is called once, it’s often immediately called again. -This is known as an experiential fact and this cache records the high hit rate.

-

What is looking up the cache is the first half of rb_call(). Only with

-
-ent = cache + EXPR1(klass, mid);
-
-

this line, the cache is searched. -We’ll examine its mechanism in detail later.

-

When any cache was not hit, the next rb_get_method_body() searches the class -tree step-by-step and caches the result at the same time. -Figure 2 shows the entire flow of searching.

-
-

(msearch)
-Figure 2: Method Search

-
    -
  • キャッシュ cache
  • -
  • クラスツリー the class tree -
- -

Method Cache

-

Next, let’s examine the structure of the method cache in detail.

-

▼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)
-
-

If I describe the mechanism shortly, it is a hash table. I mentioned that the -principle of the hash table is to convert a table search to an indexing of an -array. Three things are necessary to accomplish: an array to store the data, -a key, and a hash function.

-

First, the array here is an array of struct cache_entry. And the method is -uniquely determined by only the class and the method name, so these two become -the key of the hash calculation. The rest is done by creating a hash function -to generate the index (0x000 ~ 0x7ff) of the cache array form the key. -It is EXPR1(). Among its arguments, c is the class object and m is the -method name (ID). (Figure 3)

-
-

(mhash)
-Figure 3: Method Cache

-
    -
  • クラス、メソッドID class, method ID -
- -

However, EXPR1() is not a perfect hash function or anything, so a different -method can generate the same index coincidentally. But because this is nothing -more than a cache, conflicts do not cause a problem. -It just slows its performance down a little.

-

The effect of Method Cache

-

By the way, how much effective is the method cache in actuality? -We could not be convinced just by being said “it is known as …”. -Let’s measure by ourselves.

- - - - - - - - - - - - - - - - - - - - - -
Type Program Hit Rate
generating LALR parser racc ruby.y 99.9%
generating a mail thread a mailer 99.1%
generating a document rd2html rubyrefm.rd 97.8%
-

Surprisingly, in all of the three experiments the hit rate is more than 95%. -This is awesome. Apparently, the effect of “it is know as …” is outstanding.

-

Invocation

-

rb_call0()

-

There have been many things and finally we arrived at the method invoking. -However, this rb_call0() is huge. As it’s more than 200 lines, it would come -to 5,6 pages. If the whole part is laid out here, it would be disastrous. Let’s -look at it by dividing into small portions. Starting with the outline:

-

rb_call0() (Outline)

- -
-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)) {
-              /* ... main process ... */
-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, an ITER is pushed and whether or not the method is an iterator is -finally fixed. As its value is used by the PUSH_FRAME() which comes -immediately after it, PUSH_ITER() needs to appear beforehand. -PUSH_FRAME() will be discussed soon.

-

And if I first describe about the “… main process …” part, -it branches based on the following node types -and each branch does its invoking process.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NODE_CFUNC methods defined in C
NODE_IVAR attr_reader
NODE_ATTRSET attr_writer
NODE_SUPER super
NODE_ZSUPER super without arguments
NODE_DMETHOD invoke UnboundMethod
NODE_BMETHOD invoke Method
NODE_SCOPE methods defined in Ruby
-

Some of the above nodes are not explained in this book but not so important and -could be ignored. The important things are only NODE_CFUNC, NODE_SCOPE and -NODE_ZSUPER.

-

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, we’d like to make sure the entire FRAME is allocated on the stack. -This is identical to module_setup(). The rest is basically just doing -ordinary initializations.

-

If I add one more description, the flag FRAME_ALLOCA indicates the allocation -method of the FRAME. FRAME_ALLOCA obviously indicates “it is on the stack”.

-

rb_call0()NODE_CFUNC

-

A lot of things are written in this part of the original code, -but most of them are related to trace_func and substantive code is only the -following line:

-

rb_call0()NODE_CFUNC (simplified)

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

Then, as for call_cfunc()

-

call_cfunc() (simplified)

- -
-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)
-
-

As shown above, it branches based on the argument count. -The maximum argument count is 15.

-

Note that neither SCOPE or VARS is pushed when it is NODE_CFUNC. It makes -sense because if a method is defined in C it would not use the Ruby’s local -variables. But it simultaneously means that if the “current” local variables are -accessed by C, they are actually the local variables of the previous FRAME. -And in some places, say, rb_svar (eval.c), it is actually done.

-

rb_call0()NODE_SCOPE

-

NODE_SCOPE is to invoke a method defined in Ruby. -This part forms the foundation of Ruby.

-

rb_call0()NODE_SCOPE (outline)

- -
-4568  case NODE_SCOPE:
-4569    {
-4570        int state;
-4571        VALUE *local_vars;  /* OK */
-4572        NODE *saved_cref = 0;
-4573
-4574        PUSH_SCOPE();
-4575
-            /* (A)forward CREF */
-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)initialize ruby_scope->local_vars */
-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)assign the arguments to the local variables …… */
-
-4666            if (trace_func) {
-4667                call_trace_func("call", b2, recv, id, klass);
-4668            }
-4669            ruby_last_node = b2;
-                /* (D)method body */
-4670            result = rb_eval(recv, body);
-4671        }
-4672        else if (state == TAG_RETURN) { /* back via 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) CREF forwarding, which was described at the section of constants in the -previous chapter. -In other words, cbase is transplanted to FRAME from the method entry.

-

(B) The content here is completely identical to what is done at module_setup(). -An array is allocated at local_vars of SCOPE. With this and -PUSH_SCOPE() and PUSH_VARS(), the local variable scope creation is completed. -After this, one can execute rb_eval() in the exactly same environment as the -interior of the method.

-

(C) This sets the received arguments to the parameter variables. -The parameter variables are in essence identical to the local variables. Things -such as the number of arguments are specified by NODE_ARGS, all it has to do -is setting one by one. Details will be explained soon. And,

-

(D) this executes the method body. Obviously, the receiver (recv) becomes -self. In other words, it becomes the first argument of rb_eval(). After all, -the method is completely invoked.

-

Set Parameters

-

Then, we’ll examine the totally skipped part, which sets parameters. -But before that, I’d like you to first check the syntax tree of the method 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 is the node to specify the parameters of a method. -I aggressively dumped several things, -and it seemed its members are used as follows:

- - - - - - - - - - - - - -
nd_cnt the number of the normal parameters
nd_rest the variable ID of the rest parameter. -1 if the rest parameter is missing
nd_opt holds the syntax tree to represent the default values of the option parameters. a list of NODE_BLOCK
-

If one has this amount of the information, the local variable ID for each -parameter variable can be uniquely determined. -First, I mentioned that 0 and 1 are always $_ and $~. -In 2 and later, the necessary number of ordinary parameters are in line. -The number of option parameters can be determined by the length of NODE_BLOCK. -Again next to them, the rest-parameter comes.

-

For example, if you write a definition as below,

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

local variable IDs are assigned as follows.

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

Are you still with me? -Taking this into considerations, let’s look at the code.

-

rb_call0()NODE_SCOPE −assignments of arguments

- -
-4601  if (nd_type(body) == NODE_ARGS) { /* no body */
-4602      node = body;           /* NODE_ARGS */
-4603      body = 0;              /* the method body */
-4604  }
-4605  else if (nd_type(body) == NODE_BLOCK) { /* has body */
-4606      node = body->nd_head;  /* NODE_ARGS */
-4607      body = body->nd_next;  /* the method body */
-4608  }
-4609  if (node) {  /* have somewhat 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) {  /* no rest parameter */
-              /* counting the number of parameters */
-4620          int opt = i;   /* the 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) {
-4628              rb_raise(rb_eArgError,
-4629                  "wrong number of arguments(%d for %d)", argc, opt);
-4630          }
-              /* assigning at the second time in rb_call0 */
-4631          ruby_frame->argc = opt;
-4632          ruby_frame->argv = local_vars+2;
-4633      }
-4634
-4635      if (local_vars) { /* has parameters */
-4636          if (i > 0) {             /* has normal parameters */
-4637              /* +2 to skip the spaces for $_ and $~ */
-4638              MEMCPY(local_vars+2, argv, VALUE, i);
-4639          }
-4640          argv += i; argc -= i;
-4641          if (node->nd_opt) {      /* has option 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) { /* has rest parameter */
-4655              VALUE v;
-4656
-                  /* make an array of the remainning parameters and assign it to a 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)
-
-

Since comments are added more than before, -you might be able to understand what it is doing by following step-by-step.

-

One thing I’d like to mention is about argc and argv of ruby_frame. -It seems to be updated only when any rest-parameter does not exist, -why is it only when any rest-parameter does not exist?

-

This point can be understood by thinking about the purpose of argc and argv. -These members actually exist for super without arguments. -It means the following form:

-
-super
-
-

This super has a behavior to directly pass the parameters of the currently executing method. -In order to enable to pass at the moment, the arguments are saved in ruby_frame->argv.

-

Going back to the previous story here, -if there’s a rest-parameter, passing the original parameters list somehow seems more convenient. -If there’s not, the one after option parameters are assigned seems better.

-
-def m(a, b, *rest)
-  super     # probably 5, 6, 7, 8 should be passed
-end
-m(5, 6, 7, 8)
-
-def m(a, b = 6)
-  super     # probably 5, 6 should be passed
-end
-m(5)
-
-

This is a question of which is better as a specification rather than “it must be”. -If a method has a rest-parameter, -it supposed to also have a rest-parameter at superclass. -Thus, if the value after processed is passed, there’s the high possibility of being inconvenient.

-

Now, I’ve said various things, but the story of method invocation is all done. -The rest is, as the ending of this chapter, looking at the implementation of -super which is just discussed.

-

super

-

What corresponds to super are NODE_SUPER and NODE_ZSUPER. -NODE_SUPER is ordinary super, -and NODE_ZSUPER is super without arguments.

-

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)case when super is forbidden */
-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)setup or evaluate parameters */
-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)yet mysterious 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)
-
-

For super without arguments, I said that ruby_frame->argv is directly used -as arguments, this is directly shown at (B).

-

(C) just before calling rb_call(), doing PUSH_ITER(). -This is also what cannot be explained in detail, but in this way the block -passed to the current method can be handed over to the next method (meaning, the -method of superclass that is going to be called).

-

And finally, (A) when ruby_frame->last_class is 0, calling super seems forbidden. -Since the error message says “must be enabled by rb_enable_super()”, -it seems it becomes callable by calling rb_enable_super(). -
((errata: The error message “must be enabled by rb_enable_super()” exists not -in this list but in rb_call_super().)) -
Why?

-

First, If we investigate in what kind of situation last_class becomes 0, -it seems that it is while executing the method whose substance is defined in C (NODE_CFUNC). -Moreover, it is the same when doing alias or replacing such method.

-

I’ve understood until there, but even though reading source codes, I couldn’t -understand the subsequents of them. -Because I couldn’t, I searched “rb_enable_super” over the ruby’s -mailing list archives and found it. -According to that mail, the situation looks like as follows:

-

For example, there’s a method named String.new. -Of course, this is a method to create a string. -String.new creates a struct of T_STRING. -Therefore, you can expect that the receiver is always of T_STRING when -writing an instance methods of String.

-

Then, super of String.new is Object.new. -Object.new create a struct of T_OBJECT. -What happens if String.new is replaced by new definition and super is called?

-
-def String.new
-  super
-end
-
-

As a consequence, an object whose struct is of T_OBJECT but whose class is String is created. -However, a method of String is written with expectation of a struct of T_STRING, -so naturally it downs.

-

How can we avoid this? The answer is to forbid to call any method expecting a -struct of a different struct type. -But the information of “expecting struct type” is not attached to method, -and also not to class. -For example, if there’s a way to obtain T_STRING from String class, -it can be checked before calling, but currently we can’t do such thing. -Therefore, as the second-best plan, -“super from methods defined in C is forbidden” is defined. -In this way, if the layer of methods at C level is precisely created, -it cannot be got down at least. -And, when the case is “It’s absolutely safe, so allow super”, -super can be enabled by calling rb_enable_super().

-

In short, the heart of the problem is miss match of struct types. -This is the same as the problem that occurs at the allocation framework.

-

Then, how to solve this is to solve the root of the problem that “the class -does not know the struct-type of the instance”. -But, in order to resolve this, at least new API is necessary, -and if doing more deeply, compatibility will be lost. -Therefore, for the time being, the final solution has not decided yet.

- - - -
- - diff --git a/htmls/minimum.html b/htmls/minimum.html deleted file mode 100644 index 3d50c18..0000000 --- a/htmls/minimum.html +++ /dev/null @@ -1,1251 +0,0 @@ - - - - - A Minimal Introduction to Ruby | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Sebastian Krause

-

Chapter 1: Introduction

-

A Minimal Introdution to Ruby

-

Here the Ruby prerequisites are explained, which one needs to know -in order to understand the first section. -I won’t point out programming techniques or points one should be -careful about. So don’t think you’ll be able to write Ruby programs just because -you read this chapter. Readers who have prior experience with Ruby -can skip this chapter.

-

We will talk about grammar extensively in the second section, hence -I won’t delve into the finer points of grammar here. From hash literals -and such I’ll show only the most widely used notations. On principle -I won’t omit things even if I can. This way the syntax becomes more simple. -I won’t always say “We can omit this”.

-

Objects

-

Strings

-

Everything that can be manipulated in a Ruby program is an object. -There are no primitives as Java’s int and long. For instance -if we write as below it denotes a string object with content content.

-
-"content"
-
-

I casually called it a string object but to be precise this is an expression which generates -a string object. Therefore if we write it several times each time -another string object is generated.

-
-"content"
-"content"
-"content"
-
-

Here three string objects with content content are generated.

-

Besides, a program won’t do any good without some output. Let’s show how to print on the terminal.

-
-p("content")   # Shows "content"
-
-

Everything after an # is a comment. From now on, I’ll put the result -of an expression in a comment behind.

-

p(……) calls the function p. It displays arbitrary objects “as such”. -It’s basically a debugging function.

-

Precisely speaking, there are no functions in Ruby, but just for now -we can think of it as a function.

-

Various Literals

-

Now, let’s explain some more the expressions which directly generate objects, -the so-called literals. -First the integers and floating point numbers.

-
-# Integer
-1
-2
-100
-9999999999999999999999999   # Arbitrarily big integers
-
-# Float
-1.0
-99.999
-1.3e4     # 1.3×10^4
-
-

Don’t forget that these are all expressions which generate objects. -I’m repeating myself but there are no primitives in Ruby.

-

Below an array object is generated.

-
-[1, 2, 3]
-
-

This program generates an array which consists of the three integers -1, 2 and 3 in that order. As the elements of an array can be arbitrary -objects the following is also possible.

-
-[1, "string", 2, ["nested", "array"]]
-
-

And finally, a hash table is generated by the expression below.

-
-{"key"=>"value", "key2"=>"value2", "key3"=>"value3"}
-
-

A hash table is a structure which establishes a one-on-one relation between pairs of -arbitrary objects. The above line creates a table which stores the following table.

-
-"key"   →  "value"
-"key2"  →  "value2"
-"key3"  →  "value3"
-
-

If we ask the hash table above “What’s corresponding to key?”, it’ll -answer “That’s value.” How can we ask? We use methods.

-

Method Calls

-

We can call methods on an object. In C++ Jargon they are member functions. -I don’t think it’s necessary to explain what a method is. I’ll just explain -the notation.

-
-"content".upcase()
-
-

Here the upcase method is called on a string object ( with content content). -As upcase is a method which -returns a new string with the small letters replaced by capital letters -we get the following result.

-
-p("content".upcase())   # Shows "CONTENT"
-
-

Method calls can be chained.

-
-"content".upcase().downcase()
-
-

Here the method downcase is called on the return value of "content".upcase().

-

There are no public fields (member variables) as in Java or C++ (Note: need to check this). The object interface consists of methods only.

-

The Program

-

Top Level

-

In Ruby we can just write expressions and it becomes a program. -One doesn’t need to define a main() as in C++ or Java.

-
-p("content")
-
-

This is a complete Ruby program. If we put this into a file called -first.rb we can execute it from the command line as follows.

-
-% ruby first.rb
-"content"
-
-

With the -e option of the ruby program we don’t even need to create a file.

-
-% ruby -e 'p("content")'
-"content"
-
-

By the way, the place where p is written is the lowest level of the program, -or the highest level from the program’s standpoint. Hence it’s called the -toplevel. -The existence of a toplevel is a characteristic trait of a scripting language.

-

In Ruby, one line is usually one statement. A semicolon at the end isn’t necessary. -Therefore the program below is interpreted as three statements.

-
-p("content")
-p("content".upcase())
-p("CONTENT".downcase())
-
-

When we execute it it looks like this.

-
-% ruby second.rb
-"content"
-"CONTENT"
-"content"
-
-

Local Variables

-

In Ruby all variables and constants store references to objects. -That’s why one can’t copy the content by assigning one variable to another variable. -Think of object type variables in Java or pointers in C++. But you can’t change the value -of these pointers.

-

In Ruby one can tell the scope of a variable by its name’s first letter. -Local variables start with a small letter or an underscore. One can write -an “=” for variable assignment.

-
-str = "content"
-arr = [1,2,3]
-
-

An initial assignment serves as declaration, an explicit declaration is -not necessary. Because variables don’t have a type we can assign any type without -distinction. The program below is completely legal.

-
-lvar = "content"
-lvar = [1,2,3]
-lvar = 1
-
-

But just because we can we shouldn’t necessarily do it. If different -objects are put in one variable it tends to become difficult to read. In a -real world Ruby program one doesn’t do this kind of things without a good reason. -The above was just an example for the sake of it.

-

Variable reference has also a pretty straightforward notation.

-
-str = "content"
-p(str)           # Shows "content"
-
-

Now let’s look at how a variable stores a reference.

-
-a = "content"
-b = a
-c = b
-
-

After we execute this program all three local variables a b c -point to the same object, a string object with content "content"

-

-

(reference)
-Figure 1: Ruby variables store references to objects

-

-

Besides, these variables are called local. Hence there should be a scope -but we cannot talk about this scope without reading a bit further. -Let’s say for now that the top level is one local scope.

-

Constants

-

Constants start with a capital letter. They can only be assigned -once (at their creation).

-
-Const = "content"
-PI = 3.1415926535
-
-p(Const)   # Shows "content"
-
-

I’d like to say that if we assign twice an error occurs. But there -is just a warning, not an error. That’s because of applications -which use Ruby, for instance development environments. There shouldn’t -be an error when they load the same file twice. I recognize that -it had to be that way for practicality but there really should be an error. -Up until version 1.1 there really was an error.

-
-C = 1
-C = 2   # There is a warning but ideally there should be an error.
-
-

A lot of people are fooled by the word constant. -A constant only does not switch objects once it is assigned. -But the object itself might as well change. The term “read only” -might capture the concept better than “constant”.

-

By the way, to indicate that an object itself shouldn’t be changed -another means is used: freeze.

-

-

(const)
-Figure 2: constant means read only

-

-

And we cannot talk about the scope yet. We talk about it later in -the context of classes.

-

Control Structures

-

Unfortunately Ruby has a wide abundance of control structures. -For the time being we pretend there are just if and while.

-
-if i < 10 then
-  # body
-end
-
-while i < 10 do
-  # body
-end
-
-

Only false and nil are false in a conditional expression, all -other various objects are true. 0 or the empty string are also true of course.

-

By the way, it wouldn’t be wise if there were just false, there is also true. -And it is of course true.

-

Classes and Methods

-

Classes

-

In object orientation methods belong to objects, in a perfect -world, though. But in a normal program there are a lot of objects which have the -same set of methods. Usually a mechanism like classes or -multimethods is used to get rid of the duplication of definitions.

-

In Ruby the traditional concept of classes is used to bind objects and -methods together. Namely every object belongs to a class, the methods -which can be called are determined by the class. Hence a method is -called an instance of a class.

-

For example the string "str" is called an instance of the class String. -And in this class String the methods upcase, downcase, strip and -many others are defined. So it looks as if each string object has all these -methods.

-
-# They all belong to the String class,
-# hence the same methods are defined
-       "content".upcase()
-"This is a pen.".upcase()
-    "chapter II".upcase()
-
-       "content".length()
-"This is a pen.".length()
-    "chapter II".length()
-
-

By the way, what happens if the called method isn’t defined? -In a static language a compiler error occurs but in Ruby there -is a runtime exception. Let’s try it out. For this kind of programs the --e option is handy.

-
-% ruby -e '"str".bad_method()'
--e:1: undefined method `bad_method' for "str":String (NoMethodError)
-
-

When the method isn’t found there’s apparently a NoMethodError.

-

Always talking about “the upcase method of String” and such is cumbersome. -Let’s introduce a special notation String#upcase refers to the method -upcase defined in the class String.

-

By the way, if we write String.upcase it has a completely different -meaning in the Ruby world. What could that be? I explain it in the -next paragraph.

-

Class Definition

-

Up to now we talked about already defined classes. -We can of course also define our own classes. -To define classes we use the word class.

-
-class C
-end
-
-

This is the definition of a new class C. After we defined it we -can use it as follows.

-
-class C
-end
-c = C.new()   # create an instance of C and assign it to the variable c
-
-

Note that the notation for creating a new instance is not new C. -The astute reader might think: -Hmm, this C.new() really looks like a method call. -In Ruby the object generating expressions are indeed just methods.

-

In Ruby class names and constant names are the same. But what is -contained in a class name, where there’s a constant with the same name? It’s the class. -In Ruby all things which a program can manipulate are objects. So -of course classes are also expressed as objects. Let’s call these -class objects. Every class is an instance of the class Class.

-

In other words a class statement creates a new class object and -it assigns a constant named -with the classname to the class. On the other hand -the generation of an instance references this constant and calls a method -on this object ( usually new). If we look at the example below, it’s -pretty obvious that the creation of an instance doesn’t differ -from a normal method call.

-
-S = "content"
-class C
-end
-
-S.upcase()  # Get the object the constant S points to and call upcase
-C.new()     # Get the object the constant C points to and call new
-
-

So new is not a keyword in Ruby.

-

And we can also use p for an instance of a created class.

-
-class C
-end
-
-c = C.new()
-p(c)       # #<C:0x2acbd7e4>
-
-

It won’t display as nicely as a string or an integer but it shows -its respective class and it’s internal ID. This ID is the pointer value -which points to the object.

-

Oh, I completely forgot but about the notation of method names: -Object.new calls the method new of the class object Object itself. -So Object#new and Object.new are completely different things, we have -to separate them strictly.

-
-obj = Object.new()   # Object.new
-obj.new()            # Object#new
-
-

In practice a method Object#new is almost never defined so the -second line will return an error. Please keep this example in mind.

-

Method Definition

-

If we can define classes we should also be able to define methods. -Let’s define a method for our class C.

-
-class C
-  def myupcase( str )
-    return str.upcase()
-  end
-end
-
-

To define a method we use the word def. In this example we -defined the method myupcase. The name of the only parameter is str. -As with variables it’s not necessary to write down the type of the parameter. -And we can use any number of parameters.

-

Let’s use the defined method. Methods are usually called from the -outside.

-
-c = C.new()
-result = c.myupcase("content")
-p(result)   # Shows "CONTENT"
-
-

Of course if you get used to it you don’t need to assign everything. -The line below gives the same result.

-
-p(C.new().myupcase("content"))   # Also shows "CONTENT"
-
-

self

-

During the execution of a method the information about itself (the instance -which called the method) is saved and can be picked up in self. -Like the this in C++ or Java. Let’s check this out.

-
-class C
-  def get_self()
-    return self
-  end
-end
-
-c = C.new()
-p(c)              # #<C:0x40274e44>
-p(c.get_self())   # #<C:0x40274e44>
-
-

As we see, the exact same object is returned. -We ascertained that for the called method self is c.

-

How should a method against oneself be called? -It comes to mind to do this also via self.

-
-class C
-  def my_p( obj )
-    self.real_my_p(obj)   # called a method against oneself
-  end
-
-  def real_my_p( obj )
-    p(obj)
-  end
-end
-
-C.new().my_p(1)   # Output 1
-
-

But always adding the self when calling an own method is tedious. -Hence, whenever one calls self one can omit the called object ( the receiver) by convention.

-
-class C
-  def my_p( obj )
-    real_my_p(obj)   # Calling without writing down the receiver.
-  end
-
-  def real_my_p( obj )
-    p(obj)
-  end
-end
-
-C.new().my_p(1)   # Output 1
-
-

Instance Variables

-

The saying goes “Objects are data and code”. So the definition -of methods alone would be useless. Objects must also be able -to store data. In other words instance variables. -Or in C++ jargon member variables. (Note: Check this.)

-

In the fashion of Ruby’s variable naming convention, the first -letter determines the variable type. For instance variables it’s -an @.

-
-class C
-  def set_i(value)
-    @i = value
-  end
-
-  def get_i()
-    return @i
-  end
-end
-
-c = C.new()
-c.set_i("ok")
-p(c.get_i())   # Shows "ok"
-
-

Instance variables differ a bit from the variables seen before: -We can reference them without assigning or defining them. -To see what happens we add the following lines to the code above.

-
-c = C.new()
-p(c.get_i())   # Shows nil
-
-

Calling get without set gives nil. nil is the object -which indicates “nothing”. It’s mysterious why there’s an object -where there should be nothing, but that’s just the way it is.

-

We can use nil like a literal as well.

-
-p(nil)   # Shows nil
-
-

initialize

-

As we saw before, when we call ‘new’ on a freshly defined class, -we can create an instance. That’s surely a good thing, but -sometimes we might want to have a peculiar instantiation. -In this case we don’t change method new, we change the method initialize. -When we do this it get’s called within new.

-
-class C
-  def initialize()
-    @i = "ok"
-  end
-  def get_i()
-    return @i
-  end
-end
-c = C.new()
-p(c.get_i())   # Shows "ok"
-
-

Strictly speaking this is the work of the new method not the -work of the language itself.

-

Inheritance

-

Classes can inherit from other classes. For instance String -inherits from Object. In this text we’’ll indicate this relation -by a vertical arrow as in Fig.3.

-

-

(supersub)
-Figure 3: Inheritance

-

-

In the illustration the inherited class (Object) is called -superclass or superior class. The inheriting class (String) is called -subclass or inferior class. This point differs from C++ jargon, be careful. -But it’s the same as in Java.

-

Anyway let’s try it out. Let’s inherit for our created class from another -class. To inherit from another class ( or designate a superclass) -write the following.

-
-class C < SuperClassName
-end
-
-

When we leave out the superclass like in the cases before the -class Object becomes tacitly the superclass.

-

Now, why should we want to inherit? Of course to hand over methods. -Handing over means that the methods which were defined in the -superclass also work in the subclass as if they were defined in there once more. -Let’s check it out.

-
-class C
-  def hello()
-    return "hello"
-  end
-end
-
-class Sub < C
-end
-
-sub = Sub.new()
-p(sub.hello())   # Shows "hello"
-
-

hello was defined in the class C but we could call it from -the class Sub as well. Of course we don’t need to assign variables. -The above is the same as the line below.

-
-p(Sub.new().hello())
-
-

When we define a method with the same name we overwrite a method. -In C++ and Object Pascal (Delphi) it’s only possible to overwrite -explicitly with the keyword virtual but in Ruby every method -can be overwritten unconditionally.

-
-class C
-  def hello()
-    return "Hello"
-  end
-end
-
-class Sub < C
-  def hello()
-    return "Hello from Sub"
-  end
-end
-
-p(Sub.new().hello())   # Shows "Hello from Sub"
-p(C.new().hello())     # Shows "Hello"
-
-

We can inherit over several steps. For instance as in Fig.4 -Fixnum inherits every method from Object, Numeric and Integer. -When there are methods with the same name the nearer classes take -preference. As type overloading isn’t there at all the requisites are -extremely straigtforward.

-

-

(multiinherit)
-Figure 4: Inheitance over multiple steps

-

-

In C++ it’s possible to create a class which inherits nothing. -While in Ruby one has to inherit from the Object class either -directly or indirectly. In other words when we draw the inheritance -relations it becomes a single tree with Object at the top.

-

-

(classtree)
-Figure 5: Ruby’s class tree

-

-

(Note: changed in 1.9: Socket isn’t builtin anymore, might want to add -Fiber, String, Symbol)

-

When the superclass is appointed ( in the definition statement ) it’s -not possible to change it anymore. In other words, one can add to the class tree -but cannot change a position or delete a class.

-

Inheritance of Variables……?

-

In Ruby (instance) variables aren’t inherited. -Even when inheriting, there’s no information what variables that class -uses.

-

But when an inherited method is called ( in an instance of a subclass), -assignment of instance variables happens. Which means they -become defined. Then, since the namespace of instance variables -is completely flat, it can be accessed by whichever method.

-
-class A
-  def initialize()   # called from when processing new()
-    @i = "ok"
-  end
-end
-
-class B < A
-  def print_i()
-    p(@i)
-  end
-end
-
-B.new().print_i()   # Shows "ok"
-
-

If you can’t agree with this behavior let’s think more about classses -and inheritance. When there’s an instance obj of the -the class C then all the methods of the superclass of C are as if -defined in C. Of course we keep the overwrite rule in mind. -Then the methods of C get attached to the instance obj (Fig.6). -This strong palpability is a specialty of Ruby’s object orientation.

-

-

(objimage)
-Figure 6: A conception of a Ruby object

-

-

(メソッド:method)

-

Modules

-

Only a single superclass can be designated. So Ruby looks like -single inheritance. But because of modules it has in practice -the same abilities as a multiple inheritance language. -Let’s explain these modules next.

-

In short, modules are classes for which a superclass cannot be -designated and instances cannot be created. -For the definition we write as follows.

-
-module M
-end
-
-

Here the module M was defined. Methods are defined exactly the -same way as for classes.

-
-module M
-  def myupcase( str )
-    return str.upcase()
-  end
-end
-
-

But because instances cannot be directly created we cannot call -these directly. What can we do about it? We can use these methods -by including the module into other classes. When doing so it’s as if -the module inherits to the class.

-
-module M
-  def myupcase( str )
-    return str.upcase()
-  end
-end
-
-class C
-  include M
-end
-
-p(C.new().myupcase("content"))  # "CONTENT" is shown
-
-

Even though no method was defined in the class C we can call -the method myupcase. It was inherited from the module M. -Inclusion is functionally completely the same as inheritance. -There’s no limit on the access of methods and instance variables.

-

A superclass cannot be assigned to a module, but -other modules can be included.

-
-module M
-end
-
-module M2
-  include M
-end
-
-

In other words it’s functionally the same as appointing a superclass. -But a class cannot come above a module. Only modules are allowed -above modules.

-

The example below also contains the inheritance of methods.

-
-module OneMore
-  def method_OneMore()
-    p("OneMore")
-  end
-end
-
-module M
-  include OneMore
-
-  def method_M()
-    p("M")
-  end
-end
-
-class C
-  include M
-end
-
-C.new().method_M()         # Output "M"
-C.new().method_OneMore()   # Output "OneMore"
-
-

As with classes when we sketch inheritance it looks like Fig.7

-

-

(modinherit)
-Figure 7: multilevel inheritance

-

-

Besides, the class C also has a superclass. What might be its -relationship with the included modules. For instance we could write -as follows.

-
-# modcls.rb
-
-class Cls
-  def test()
-    return "class"
-  end
-end
-
-module Mod
-  def test()
-    return "module"
-  end
-end
-
-class C < Cls
-  include Mod
-end
-
-p(B.new().test())   # "class"? "module"?
-
-

C inherits from Cls and includes Mod. What will be shown? -"class" or "module"? In other words which one is closer? -The superclass or the module? -We can ask Ruby about Ruby:

-
-% ruby modcls.rb
-"module"
-
-

Apparently a module takes preference before the superclass.

-

Broadly speaking, in Ruby an included module inherits by going in between -the class and the superclass. As a picture it might look like Fig.8.

-

-

(modclass)
-Figure 8: The relation between modules and classes

-

-

And modules included in modules look like Fig.9

-

-

(modclass2)
-Figure 9: The relation between modules and classes(2)

-

-

(SomeClassのスーパークラス:superclass of SomeClass)

-

The Program revisited

-

Caution. Now I explain an extremely important element which is probably -hard to get used to for programmers who have only used static languages before. -You can skip the rest but please read this carefully. I’ll -explain this also in relative depth.

-

Nesting of Constants

-

First a repetition of constants. As a constant begins with a capital -letter the definition goes as follows.

-
-Const = 3
-
-

Now we reference the constant in this way.

-
-p(Const)   # Shows 3
-
-

Actually we can also write this.

-
-p(::Const)   # Shows 3 in the same way.
-
-

The :: in front shows that it’s a constant defined at the top level. -You can think of the path in a filesystem. Assume there is a file vmunix -at rootlevel. Being at / one can write vmunix to access the file. One -can also write /vmunix. It’s the same with Const and ::Const. -At top level it’s okay to write only Const or to write the full path ::Const

-

And what corresponds to a filesystem’s directories in Ruby? -That should be class and module definition statements. -However mentioning both is cumbersome, so I’ll just subsume them under -class definition. When one enters a class definition the level -for constants rises ( as if entering a directory).

-
-class SomeClass
-  Const = 3
-end
-
-p(::SomeClass::Const)   # Shows 3
-p(  SomeClass::Const)   # The same. Shows 3
-
-

SomeClass is defined at toplevel. Hence one can reference it by writing -either SomeClass or ::SomeClass. And in class is the constant -Const. It becomes ::SomeClass::Const.

-

A class inside a class is like a directory in a directory. -For instance like this:

-
-class C        # ::C
-  class C2     # ::C::C2
-    class C3   # ::C::C2::C3
-    end
-  end
-end
-
-

Is it always necessary to reference a constant inside a class by its -full name? Of course not. As with the filesystem, if one is inside the -same class definition one can skip the ::. It becomes like that:

-
-class SomeClass
-  Const = 3
-  p(Const)   # Shows 3.
-end
-
-

“What?” you might think. Why’s the code inside a class definition executed? -People who are used to only static languages will find this quite exceptional. -I was also flabbergasted the first time I saw it.

-

Let’s add that we can of course also view a constant inside a method. -The reference rules are the same -as within the class definition (outside the method).

-
-class C
-  Const = "ok"
-  def test()
-    p(Const)
-  end
-end
-
-C.new().test()   # Shows "ok"
-
-

Everything is executed

-

Looking at the big picture I want to write one more thing. -In Ruby almost the whole program is executed. -Constant definitions, class definitions and method definitions -and the rest is executed in the apparent order.

-

Look for instance at the following code. -I used various constructions which haven’t been used before.

-
- 1:  p("first")
- 2:
- 3:  class C < Object
- 4:    Const = "in C"
- 5:
- 6:    p(Const)
- 7:
- 8:    def myupcase(str)
- 9:       return str.upcase()
-10:    end
-11:  end
-12:
-13:  p(C.new().myupcase("content"))
-
-

This program is executed in the following order:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: p("first")Shows "first"
3: < ObjectThe constant Object is referenced and the class object Object is gained
3: class CA new class object with superclass Object is generated, and assigned to the constant C
4: Const = "in C"Assigning the value "in C" to the constant ::C::Const
6: p(Const)Showing the constant ::C::Const hence "in C"
8: def myupcase(...)...endDefine C#myupcase
13: C.new().myupcase(...)Refer the constant C, call the method new on it, and then myupcase on the return value
9: return str.upcase()Returns "CONTENT"
13: p(...)Shows "CONTENT"
-

The Scope of Local Variables

-

At last we can talk about the scope of local variables.

-

The toplevel, the interior of a class definition, the interior of a module definition and a method body are all -scopes for independent local variables. In other words in the following program all variables -lvar are different. There’s no connection between them.

-
-lvar = 'toplevel'
-
-class C
-  lvar = 'in C'
-  def method()
-    lvar = 'in C#method'
-  end
-end
-
-p(lvar)   # Shows "toplevel"
-
-module M
-  lvar = 'in M'
-end
-
-p(lvar)   # Shows "toplevel"
-
-

self as context

-

I said before, that oneself is self during method execution. -That’s true but only half true. It’s really so that during execution -self is always set up. So also at toplevel and also in a class definition.

-

For instance the self at the toplevel is main. It’s an instance -of the Object class, as might be expected. main is provided -to set up self for the time being. There’s no deeper meaning attached -to it.

-

Hence the toplevel’s self i.e. main is an instance of Object, -such that one can call the methods of Object there. And in Object -the module Kernel is included. In there the function type methods -like p and puts are defined (Fig.10). That’s why one can -call puts and p also at the toplevel.

-

-

(Kernel)
-Figure 10: main, Object and Kernel

-

-

(トップレベル:toplevel)

-

Thus p isn’t a function, it’s a method. It’s just -defined in Kernel and thus can be called from everywhere. Or no matter what self is, - p is a method of self and can be called. -That’s why there aren’t really functions in Ruby. There are only methods.

-

By the way, besides p and puts there are the function type -methods print, puts, printf, sprintf, gets, fork, and exec -and many more with somewhat familiar names. When you look at the choice -of names you might imagine Ruby’s character.

-

I mentioned that self is set up everywhere, so it should also -be in a class definition. There it is the class ( class object) -itself. Hence we get this.

-
-class C
-  p(self)   # C
-end
-
-

What should this be good for? -Let’s look at a much more useful example.

-
-module M
-end
-class C
-  include M
-end
-
-

This include is a method call to the class object C. -I haven’t mentioned it yet but the parentheses around arguments -can be omitted for method calls. And I omitted the parantheses -around include such that it doesn’t look like a method call, which might -have been confusing without knowing the whole story.

-

Loading Libraries

-

In Ruby the loading of libraries also happens at runtime. -Normally one writes this.

-
-require("library_name")
-
-

The impression isn’t false, require is a method. It’s not even -a reserved word. When one writes that line the loaded library will be -executed where the line is written. As there is no concept like Java packages in Ruby, -one has to use files and directories to separate the namespace.

-
-require("somelib/file1")
-require("somelib/file2")
-
-

And in the library file there are usually class and module statements. The toplevel constant scope -is independent of the file, so one can see at once classes which where defined in another file. -To partition the namespace of class names one has to explicitly nest modules as shown below.

-
-# example of the namespace partion of the net library
-module Net
-  class SMTP
-    # ...
-  end
-  class POP
-    # ...
-  end
-  class HTTP
-    # ...
-  end
-end
-
-

More about Classes

-

Constants revisited

-

Up to now we used the filesystem metaphor for -the scope of constants, but I want you to completely forget that.

-

There is more about constants. Firstly one can also see constants outside -the class.

-
-Const = "ok"
-class C
-  p(Const)   # Shows "ok"
-end
-
-

This becomes useful, when modules are used as namespaces. -Let’s explain this by looking at the net library from before.

-
-module Net
-  class SMTP
-    # Uses Net::SMTPHelper in the methods
-  end
-  class SMTPHelper   # Supports the class Net::SMTP
-  end
-end
-
-

In this case it’s convenient to just refer to SMTPHelper -from within SMTP. That’s the reason why it’s convenient to -be able to see outside a class.

-

The outer class can be referenced over several levels. -When the same name is defined on different levels, the one which will -first be found from within will be referred to.

-
-Const = "far"
-class C
-  Const = "near" # This one is closer than the one above
-  class C2
-    class C3
-      p(Const)   # "near" is shown
-    end
-  end
-end
-
-

There’s another way of searching constants. If the toplevel is reached -when going further and further outside then the own superclass is -searched for the constant.

-
-class A
-  Const = "ok"
-end
-class B < A
-  p(Const)   # "ok" is shown
-end
-
-

Really, that’s pretty complicated.

-

Let’s summarize. When looking up a constant, first the outer class is -searched then the superclass. This is quite contrived, -but let’s assume a class hierarchy as follows.

-
-class A1
-end
-class A2 < A1
-end
-class A3 < A2
-  class B1
-  end
-  class B2 < B1
-  end
-  class B3 < B2
-    class C1
-    end
-    class C2 < C1
-    end
-    class C3 < C2
-      p(Const)
-    end
-  end
-end
-
-

When the constant Const in C3 is referenced, it’s looked -up in the order depicted in -Fig.11.

-

-

(constref)
-Figure 11: Search order for constants

-

-

Be careful about one point. The superclasses of the classes outside, -for instance A1 and B2, aren’t searched at all. -If it’s outside once it’s always outside and if it’s superclass once -it’s always superclass. If it weren’t so the number of classes would -become to big and the behavior would become unpredictable.

-

Metaclasses

-

We said, that one can call methods on objects. -We also said that the methods which we can call -are determined by the object’s class. Then shouldn’t there be -a class for class objects? (Fig.12)

-

-

(classclass)
-Figure 12: A class of classes?

-

-

For this we can check Ruby. -The method which returns the class of oneself is Object#class

-
-p("string".class())   # String is shown
-p(String.class())     # Class is shown
-p(Object.class())     # Class is shown
-
-

String belongs to the class Class. Then what’s the class of Class?

-
-p(Class.class())      # Class is shown
-
-

Again Class. In other words if one applies to any class -.class().class().class() long enough one reaches Class. -There the loop will stall. (Fig.13)

-

-

(ccc)
-Figure 13: The class of the class of the class…

-

-

Class is the class of classes. And whenever there is a -recursive structure from the form X of Xs we call it a meta-X. -Hence Class is a metaclass.

-

Metaobjects

-

Let’s change the subject and talk about modules. -As modules are also objects, there also should be a class for them. -Let’s see.

-
-module M
-end
-p(M.class())   # Module is shown
-
-

The class of a module seems to be Module. And what should be -the class of the class Module?

-
-p(Module.class())   # Class
-
-

It’s again Class

-

Now we change the direction and examine the inheritance relationships. -What’s the superclass of Class and Module? -We can find it out with Ruby’s Class#superclass.

-
-p(Class.superclass())    # Module
-p(Module.superclass())   # Object
-p(Object.superclass())   # nil
-
-

So Class is a subclass of Module. -A diagram of the important Ruby classes is in Fig.14.

-

-

(metaobjects)
-Figure 14: The class relationship between the important Ruby classes

-

-

Up to now we used new and include without an explanation of -their true form. new is really a method defined for the class Class. -That’s why new can be used in any class because it’s an instance -of Class. But new isn’t defined in Module. Hence it’s not -possible to create instances in a module. And include is defined -in the Module class. It can be called on modules and classes.

-

These three classes Object, Module and class are the centerpiece -of Ruby’s object world, they describe it. They are objects -describing objects. So Object, Module and Class are Ruby’s -metaobjects.

-

Singleton Methods

-

Methods can be called on objects. We said that the callable methods -are determined by the object’s class. But we also said that ideally, methods should -belong to the object. Classes are a means to -eliminate the effort of defining the same method more than once.

-

In Ruby there’s also a means to define methods for individual objects. -One writes this.

-
-obj = Object.new()
-def obj.my_first()
-  puts("My first singleton method")
-end
-obj.my_first()   # Shows My first singleton method
-
-

As you already know Object is the root for every class. -One sholdn’t add a weird method like my_first to such an important -class. And obj is an instance of Object. However the method my_first -can be called from obj. Hence we have created without doubt -a method which has nothing to do with the class the object belongs to. -These methods which are defined for each object individually are -called singleton methods.

-

When are singleton methods used? They are used in place of Java or C++ static -methods. In other words methods which can be used -without creating an instance. These methods are expressed in Ruby -as singleton methods of a class object.

-

For example in UNIX there’s a system call unlink. This command -deletes a file entry from the filesystem. In Ruby it can be used -directly as the singleton method unlink from the File class. -Let’s try it out.

-
-File.unlink("core")  # deletes the coredump
-
-

It’s cumbersome to say “the singleton method unlink -of the object File”. We simply write File.unlink. Don’t mix -it up and write File#unlink, or vice versa don’t write File.write -for the method write defined in File.

-

▼ A summary of the method notation

- - - - - - - - - - - - - - - - -
notationcalled on objectexample
File.unlinkthe Fileclass itselfFile.unlink("core")
File#writean instance of Filef.write("str")
-

Class Variables

-

Class variables were added to Ruby from 1.6 on, they are a relatively new mechanism. -They can be referenced and assigned from both the class and its instances. -Let’s look at an example. The beginning of the name is @@.

-
-class C
-  @@cvar = "ok"
-  p(@@cvar)      # "ok" is shown
-
-  def print_cvar()
-    p(@@cvar)
-  end
-end
-
-C.new().print_cvar()  # "ok" is shown
-
-

As the first assignment serves as the definition, a reference -before an assignment leads to an error. This is shown below. -There is an ´@´ in front but the behavior differs completely -from instance variables.

-
-% ruby -e '
-class C
-  @@cvar
-end
-'
--e:3: uninitialized class variable @@cvar in C (NameError)
-
-

Here I was a bit lazy and used the -e option. The program -is the three lines between the single quotes.

-

Class variables are inherited. Or saying it differently, -a variable in a superior class can be assigned and referenced in the -inferior class.

-
-class A
-  @@cvar = "ok"
-end
-
-class B < A
-  p(@@cvar)            # Shows "ok"
-  def print_cvar()
-    p(@@cvar)
-  end
-end
-
-B.new().print_cvar()   # Shows "ok"
-
-

Global Variables

-

At last there are also global variables. They can be referenced from -everywhere and assigned everywhere. The first letter of the name is a $.

-
-$gvar = "global variable"
-p($gvar)   # Shows "global variable"
-
-

As with instance variables all kinds of names are considered defined -for global variables. -In other words a reference before an assignment gives a nil and -doesn’t raise an error.

-
-

Copyright © 2002-2004 Minero Aoki, All rights reserved.

-

English Translation: Sebastian Krause <skra@pantolog.de>

- - - -
- - diff --git a/htmls/module.html b/htmls/module.html deleted file mode 100644 index 942d2b8..0000000 --- a/htmls/module.html +++ /dev/null @@ -1,1560 +0,0 @@ - - - - - Chapter 14: Context | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 14: Context

-

The range covered by this chapter is really broad. First of all, I’ll describe -about how the internal state of the evaluator is expressed. After that, as -an actual example, we’ll read how the state is changed on a class definition -statement. Subsequently, we’ll examine how the internal state influences method -definition statements. Lastly, we’ll observe how the both statements change the -behaviors of the variable definitions and the variable references.

-

The Ruby stack

-

Context and Stack

-

With an image of a typical procedural language, each time calling a procedure, -the information which is necessary to execute the procedure such as the local -variable space and the place to return is stored in a struct (a stack frame) -and it is pushed on the stack. -When returning from a procedure, the struct which is on the top of the stack -is popped and the state is returned to the previous method. -The executing image of a C program which was explained at Chapter 5: Garbage collection -is a perfect example.

-

What to be careful about here is, what is changing during the execution is only -the stack, on the contrary, the program remains unchanged wherever it is. -For example, if it is "a reference to the local variable i ", there’s just an -order of “give me i of the current frame”, it is not written as “give me i -of that frame”. In other words, “only” the state of the stack influences the -consequence. This is why, -even if a procedure is called anytime and any number of times, -we only have to write its code once (Fig. 1).

-

-

(stack)
-Fig.1: What is changing is only the stack

-

-

The execution of Ruby is also basically nothing but chained calls of methods -which are procedures, so essentially it has the same image as above. -In other words, with the same code, things being accessed such as local -variable scope and the block local scope will be changing. -And these kind of scopes are expressed by stacks.

-

However in Ruby, for instance, you can temporarily go back to the scope -previously used by using iterators or Proc . -This cannot be implemented with just simply pushing/popping a stack. -Therefore the frames of the Ruby stack will be intricately rearranged during -execution. Although I call it “stack”, it could be better to consider it -as a list.

-

Other than the method call, the local variable scope can also be changed on the -class definitions. So, the method calls does not match the transitions of the -local variable scope. Since there are also blocks, it’s necessary to handle them -separately. For these various reasons, surprisingly, there are seven stacks.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Stack Pointer Stack Frame Type Description
ruby_frame struct FRAME the records of method calls
ruby_scope struct SCOPE the local variable scope
ruby_block struct BLOCK the block scope
ruby_iter struct iter whether or not the current FRAME is an iterator
ruby_class VALUE the class to define methods on
ruby_cref NODE ( NODE_CREF ) the class nesting information
-

C has only one stack and Ruby has seven stacks, by simple arithmetic, the -executing image of Ruby is at least seven times more complicated than C. -But it is actually not seven times at all, -it’s at least twenty times more complicated.

-

First, I’ll briefly describe about these stacks and their stack frame structs. -The defined file is either eval.c or evn.h . Basically these stack frames -are touched only by eval.c … is what it should be if it were possible, -but gc.c needs to know the struct types when marking, -so some of them are exposed in env.h .

-

Of course, marking could be done in the other file but gc.c , but it requires -separated functions which cause slowing down. The ordinary programs had better -not care about such things, but both the garbage collector and the core of the -evaluator is the ruby’s biggest bottleneck, so it’s quite worth to optimize -even for just one method call.

-

ruby_frame

-

ruby_frame is a stack to record method calls. The stack frame struct is -struct FRAME. This terminology is a bit confusing but please be aware that -I’ll distinctively write it just a frame when it means a “stack frame” as a -general noun and FRAME when it means struct FRAME.

-

ruby_frame

- -
-  16  extern struct FRAME {
-  17      VALUE self;          /* self */
-  18      int argc;            /* the argument count */
-  19      VALUE *argv;         /* the array of argument values */
-  20      ID last_func;        /* the name of this FRAME (when called) */
-  21      ID orig_func;        /* the name of this FRAME (when defined) */
-  22      VALUE last_class;    /* the class of last_func's receiver */
-  23      VALUE cbase;         /* the base point for searching constants and class variables */
-  24      struct FRAME *prev;
-  25      struct FRAME *tmp;   /* to protect from GC. this will be described later */
-  26      struct RNode *node;  /* the file name and the line number of the currently executed line. */
-  27      int iter;            /* is this called with a block? */
-  28      int flags;           /* the below two */
-  29  } *ruby_frame;
-
-  33  #define FRAME_ALLOCA 0   /* FRAME is allocated on the machine stack */
-  34  #define FRAME_MALLOC 1   /* FRAME is allocated by malloc */
-
-(env.h)
-
-

First af all, since there’s the prev member, you can infer that the stack is -made of a linked list. (Fig.2)

-

-

(framestack)
-Fig.2: ruby_frame

-

-

The fact that ruby_xxxx points to the top stack frame is common to all stacks -and won’t be mentioned every time.

-

The first member of the struct is self . -There is also self in the arguments of rb_eval() , -but why this struct remembers another self ? -This is for the C-level functions. More precisely, it’s for rb_call_super() that is -corresponding to super . In order to execute super , it requires the receiver -of the current method, but the caller side of rb_call_super() could not have -such information. However, the chain of rb_eval() is interrupted before the -time when the execution of the user-defined C code starts. Therefore, the -conclusion is that there need a way to obtain the information of self out of -nothing. And, FRAME is the right place to store it.

-

Thinking a little further, It’s mysterious that there are argc and argv . -Because parameter variables are local variables after all, it is unnecessary to -preserve the given arguments after assigning them into the local variable with -the same names at the beginning of the method, isn’t it? -Then, what is the use of them ? The answer is that this is actually for -super again. In Ruby, when calling super without any arguments, the values of -the parameter variables of the method will be passed to the method of the -superclass. -Thus, (the local variable space for) the parameter variables must be reserved.

-

Additionally, the difference between last_func and orig_func will be come -out in the cases like when the method is alias ed. -For instance,

-
-class C
-  def orig() end
-  alias ali orig
-end
-C.new.ali
-
-

in this case, last_func=ali and orig_func=orig . -Not surprisingly, these members also have to do with super .

-

ruby_scope

-

ruby_scope is the stack to represent the local variable scope. The method and -class definition statements, the module definition statements and the singleton -class definition statements, all of them are different scopes. The stack frame -struct is struct SCOPE. -I’ll call this frame SCOPE .

-

ruby_scope

- -
-  36  extern struct SCOPE {
-  37      struct RBasic super;
-  38      ID *local_tbl;        /* an array of the local variable names */
-  39      VALUE *local_vars;    /* the space to store local variables */
-  40      int flags;            /* the below four */
-  41  } *ruby_scope;
-
-  43  #define SCOPE_ALLOCA  0         /* local_vars is allocated by alloca */
-  44  #define SCOPE_MALLOC  1         /* local_vars is allocated by malloc */
-  45  #define SCOPE_NOSTACK 2         /* POP_SCOPE is done  */
-  46  #define SCOPE_DONT_RECYCLE 4    /* Proc is created with this SCOPE */
-
-(env.h)
-
-

Since the first element is struct RBasic, this is a Ruby object. This is in -order to handle Proc objects. For example, let’s try to think about the case -like this:

-
-def make_counter
-  lvar = 0
-  return Proc.new { lvar += 1 }
-end
-
-cnt = make_counter()
-p cnt.call    # 1
-p cnt.call    # 2
-p cnt.call    # 3
-cnt = nil  # cut the reference. The created Proc finally becomes unnecessary here.
-
-

The Proc object created by this method will persist longer than the method that -creates it. And, because the Proc can refer to the local variable lvar , -the local variables must be preserved until the Proc will disappear. -Thus, if it were not handled by the garbage collector, no one can determine the -time to free.

-

There are two reasons why struct SCOPE is separated from struct FRAME. -Firstly, the things like class definition statements are not method -calls but create distinct local variable scopes. -Secondly, when a called method is defined in C the Ruby’s local -variable space is unnecessary.

-

ruby_block

-

struct BLOCK is the real body of a Ruby’s iterator block or a Proc object, -it is also kind of a snapshot of the evaluator at some point. -This frame will also be briefly written as BLOCK as in the same manner as -FRAME and SCOPE .

-

ruby_block

- -
- 580  static struct BLOCK *ruby_block;
-
- 559  struct BLOCK {
- 560      NODE *var;               /* the block parameters(mlhs) */
- 561      NODE *body;              /* the code of the block body */
- 562      VALUE self;              /* the self when this BLOCK is created */
- 563      struct FRAME frame;      /* the copy of ruby_frame when this BLOCK is created */
- 564      struct SCOPE *scope;     /* the ruby_scope when this BLOCK is created */
- 565      struct BLOCKTAG *tag;    /* the identity of this BLOCK */
- 566      VALUE klass;             /* the ruby_class when this BLOCK is created */
- 567      int iter;                /* the ruby_iter when this BLOCK is created */
- 568      int vmode;               /* the scope_vmode when this BLOCK is created */
- 569      int flags;               /* BLOCK_D_SCOPE, BLOCK_DYNAMIC */
- 570      struct RVarmap *dyna_vars;   /* the block local variable space */
- 571      VALUE orig_thread;       /* the thread that creates this BLOCK */
- 572      VALUE wrapper;           /* the ruby_wrapper when this BLOCK is created */
- 573      struct BLOCK *prev;
- 574  };
-
- 553  struct BLOCKTAG {
- 554      struct RBasic super;
- 555      long dst;                /* destination, that is, the place to return */
- 556      long flags;              /* BLOCK_DYNAMIC, BLOCK_ORPHAN */
- 557  };
-
- 576  #define BLOCK_D_SCOPE 1      /* having distinct block local scope */
- 577  #define BLOCK_DYNAMIC 2      /* BLOCK was taken from a Ruby program */
- 578  #define BLOCK_ORPHAN  4      /* the FRAME that creates this BLOCK has finished */
-
-
-(eval.c)
-
-

Note that frame is not a pointer. This is because the entire content of -struct FRAME will be all copied and preserved. The entire struct FRAME is -(for better performance) allocated on the machine stack, but BLOCK could -persist longer than the FRAME that creates it, the preservation is a -preparation for that case.

-

Additionally, struct BLOCKTAG is separated in order to detect the same block -when multiple Proc objects are created from the block. The Proc objects -which were created from the one same block have the same BLOCKTAG .

-

ruby_iter

-

The stack ruby_iter indicates whether currently calling method is an iterator -(whether it is called with a block). The frame is struct iter. -But for consistency I’ll call it ITER .

-

ruby_iter

- -
- 767  static struct iter *ruby_iter;
-
- 763  struct iter {
- 764      int iter;           /* the below three */
- 765      struct iter *prev;
- 766  };
-
- 769  #define ITER_NOT 0      /* the currently evaluated method is not an iterator */
- 770  #define ITER_PRE 1      /* the method which is going to be evaluated next is an iterator */
- 771  #define ITER_CUR 2      /* the currently evaluated method is an iterator */
-(eval.c)
-
-

Although for each method we can determine whether it is an iterator or not, -there’s another struct that is distinct from struct FRAME. Why?

-

It’s obvious you need to inform it to the method when “it is an iterator”, -but you also need to inform the fact when “it is not an iterator”. -However, pushing a whole BLOCK just for this is very heavy. It will also -cause that in the caller side the procedures such as variable references -would needlessly increase. -Thus, it’s better to push the smaller and lighter ITER instead of BLOCK . -This will be discussed in detail in Chapter 16: Blocks.

-

ruby_dyna_vars

-

The block local variable space. The frame struct is struct RVarmap that has -already seen in Part 2. Form now on, I’ll call it just VARS .

-

struct RVarmap

- -
-  52  struct RVarmap {
-  53      struct RBasic super;
-  54      ID id;                  /* the name  of the variable */
-  55      VALUE val;              /* the value of the variable */
-  56      struct RVarmap *next;
-  57  };
-
-(env.h)
-
-

Note that a frame is not a single struct RVarmap but a list of the structs (Fig.3). -And each frame is corresponding to a local variable scope. -Since it corresponds to “local variable scope” and not “block local variable scope”, -for instance, even if blocks are nested, only a single list is used to express. -The break between blocks are similar to the one of the parser, -it is expressed by a RVarmap (header) whose id is 0 . -Details are deferred again. It will be explained in Chapter 16: Blocks.

-

-

(vars)
-Fig.3: ruby_dyna_vars

-

-

ruby_class

-

ruby_class represents the current class to which a method is defined. Since -self will be that class when it’s a normal class definition statement, -ruby_class == self. But, when it is the top level or in the middle of -particular methods like eval and instance_eval , self != ruby_class is -possible.

-

The frame of ruby_class is a simple VALUE and there’s no particular frame -struct. Then, how could it be like a stack? Moreover, there were many structs -without the prev pointer, how could these form a stack? The answer is deferred -to the next section.

-

From now on, I’ll call this frame CLASS .

-

ruby_cref

-

ruby_cref represents the information of the nesting of a class. -I’ll call this frame CREF with the same way of naming as before. -Its struct is …

-

ruby_cref

- -
- 847  static NODE *ruby_cref = 0;
-
-(eval.c)
-
-

… surprisingly NODE . This is used just as a "defined struct which can be -pointed by a VALUE ". The node type is NODE_CREF and the assignments of its -members are shown below:

- - - - - - - - - - - - - - - - - - - - - -
Union Member Macro To Access Usage
u1.value nd_clss the outer class ( VALUE )
u2
u3.node nd_next preserve the previous CREF
-

Even though the member name is nd_next , the value it actually has is the -“previous (prev)” CREF . Taking the following program as an example, I’ll -explain the actual appearance.

-
-class A
-  class B
-    class C
-      nil   # (A)
-    end
-  end
-end
-
-

Fig.4 shows how ruby_cref is when evaluating the code (A).

-

-

(crefstack)
-Fig.4: ruby_cref

-

-

However, illustrating this image everytime is tedious and its intention becomes unclear. -Therefore, the same state as Fig.4 will be expressed in the following notation:

-
-A ← B ← C
-
-

PUSH / POP Macros

-

For each stack frame struct, the macros to push and pop are available. -For instance, PUSH_FRAME and POP_FRAME for FRAME . -Because these will appear in a moment, -I’ll then explain the usage and content.

-

The other states

-

While they are not so important as the main stacks, the evaluator of ruby has -the several other states. This is a brief list of them. However, some of them -are not stacks. Actually, most of them are not.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Variable Name Type Meaning
scope_vmode int the default visibility when a method is defined
ruby_in_eval int whether or not parsing after the evaluation is started
ruby_current_node NODE* the file name and the line number of what currently being evaluated
ruby_safe_level int $SAFE
ruby_errinfo VALUE the exception currently being handled
ruby_wrapper VALUE the wrapper module to isolate the environment
-

Module Definition

-

The class statement and the module statement and the singleton class -definition statement, they are all implemented in similar ways.

-

Because seeing similar things continuously three times is not interesting, this time let’s -examine the module statement which has the least elements (thus, is simple).

-

First of all, what is the module statement? Conversely, what should happen is -the module statement ? Let’s try to list up several features:

-
    -
  • a new module object should be created
  • -
  • the created module should be self
  • -
  • it should have an independent local variable scope
  • -
  • if you write a constant assignment, a constant should be defined on the module
  • -
  • if you write a class variable assignment, - a class variable should be defined on the module.
  • -
  • if you write a def statement, a method should be defined on the module
  • -
-

What is the way to archive these things? … is the point of this section. -Now, let’s start to look at the codes.

-

Investigation

-

▼The Source Program

- -
-module M
-  a = 1
-end
-
-

▼Its Syntax Tree

- -
-NODE_MODULE
-nd_cname = 9621 (M)
-nd_body:
-    NODE_SCOPE
-    nd_rval = (null)
-    nd_tbl = 3 [ _ ~ a ]
-    nd_next:
-        NODE_LASGN
-        nd_cnt = 2
-        nd_value:
-            NODE_LIT
-            nd_lit = 1:Fixnum
-
-

nd_cname seems the module name. cname is probably either Const NAME or Class -NAME. I dumped several things and found that there’s always NODE_SCOPE in -nd_body . Since its member nd_tbl holds a local variable table and its name -is similar to struct SCOPE, it appears certain that this NODE_SCOPE -plays an important role to create a local variable scope.

-

NODE_MODULE

-

Let’s examine the handler of NODE_MODULE of rb_eval() . The parts that are -not close to the main line, such as ruby_raise() and error handling were cut -drastically. So far, there have been a lot of cutting works for 200 pages, -it has already became unnecessary to show the original code.

-

rb_eval()NODE_MODULE (simplified)

- -
-case NODE_MODULE:
-  {
-      VALUE module;
-
-      if (rb_const_defined_at(ruby_class, node->nd_cname)) {
-          /* just obtain the already created module */
-          module = rb_const_get(ruby_class, node->nd_cname);
-      }
-      else {
-          /* create a new module and set it into the constant */
-          module = rb_define_module_id(node->nd_cname);
-          rb_const_set(ruby_cbase, node->nd_cname, module);
-          rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
-      }
-
-      result = module_setup(module, node->nd_body);
-  }
-  break;
-
-

First, we’d like to make sure the module is nested and defined above (the module holded by) ruby_class . -We can understand it from the fact that it calls ruby_const_xxxx() on ruby_class . -Just once ruby_cbase appears, but it is usually identical to ruby_class , -so we can ignore it. Even if they are different, it rarely causes a problem.

-

The first half, it is branching by if because it needs to check if the -module has already been defined. This is because, in Ruby, -we can do “additional” definitions on the same one module any number of times.

-
-module M
-  def a    # M#a is deifned
-  end
-end
-module M   # add a definition (not re-defining or overwriting)
-  def b    # M#b is defined
-  end
-end
-
-

In this program, the two methods, a and b , will be defined on the module M .

-

In this case, on the second definition of M the module M was already set to -the constant, just obtaining and using it would be sufficient. If the constant -M does not exist yet, it means the first definition and the module is created -(by rb_define_module_id() )

-

Lastly, module_setup() is the function executing the body of a module -statement. Not only the module statements but the class statements and the -singleton class statements are executed by module_setup() . -This is the reason why I said “all of these three type of statements are -similar things”. -For now, I’d like you to note that node->nd_body ( NODE_SCOPE ) is passed as -an argument.

-

module_setup

-

For the module and class and singleton class statements, module_setup() -executes their bodies. Finally, the Ruby stack manipulations will appear in -large amounts.

-

module_setup()

- -
-3424  static VALUE
-3425  module_setup(module, n)
-3426      VALUE module;
-3427      NODE *n;
-3428  {
-3429      NODE * volatile node = n;
-3430      int state;
-3431      struct FRAME frame;
-3432      VALUE result;               /* OK */
-3433      TMP_PROTECT;
-3434
-3435      frame = *ruby_frame;
-3436      frame.tmp = ruby_frame;
-3437      ruby_frame = &frame;
-3438
-3439      PUSH_CLASS();
-3440      ruby_class = module;
-3441      PUSH_SCOPE();
-3442      PUSH_VARS();
-3443
-          /* (A)ruby_scope->local_vars initialization */
-3444      if (node->nd_tbl) {
-3445          VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
-3446          *vars++ = (VALUE)node;
-3447          ruby_scope->local_vars = vars;
-3448          rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
-3449          ruby_scope->local_tbl = node->nd_tbl;
-3450      }
-3451      else {
-3452          ruby_scope->local_vars = 0;
-3453          ruby_scope->local_tbl  = 0;
-3454      }
-3455
-3456      PUSH_CREF(module);
-3457      ruby_frame->cbase = (VALUE)ruby_cref;
-3458      PUSH_TAG(PROT_NONE);
-3459      if ((state = EXEC_TAG()) == 0) {
-3460          if (trace_func) {
-3461              call_trace_func("class", ruby_current_node, ruby_class,
-3462                              ruby_frame->last_func,
-3463                              ruby_frame->last_class);
-3464          }
-3465          result = rb_eval(ruby_class, node->nd_next);
-3466      }
-3467      POP_TAG();
-3468      POP_CREF();
-3469      POP_VARS();
-3470      POP_SCOPE();
-3471      POP_CLASS();
-3472
-3473      ruby_frame = frame.tmp;
-3474      if (trace_func) {
-3475          call_trace_func("end", ruby_last_node, 0,
-3476                          ruby_frame->last_func, ruby_frame->last_class);
-3477      }
-3478      if (state) JUMP_TAG(state);
-3479
-3480      return result;
-3481  }
-
-(eval.c)
-
-

This is too big to read all in one gulp. -Let’s cut the parts that seems unnecessary.

-

First, the parts around trace_func can be deleted unconditionally.

-

We can see the idioms related to tags. Let’s simplify them by expressing with -the Ruby’s ensure.

-

Immediately after the start of the function, the argument n is purposefully -assigned to the local variable node , but volatile is attached to node and -it would never be assigned after that, thus this is to prevent from being -garbage collected. If we assume that the argument was node from the beginning, -it would not change the meaning.

-

In the first half of the function, there’s the part manipulating ruby_frame -complicatedly. It is obviously paired up with the part ruby_frame = frame.tmp -in the last half. We’ll focus on this part later, but for the time being this -can be considered as push pop of ruby_frame .

-

Plus, it seems that the code (A) can be, as commented, summarized as the -initialization of ruby_scope->local_vars . This will be discussed later.

-

Consequently, it could be summarized as follows:

-

module_setup (simplified)

- -
-static VALUE
-module_setup(module, node)
-    VALUE module;
-    NODE *node;
-{
-    struct FRAME frame;
-    VALUE result;
-
-    push FRAME
-    PUSH_CLASS();
-    ruby_class = module;
-    PUSH_SCOPE();
-    PUSH_VARS();
-    ruby_scope->local_vars initializaion
-    PUSH_CREF(module);
-    ruby_frame->cbase = (VALUE)ruby_cref;
-    begin
-        result = rb_eval(ruby_class, node->nd_next);
-    ensure
-        POP_TAG();
-        POP_CREF();
-        POP_VARS();
-        POP_SCOPE();
-        POP_CLASS();
-        pop FRAME
-    end
-    return result;
-}
-
-

It does rb_eval() with node->nd_next , -so it’s certain that this is the code of the module body. -The problems are about the others. There are 5 points to see.

-
    -
  • Things occur on PUSH_SCOPE() PUSH_VARS()
  • -
  • How the local variable space is allocated
  • -
  • The effect of PUSH_CLASS
  • -
  • The relationship between ruby_cref and ruby_frame->cbase
  • -
  • What is done by manipulating ruby_frame
  • -
-

Let’s investigate them in order.

-

Creating a local variable scope

-

PUSH_SCOPE pushes a local variable space and PUSH_VARS() pushes a block -local variable space, thus a new local variable scope is created by these two. -Let’s examine the contents of these macros and what is done.

-

PUSH_SCOPE() POP_SCOPE()

- -
- 852  #define PUSH_SCOPE() do {               \
- 853      volatile int _vmode = scope_vmode;  \
- 854      struct SCOPE * volatile _old;       \
- 855      NEWOBJ(_scope, struct SCOPE);       \
- 856      OBJSETUP(_scope, 0, T_SCOPE);       \
- 857      _scope->local_tbl = 0;              \
- 858      _scope->local_vars = 0;             \
- 859      _scope->flags = 0;                  \
- 860      _old = ruby_scope;                  \
- 861      ruby_scope = _scope;                \
- 862      scope_vmode = SCOPE_PUBLIC
-
- 869  #define POP_SCOPE()                                      \
- 870      if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {        \
- 871         if (_old) scope_dup(_old);                        \
- 872      }                                                    \
- 873      if (!(ruby_scope->flags & SCOPE_MALLOC)) {           \
- 874          ruby_scope->local_vars = 0;                      \
- 875          ruby_scope->local_tbl  = 0;                      \
- 876          if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \
- 877              ruby_scope != top_scope) {                   \
- 878              rb_gc_force_recycle((VALUE)ruby_scope);      \
- 879          }                                                \
- 880      }                                                    \
- 881      ruby_scope->flags |= SCOPE_NOSTACK;                  \
- 882      ruby_scope = _old;                                   \
- 883      scope_vmode = _vmode;                                \
- 884  } while (0)
-
-(eval.c)
-
-

As the same as tags, SCOPE s also create a stack by being synchronized with the -machine stack. What differentiate slightly is that the spaces of the stack -frames are allocated in the heap, the machine stack is used in order to create -the stack structure (Fig.5.).

-

-

(scopestack)
-Fig.5. The machine stack and the SCOPE Stack

-

-

Additionally, the flags like SCOPE_ something repeatedly appearing in the -macros are not able to be explained until I finish to talk all about -in what form each stack frame is remembered and about blocks. -Thus, these will be discussed in Chapter 16: Blocks all at once.

-

Allocating the local variable space

-

As I mentioned many times, the local variable scope is represented by struct SCOPE. -But struct SCOPE is literally a “scope” and it does not have the real body -to store local variables. To put it more precisely, it has the pointer to a -space but there’s still no array at the place where the one points to. The -following part of module_setup prepares the array.

-

▼The preparation of the local variable slots

- -
-3444  if (node->nd_tbl) {
-3445      VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
-3446      *vars++ = (VALUE)node;
-3447      ruby_scope->local_vars = vars;
-3448      rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
-3449      ruby_scope->local_tbl = node->nd_tbl;
-3450  }
-3451  else {
-3452      ruby_scope->local_vars = 0;
-3453      ruby_scope->local_tbl  = 0;
-3454  }
-
-(eval.c)
-
-

The TMP_ALLOC() at the beginning will be described in the next section. If I -put it shortly, it is “alloca that is assured to allocate on the stack -(therefore, we do not need to worry about GC)”.

-

node->nd_tbl holds in fact the local variable name table that has appeared -in Chapter 12: Syntax tree construction. It means that nd_tbl[0] contains the table size and the rest is -an array of ID . This table is directly preserved to local_tbl of SCOPE -and local_vars is allocated to store the local variable values. -Because they are confusing, it’s a good thing writing some comments such as -“This is the variable name”, “this is the value”. -The one with tbl is for the names.

-

-

(localvars)
-Fig.6. ruby_scope->local_vars

-

-

Where is this node used? -I examined the all local_vars members but could not find the access to index --1 in eval.c . Expanding the range of files to investigate, I found the -access in gc.c .

-

rb_gc_mark_children()T_SCOPE

- -
- 815  case T_SCOPE:
- 816    if (obj->as.scope.local_vars &&
-            (obj->as.scope.flags & SCOPE_MALLOC)) {
- 817        int n = obj->as.scope.local_tbl[0]+1;
- 818        VALUE *vars = &obj->as.scope.local_vars[-1];
- 819
- 820        while (n--) {
- 821            rb_gc_mark(*vars);
- 822            vars++;
- 823        }
- 824    }
- 825    break;
-
-(gc.c)
-
-

Apparently, this is a mechanism to protect node from GC. -But why is it necessary to to mark it here? -node is purposefully store into the volatile local variable, so -it would not be garbage-collected during the execution of module_setup() .

-

Honestly speaking, I was thinking it might merely be a mistake for a while but -it turned out it’s actually very important. The issue is this at the next -line of the next line:

-

ruby_scope->local_tbl

- -
-3449  ruby_scope->local_tbl = node->nd_tbl;
-
-(eval.c)
-
-

The local variable name table prepared by the parser is directly used. When is -this table freed? It’s the time when the node become not to be referred from -anywhere. Then, when should node be freed? It’s the time after the SCOPE -assigned on this line will disappear completely. Then, when is that?

-

SCOPE sometimes persists longer than the statement that causes the creation -of it. As it will be discussed at Chapter 16: Blocks, -if a Proc object is created, it refers SCOPE . -Thus, If module_setup() has finished, the SCOPE created there is not -necessarily be what is no longer used. That’s why it’s not sufficient that -node is only referred from (the stack frame of) module_setup() . -It must be referred “directly” from SCOPE .

-

On the other hand, the volatile node of the local variable cannot be removed. -Without it, node is floating on air until it will be assigned to local_vars .

-

However then, local_vars of SCOPE is not safe, isn’t it? -TMP_ALLOC() is, as I mentioned, the allocation on the stack, it becomes -invalid at the time module_setup() ends. This is in fact, at the moment when -Proc is created, the allocation method is abruptly switched to malloc() . -Details will be described in Chapter 16: Blocks.

-

Lastly, rb_mem_clear() seems zero-filling but actually it is Qnil -filling to -an array of VALUE ( array.c ). By this, all defined local variables are -initialized as nil .

-

TMP_ALLOC

-

Next, let’s read TMP_ALLOC that allocates the local variable space. -This macro is actually paired with TMP_PROTECT existing silently at the -beginning of module_setup() . Its typical usage is this:

-
-VALUE *ptr;
-TMP_PROTECT;
-
-ptr = TMP_ALLOC(size);
-
-

The reason why TMP_PROTECT is in the place for the local variable definitions -is that … Let’s see its definition.

-

TMP_ALLOC()

- -
-1769  #ifdef C_ALLOCA
-1770  # define TMP_PROTECT NODE * volatile tmp__protect_tmp=0
-1771  # define TMP_ALLOC(n) \
-1772      (tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA,                 \
-1773                               ALLOC_N(VALUE,n), tmp__protect_tmp, n), \
-1774       (void*)tmp__protect_tmp->nd_head)
-1775  #else
-1776  # define TMP_PROTECT typedef int foobazzz
-1777  # define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
-1778  #endif
-
-(eval.c)
-
-

… it is because it defines a local variable.

-

As described in Chapter 5: Garbage collection, in the environment of #ifdef C_ALLOCA (that is, -the native alloca() does not exist) malloca() is used to emulate alloca() . -However, the arguments of a method are obviously VALUE s and -the GC could not find a VALUE if it is stored in the heap. -Therefore, it is enforced that GC can find it through NODE .

-

-

(tmpprotecttmp)
-Fig.7. anchor the space to the stack through NODE

-

-

On the contrary, in the environment with the true alloca() , we can naturally -use alloca() and there’s no need to use TMP_PROTECT . Thus, a harmless -statement is arbitrarily written.

-

By the way, why do they want to use alloca() very much by all means. -It’s merely because " alloca() is faster than malloc() ", they said. -One can think that it’s not so worth to care about such tiny difference, -but because the core of the evaluator is the biggest bottleneck of ruby , -… the same as above.

-

Changing the place to define methods on.

-

The value of the stack ruby_class is the place to define a method on at the -time. Conversely, if one push a value to ruby_class , it changes the class to -define a method on. This is exactly what is necessary for a class statement. -Therefore, It’s also necessary to do PUSH_CLASS() in module_setup() . -Here is the code for it:

-
-PUSH_CLASS();
-ruby_class = module;
-     :
-     :
-POP_CLASS();
-
-

Why is there the assignment to ruby_class after doing PUSH_CLASS() . -We can understand it unexpectedly easily by looking at the definition.

-

PUSH_CLASS() POP_CLASS()

- -
- 841  #define PUSH_CLASS() do { \
- 842      VALUE _class = ruby_class
-
- 844  #define POP_CLASS() ruby_class = _class; \
- 845  } while (0)
-
-(eval.c)
-
-

Because ruby_class is not modified even though PUSH_CLASS is done, -it is not actually pushed until setting by hand. -Thus, these two are closer to “save and restore” rather than “push and pop”.

-

You might think that it can be a cleaner macro if passing a class as the -argument of PUSH_CLASS() … It’s absolutely true, but because there are some -places we cannot obtain the class before pushing, it is in this way.

-

Nesting Classes

-

ruby_cref represents the class nesting information at runtime. Therefore, it’s -naturally predicted that ruby_cref will be pushed on the module statements or -on the class statements. -In module_setup() , it is pushed as follows:

-
-PUSH_CREF(module);
-ruby_frame->cbase = (VALUE)ruby_cref;
-   :
-   :
-POP_CREF();
-
-

Here, module is the module being defined. -Let’s also see the definitions of PUSH_CREF() and POP_CREF() .

-

PUSH_CREF() POP_CREF()

- -
- 849  #define PUSH_CREF(c) \
-          ruby_cref = rb_node_newnode(NODE_CREF,(c),0,ruby_cref)
- 850  #define POP_CREF() ruby_cref = ruby_cref->nd_next
-
-(eval.c)
-
-

Unlike PUSH_SCOPE or something, there are not any complicated techniques and -it’s very easy to deal with. -It’s also not good if there’s completely not any such thing.

-

The problem remains unsolved is what is the meaning of ruby_frame->cbase . -It is the information to refer a class variable or a constant from the current FRAME . -Details will be discussed in the last section of this chapter.

-

Replacing frames

-

Lastly, let’s focus on the manipulation of ruby_frame . The first thing is its -definition:

-
-struct FRAME frame;
-
-

It is not a pointer. This means that the entire FRAME is allocated on the stack. -Both the management structure of the Ruby stack and the local variable -space are on the stack, but in the case of FRAME the entire struct is stored -on the stack. The extreme consumption of the machine stack by ruby is the -fruit of these “small techniques” piling up.

-

Then next, let’s look at where doing several things with frame .

-
-frame = *ruby_frame;      /* copy the entire struct */
-frame.tmp = ruby_frame;   /* protect the original FRAME from GC */
-ruby_frame = &frame;      /* replace ruby_frame */
-       :
-       :
-ruby_frame = frame.tmp;   /* restore */
-
-

That is, ruby_frame seems temporarily replaced (not pushing). -Why is it doing such thing?

-

I described that FRAME is “pushed on method calls”, but to be more precise, -it is the stack frame to represent “the main environment to execute a Ruby program”. -You can infer it from, for instance, ruby_frame->cbase which appeared previously. -last_func which is “the last called method name” also suggests it.

-

Then, why is FRAME not straightforwardly pushed? -It is because this is the place where it is not allowed to push FRAME . -FRAME is wanted to be pushed, but if FRAME is pushed, -it will appear in the backtraces of the program when an exception occurs. -The backtraces are things displayed like followings:

-
-% ruby t.rb
-t.rb:11:in `c': some error occured (ArgumentError)
-        from t.rb:7:in `b'
-        from t.rb:3:in `a'
-        from t.rb:14
-
-

But the module statements and the class statements are not method calls, -so it is not desirable to appear in this. That’s why it is “replaced” instead -of “pushed”.

-

The method definition

-

As the next topic of the module definitions, let’s look at the method definitions.

-

Investigation

-

▼The Source Program

- -
-def m(a, b, c)
-  nil
-end
-
-

▼Its Syntax Tree

- -
-NODE_DEFN
-nd_mid  = 9617 (m)
-nd_noex = 2 (NOEX_PRIVATE)
-nd_defn:
-    NODE_SCOPE
-    nd_rval = (null)
-    nd_tbl = 5 [ _ ~ a b c ]
-    nd_next:
-        NODE_ARGS
-        nd_cnt  = 3
-        nd_rest = -1
-        nd_opt = (null)
-        NODE_NIL
-
-

I dumped several things and found that there’s always NODE_SCOPE in nd_defn . -NODE_SCOPE is, as we’ve seen at the module statements, -the node to store the information to push a local variable scope.

-

NODE_DEFN

-

Subsequently, we will examine the corresponding code of rb_eval() . This part -contains a lot of error handlings and tedious, they are all omitted again. -The way of omitting is as usual, deleting the every parts to directly or -indirectly call rb_raise() rb_warn() rb_warning().

-

rb_eval()NODE_DEFN (simplified)

- -
-NODE *defn;
-int noex;
-
-if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
-    noex = NOEX_PRIVATE;                 (A)
-}
-else if (SCOPE_TEST(SCOPE_PROTECTED)) {
-    noex = NOEX_PROTECTED;               (B)
-}
-else if (ruby_class == rb_cObject) {
-    noex =  node->nd_noex;               (C)
-}
-else {
-    noex = NOEX_PUBLIC;                  (D)
-}
-
-defn = copy_node_scope(node->nd_defn, ruby_cref);
-rb_add_method(ruby_class, node->nd_mid, defn, noex);
-result = Qnil;
-
-

In the first half, there are the words like private or protected , so it is -probably related to visibility. noex , which is used as the names of flags, -seems NOde EXposure. Let’s examine the if statements in order.

-

(A) SCOPE_TEST() is a macro to check if there’s an argument flag in -scope_vmode . Therefore, the first half of this conditional statement means -“is it a private scope?”. -The last half means "it’s private if this is defining initialize ". -The method initialize to initialize an object will unquestionably become private .

-

(B) It is protected if the scope is protected (not surprisingly). -My feeling is that there’re few cases protected is required in Ruby.

-

© This is a bug. I found this just before the submission of this book, -so I couldn’t fix this beforehand. -In the latest code this part is probably already removed. -The original intention is to enforce the methods defined at top level to be private .

-

(D) If it is not any of the above conditions, it is public .

-

Actually, there’s not a thing to worth to care about until here. The important -part is the next two lines.

-
-defn = copy_node_scope(node->nd_defn, ruby_cref);
-rb_add_method(ruby_class, node->nd_mid, defn, noex);
-
-

copy_node_scope() is a function to copy (only) NODE_SCOPE attached to the -top of the method body. It is important that ruby_cref is passed … -but details will be described soon.

-

After copying, the definition is finished by adding it by rb_add_method() . -The place to define on is of course ruby_class .

-

copy_node_scope()

-

copy_node_scope() is called only from the two places: the method definition -( NODE_DEFN ) and the singleton method definition ( NODE_DEFS ) in rb_eval() . -Therefore, looking at these two is sufficient to detect how it is used. Plus, -the usages at these two places are almost the same.

-

copy_node_scope()

- -
-1752  static NODE*
-1753  copy_node_scope(node, rval)
-1754      NODE *node;
-1755      VALUE rval;
-1756  {
-1757      NODE *copy = rb_node_newnode(NODE_SCOPE,0,rval,node->nd_next);
-1758
-1759      if (node->nd_tbl) {
-1760          copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1);
-1761          MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1);
-1762      }
-1763      else {
-1764          copy->nd_tbl = 0;
-1765      }
-1766      return copy;
-1767  }
-
-(eval.c)
-
-

I mentioned that the argument rval is the information of the class nesting -( ruby_cref ) of when the method is defined. Apparently, it is rval because it -will be set to nd_rval .

-

In the main if statement copies nd_tbl of NODE_SCOPE . -It is a local variable name table in other words. The +1 at ALLOC_N is to -additionally allocate the space for nd_tbl[0] . As we’ve seen in Part 2, -nd_tbl[0] holds the local variables count, that was “the actual length of -nd_tbl – 1”.

-

To summarize, copy_node_scope() makes a copy of the NODE_SCOPE which is the -header of the method body. However, nd_rval is additionally set and it is the -ruby_cref (the class nesting information) of when the class is defined. This -information will be used later when referring constants or class variables.

-

rb_add_method()

-

The next thing is rb_add_method() that is the function to register a method entry.

-

rb_add_method()

- -
- 237  void
- 238  rb_add_method(klass, mid, node, noex)
- 239      VALUE klass;
- 240      ID mid;
- 241      NODE *node;
- 242      int noex;
- 243  {
- 244      NODE *body;
- 245
- 246      if (NIL_P(klass)) klass = rb_cObject;
- 247      if (ruby_safe_level >= 4 &&
-              (klass == rb_cObject || !OBJ_TAINTED(klass))) {
- 248          rb_raise(rb_eSecurityError, "Insecure: can't define method");
- 249      }
- 250      if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
- 251      rb_clear_cache_by_id(mid);
- 252      body = NEW_METHOD(node, noex);
- 253      st_insert(RCLASS(klass)->m_tbl, mid, body);
- 254  }
-
-(eval.c)
-
-

NEW_METHOD() is a macro to create NODE . -rb_clear_cache_by_id() is a function to manipulate the method cache. -This will be explained in the next chapter “Method”.

-

Let’s look at the syntax tree which is eventually stored in m_tbl of a class. -I prepared nodedump-method for this kind of purposes. -(nodedump-method : comes with nodedump . nodedump is tools/nodedump.tar.gz of the attached CD-ROM)

-
-% ruby -e '
-class C
-  def m(a)
-    puts "ok"
-  end
-end
-require "nodedump-method"
-NodeDump.dump C, :m        # dump the method m of the class C
-'
-NODE_METHOD
-nd_noex = 0 (NOEX_PUBLIC)
-nd_cnt = 0
-nd_body:
-    NODE_SCOPE
-    nd_rval = Object <- C
-    nd_tbl = 3 [ _ ~ a ]
-    nd_next:
-        NODE_ARGS
-        nd_cnt  = 1
-        nd_rest = -1
-        nd_opt = (null)
-        U牙S頏著
-
-
-** unhandled**
-
-
-
-

There are NODE_METHOD at the top -and NODE_SCOPE previously copied by copy_node_scope() at the next. -These probably represent the header of a method. -I dumped several things and there’s not any NODE_SCOPE with the methods defined in C, -thus it seems to indicate that the method is defined at Ruby level.

-

Additionally, at nd_tbl of NODE_SCOPE the parameter variable name ( a ) appears. -I mentioned that the parameter variables are equivalent to the local variables, -and this briefly implies it.

-

I’ll omit the explanation about NODE_ARGS here -because it will be described at the next chapter “Method”.

-

Lastly, the nd_cnt of the NODE_METHOD , it’s not so necessary to care about -this time. It is used when having to do with alias .

-

Assignment and Reference

-

Come to think of it, most of the stacks are used to realize a variety of -variables. We have learned to push various stacks, this time let’s examine the -code to reference variables.

-

Local variable

-

The all necessary information to assign or refer local variables has appeared, -so you are probably able to predict. -There are the following two points:

-
    -
  • local variable scope is an array which is pointed by ruby_scope->local_vars
  • -
  • the correspondence between each local variable name and each array index has - already resolved at the parser level.
  • -
-

Therefore, the code for the local variable reference node NODE_LVAR is as -follows:

-

rb_eval()NODE_LVAR

- -
-2975  case NODE_LVAR:
-2976    if (ruby_scope->local_vars == 0) {
-2977        rb_bug("unexpected local variable");
-2978    }
-2979    result = ruby_scope->local_vars[node->nd_cnt];
-2980    break;
-
-(eval.c)
-
-

It goes without saying but node->nd_cnt is the value that local_cnt() of the -parser returns.

-

Constant

-

Complete Specification

-

In Chapter 6: Variables and constants, -I talked about in what form constants are stored and API. -Constants are belong to classes and inherited as the same as methods. -As for their actual appearances, they are registered to iv_tbl of -struct RClass with instance variables and class variables.

-

The searching path of a constant is firstly the outer class, secondly the -superclass, however, rb_const_get() only searches the superclass. Why? -To answer this question, I need to reveal the last specification of constants. -Take a look at the following code:

-
-class A
-  C = 5
-  def A.new
-    puts C
-    super
-  end
-end
-
-

A.new is a singleton method of A , so its class is the singleton class (A) . -If it is interpreted by following the rule, -it cannot obtain the constant C which is belongs to A .

-

But because it is written so close, to become to want refer the constant C -is human nature. Therefore, such reference is possible in Ruby. -It can be said that this specification reflects the characteristic of Ruby -“The emphasis is on the appearance of the source code”.

-

If I generalize this rule, when referring a constant from inside of a method, -by setting the place which the method definition is “written” as the start -point, it refers the constant of the outer class. -And, “the class of where the method is written” depends on its context, -thus it could not be handled without the information from both the parser and -the evaluator. This is why rb_cost_get() did not have the searching path of -the outer class.

-

cbase

-

Then, let’s look at the code to refer constants including the outer class. -The ordinary constant references to which :: is not attached, become -NODE_CONST in the syntax tree. The corresponding code in rb_eval() is …

-

rb_eval()NODE_CONST

- -
-2994  case NODE_CONST:
-2995    result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid, self);
-2996    break;
-
-(eval.c)
-
-

First, nd_vid appears to be Variable ID and it probably means a constant name. -And, ruby_frame->cbase is “the class where the method definition is written”. -The value will be set when invoking the method, thus the code to set has not appeared yet. -And the place where the value to be set comes from is the nd_rval -that has appeared in copy_node_scope() of the method definition. -I’d like you to go back a little and check that the member holds the -ruby_cref of when the method is defined.

-

This means, first, the ruby_cref link is built when defining a class or a module. -Assume that the just defined class is C (Fig.81),

-

Defining the method m (this is probably C#m ) here, -then the current ruby_cref is memorized by the method entry (Fig.82).

-

After that, when the class statement finished the ruby_cref would start to -point another node, but node->nd_rval naturally continues to point to the -same thing. (Fig.83)

-

Then, when invoking the method C#m , get node->nd_rval -and insert into the just pushed ruby_frame->cbase . (Fig.84)

-

… This is the mechanism. Complicated.

-

-

(cbase)
-Fig 8. CREF Trasfer

-

-

ev_const_get()

-

Now, let’s go back to the code of NODE_CONST . -Since only ev_const_get() is left, we’ll look at it.

-

ev_const_get()

- -
-1550  static VALUE
-1551  ev_const_get(cref, id, self)
-1552      NODE *cref;
-1553      ID id;
-1554      VALUE self;
-1555  {
-1556      NODE *cbase = cref;
-1557      VALUE result;
-1558
-1559      while (cbase && cbase->nd_next) {
-1560          VALUE klass = cbase->nd_clss;
-1561
-1562          if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
-1563          if (RCLASS(klass)->iv_tbl &&
-                  st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
-1564              return result;
-1565          }
-1566          cbase = cbase->nd_next;
-1567      }
-1568      return rb_const_get(cref->nd_clss, id);
-1569  }
-
-(eval.c)
-
-

(( According to the errata, the description of ev_const_get() was wrong. - I omit this part for now. ))

-

Class variable

-

What class variables refer to is also ruby_cref . Needless to say, -unlike the constants which search over the outer classes one after another, -it uses only the first element. -Let’s look at the code of NODE_CVAR which is the node to refer to a class -variable.

-

What is the cvar_cbase() ? As cbase is attached, -it is probably related to ruby_frame->cbase , but how do they differ? -Let’s look at it.

-

cvar_cbase()

- -
-1571  static VALUE
-1572  cvar_cbase()
-1573  {
-1574      NODE *cref = RNODE(ruby_frame->cbase);
-1575
-1576      while (cref && cref->nd_next &&
-                 FL_TEST(cref->nd_clss, FL_SINGLETON)) {
-1577          cref = cref->nd_next;
-1578          if (!cref->nd_next) {
-1579    rb_warn("class variable access from toplevel singleton method");
-1580          }
-1581      }
-1582      return cref->nd_clss;
-1583  }
-
-(eval.c)
-
-

It traverses cbase up to the class that is not the singleton class, it -seems. This feature is added to counter the following kind of code:

-
-class C                           class C
-  @@cvar = 1                        @@cvar = 1
-  class << C                        def C.m
-    def m                             @@cvar
-      @@cvar                        end
-    end                             def C.m2
-    def m2                            @@cvar + @@cvar
-      @@cvar + @@cvar               end
-    end                           end
-  end
-end
-
-

Both the left and right code ends up defining the same method, -but if you write in the way of the right side it is tedious to write the class -name repeatedly as the number of methods increases. Therefore, when defining -multiple singleton methods, many people choose to write in the left side way -of using the singleton class definition statement to bundle.

-

However, these two differs in the value of ruby_cref . The one using the -singleton class definition is ruby_cref=(C) and the other one defining -singleton methods separately is ruby_cref=C . This may cause to differ in the -places where class variables refer to, so this is not convenient.

-

Therefore, assuming it’s rare case to define class variables on singleton -classes, it skips over singleton classes. This reflects again that the emphasis -is more on the usability rather than the consistency.

-

And, when the case is a constant reference, -since it searches all of the outer classes, -C is included in the search path in either way, so there’s no problem. -Plus, as for an assignment, since it couldn’t be written inside methods in the -first place, it is also not related.

-

Multiple Assignment

-

If someone asked “where is the most complicated specification of Ruby?”, I -would instantly answer that it is multiple assignment. -It is even impossible to understand the big picture of multiple assignment, I -have an account of why I think so. In short, the specification of the multiple -assignment is defined without even a subtle intention to construct so that the -whole specification is well-organized. The basis of the specification is always -“the behavior which seems convenient in several typical use cases”. This can be -said about the entire Ruby, but particularly about the multiple assignment.

-

Then, how could we avoid being lost in the jungle of codes. This is similar to -reading the stateful scanner and it is not seeing the whole picture. There’s -no whole picture in the first place, we could not see it. Cutting the code into -blocks like, this code is written for this specification, that code is written -for that specification, … understanding the -correspondences one by one in such manner is the only way.

-

But this book is to understand the overall structure of ruby and is not -“Advanced Ruby Programming”. Thus, dealing with very tiny things is not fruitful. -So here, we only think about the basic structure of multiple assignment -and the very simple “multiple-to-multiple” case.

-

First, following the standard, let’s start with the syntax tree.

-

▼The Source Program

- -
-a, b = 7, 8
-
-

▼Its Syntax Tree

- -
-NODE_MASGN
-nd_head:
-    NODE_ARRAY [
-    0:
-        NODE_LASGN
-        nd_cnt = 2
-        nd_value:
-    1:
-        NODE_LASGN
-        nd_cnt = 3
-        nd_value:
-    ]
-nd_value:
-    NODE_REXPAND
-    nd_head:
-        NODE_ARRAY [
-        0:
-            NODE_LIT
-            nd_lit = 7:Fixnum
-        1:
-            NODE_LIT
-            nd_lit = 8:Fixnum
-        ]
-
-

Both the left-hand and right-hand sides are the lists of NODE_ARRAY , -there’s additionally NODE_REXPAND in the right side. REXPAND may be “Right -value EXPAND”. We are curious about what this node is doing. Let’s see.

-

rb_eval()NODE_REXPAND

- -
-2575  case NODE_REXPAND:
-2576    result = avalue_to_svalue(rb_eval(self, node->nd_head));
-2577    break;
-
-(eval.c)
-
-

You can ignore avalue_to_svalue() . -NODE_ARRAY is evaluated by rb_eval() , (because it is the node of the array -literal), it is turned into a Ruby array and returned back. -So, before the left-hand side is handled, all in the right-hand side are -evaluated. This enables even the following code:

-
-a, b = b, a    # swap variables in oneline
-
-

Let’s look at NODE_MASGN in the left-hand side.

-

rb_eval()NODE_MASGN

- -
-2923  case NODE_MASGN:
-2924    result = massign(self, node, rb_eval(self, node->nd_value),0);
-2925    break;
-
-(eval.c)
-
-

Here is only the evaluation of the right-hand side, the rests are delegated to -massign() .

-

massign()

-

massi ……

- -
-3917  static VALUE
-3918  massign(self, node, val, pcall)
-3919      VALUE self;
-3920      NODE *node;
-3921      VALUE val;
-3922      int pcall;
-3923  {
-
-(eval.c)
-
-

I’m sorry this is halfway, but I’d like you to stop and pay attention to the -4th argument. pcall is Proc CALL, this indicates whether or not the -function is used to call Proc object. Between Proc calls and the others -there’s a little difference in the strictness of the check of the multiple -assignments, so a flag is received to check. -Obviously, the value is decided to be either 0 or 1.

-

Then, I’d like you to look at the previous code calling massign() , it was -pcall=0 . Therefore, we probably don’t mind if assuming it is pcall=0 for the -time being and extracting the variables. That is, when there’s an argument like -pcall which is slightly changing the behavior, we always need to consider the -two patterns of scenarios, so it is really cumbersome. If there’s only one -actual function massign() , to think as if there were two functions, pcall=0 -and pcall=1 , is way simpler to read.

-

When writing a program we must avoid duplications as much as possible, -but this principle is unrelated if it is when reading. -If patterns are limited, -copying it and letting it to be redundant is rather the right approach. -There are wordings “optimize for speed” “optimize for the code size”, -in this case we’ll “optimize for readability”.

-

So, assuming it is pcall=0 and cutting the codes as much as possible and the -final appearance is shown as follows:

-

massign() (simplified)

- -
-static VALUE
-massign(self, node, val  /* , pcall=0 */)
-    VALUE self;
-    NODE *node;
-    VALUE val;
-{
-    NODE *list;
-    long i = 0, len;
-
-    val = svalue_to_mvalue(val);
-    len = RARRAY(val)->len;
-    list = node->nd_head;
-    /* (A) */
-    for (i=0; list && i<len; i++) {
-        assign(self, list->nd_head, RARRAY(val)->ptr[i], pcall);
-        list = list->nd_next;
-    }
-    /* (B) */
-    if (node->nd_args) {
-        if (node->nd_args == (NODE*)-1) {
-            /* no check for mere `*' */
-        }
-        else if (!list && i<len) {
-            assign(self, node->nd_args,
-                   rb_ary_new4(len-i, RARRAY(val)->ptr+i), pcall);
-        }
-        else {
-            assign(self, node->nd_args, rb_ary_new2(0), pcall);
-        }
-    }
-
-    /* (C) */
-    while (list) {
-        i++;
-        assign(self, list->nd_head, Qnil, pcall);
-        list = list->nd_next;
-    }
-    return val;
-}
-
-

val is the right-hand side value. And there’s the suspicious conversion called -svalue_to_mvalue() , since mvalue_to_svalue() appeared previously and -svalue_to_mvalue() in this time, so you can infer “it must be getting back”. -((errata: it was avalue_to_svalue() in the previous case. -Therefore, it’s hard to infer “getting back”, but you can ignore them anyway.)) -Thus, the both are deleted. In the next line, since it uses RARRAY() , -you can infer that the right-hand side value is an Array of Ruby. -Meanwhile, the left-hand side is node->nd_head , so it is the value assigned to -the local variable list . This list is also a node ( NODE_ARRAY ).

-

We’ll look at the code by clause.

-

(A) assign is, as the name suggests, a function to perform an one-to-one -assignment. Since the left-hand side is expressed by a node, -if it is, for instance, NODE_IASGN (an assignment to an instance variable), -it assigns with rb_ivar_set() . -So, what it is doing here is adjusting to either list and val which is -shorter and doing one-to-one assignments. (Fig.9)

-

-

(massign)
-Fig.9. assign when corresponded

-

-

(B) if there are remainders on the right-hand side, turn them into a Ruby -array and assign it into (the left-hand side expressed by) the node->nd_args .

-

© if there are remainders on the left-hand side, assign nil to all of them.

-

By the way, the procedure which is assuming pcall=0 then cutting out is very -similar to the data flow analytics / constant foldings used on the optimization -phase of compilers. -Therefore, we can probably automate it to some extent.

- - - -
- - diff --git a/htmls/name.html b/htmls/name.html deleted file mode 100644 index d6e5a38..0000000 --- a/htmls/name.html +++ /dev/null @@ -1,591 +0,0 @@ - - - - - Names and Name Table | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Clifford Escobar CAOILE

-

Chapter 3: Names and Name Table

-

st_table

-

st_table has already appeared several times as a method table and an instance -table. In this chapter let’s look at the structure of the st_table in detail.

-

Summary

-

I previously mentioned that the st_table is a hash table. What is a hash -table? It is a data structure that records one-to-one relations, for example, a -variable name and its value, or a function name and its body, etc.

-

However, data structures other than hash tables can, of course, record -one-to-one relations. For example, a list of the following structs will suffice -for this purpose.

-
-struct entry {
-    ID key;
-    VALUE val;
-    struct entry *next;  /* point to the next entry */
-};
-
-

However, this method is slow. If the list contains a thousand items, in the -worst case, it is necessary to traverse a thousand links. In other words, the -search time increases in proportion to the number of elements. This is bad. -Since ancient times, various speed improvement methods have been conceived. The -hash table is one of those improved methods. In other words, the point is not -that the hash table is necessary but that it can be made faster.

-

Now then, let us examine the st_table. As it turns out, this library is not -created by Matsumoto, rather:

-

st.c credits

-
-   1  /* This is a public domain general purpose hash table package
-         written by Peter Moore @ UCB. */
-
-(st.c)
-
-

as shown above.

-

By the way, when I searched Google and found another version, it mentioned -that st_table is a contraction of “STring TABLE”. However, I find it -contradictory that it has both “general purpose” and “string” aspects.

-

What is a hash table?

-

A hash table can be thought as the following: Let us think of an array with -n items. For example, let us make n=64 (figure 1).

-

-

(array)
-Figure 1: Array

-

-

Then let us specify a function f that takes a key and produces an integer i -from 0 to n-1 (0-63). We call this f a hash function. f when given the -same key always produces the same i. For example, if we can assume that the -key is limited to positive integers, when the key is divided by 64, the -remainder should always fall between 0 and 63. Therefore, this calculating -expression has a possibility of being the function f.

-

When recording relationships, given a key, function f generates i, and -places the value into index i of the array we have prepared. Index access -into an array is very fast. The key concern is changing a key into an integer.

-

-

(aset)
-Figure 2: Array assignment

-

-

However, in the real world it isn’t that easy. There is a critical problem with -this idea. Because n is only 64, if there are more than 64 relationships to -be recorded, it is certain that there will be the same index for two different -keys. It is also possible that with fewer than 64, the same thing can occur. -For example, given the previous hash function “key % 64”, keys 65 and 129 will -both have a hash value of 1. This is called a hash value collision. There are -many ways to resolve such a collision.

-

One solution is to insert into the next element when a collision occurs. -This is called open addressing. (Figure 3).

-

-

(nexti)
-Figure 3: Open addressing

-

-

Other than using the array like this, there are other possible approaches, like using -a pointer to a respective linked list in each element of the array. Then when a -collision occurs, grow the linked list. This is called chaining. (Figure -4) st_table uses this chaining method.

-

-

(chain)
-Figure 4: Chaining

-

-

However, if it can be determined a priori what set of keys will be used, -it is possible to imagine a hash function that will never create -collisions. This type of function is called a “perfect hash function”. -Actually, there are tools which create a perfect hash function given a set -of arbitrary strings. GNU gperf is one of those. ruby‘s parser -implementation uses GNU gperf but… this is not the time to discuss it. -We’ll discuss this in the second part of the book.

-

Data Structure

-

Let us start looking at the source code. As written in the introductory -chapter, if there is data and code, it is better to read the data first. -The following is the data type of st_table.

-

st_table

-
-   9  typedef struct st_table st_table;
-
-  16  struct st_table {
-  17      struct st_hash_type *type;
-  18      int num_bins;                   /* slot count */
-  19      int num_entries;                /* total number of entries */
-  20      struct st_table_entry **bins;   /* slot */
-  21  };
-
-(st.h)
-
-

struct st_table_entry

-
-  16  struct st_table_entry {
-  17      unsigned int hash;
-  18      char *key;
-  19      char *record;
-  20      st_table_entry *next;
-  21  };
-
-(st.c)
-
-

st_table is the main table structure. st_table_entry is a holder that -stores one value. st_table_entry contains a member called next which of -course is used to make st_table_entry into a linked list. This is the chain - part of the chaining method. The st_hash_type data type is used, but I will - explain this later. First let me explain the other parts so you can compare -and understand the roles.

-

-

(sttable)
-Figure 5: st_table data structure

-

-

So, let us comment on st_hash_type.

-

struct st_hash_type

-
-  11  struct st_hash_type {
-  12      int (*compare)();   /* comparison function */
-  13      int (*hash)();      /* hash function */
-  14  };
-
-(st.h)
-
-

This is still Chapter 3 so let us examine it attentively.

-
-int (*compare)()
-
-

This part shows, of course, the member compare which has a data type of -“a pointer to a function that returns an int”. hash is also of the same type. -This variable is substituted in the following way:

-
-int
-great_function(int n)
-{
-    /* ToDo: Do something great! */
-    return n;
-}
-
-{
-    int (*f)();
-    f = great_function;
-
-

And it is called like this:

-
-    (*f)(7);
-}
-
-

Here let us return to the st_hash_type commentary. Of the two members -hash and compare, hash is the hash function f explained previously.

-

On the other hand, compare is a function that evaluates if the key is actually the -same or not. With the chaining method, in the spot with the same hash value -n, multiple elements can be inserted. To know exactly which element is -being searched for, this time it is necessary to use a comparison function -that we can absolutely trust. compare will be that function.

-

This st_hash_type is a good generalized technique. The hash table itself -cannot determine what the stored keys’ data type will be. For example, in -ruby, st_table’s keys are ID or char* or VALUE, but to write the -same kind of hash for each (data type) is foolish. Usually, the things -that change with the different key data types are things like the hash -function. For things like memory allocation and collision detection, -typically most of the code is the same. Only the parts where the -implementation changes with a differing data type will be bundled up into a -function, and a pointer to that function will be used. In this fashion, the -majority of the code that makes up the hash table implementation can -use it.

-

In object-oriented languages, in the first place, you can attach a procedure -to an object and pass it (around), so this mechanism is not necessary. -Perhaps it more correct to say that this mechanism is built-in as a -language’s feature.

-

st_hash_type example

-

The usage of a data structure like st_hash_type is good as an -abstraction. On the other hand, what kind of code it actually passes -through may be difficult to understand. If we do not examine what sort of -function is used for hash or compare, we will not grasp the reality. -To understand this, it is probably sufficient to look at st_init_numtable() -introduced in the previous chapter. This function creates a table for -integer data type keys.

-

st_init_numtable()

-
- 182  st_table*
- 183  st_init_numtable()
- 184  {
- 185      return st_init_table(&type_numhash);
- 186  }
-
-(st.c)
-
-

st_init_table() is the function that allocates the table memory and so -on. type_numhash is an st_hash_type (it is the member named “type” of st_table). -Regarding this type_numhash:

-

type_numhash

-
-  37  static struct st_hash_type type_numhash = {
-  38      numcmp,
-  39      numhash,
-  40  };
-
- 552  static int
- 553  numcmp(x, y)
- 554      long x, y;
- 555  {
- 556      return x != y;
- 557  }
-
- 559  static int
- 560  numhash(n)
- 561      long n;
- 562  {
- 563      return n;
- 564  }
-
-(st.c)
-
-

Very simple. The table that the ruby interpreter uses is by and large -this type_numhash.

-

st_lookup()

-

Now then, let us look at the function that uses this data structure. First, -it’s a good idea to look at the function that does the searching. Shown below is the -function that searches the hash table, st_lookup().

-

st_lookup()

-
- 247  int
- 248  st_lookup(table, key, value)
- 249      st_table *table;
- 250      register char *key;
- 251      char **value;
- 252  {
- 253      unsigned int hash_val, bin_pos;
- 254      register st_table_entry *ptr;
- 255
- 256      hash_val = do_hash(key, table);
- 257      FIND_ENTRY(table, ptr, hash_val, bin_pos);
- 258
- 259      if (ptr == 0) {
- 260          return 0;
- 261      }
- 262      else {
- 263          if (value != 0)  *value = ptr->record;
- 264          return 1;
- 265      }
- 266  }
-
-(st.c)
-
-

The important parts are pretty much in do_hash() and FIND_ENTRY(). Let us -look at them in order.

-

do_hash()

-
-  68  #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
-
-(st.c)
-
-

Just in case, let us write down the macro body that is difficult to understand:

-
-(table)->type->hash
-
-

is a function pointer where the key is passed as a parameter. This is the -syntax for calling the function. * is not applied to table. In other words, -this macro is a hash value generator for a key, using the prepared hash -function type->hash for each data type.

-

Next, let us examine FIND_ENTRY().

-

FIND_ENTRY()

-
- 235  #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
- 236      bin_pos = hash_val%(table)->num_bins;\
- 237      ptr = (table)->bins[bin_pos];\
- 238      if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
- 239          COLLISION;\
- 240          while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
- 241              ptr = ptr->next;\
- 242          }\
- 243          ptr = ptr->next;\
- 244      }\
- 245  } while (0)
-
- 227  #define PTR_NOT_EQUAL(table, ptr, hash_val, key) ((ptr) != 0 && \
-          (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
-
-  66  #define EQUAL(table,x,y) \
-          ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
-
-(st.c)
-
-

COLLISION is a debug macro so we will (should) ignore it.

-

The parameters of FIND_ENTRY(), starting from the left are:

-
    -
  1. st_table
  2. -
  3. the found entry will be pointed to by this parameter
  4. -
  5. hash value
  6. -
  7. temporary variable
  8. -
-

And, the second parameter will point to the found st_table_entry*.

-

At the outermost level, a do .. while(0) is used to safely wrap up a -multiple expression macro. This is ruby‘s, or rather, C language’s preprocessor -idiom. In the case of if(1), there may be a danger of adding an else part. -In the case of while(1), it becomes necessary to add a break at the very -end.

-

Also, there is no semicolon added after the while(0).

-
-FIND_ENTRY();
-
-

This is so that the semicolon that is normally written at the end of an -expression will not go to waste.

-

st_add_direct()

-

Continuing on, let us examine st_add_direct() which is a function that adds a -new relationship to the hash table. This function does not check if the key is -already registered. It always adds a new entry. This is the meaning of direct -in the function name.

-

st_add_direct()

-
- 308  void
- 309  st_add_direct(table, key, value)
- 310      st_table *table;
- 311      char *key;
- 312      char *value;
- 313  {
- 314      unsigned int hash_val, bin_pos;
- 315
- 316      hash_val = do_hash(key, table);
- 317      bin_pos = hash_val % table->num_bins;
- 318      ADD_DIRECT(table, key, value, hash_val, bin_pos);
- 319  }
-
-(st.c)
-
-

Just as before, the do_hash() macro that obtains a value is called here. -After that, the next calculation is the same as at the start of -FIND_ENTRY(), which is to exchange the hash value for a real index.

-

Then the insertion operation seems to be implemented by ADD_DIRECT(). -Since the name is all uppercase, we can anticipate that is a macro.

-

ADD_DIRECT()

-
- 268  #define ADD_DIRECT(table, key, value, hash_val, bin_pos) \
- 269  do {                                                     \
- 270      st_table_entry *entry;                               \
- 271      if (table->num_entries / (table->num_bins)           \
-                              > ST_DEFAULT_MAX_DENSITY) {      \
- 272          rehash(table);                                   \
- 273          bin_pos = hash_val % table->num_bins;            \
- 274      }                                                    \
- 275                                                           \
-          /* (A) */                                            \
- 276      entry = alloc(st_table_entry);                       \
- 277                                                           \
- 278      entry->hash = hash_val;                              \
- 279      entry->key = key;                                    \
- 280      entry->record = value;                               \
-          /* (B) */                                            \
- 281      entry->next = table->bins[bin_pos];                  \
- 282      table->bins[bin_pos] = entry;                        \
- 283      table->num_entries++;                                \
- 284  } while (0)
-
-(st.c)
-
-

The first if is an exception case so I will explain it afterwards.

-

(A) Allocate and initialize a st_table_entry.

-

(B) Insert the entry into the start of the list. -This is the idiom for handling the list. In other words,

-
-entry->next = list_beg;
-list_beg = entry;
-
-

makes it possible to insert an entry to the front of the list. This is similar -to “cons-ing” in the Lisp language. Check for yourself that even if list_beg -is NULL, this code holds true.

-

Now, let me explain the code I left aside.

-

ADD_DIRECT()-rehash

-
- 271      if (table->num_entries / (table->num_bins)           \
-                              > ST_DEFAULT_MAX_DENSITY) {      \
- 272          rehash(table);                                   \
- 273          bin_pos = hash_val % table->num_bins;            \
- 274      }                                                    \
-
-(st.c)
-
-

DENSITY is “concentration”. In other words, this conditional checks if the -hash table is “crowded” or not. In the st_table, as the number of values that -use the same bin_pos increases, the longer the link list becomes. In other -words, search becomes slower. That is why for a given bin count, when the average elements -per bin become too many, bin is increased and the crowding is reduced.

-

The current ST_DEFAULT_MAX_DENSITY is

-

ST_DEFAULT_MAX_DENSITY

-
-  23  #define ST_DEFAULT_MAX_DENSITY 5
-
-(st.c)
-
-

Because of this setting, if in all bin_pos there are 5 st_table_entries, -then the size will be increased.

-

st_insert()

-

st_insert() is nothing more than a combination of st_add_direct() and -st_lookup(), so if you understand those two, this will be easy.

-

st_insert()

-
- 286  int
- 287  st_insert(table, key, value)
- 288      register st_table *table;
- 289      register char *key;
- 290      char *value;
- 291  {
- 292      unsigned int hash_val, bin_pos;
- 293      register st_table_entry *ptr;
- 294
- 295      hash_val = do_hash(key, table);
- 296      FIND_ENTRY(table, ptr, hash_val, bin_pos);
- 297
- 298      if (ptr == 0) {
- 299          ADD_DIRECT(table, key, value, hash_val, bin_pos);
- 300          return 0;
- 301      }
- 302      else {
- 303          ptr->record = value;
- 304          return 1;
- 305      }
- 306  }
-
-(st.c)
-
-

It checks if the element is already registered in the table. Only when it is -not registered will it be added. If there is a insertion, return 0. If there is -no insertion, return a 1.

-

ID and Symbols

-

I’ve already discussed what an ID is. It is a correspondence between an -arbitrary string of characters and a value. It is used to declare various -names. The actual data type is unsigned int.

-

From char* to ID

-

The conversion from string to ID is executed by rb_intern(). This function -is rather long, so let’s omit the middle.

-

rb_intern() (simplified)

-
-5451  static st_table *sym_tbl;       /*  char* to ID   */
-5452  static st_table *sym_rev_tbl;   /*  ID to char*   */
-
-5469  ID
-5470  rb_intern(name)
-5471      const char *name;
-5472  {
-5473      const char *m = name;
-5474      ID id;
-5475      int last;
-5476
-          /* If for a name, there is a corresponding ID that is already
-          registered, then return that ID */
-5477      if (st_lookup(sym_tbl, name, &id))
-5478          return id;
-
-          /* omitted ... create a new ID */
-
-          /* register the name and ID relation */
-5538    id_regist:
-5539      name = strdup(name);
-5540      st_add_direct(sym_tbl, name, id);
-5541      st_add_direct(sym_rev_tbl, id, name);
-5542      return id;
-5543  }
-
-(parse.y)
-
-

The string and ID correspondence relationship can be accomplished by using the -st_table. There probably isn’t any especially difficult part here.

-

What is the omitted section doing? It is treating global variable names and -instance variables names as special and flagging them. This is because in the -parser, it is necessary to know the variable’s classification from the ID. -However, the fundamental part of ID is unrelated to this, so I won’t explain -it here.

-

From ID to char*

-

The reverse of rb_intern() is rb_id2name(), which takes an ID and -generates a char*. You probably know this, but the 2 in id2name is “to”. -“To” and “two” have the same pronounciation, so “2” is used for “to”. This -syntax is often seen.

-

This function also sets the ID classification flags so it is long. Let me -simplify it.

-

rb_id2name() (simplified)

-
-char *
-rb_id2name(id)
-    ID id;
-{
-    char *name;
-
-    if (st_lookup(sym_rev_tbl, id, &name))
-        return name;
-    return 0;
-}
-
-

Maybe it seems that it is a little over-simplified, but in reality if we remove -the details it really becomes this simple.

-

The point I want to emphasize is that the found name is not copied. The -ruby API does not require (or rather, it forbids) the free()-ing of the -return value. Also, when parameters are passed, it always -copies them. In other words, the creation and release is -completed by one side, either by the user or by ruby.

-

So then, when creation and release cannot be accomplished (when passed it is -not returned) on a value, then a Ruby object is used. I have not yet discussed -it, but a Ruby object is automatically released when it is no longer needed, -even if we are not taking care of the object.

-

Converting VALUE and ID

-

ID is shown as an instance of the Symbol class at the Ruby level. -And it can be obtained like so: "string".intern. The implementation of -String#intern is rb_str_intern().

-

rb_str_intern()

-
-2996  static VALUE
-2997  rb_str_intern(str)
-2998      VALUE str;
-2999  {
-3000      ID id;
-3001
-3002      if (!RSTRING(str)->ptr || RSTRING(str)->len == 0) {
-3003          rb_raise(rb_eArgError, "interning empty string");
-3004      }
-3005      if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len)
-3006          rb_raise(rb_eArgError, "string contains `\\0'");
-3007      id = rb_intern(RSTRING(str)->ptr);
-3008      return ID2SYM(id);
-3009  }
-
-(string.c)
-
-

This function is quite reasonable as a ruby class library code example. -Please pay attention to the part where RSTRING() is used and casted, and -where the data structure’s member is accessed.

-

Let’s read the code. First, rb_raise() is merely error handling so we ignore -it for now. The rb_intern() we previously examined is here, and also ID2SYM -is here. ID2SYM() is a macro that converts ID to Symbol.

-

And the reverse operation is accomplished using Symbol#to_s and such. -The implementation is in sym_to_s.

-

sym_to_s()

-
- 522  static VALUE
- 523  sym_to_s(sym)
- 524      VALUE sym;
- 525  {
- 526      return rb_str_new2(rb_id2name(SYM2ID(sym)));
- 527  }
-
-(object.c)
-
-

SYM2ID() is the macro that converts Symbol (VALUE) to an ID.

-

It looks like the function is not doing anything unreasonable. However, it -is probably necessary to pay attention to the area around the memory handling. -rb_id2name() returns a char* that must not be free(). rb_str_new2() -copies the parameter’s char* and uses the copy (and does not change the -parameter). In this way the policy is consistent, which allows the line to be -written just by chaining the functions.

- - - -
- - diff --git a/htmls/object.html b/htmls/object.html deleted file mode 100644 index 4d62593..0000000 --- a/htmls/object.html +++ /dev/null @@ -1,1011 +0,0 @@ - - - - - Objects - Structure of Ruby objects | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Vincent ISAMBART

-

Chapter 2: Objects

-

Structure of Ruby objects

-

Guideline

-

In this chapter we will begin exploring the ruby source code, starting by -studying the declaration of object structures.

-

What do objects need to exist? There are many answers to this question, but for -our purposes an object only needs three things:

-
    -
  1. The ability to differentiate itself from other objects (an identity)
  2. -
  3. The ability to respond to messages (methods)
  4. -
  5. The ability to store internal state (instance variables)
  6. -
-

In this chapter, we are going to confirm these three features one by one.

-

The most interesting file in this quest will be ruby.h, but we will also -briefly look at other files such as object.c, class.c or variable.c.

-

Structure of VALUE and objects

-

In ruby, the contents of an object are expressed by a C structure, always -handled via a pointer. A different kind of structure is used for each class, but -the pointer type will always be VALUE (figure 1).

-

-

(value)
-Figure 1: VALUE and structure

-

-

Here is the definition of VALUE:

-

VALUE

-
-  71  typedef unsigned long VALUE;
-
-(ruby.h)
-
-

In practice, a VALUE must be cast to different types of structure pointer. -Therefore if an unsigned long and a pointer have a different size, ruby -will not work well. Strictly speaking, it will not work for pointer types -bigger than sizeof(unsigned long). Fortunately, no recent machine feature -this capability, even if some time ago there were quite a few of them.

-

Several structures are available according to object classes:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct RObject all things for which none of the following - applies
struct RClass class object
struct RFloat small numbers
struct RString string
struct RArray array
struct RRegexp regular expression
struct RHash hash table
struct RFile IO, File, Socket, etc…
struct RData all the classes defined at C level, except the - ones mentioned above
struct RStruct Ruby’s Struct class
struct RBignum big integers
-

For example, for an string object, struct RString is used, so we will have -something like the following.

-

-

(string)
-Figure 2: String object

-

-

Let’s look at the definition of a few object structures.

-

▼ Examples of object structure

-
-      /* structure for ordinary objects */
- 295  struct RObject {
- 296      struct RBasic basic;
- 297      struct st_table *iv_tbl;
- 298  };
-
-      /* structure for strings (instance of String) */
- 314  struct RString {
- 315      struct RBasic basic;
- 316      long len;
- 317      char *ptr;
- 318      union {
- 319          long capa;
- 320          VALUE shared;
- 321      } aux;
- 322  };
-
-      /* structure for arrays (instance of Array) */
- 324  struct RArray {
- 325      struct RBasic basic;
- 326      long len;
- 327      union {
- 328          long capa;
- 329          VALUE shared;
- 330      } aux;
- 331      VALUE *ptr;
- 332  };
-
-(ruby.h)
-
-

Before looking at every one of them in detail, let’s begin with something more -general.

-

First, as VALUE is defined as unsigned long, it must be cast before -being used. That’s why Rxxxx() macros have been made for each object -structure. For example, for struct RString there is RSTRING(), for -struct RArray there is RARRAY(), etc… These macros are used like this:

-
-
-VALUE str = ....;
-VALUE arr = ....;
-RSTRING(str)->len;   /* ((struct RString*)str)->len */
-RARRAY(arr)->len;    /* ((struct RArray*)arr)->len */
-
-

Another important point to mention is that all object structures start with a -member basic of type struct RBasic. As a result, if you cast this VALUE to -struct RBasic*, you will be able to access the content of basic, regardless -of the type of structure pointed to by VALUE.

-

-

(rbasic)
-Figure 3: struct RBasic

-

-

You probably guessed that struct RBasic has been designed to contain some -important information shared by all object structures. Here is the definition -for struct RBasic:

-

struct RBasic

-
- 290  struct RBasic {
- 291      unsigned long flags;
- 292      VALUE klass;
- 293  };
-
-(ruby.h)
-
-

flags are multipurpose flags, mostly used to register the structure type -(for instance struct RObject). The type flags are named T_xxxx, and can be -obtained from a VALUE using the macro TYPE(). Here is an example:

-
-VALUE str;
-str = rb_str_new();    /* creates a Ruby string (its structure is RString) */
-TYPE(str);             /* the return value is T_STRING */
-
-

The names of these T_xxxx flags are directly linked to the corresponding type -name, like T_STRING for struct RString and T_ARRAY for struct RArray.

-

The other member of struct RBasic, klass, contains the class this object -belongs to. As the klass member is of type VALUE, what is stored is (a -pointer to) a Ruby object. In short, it is a class object.

-

-

(class)
-Figure 4: object and class

-

-

The relation between an object and its class will be detailed in the “Methods” -section of this chapter.

-

By the way, this member is named klass so as not to conflict with the reserved -word class when the file is processed by a C++ compiler.

-

About structure types

-

I said that the type of structure is stored in the flags member of -struct Basic. But why do we have to store the type of structure? It’s to be -able to handle all different types of structure via VALUE. If you cast a -pointer to a structure to VALUE, as the type information does not remain, -the compiler won’t be able to help. Therefore we have to manage the type -ourselves. That’s the consequence of being able to handle all the structure -types in a unified way.

-

OK, but the used structure is defined by the class so why are the structure -type and class are stored separately? Being able to find the structure type -from the class should be enough. There are two reasons for not doing this.

-

The first one is (I’m sorry for contradicting what I said before), in fact -there are structures that do not have a struct RBasic (i.e. they have no -klass member). For example struct RNode that will appear in the second -part of the book. However, flags is guaranteed to be in the beginning -members even in special structures like this. So if you put the type of -structure in flags, all the object structures can be differentiated in one -unified way.

-

The second reason is that there is no one-to-one correspondence between class -and structure. For example, all the instances of classes defined at the Ruby -level use struct RObject, so finding a structure from a class would require -to keep the correspondence between each class and structure. That’s why it’s -easier and faster to put the information about the type in the structure.

-

The use of basic.flags

-

As limiting myself to saying that basic.flags is used for different things -including the type of structure makes me feel bad, here’s a general -illustration for it (figure 5). There is no need to understand everything -right away, I just wanted to show its uses while it was bothering me.

-

-

(flags)
-Figure 5: Use of flags

-

-

When looking at the diagram, it looks like that 21 bits are not used on 32 bit -machines. On these additional bits, the flags FL_USER0 to FL_USER8 are -defined, and are used for a different purpose for each structure. In the -diagram I also put FL_USER0 (FL_SINGLETON) as an example.

-

Objects embedded in VALUE

-

As I said, VALUE is an unsigned long. As VALUE is a pointer, it may look -like void* would also be all right, but there is a reason for not doing -this. In fact, VALUE can also not be a pointer. The 6 cases for which -VALUE is not a pointer are the following:

-
    -
  1. small integers
  2. -
  3. symbols
  4. -
  5. true
  6. -
  7. false
  8. -
  9. nil
  10. -
  11. Qundef
  12. -
-

I’ll explain them one by one.

-

Small integers

-

Just like in Ruby itself, all data are objects. Likewise, integers are objects. -However during normal program execution, lots of instances of integers are -created. Using structures to express them would risk slowing down execution. For -example, if we created 50000 objects when incrementing from 0 to 50000 we’d -definitely have to consider the performance issues.

-

That’s why in ruby, to some extent, small integers are treated specially and -embedded directly into VALUE. “Small” means signed integers that can be held -in sizeof(VALUE)*8-1 bits. In other words, on 32 bits machines, the integers -have 1 bit for the sign, and 30 bits for the integer part. Integers in this -range will belong to the Fixnum class and the other integers will belong to -the Bignum class.

-

Let’s see in practice the INT2FIX() macro that converts from a C int -to a Fixnum, and confirm that Fixnum are directly embedded in VALUE.

-

INT2FIX

-
- 123  #define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
- 122  #define FIXNUM_FLAG 0x01
-
-(ruby.h)
-
-

In brief, shift 1 bit to the left, and bitwise or it with 1.

- - - - - - - - - -
110100001000 before conversion
1101000010001 after conversion
-

That means that Fixnum as VALUE will always be an odd number. On the other -hand, as Ruby object structures are allocated with malloc(), they are -generally arranged on addresses multiple of 4. So they do not overlap with the -values of Fixnum as VALUE.

-

Also, to convert int or long to VALUE, we can use macros like -INT2NUM() or LONG2NUM(). Any conversion macro XXXX2XXXX with a name -containing NUM can manage both Fixnum and Bignum. For example if -INT2NUM() can’t convert an integer into a Fixnum, it will automatically -convert it to Bignum. NUM2INT() will convert both Fixnum and Bignum to -int. If the number can’t fit in an int, an exception will be raised, so -there is no need to check the value range.

-

Symbols

-

What are symbols?

-

As this question is quite troublesome to answer, let’s start with the reasons -why symbols were necessary. First, let’s start with the ID type used inside -ruby. It’s like this:

-

ID

-
-  72  typedef unsigned long ID;
-
-(ruby.h)
-
-

This ID is a number having a one-to-one association with a string. However, -in this world it’s not possible to have an association between all strings and -a numerical value. That’s why they are limited to the one to one relationships -inside one ruby process. I’ll speak of the method to find an ID in the -next chapter “Names and name tables”.

-

In language implementations, there are a lot of names to handle. Method names -or variable names, constant names, file names in class names… It’s -troublesome to handle all of them as strings (char*), because of memory -management and memory management and memory management… Also, lots of -comparisons would certainly be necessary, but comparing strings character by -character will slow down the execution. That’s why strings are not handled -directly, something will be associated and used instead. And generally that -“something” will be integers, as they are the simplest to handle.

-

These ID are found as symbols in the Ruby world. Up to ruby 1.4, the -values of ID were converted to Fixnum, but used as symbols. Even today -these values can be obtained using Symbol#to_i. However, as real use results -came piling up, it was understood that making Fixnum and Symbol the same -was not a good idea, so since 1.6 an independent class Symbol has been -created.

-

Symbol objects are used a lot, especially as keys for hash tables. That’s -why Symbol, like Fixnum, was made stored in VALUE. Let’s look at the -ID2SYM() macro converting ID to Symbol object.

-

ID2SYM

-
- 158  #define SYMBOL_FLAG 0x0e
- 160  #define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG))
-
-(ruby.h)
-
-

When shifting 8 bits left, x becomes a multiple of 256, that means a -multiple of 4. Then after with a bitwise or (in this case it’s the same as -adding) with 0x0e (14 in decimal), the VALUE expressing the symbol is not -a multiple of 4. Or even an odd number. So it does not overlap the range of -any other VALUE. Quite a clever trick.

-

Finally, let’s see the reverse conversion of ID2SYM(), SYM2ID().

-

SYM2ID()

-
- 161  #define SYM2ID(x) RSHIFT((long)x,8)
-
-(ruby.h)
-
-

RSHIFT is a bit shift to the right. As right shift may keep or not the sign -depending of the platform, it became a macro.

-

true false nil

-

These three are Ruby special objects. true and false represent the boolean -values. nil is an object used to denote that there is no object. Their -values at the C level are defined like this:

-

true false nil

-
- 164  #define Qfalse 0        /* Ruby's false */
- 165  #define Qtrue  2        /* Ruby's true */
- 166  #define Qnil   4        /* Ruby's nil */
-
-(ruby.h)
-
-

This time it’s even numbers, but as 0 or 2 can’t be used by pointers, they -can’t overlap with other VALUE. It’s because usually the first bloc of -virtual memory is not allocated, to make the programs dereferencing a NULL -pointer crash.

-

And as Qfalse is 0, it can also be used as false at C level. In practice, in -ruby, when a function returns a boolean value, it’s often made to return an -int or VALUE, and returns Qtrue/Qfalse.

-

For Qnil, there is a macro dedicated to check if a VALUE is Qnil or not, -NIL_P().

-

NIL_P()

-
- 170  #define NIL_P(v) ((VALUE)(v) == Qnil)
-
-(ruby.h)
-
-

The name ending with p is a notation coming from Lisp denoting that it is a -function returning a boolean value. In other words, NIL_P means “is the -argument nil?”. It seems the “p” character comes from “predicate.” This -naming rule is used at many different places in ruby.

-

Also, in Ruby, false and nil are falsy (that is, they count as false in -conditional statements) and all the other objects are truthy. -However, in C, nil (Qnil) is true. That’s why in C a Ruby-style macro, -RTEST(), has been created.

-

RTEST()

-
- 169  #define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
-
-(ruby.h)
-
-

As in Qnil only the third lower bit is 1, in ~Qnil only the third lower -bit is 0. Then only Qfalse and Qnil become 0 with a bitwise and.

-

!=0 has been added to be certain to only have 0 or 1, to satisfy the -requirements of the glib library that only wants 0 or 1 -([ruby-dev:11049]).

-

By the way, what is the ‘Q’ of Qnil? ‘R’ I would have understood but why -‘Q’? When I asked, the answer was “Because it’s like that in Emacs.” I did -not have the fun answer I was expecting…

-

Qundef

-

Qundef

-
- 167  #define Qundef 6                /* undefined value for placeholder */
-
-(ruby.h)
-
-

This value is used to express an undefined value in the interpreter. It can’t -be found at all at the Ruby level.

-

Methods

-

I already brought up the three important points of a Ruby object: having an -identity, being able to call a method, and keeping data for each instance. In -this section, I’ll explain in a simple way the structure linking objects and -methods.

-

struct RClass

-

In Ruby, classes exist as objects during the execution. Of course. So there -must be a structure for class objects. That structure is struct RClass. Its -structure type flag is T_CLASS.

-

As class and modules are very similar, there is no need to differentiate their -content. That’s why modules also use the struct RClass structure, and are -differentiated by the T_MODULE structure flag.

-

struct RClass

-
- 300  struct RClass {
- 301      struct RBasic basic;
- 302      struct st_table *iv_tbl;
- 303      struct st_table *m_tbl;
- 304      VALUE super;
- 305  };
-
-(ruby.h)
-
-

First, let’s focus on the m_tbl (Method TaBLe) member. struct st_table is -an hashtable used everywhere in ruby. Its details will be explained in the -next chapter “Names and name tables”, but basically, it is a table mapping -names to objects. In the case of m_tbl, it keeps the -correspondence between the name (ID) of the methods possessed by this class -and the methods entity itself.

-

The fourth member super keeps, like its name suggests, the superclass. As -it’s a VALUE, it’s (a pointer to) the class object of the superclass. In Ruby -there is only one class that has no superclass (the root class): Object.

-

However I already said that all Object methods are defined in the Kernel -module, Object just includes it. As modules are functionally similar to -multiple inheritance, it may seem having just super is problematic, but -in ruby some clever changes are made to make it look like single -inheritance. The details of this process will be explained in the fourth -chapter “Classes and modules”.

-

Because of this, super of the structure of Object points to struct RClass -of the Kernel object. Only the super of Kernel is NULL. So contrary to -what I said, if super is NULL, this RClass is the Kernel object (figure -6).

-

-

(classtree)
-Figure 6: Class tree at the C level

-

-

Methods search

-

With classes structured like this, you can easily imagine the method call -process. The m_tbl of the object’s class is searched, and if the method was -not found, the m_tbl of super is searched, and so on. If there is no more -super, that is to say the method was not found even in Object, then it -must not be defined.

-

The sequential search process in m_tbl is done by search_method().

-

search_method()

-
- 256  static NODE*
- 257  search_method(klass, id, origin)
- 258      VALUE klass, *origin;
- 259      ID id;
- 260  {
- 261      NODE *body;
- 262
- 263      if (!klass) return 0;
- 264      while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
- 265          klass = RCLASS(klass)->super;
- 266          if (!klass) return 0;
- 267      }
- 268
- 269      if (origin) *origin = klass;
- 270      return body;
- 271  }
-
-(eval.c)
-
-

This function searches the method named id in the class object klass.

-

RCLASS(value) is the macro doing:

-
-((struct RClass*)(value))
-
-

st_lookup() is a function that searches in st_table the value -corresponding to a key. If the value is found, the function returns true and -puts the found value at the address given in third parameter (&body).

-

Nevertheless, doing this search each time whatever the circumstances would be -too slow. That’s why in reality, once called, a method is cached. So starting -from the second time it will be found without following super one by one. -This cache and its search will be seen in the 15th chapter “Methods”.

-

Instance variables

-

In this section, I will explain the implementation of the third essential -condition, instance variables.

-

rb_ivar_set()

-

Instance variables are what allows each object to store characteristic data. -Having it stored in the object itself (i.e. in the object structure) may seem -all right but how is it in practice? Let’s look at the function -rb_ivar_set() that puts an object in an instance variable.

-

rb_ivar_set()

-
-      /* write val in the id instance of obj */
- 984  VALUE
- 985  rb_ivar_set(obj, id, val)
- 986      VALUE obj;
- 987      ID id;
- 988      VALUE val;
- 989  {
- 990      if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
- 991          rb_raise(rb_eSecurityError,
-                       "Insecure: can't modify instance variable");
- 992      if (OBJ_FROZEN(obj)) rb_error_frozen("object");
- 993      switch (TYPE(obj)) {
- 994        case T_OBJECT:
- 995        case T_CLASS:
- 996        case T_MODULE:
- 997          if (!ROBJECT(obj)->iv_tbl)
-                  ROBJECT(obj)->iv_tbl = st_init_numtable();
- 998          st_insert(ROBJECT(obj)->iv_tbl, id, val);
- 999          break;
-1000        default:
-1001          generic_ivar_set(obj, id, val);
-1002          break;
-1003      }
-1004      return val;
-1005  }
-
-(variable.c)
-
-

rb_raise() and rb_error_frozen() are both error checks. Error checks are -necessary, but it’s not the main part of the treatment, so you should ignore -them at first read.

-

After removing error treatment, only the switch remains, but this

-
-switch (TYPE(obj)) {
-  case T_aaaa:
-  case T_bbbb:
-     ...
-}
-
-

form is characteristic of ruby. TYPE() is the macro returning the type -flag of the object structure (T_OBJECT, T_STRING, etc.). In other words as -the type flag is an integer constant, we can branch depending on it with a -switch. Fixnum or Symbol do not have structures, but inside TYPE() a -special treatment is done to properly return T_FIXNUM and T_SYMBOL, so -there’s no need to worry.

-

Well, let’s go back to rb_ivar_set(). It seems only the treatments of -T_OBJECT, T_CLASS and T_MODULE are different. These 3 have been chosen on -the basis that their second member is iv_tbl. Let’s confirm it in practice.

-

▼ Structures whose second member is iv_tbl

-
-      /* TYPE(val) == T_OBJECT */
- 295  struct RObject {
- 296      struct RBasic basic;
- 297      struct st_table *iv_tbl;
- 298  };
-
-      /* TYPE(val) == T_CLASS or T_MODULE */
- 300  struct RClass {
- 301      struct RBasic basic;
- 302      struct st_table *iv_tbl;
- 303      struct st_table *m_tbl;
- 304      VALUE super;
- 305  };
-
-(ruby.h)
-
-

iv_tbl is the Instance Variable TaBLe. It stores instance variable names and -their corresponding value.

-

In rb_ivar_set(), let’s look again the code for the structures having -iv_tbl.

-
-if (!ROBJECT(obj)->iv_tbl)
-    ROBJECT(obj)->iv_tbl = st_init_numtable();
-st_insert(ROBJECT(obj)->iv_tbl, id, val);
-break;
-
-

ROBJECT() is a macro that casts a VALUE into a `struct -RObject*. It's possible that obj` points to a struct RClass, but as -we’re only going to access the second member no problem will occur.

-

st_init_numtable() is a function creating a new st_table. st_insert() is -a function doing associations in a st_table.

-

In conclusion, this code does the following: if iv_tbl does not exist, it -creates it, then stores the [variable name → object] association.

-

Warning: as struct RClass is a class object, this instance variable table is -for the use of the class object itself. In Ruby programs, it corresponds to -something like the following:

-
-class C
-  @ivar = "content"
-end
-
-

generic_ivar_set()

-

For objects for which the structure used is not T_OBJECT, T_MODULE, or -T_CLASS, what happens when modifying an instance variable?

-

rb_ivar_set() in the case there is no iv_tbl

-
-1000  default:
-1001    generic_ivar_set(obj, id, val);
-1002    break;
-
-(variable.c)
-
-

The control is transferred to generic_ivar_set(). Before looking at this -function, let’s first explain its general idea.

-

Structures that are not T_OBJECT, T_MODULE or T_CLASS do not have an -iv_tbl member (the reason why they do not have it will be explained later). -However, a method linking an instance to a struct st_table would allow -instances to have instance variables. In ruby, this was solved by using a -global st_table, generic_iv_table (figure 7) for these associations.

-

-

(givtable)
-Figure 7: generic_iv_table

-

-

Let’s see this in practice.

-

generic_ivar_set()

-
- 801  static st_table *generic_iv_tbl;
-
- 830  static void
- 831  generic_ivar_set(obj, id, val)
- 832      VALUE obj;
- 833      ID id;
- 834      VALUE val;
- 835  {
- 836      st_table *tbl;
- 837
-          /* for the time being you should ignore this */
- 838      if (rb_special_const_p(obj)) {
- 839          special_generic_ivar = 1;
- 840      }
-          /* initialize generic_iv_tbl if it does not exist */
- 841      if (!generic_iv_tbl) {
- 842          generic_iv_tbl = st_init_numtable();
- 843      }
- 844
-          /* the treatment itself */
- 845      if (!st_lookup(generic_iv_tbl, obj, &tbl)) {
- 846          FL_SET(obj, FL_EXIVAR);
- 847          tbl = st_init_numtable();
- 848          st_add_direct(generic_iv_tbl, obj, tbl);
- 849          st_add_direct(tbl, id, val);
- 850          return;
- 851      }
- 852      st_insert(tbl, id, val);
- 853  }
-
-(variable.c)
-
-

rb_special_const_p() is true when its parameter is not a pointer. However, -as this if part requires knowledge of the garbage collector, we’ll skip it -for now. I’d like you to check it again after reading the chapter 5 “Garbage -collection”.

-

st_init_numtable() already appeared some time ago. It creates a new hash -table.

-

st_lookup() searches a value corresponding to a key. In this case it -searches for what’s attached to obj. If an attached value can be found, the -whole function returns true and stores the value at the address (&tbl) given -as third parameter. In short, !st_lookup(...) can be read “if a value can’t -be found”.

-

st_insert() was also already explained. It stores a new association in a -table.

-

st_add_direct() is similar to st_insert(), but the part before adding the -association that checks if the key was already stored or not is different. In -other words, in the case of st_add_direct(), if a key already registered is -being used, two associations linked to this same key will be stored. -st_add_direct() can be used when the check for existence has already been -done, as is the case here, or when a new table has just been created.

-

FL_SET(obj, FL_EXIVAR) is the macro that sets the FL_EXIVAR flag in the -basic.flags of obj. The basic.flags flags are all named FL_xxxx and -can be set using FL_SET(). These flags can be unset with FL_UNSET(). The -EXIVAR from FL_EXIVAR seems to be the abbreviation of EXternal Instance -VARiable.

-

The setting of these flags is done to speed up the reading of instance -variables. If FL_EXIVAR is not set, even without searching in -generic_iv_tbl, we directly know if the object has instance variables. And -of course a bit check is way faster than searching a struct st_table.

-

Gaps in structures

-

Now you should understand how the instance variables are stored, but why are -there structures without iv_tbl? Why is there no iv_tbl in -struct RString or struct RArray? Couldn’t iv_tbl be part of RBasic?

-

Well, this could have been done, but there are good reasons why it was not. As -a matter of fact, this problem is deeply linked to the way ruby manages -objects.

-

For example, in ruby, memory used by string data (char[]) is directly -allocated using malloc(). However, the object structures are handled in a -particular way. ruby allocates them by clusters, and then distribute them -from these clusters. As at allocation time the diversity of types (and sizes) -of structures is difficult to handle, a type (union) that combines all -structures RVALUE was declared and an array of this type is managed. As this -type’s size is the same as the biggest one of its members, if there is only -one big structure, there is a lot of unused space. That’s why doing as much as -possible to regroup structures of similar size is desirable. The details about -RVALUE will be explained in chapter 5 “Garbage collection”.

-

Generally the most used structure is struct RString. After that, in programs -there are struct RArray (array), RHash (hash), RObject (user defined -object), etc. However, this struct RObject only uses the space of -struct RBasic + 1 pointer. On the other hand, struct RString, RArray and -RHash take the space of struct RBasic + 3 pointers. In other words, when -putting a struct RObject in the shared entity, the space for 2 pointers is -useless. And beyond that, if RString had 4 pointers, RObject would use less -that half the size of the shared entity. As you would expect, it’s wasteful.

-

So the received merit for iv_tbl is more or less saving memory and speeding -up. Furthermore we do not know if it is used often or not. In fact, -generic_iv_tbl was not introduced before ruby 1.2, so it was not possible -to use instance variables in String or Array at that time. Nevertheless, it -was not much of a problem. Making large amounts of memory useless just for -such functionality looks stupid.

-

If you take all this into consideration, you can conclude that increasing the -size of object structures does not do any good.

-

rb_ivar_get()

-

We saw the rb_ivar_set() function that sets variables, so let’s see quickly -how to get them.

-

rb_ivar_get()

-
- 960  VALUE
- 961  rb_ivar_get(obj, id)
- 962      VALUE obj;
- 963      ID id;
- 964  {
- 965      VALUE val;
- 966
- 967      switch (TYPE(obj)) {
-      /* (A) */
- 968        case T_OBJECT:
- 969        case T_CLASS:
- 970        case T_MODULE:
- 971          if (ROBJECT(obj)->iv_tbl &&
-                  st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
- 972              return val;
- 973          break;
-      /* (B) */
- 974        default:
- 975          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
- 976              return generic_ivar_get(obj, id);
- 977          break;
- 978      }
-      /* (C) */
- 979      rb_warning("instance variable %s not initialized", rb_id2name(id));
- 980
- 981      return Qnil;
- 982  }
-
-(variable.c)
-
-

The structure is strictly the same.

-

(A) For struct RObject or RClass, we search the variable in iv_tbl. As -iv_tbl can also be NULL, we must check it before using it. Then if -st_lookup() finds the relation, it returns true, so the whole if can be -read as “If the instance variable has been set, return its value”.

-

(C) If no correspondence could be found, in other words if we read an -instance variable that has not been set, we first leave the if then the -switch. rb_warning() will then issue a warning and nil will be returned. -That’s because you can read instance variables that have not been set in Ruby.

-

(B) On the other hand, if the structure is neither struct RObject nor -RClass, the instance variable table is searched in generic_iv_tbl. What -generic_ivar_get() does can be easily guessed, so I won’t explain it. I’d -rather want you to focus on the if.

-

I already told you that generic_ivar_set() sets the FL_EXIVAR flag to make -the check faster.

-

And what is rb_special_const_p()? This function returns true when its -parameter obj does not point to a structure. As no structure means no -basic.flags, no flag can be set, and FL_xxxx() will always returns false. -That’s why these objects have to be treated specially.

-

Structures for objects

-

In this section we’ll see simply, among object structures, what the important -ones contain and how they are handled.

-

struct RString

-

struct RString is the structure for the instances of the String class and -its subclasses.

-

struct RString

-
- 314  struct RString {
- 315      struct RBasic basic;
- 316      long len;
- 317      char *ptr;
- 318      union {
- 319          long capa;
- 320          VALUE shared;
- 321      } aux;
- 322  };
-
-(ruby.h)
-
-

ptr is a pointer to the string, and len the length of that string. Very -straightforward.

-

Rather than a string, Ruby’s string is more a byte array, and can contain any -byte including NUL. So when thinking at the Ruby level, ending the string -with NUL does not mean anything. As C functions require NUL, for -convenience the ending NUL is there, however, it is not included in len.

-

When dealing with a string coming from the interpreter or an extension -library, you can write RSTRING(str)->ptr or RSTRING(str)->len, and access -ptr and len. But there are some points to pay attention to.

-
    -
  1. you have to check before if str really points to a struct RString
  2. -
  3. you can read the members, but you must not modify them
  4. -
  5. you can’t store RSTRING(str)->ptr in something like a local variable and -use it later
  6. -
-

Why is that? First, there is an important software engineering principle: -Don’t arbitrarily tamper with someone’s data. Interface functions are there -for a reason. However, there are concrete reasons in ruby‘s design -why you should not do such things as consulting or storing a pointer, and -that’s related to the fourth member aux. However, to explain properly how to -use aux, we have to explain first a little more of Ruby’s strings’ -characteristics.

-

Ruby’s strings can be modified (are mutable). By mutable I mean after the -following code:

-
-s = "str"        # create a string and assign it to s
-s.concat("ing")  # append "ing" to this string object
-p(s)             # show the string
-
-

the content of the object pointed by s will become “string”. It’s -different from Java or Python string objects. Java’s StringBuffer is closer.

-

And what’s the relation? First, mutable means the length (len) of the string -can change. We have to increase or decrease the allocated memory size each time -the length changes. We can of course use realloc() for that, but generally -malloc() and realloc() are heavy operations. Having to realloc() each -time the string changes is a huge burden.

-

That’s why the memory pointed by ptr has been allocated with a size a little -bigger than len. Because of that, if the added part can fit into the -remaining memory, it’s taken care of without calling realloc(), so it’s -faster. The structure member aux.capa contains the length including this -additional memory.

-

So what is this other aux.shared? It’s to speed up the creation of literal -strings. Have a look at the following Ruby program.

-
-while true do  # repeat indefinitely
-  a = "str"        # create a string with "str" as content and assign it to a
-  a.concat("ing")  # append "ing" to the object pointed by a
-  p(a)             # show "string"
-end
-
-

Whatever the number of times you repeat the loop, the fourth line’s p has to -show "string". That’s why the code "str" should create, each time, a string -object holding a different char[]. However, if no change occurs for a lot of -strings, useless copies of char[] can be created many times. It would be better -to share one common char[].

-

The trick that allows this to happen is aux.shared. String objects created -with a literal use one shared char[]. When a change occurs, the string is -copied in unshared memory, and the change is done on this new copy. This -technique is called “copy-on-write”. When using a shared char[], the flag -ELTS_SHARED is set in the object structure’s basic.flags, and aux.shared -contains the original object. ELTS seems to be the abbreviation of -ELemenTS.

-

But, well, let’s return to our talk about RSTRING(str)->ptr. Even if -consulting the pointer is OK, you must not modify it, first because the value -of len or capa will no longer agree with the content, and also because when -modifying strings created as litterals, aux.shared has to be separated.

-

To finish this section about RString, let’s write some examples how to use -it. str is a VALUE that points to RString.

-
-RSTRING(str)->len;               /* length */
-RSTRING(str)->ptr[0];            /* first character */
-str = rb_str_new("content", 7);  /* create a string with "content" as its content
-                                    the second parameter is the length */
-str = rb_str_new2("content");    /* create a string with "content" as its content
-                                    its length is calculated with strlen() */
-rb_str_cat2(str, "end");         /* Concatenate a C string to a Ruby string */
-
-

struct RArray

-

struct RArray is the structure for the instances of Ruby’s array class -Array.

-

struct RArray

-
- 324  struct RArray {
- 325      struct RBasic basic;
- 326      long len;
- 327      union {
- 328          long capa;
- 329          VALUE shared;
- 330      } aux;
- 331      VALUE *ptr;
- 332  };
-
-(ruby.h)
-
-

Except for the type of ptr, this structure is almost the same as -struct RString. ptr points to the content of the array, and len is its -length. aux is exactly the same as in struct RString. aux.capa is the -“real” length of the memory pointed by ptr, and if ptr is shared, -aux.shared stores the shared original array object.

-

From this structure, it’s clear that Ruby’s Array is an array and not a -list. So when the number of elements changes in a big way, a realloc() must -be done, and if an element must be inserted at an other place than the end, a -memmove() will occur. But even if we do it, it’s moving so fast it’s really -impressive on current machines.

-

That’s why the way to access it is similar to RString. You can consult -RARRAY(arr)->ptr and RARRAY(arr)->len members, but can’t set them, etc., -etc. We’ll only look at simple examples:

-
-/* manage an array from C */
-VALUE ary;
-ary = rb_ary_new();             /* create an empty array */
-rb_ary_push(ary, INT2FIX(9));   /* push a Ruby 9 */
-RARRAY(ary)->ptr[0];            /* look what's at index 0 */
-rb_p(RARRAY(ary)->ptr[0]);      /* do p on ary[0] (the result is 9) */
-
-# manage an array from Ruby
-ary = []      # create an empty array
-ary.push(9)   # push 9
-ary[0]        # look what's at index 0
-p(ary[0])     # do p on ary[0] (the result is 9)
-
-

struct RRegexp

-

It’s the structure for the instances of the regular expression class Regexp.

-

struct RRegexp

-
- 334  struct RRegexp {
- 335      struct RBasic basic;
- 336      struct re_pattern_buffer *ptr;
- 337      long len;
- 338      char *str;
- 339  };
-
-(ruby.h)
-
-

ptr is the regular expression after compilation. str is the string before -compilation (the source code of the regular expression), and len is this -string’s length.

-

As the Regexp object handling code doesn’t appear in this book, we won’t see -how to use it. Even if you use it in extension libraries, as long as you do -not want to use it a very particular way, the interface functions are enough.

-

struct RHash

-

struct RHash is the structure for Ruby’s Hash objects.

-

struct RHash

-
- 341  struct RHash {
- 342      struct RBasic basic;
- 343      struct st_table *tbl;
- 344      int iter_lev;
- 345      VALUE ifnone;
- 346  };
-
-(ruby.h)
-
-

It’s a wrapper for struct st_table. st_table will be detailed in the next -chapter “Names and name tables”.

-

ifnone is the value when a key does not have an attached value, its default -is nil. iter_lev is to make the hashtable reentrant (multithread safe).

-

struct RFile

-

struct RFile is a structure for instances of the built-in IO class and -its subclasses.

-

struct RFile

-
- 348  struct RFile {
- 349      struct RBasic basic;
- 350      struct OpenFile *fptr;
- 351  };
-
-(ruby.h)
-
-

OpenFile

-
-  19  typedef struct OpenFile {
-  20      FILE *f;                    /* stdio ptr for read/write */
-  21      FILE *f2;                   /* additional ptr for rw pipes */
-  22      int mode;                   /* mode flags */
-  23      int pid;                    /* child's pid (for pipes) */
-  24      int lineno;                 /* number of lines read */
-  25      char *path;                 /* pathname for file */
-  26      void (*finalize) _((struct OpenFile*)); /* finalize proc */
-  27  } OpenFile;
-
-(rubyio.h)
-
-

All members have been transferred in struct OpenFile. As there aren’t many -instances of IO objects, it’s OK to do it like this. The purpose of each member -is written in the comments. Basically, it’s a wrapper around C’s stdio.

-

struct RData

-

struct RData has a different tenor from what we saw before. It is the -structure for implementation of extension libraries.

-

Of course structures for classes created in extension libraries as necessary, -but as the types of these structures depend of the created class, it’s -impossible to know their size or structure in advance. That’s why a “structure -for managing a pointer to a user defined structure” has been created on -ruby’s side to manage this. This structure is struct RData.

-

struct RData

-
- 353  struct RData {
- 354      struct RBasic basic;
- 355      void (*dmark) _((void*));
- 356      void (*dfree) _((void*));
- 357      void *data;
- 358  };
-
-(ruby.h)
-
-

data is a pointer to the user defined structure, -dfree is the function used to free this structure, and -dmark is the function for when the “mark” of the mark and sweep occurs.

-

Because explaining struct RData is still too complicated, for -the time being let’s just look at its representation (figure 8). You’ll read -a detailed explanation of its members in chapter 5 “Garbage collection” where -there’ll be presented once again.

-

-

(rdata)
-Figure 8: Representation of struct RData

-

- - - -
- - diff --git a/htmls/parser.html b/htmls/parser.html deleted file mode 100644 index 7ce5a6e..0000000 --- a/htmls/parser.html +++ /dev/null @@ -1,2014 +0,0 @@ - - - - - Parser | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Robert GRAVINA & ocha-

-

Chapter 10: Parser

-

Outline of this chapter

-

Parser construction

-

The main source of the parser is parser.y. -Because it is *.y, it is the input for yacc -and parse.c is generated from it.

-

Although one would expect lex.c to contain the scanner, this is not the case. -This file is created by gperf, taking the file keywords as input, and -defines the reserved word hashtable. This tool-generated lex.c is #included -in (the also tool-generated) parse.c. The details of this process is somewhat -difficult to explain at this time, so we shall return to this later.

-

Figure 1 shows the parser construction process. For the benefit of those readers -using Windows who may not be aware, the mv (move) command creates a new copy -of a file and removes the original. cc is, of course, the C compiler and cpp -the C pre-processor.

-

-

(build)
-Figure 1: Parser construction process

-

-

Dissecting parse.y

-

Let’s now look at parse.y in a bit more detail. The following figure presents -a rough outline of the contents of parse.y.

-

▼ parse.y -

-%{
-header
-%}
-%union ….
-%token ….
-%type ….

-

%%

-

rules

-

%% -user code section - parser interface - scanner (character stream processing) - syntax tree construction - semantic analysis - local variable management - ID implementation -

-

As for the rules and definitions part, it is as previously described. -Since this part is indeed the heart of the parser, -I’ll start to explain it ahead of the other parts in the next section.

-

There are a considerable number of support functions defined in the user code -section, but roughly speaking, they can be divided into the six parts -written above. The following table shows where each of parts are -explained in this book.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PartChapterSection
Parser interfaceThis chapterSection 3 “Scanning”
ScannerThis chapterSection 3 “Scanning”
Syntax tree constructionChapter 12 “Syntax tree construction”Section 2 “Syntax tree construction”
Semantic analysisChapter 12 “Syntax tree construction”Section 3 “Semantic analysis”
Local variable managementChapter 12 “Syntax tree construction”Section 4 “Local variables”
ID implementationChapter 3 “Names and name tables”Section 2 “ID and symbols”
-

General remarks about grammar rules

-

Coding rules

-

The grammar of ruby conforms to a coding standard and is thus easy to read -once you are familiar with it.

-

Firstly, regarding symbol names, all non-terminal symbols are written in lower -case characters. Terminal symbols are prefixed by some lower case character and -then followed by upper case. Reserved words (keywords) are prefixed with the -character k. Other terminal symbols are prefixed with the character t.

-

▼ Symbol name examples

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TokenSymbol name
(non-terminal symbol)bodystmt
ifkIF
defkDEF
rescuekRESCUE
varnametIDENTIFIER
ConstNametCONST
1tINTEGER
-

The only exceptions to these rules are klBEGIN and klEND. These symbol names -refer to the reserved words for “BEGIN” and “END”, respectively, and the l -here stands for large. Since the reserved words begin and end already -exist (naturally, with symbol names kBEGIN and kEND), these non-standard -symbol names were required.

-

Important symbols

-

parse.y contains both grammar rules and actions, however, for now I would like -to concentrate on the grammar rules alone. The script sample/exyacc.rb can be -used to extract the grammar rules from this file. -Aside from this, running yacc -v will create a logfile y.output -which also contains the grammar rules, -however it is rather difficult to read. In this chapter I have used a slighty -modified version of exyacc.rb\footnote{modified exyacc.rb:tools/exyacc2.rb -located on the attached CD-ROM} to extract the grammar rules.

-

parse.y(rules) -

-program         : compstmt

-

bodystmt : compstmt - opt_rescue - opt_else - opt_ensure

-

compstmt : stmts opt_terms - : - : -

-

The output is quite long – over 450 lines of grammar rules – and as such I have -only included the most important parts in this chapter.

-

Which symbols, then, are the most important? The names such as program, expr, -stmt,primary, arg etc. are always very important. It’s because they -represent the general parts of the grammatical elements of a programming -language. The following table outlines the elements we should generally focus on -in the syntax of a program.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Syntax elementPredicted symbol names
Programprogram prog file input stmts whole
Sentencestatement stmt
Expressionexpression expr exp
Smallest elementprimary prim
Left hand side of an expressionlhs(left hand side)
Right hand side of an expressionrhs(right hand side)
Function callfuncall function_call call function
Method callmethod method_call call
Argumentargument arg
Function definitiondefun definition function fndef
Declarationsdeclaration decl
-

In general, programming languages tend to have the following hierarchy structure.

- - - - - - - - - - - - - - - - - - - - - -
Program elementProperties
ProgramUsually a list of statements
StatementWhat can not be combined with the others. A syntax tree trunk.
ExpressionWhat is a combination by itself and can also be a part of another -expression. A syntax tree internal node.
PrimaryAn element which can not be further decomposed. A syntax tree leaf node.
-

The statements are things like function definitions in C or class definitions -in Java. An expression can be a procedure call, an arithmetic expression -etc., while a primary usually refers to a string literal or number. Some languages -do not contain all of these symbol types, however they generally contain some -kind of hierarchy of symbols such as programstmtexprprimary.

-

However, a structure at a low level can be contained by a superior structure. -For example, in C a function call is an expression but it can solely be put. -It means it is an expression but it can also be a statement.

-

Conversely, when surrounded in parentheses, expressions become primaries. -It is because the lower the level of a element the higher the precedence it has.

-

The range of statements differ considerably between programming languages. -Let’s consider assignment as an example. -In C, because it is part of expressions, we can use the value of the whole -assignment expression. But in Pascal, assignment is a statement, we cannot do -such thing. Also, -function and class definitions are typically statements however in languages -such as Lisp and Scheme, since everything is an expression, -they do not have statements in the first place. -Ruby is close to Lisp’s design in this regard.

-

Program structure

-

Now let’s turn our attention to the grammar rules of ruby. Firstly, -in yacc, the left hand side of the first rule represents the entire grammar. -Currently, it is program. -Following further and further from here, -as the same as the established tactic, -the four program stmt expr primary will be found. -With adding arg to them, let’s look at their rules.

-

ruby grammar (outline) -

-program         : compstmt

-

compstmt : stmts opt_terms

-

stmts : none - | stmt - | stmts terms stmt

-

stmt : kALIAS fitem fitem - | kALIAS tGVAR tGVAR - : - : - | expr

-

expr : kRETURN call_args - | kBREAK call_args - : - : - | ‘!’ command_call - | arg

-

arg : lhs ‘=’ arg - | var_lhs tOP_ASGN arg - | primary_value ‘[’ aref_args ‘]’ tOP_ASGN arg - : - : - | arg ‘?’ arg ‘:’ arg - | primary

-

primary : literal - | strings - : - : - | tLPAREN_ARG expr ‘)’ - | tLPAREN compstmt ‘)’ - : - : - | kREDO - | kRETRY -

-

If we focus on the last rule of each element, -we can clearly make out a hierarchy of programstmtexprarg→ -primary.

-

Also, we’d like to focus on this rule of primary.

-
-primary         : literal
-                    :
-                    :
-                | tLPAREN_ARG expr  ')'      /* here */
-
-

The name tLPAREN_ARG comes from t for terminal symbol, L for left and -PAREN for parentheses – it is the open parenthesis. Why this isn’t '(' -is covered in the next section “Context-dependent scanner”. Anyway, the purpose -of this rule is demote an expr to a primary. This creates -a cycle which can the seen in Figure 2, and the arrow shows how this rule is -reduced during parsing.

-

-

(exprloop)
-Figure 2: expr demotion

-

-

The next rule is also particularly interesting.

-
-primary         : literal
-                    :
-                    :
-                | tLPAREN compstmt ')'   /* here */
-
-

A compstmt, which equals to the entire program (program), can be demoted to -a primary with this rule. The next figure illustrates this rule in action.

-

-

(progloop)
-Figure 3: program demotion

-

-

This means that for any syntax element in Ruby, if we surround it with -parenthesis it will become a primary and can be passed as an argument to a -function, be used as the right hand side of an expression etc. -This is an incredible fact. -Let’s actually confirm it.

-
-p((class C; end))
-p((def a() end))
-p((alias ali gets))
-p((if true then nil else nil end))
-p((1 + 1 * 1 ** 1 - 1 / 1 ^ 1))
-
-

If we invoke ruby with the -c option (syntax check), we get the following -output.

-
-% ruby -c primprog.rb
-Syntax OK
-
-

Indeed, it’s hard to believe but, it could actually pass. -Apparently, we did not get the wrong idea.

-

If we care about the details, -since there are what rejected by the semantic analysis (see also Chapter 12 -“Syntax tree construction”), it is not perfectly possible. -For example passing a return statement as an argument to a -function will result in an error. -But at least at the level of the outlooks, the “surrounding -anything in parenthesis means it can be passed as an argument to a function” -rule does hold.

-

In the next section I will cover the contents of the important elements one by -one.

-

program

-

program -

-program         : compstmt

-

compstmt : stmts opt_terms

-

stmts : none - | stmt - | stmts terms stmt -

-

As mentioned earlier, -program represents the entire grammar that means the entire program. -That program equals to compstmts, -and compstmts is almost equivalent to stmts. -That stmts is a list of stmts delimited by terms. -Hence, the entire program is a list of stmts delimited by terms.

-

terms is (of course) an abbreviation for “terminators”, the symbols that -terminate the sentences, such as semicolons or newlines. -opt_terms means “OPTional terms”. The definitions are as follows:

-

opt_terms -

-opt_terms       :
-                | terms

-

terms : term - | terms ‘;’

-

term : ‘;’ - | ‘\n’ -

-

The initial ; or \n of a terms can be followed by any number of ; only; based on that, you might start thinking that if there are 2 or more consecutive newlines, it could cause a problem. Let’s try and see what actually happens.

-
-1 + 1   # first newline
-        # second newline
-        # third newline
-1 + 1
-
-

Run that with ruby -c.

-
-% ruby -c optterms.rb
-Syntax OK
-
-

Strange, it worked! What actually happens is this: consecutive newlines are simply discarded by the scanner, which returns only the first newline in a series.

-

By the way, although we said that program is the same as compstmt, if that was really true, you would question why compstmt exists at all. Actually, the distinction is there only for execution of semantic actions. program exists to execute any semantic actions which should be done once in the processing of an entire program. If it was only a question of parsing, program could be omitted with no problems at all.

-

To generalize this point, the grammar rules can be divided into 2 groups: those which are needed for parsing the program structure, and those which are needed for execution of semantic actions. The none rule which was mentioned earlier when talking about stmts is another one which exists for executing actions — it’s used to return a NULL pointer for an empty list of type NODE*.

-

stmt

-

Next is stmt. This one is rather involved, so we’ll look into it a bit at a time.

-

stmt(1) -

-stmt            : kALIAS fitem  fitem
-                | kALIAS tGVAR tGVAR
-                | kALIAS tGVAR tBACK_REF
-                | kALIAS tGVAR tNTH_REF
-                | kUNDEF undef_list
-                | stmt kIF_MOD expr_value
-                | stmt kUNLESS_MOD expr_value
-                | stmt kWHILE_MOD expr_value
-                | stmt kUNTIL_MOD expr_value
-                | stmt kRESCUE_MOD stmt
-                | klBEGIN ‘{’ compstmt ‘}’
-                | klEND ‘{’ compstmt ‘}’
-

-

Looking at that, somehow things start to make sense. The first few have alias, then undef, then the next few are all something followed by _MOD — those should be statements with postposition modifiers, as you can imagine.

-

expr_value and primary_value are grammar rules which exist to execute semantic actions. For example, expr_value represents an expr which has a value. Expressions which don’t have values are return and break, or return/break followed by a postposition modifier, such as an if clause. For a detailed definition of what it means to “have a value”, see chapter 12, “Syntax Tree Construction”. In the same way, primary_value is a primary which has a value.

-

As explained earlier, klBEGIN and klEND represent BEGIN and END.

-

stmt(2) -

-                | lhs ‘=’ command_call
-                | mlhs ‘=’ command_call
-                | var_lhs tOP_ASGN command_call
-                | primary_value ‘[’ aref_args ‘]’ tOP_ASGN command_call
-                | primary_value ‘.’ tIDENTIFIER tOP_ASGN command_call
-                | primary_value ‘.’ tCONSTANT tOP_ASGN command_call
-                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
-                | backref tOP_ASGN command_call
-

-

Looking at these rules all at once is the right approach. -The common point is that they all have command_call on the right-hand side. command_call represents a method call with the parentheses omitted. The new symbols which are introduced here are explained in the following table. I hope you’ll refer to the table as you check over each grammar rule.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lhs the left hand side of an assignment (Left Hand Side)
mlhs the left hand side of a multiple assignment (Multiple Left Hand Side)
var_lhs the left hand side of an assignment to a kind of variable (VARiable Left Hand Side)
tOP_ASGNcompound assignment operator like += or *= (OPerator ASsiGN)
aref_argsargument to a [] method call (Array REFerence)
tIDENTIFIERidentifier which can be used as a local variable
tCONSTANTconstant identifier (with leading uppercase letter)
tCOLON2::
backref$1 $2 $3...
-

aref is a Lisp jargon. -There’s also aset as the other side of a pair, -which is an abbreviation of “array set”. -This abbreviation is used at a lot of places in the source code of ruby.

-

stmt (3)

-
-                | lhs '=' mrhs_basic
-                | mlhs '=' mrhs
-
-

These two are multiple assignments. -mrhs has the same structure as mlhs and it means multiple rhs (the right hand side). -We’ve come to recognize that knowing the meanings of names makes the comprehension much easier.

-

stmt (4)

-
-                | expr
-
-

Lastly, it joins to expr.

-

expr

-

expr

-
-expr            : kRETURN call_args
-                | kBREAK call_args
-                | kNEXT call_args
-                | command_call
-                | expr kAND expr
-                | expr kOR expr
-                | kNOT expr
-                | '!' command_call
-                | arg
-
-

Expression. The expression of ruby is very small in grammar. -That’s because those ordinary contained in expr are mostly went into arg. -Conversely speaking, those who could not go to arg are left here. -And what are left are, again, method calls without parentheses. -call_args is an bare argument list, -command_call is, as previously mentioned, a method without parentheses. -If this kind of things was contained in the “small” unit, -it would cause conflicts tremendously.

-

However, these two below are of different kind.

-
-expr kAND expr
-expr kOR expr
-
-

kAND is “and”, and kOR is “or”. -Since these two have their roles as control structures, -they must be contained in the “big” syntax unit which is larger than command_call. -And since command_call is contained in expr, -at least they need to be expr to go well. -For example, the following usage is possible …

-
-  valid_items.include? arg  or raise ArgumentError, 'invalid arg'
-# valid_items.include?(arg) or raise(ArgumentError, 'invalid arg')
-
-

However, if the rule of kOR existed in arg instead of expr, -it would be joined as follows.

-
-valid_items.include?((arg or raise)) ArgumentError, 'invalid arg'
-
-

Obviously, this would end up a parse error.

-

arg

-

arg

-
-arg             : lhs '=' arg
-                | var_lhs tOP_ASGN arg
-                | primary_value '[' aref_args ']' tOP_ASGN arg
-                | primary_value '.' tIDENTIFIER tOP_ASGN arg
-                | primary_value '.' tCONSTANT tOP_ASGN arg
-                | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
-                | backref tOP_ASGN arg
-                | arg tDOT2 arg
-                | arg tDOT3 arg
-                | arg '+' arg
-                | arg '-' arg
-                | arg '*' arg
-                | arg '/' arg
-                | arg '%' arg
-                | arg tPOW arg
-                | tUPLUS arg
-                | tUMINUS arg
-                | arg '|' arg
-                | arg '^' arg
-                | arg '&' arg
-                | arg tCMP arg
-                | arg '>' arg
-                | arg tGEQ arg
-                | arg '<' arg
-                | arg tLEQ arg
-                | arg tEQ arg
-                | arg tEQQ arg
-                | arg tNEQ arg
-                | arg tMATCH arg
-                | arg tNMATCH arg
-                | '!' arg
-                | '~' arg
-                | arg tLSHFT arg
-                | arg tRSHFT arg
-                | arg tANDOP arg
-                | arg tOROP arg
-                | kDEFINED opt_nl  arg
-                | arg '?' arg ':' arg
-                | primary
-
-

Although there are many rules here, the complexity of the grammar is not -proportionate to the number of rules. -A grammar that merely has a lot of cases can be handled very easily by yacc, -rather, the depth or recursive of the rules has more influences the complexity.

-

Then, it makes us curious about the rules are defined recursively in the form -of arg OP arg at the place for operators, -but because for all of these operators their operator precedences are defined, -this is virtually only a mere enumeration. -Let’s cut the “mere enumeration” out from the arg rule by merging.

-
-arg: lhs '=' arg              /* 1 */
-   | primary T_opeq arg       /* 2 */
-   | arg T_infix arg          /* 3 */
-   | T_pre arg                /* 4 */
-   | arg '?' arg ':' arg      /* 5 */
-   | primary                  /* 6 */
-
-

There’s no meaning to distinguish terminal symbols from lists of terminal symbols, -they are all expressed with symbols with T_. -opeq is operator + equal, -T_pre represents the prepositional operators such as '!' and '~', -T_infix represents the infix operators such as '*' and '%'.

-

To avoid conflicts in this structure, -things like written below become important -(but, these does not cover all).

-
    -
  • T_infix should not contain '='.
  • -
-

Since args partially overlaps lhs, -if '=' is contained, the rule 1 and the rule 3 cannot be distinguished.

-
    -
  • T_opeq and T_infix should not have any common rule.
  • -
-

Since args contains primary, -if they have any common rule, the rule 2 and the rule 3 cannot be distinguished.

-
    -
  • T_infix should not contain '?'.
  • -
-

If it contains, the rule 3 and 5 would produce a shift/reduce conflict.

-
    -
  • T_pre should not contain '?' or ':'.
  • -
-

If it contains, the rule 4 and 5 would conflict in a very complicated way.

-

The conclusion is all requirements are met and this grammar does not conflict. -We could say it’s a matter of course.

-

primary

-

Because primary has a lot of grammar rules, we’ll split them up and show them in parts.

-

primary (1)

-
-primary         : literal
-                | strings
-                | xstring
-                | regexp
-                | words
-                | qwords
-
-

Literals. -literal is for Symbol literals (:sym) and numbers.

-

primary (2)

-
-                | var_ref
-                | backref
-                | tFID
-
-

Variables. -var_ref is for local variables and instance variables and etc. -backref is for $1 $2 $3 … -tFID is for the identifiers with ! or ?, say, include? reject!. -There’s no possibility of tFID being a local variable, -even if it appears solely, it becomes a method call at the parser level.

-

primary (3)

-
-                | kBEGIN
-                  bodystmt
-                  kEND
-
-

bodystmt contains rescue and ensure. -It means this is the begin of the exception control.

-

primary (4)

-
-                | tLPAREN_ARG expr  ')'
-                | tLPAREN compstmt ')'
-
-

This has already described. Syntax demoting.

-

primary (5)

-
-                | primary_value tCOLON2 tCONSTANT
-                | tCOLON3 cname
-
-

Constant references. tCONSTANT is for constant names (capitalized identifiers).

-

Both tCOLON2 and tCOLON3 are ::, -but tCOLON3 represents only the :: which means the top level. -In other words, it is the :: of ::Const. -The :: of Net::SMTP is tCOLON2.

-

The reason why different symbols are used for the same token -is to deal with the methods without parentheses. -For example, it is to distinguish the next two from each other:

-
-p Net::HTTP    # p(Net::HTTP)
-p Net  ::HTTP  # p(Net(::HTTP))
-
-

If there’s a space or a delimiter character such as an open parenthesis just before it, -it becomes tCOLON3. In the other cases, it becomes tCOLON2.

-

primary (6)

-
-                | primary_value '[' aref_args ']'
-
-

Index-form calls, for instance, arr[i].

-

primary (7)

-
-                | tLBRACK aref_args ']'
-                | tLBRACE assoc_list '}'
-
-

Array literals and Hash literals. -This tLBRACK represents also '[', -'[' means a '[' without a space in front of it. -The necessity of this differentiation is also a side effect of method calls -without parentheses.

-

The terminal symbols of this rule is very incomprehensible because they differs -in just a character. -The following table shows how to read each type of parentheses, -so I’d like you to make use of it when reading.

-

▼ English names for each parentheses

- - - - - - - - - - - - - - - - - -
Symbol English Name
() parentheses
{} braces
[] brackets
-

primary (8)

-
-                | kRETURN
-                | kYIELD '(' call_args ')'
-                | kYIELD '(' ')'
-                | kYIELD
-                | kDEFINED opt_nl '('  expr ')'
-
-

Syntaxes whose forms are similar to method calls. -Respectively, return, yield, defined?.

-

There arguments for yield, but return does not have any arguments. Why? -The fundamental reason is that yield itself has its return value but -return does not. -However, even if there’s not any arguments here, -it does not mean you cannot pass values, of course. -There was the following rule in expr.

-
-kRETURN call_args
-
-

call_args is a bare argument list, -so it can deal with return 1 or return nil. -Things like return(1) are handled as return (1). -For this reason, -surrounding the multiple arguments of a return with parentheses -as in the following code should be impossible.

-
-return(1, 2, 3)   # interpreted as return  (1,2,3) and results in parse error
-
-

You could understand more about around here -if you will check this again after reading -the next chapter “Finite-State Scanner”.

-

primary (9)

-
-                | operation brace_block
-                | method_call
-                | method_call brace_block
-
-

Method calls. method_call is with arguments (also with parentheses), -operation is without both arguments and parentheses, -brace_block is either { ~ } or do ~ end -and if it is attached to a method, the method is an iterator. -For the question “Even though it is brace, why is do ~ end contained in -it?”, there’s a reason that is more abyssal than Marian Trench, -but again the only way to understand is reading -the next chapter “Finite-State Scanner”.

-

primary (10)

-
-  | kIF expr_value then compstmt if_tail kEND         # if
-  | kUNLESS expr_value then compstmt opt_else kEND    # unless
-  | kWHILE expr_value do compstmt kEND                # while
-  | kUNTIL expr_value do compstmt kEND                # until
-  | kCASE expr_value opt_terms case_body kEND         # case
-  | kCASE opt_terms case_body kEND                    # case(Form2)
-  | kFOR block_var kIN expr_value do compstmt kEND    # for
-
-

The basic control structures. -A little unexpectedly, things appear to be this big are put inside primary, -which is “small”. -Because primary is also arg, -we can also do something like this.

-
-p(if true then 'ok' end)   # shows "ok"
-
-

I mentioned “almost all syntax elements are expressions” -was one of the traits of Ruby. -It is concretely expressed by the fact that if and while are in primary.

-

Why is there no problem if these “big” elements are contained in primary? -That’s because the Ruby’s syntax has a trait that “it begins with the terminal -symbol A and ends with the terminal symbol B”. -In the next section, we’ll think about this point again.

-

primary (11)

-
-  | kCLASS cname superclass bodystmt kEND        # class definition
-  | kCLASS tLSHFT expr term bodystmt kEND        # singleton class definition
-  | kMODULE cname bodystmt kEND                  # module definition
-  | kDEF fname f_arglist bodystmt kEND           # method definition
-  | kDEF singleton dot_or_colon fname f_arglist bodystmt kEND
-                                                 # singleton method definition
-
-

Definition statements. -I’ve called them the class statements and the class statements, -but essentially I should have been called them the class primaries, probably. -These are all fit the pattern “beginning with the terminal symbol A and ending with B”, -even if such rules are increased a lot more, -it would never be a problem.

-

primary (12)

-
-                | kBREAK
-                | kNEXT
-                | kREDO
-                | kRETRY
-
-

Various jumps. -These are, well, not important from the viewpoint of grammar.

-

Conflicting Lists

-

In the previous section, the question “is it all right that if is in such -primary?” was suggested. -To proof precisely is not easy, -but explaining instinctively is relatively easy. -Here, let’s simulate with a small rule defined as follows:

-
-%token A B o
-%%
-element   : A item_list B
-
-item_list :
-          | item_list item
-
-item      : element
-          | o
-
-

element is the element that we are going to examine. -For example, if we think about if, it would be if. -element is a list that starts with the terminal symbol A and ends with B. -As for if, it starts with if and ends with end. -The o contents are methods or variable references or literals. -For an element of the list, the o or element is nesting.

-

With the parser based on this grammar, -let’s try to parse the following input.

-
-A  A  o  o  o  B  o  A  o  A  o  o  o  B  o  B  B
-
-

They are nesting too many times for humans to comprehend -without some helps such as indents. -But it becomes relatively easy if you think in the next way. -Because it’s certain that A and B which contain only several o between -them are going to appear, replace them to a single o when they appear. -All we have to do is repeating this procedure. -Figure 4 shows the consequence.

-

-

(ablist)
-Figure 4: parse a list which starts with A and ends with B

-

-

However, if the ending B is missing, …

-
-%token A o
-%%
-element   : A item_list    /* B is deleted for an experiment */
-
-item_list :
-          | item_list item
-
-item      : element
-          | o
-
-

I processed this with yacc and got 2 shift/reduce conflicts. -It means this grammar is ambiguous. -If we simply take B out from the previous one, -The input would be as follows.

-
-A  A  o  o  o  o  A  o  A  o  o  o  o
-
-

This is hard to interpret in any way. However, there was a rule that “choose -shift if it is a shift/reduce conflict”, -let’s follow it as an experiment and parse the input -with shift (meaning interior) which takes precedence. (Figure 5)

-

-

(alist)
-Figure 5: parse a list of lists which start with A

-

-

It could be parsed. However, this is completely different from the intention of -the input, there becomes no way to split the list in the middle.

-

Actually, the methods without parentheses of Ruby is in the similar situation -to this. It’s not so easy to understand but -a pair of a method name and its first argument is A. -This is because, since there’s no comma only between the two, -it can be recognized as the start of a new list.

-

Also, the “practical” HTML contains this pattern. -It is, for instance, when </p> or </i> is omitted. -That’s why yacc could not be used for ordinary HTML at all.

-

Scanner

-

Parser Outline

-

I’ll explain about the outline of the parser before moving on to the scanner. -Take a look at Figure 6.

-

-

(interf)
-Figure 6: Parser Interface (Call Graph)

-

-

There are three official interfaces of the parser: rb_compile_cstr(), -rb_compile_string(), rb_compile_file(). -They read a program from C string, -a Ruby string object and a Ruby IO object, respectively, and compile it.

-

These functions, directly or indirectly, call yycompile(), -and in the end, the control will be completely moved to yyparse(), -which is generated by yacc. -Since the heart of the parser is nothing but yyparse(), -it’s nice to understand by placing yyparse() at the center. -In other words, functions before moving on to yyparse() are all preparations, -and functions after yyparse() are merely chore functions being pushed around -by yyparse().

-

The rest functions in parse.y are auxiliary functions called by yylex(), -and these can also be clearly categorized.

-

First, the input buffer is at the lowest level of the scanner. -ruby is designed so that you can input source programs via both Ruby IO -objects and strings. -The input buffer hides that and makes it look like a single byte stream.

-

The next level is the token buffer. -It reads 1 byte at a time from the input buffer, -and keeps them until it will form a token.

-

Therefore, the whole structure of yylex can be depicted as Figure 7.

-
-

(scanner)
-Figure 7: The whole picture of the scanner

-
    -
  • 入力バッファ input buffer
  • -
  • バイト列 byte sequence
  • -
  • トークンバッファ token buffer
  • -
  • 記号列 symbol sequence -
- -

The input buffer

-

Let’s start with the input buffer. Its interfaces are only the three: nextc(), pushback(), peek().

-

Although this is sort of insistent, -I said the first thing is to investigate data structures. -The variables used by the input buffer are the followings:

-

▼ the input buffer

-
-2279  static char *lex_pbeg;
-2280  static char *lex_p;
-2281  static char *lex_pend;
-
-(parse.y)
-
-

The beginning, the current position and the end of the buffer. -Apparently, this buffer seems a simple single-line string buffer (Figure 8).

-

-

(ibuffer)
-Figure 8: The input buffer

-

-

nextc()

-

Then, let’s look at the places using them. -First, I’ll start with nextc() that seems the most orthodox.

-

nextc()

-
-2468  static inline int
-2469  nextc()
-2470  {
-2471      int c;
-2472
-2473      if (lex_p == lex_pend) {
-2474          if (lex_input) {
-2475              VALUE v = lex_getline();
-2476
-2477              if (NIL_P(v)) return -1;
-2478              if (heredoc_end > 0) {
-2479                  ruby_sourceline = heredoc_end;
-2480                  heredoc_end = 0;
-2481              }
-2482              ruby_sourceline++;
-2483              lex_pbeg = lex_p = RSTRING(v)->ptr;
-2484              lex_pend = lex_p + RSTRING(v)->len;
-2485              lex_lastline = v;
-2486          }
-2487          else {
-2488              lex_lastline = 0;
-2489              return -1;
-2490          }
-2491      }
-2492      c = (unsigned char)*lex_p++;
-2493      if (c == '\r' && lex_p <= lex_pend && *lex_p == '\n') {
-2494          lex_p++;
-2495          c = '\n';
-2496      }
-2497
-2498      return c;
-2499  }
-
-(parse.y)
-
-

It seems that the first if is to test if it reaches the end of the input buffer. -And, the if inside of it seems, since the else returns -1 (EOF), -to test the end of the whole input. -Conversely speaking, when the input ends, lex_input becomes 0. -((errata: it does not. lex_input will never become 0 during ordinary scan.))

-

From this, we can see that strings are coming bit by bit into the input buffer. -Since the name of the function which updates the buffer is lex_getline, -it’s definite that each line comes in at a time.

-

Here is the summary:

-
-if ( reached the end of the buffer )
-    if (still there's more input)
-        read the next line
-    else
-        return EOF
-move the pointer forward
-skip reading CR of CRLF
-return c
-
-

Let’s also look at the function lex_getline(), which provides lines. -The variables used by this function are shown together in the following.

-

lex_getline()

-
-2276  static VALUE (*lex_gets)();     /* gets function */
-2277  static VALUE lex_input;         /* non-nil if File */
-
-2420  static VALUE
-2421  lex_getline()
-2422  {
-2423      VALUE line = (*lex_gets)(lex_input);
-2424      if (ruby_debug_lines && !NIL_P(line)) {
-2425          rb_ary_push(ruby_debug_lines, line);
-2426      }
-2427      return line;
-2428  }
-
-(parse.y)
-
-

Except for the first line, this is not important. -Apparently, lex_gets should be the pointer to the function to read a line, -lex_input should be the actual input. -I searched the place where setting lex_gets and this is what I found:

-

▼ set lex_gets

-
-2430  NODE*
-2431  rb_compile_string(f, s, line)
-2432      const char *f;
-2433      VALUE s;
-2434      int line;
-2435  {
-2436      lex_gets = lex_get_str;
-2437      lex_gets_ptr = 0;
-2438      lex_input = s;
-
-2454  NODE*
-2455  rb_compile_file(f, file, start)
-2456      const char *f;
-2457      VALUE file;
-2458      int start;
-2459  {
-2460      lex_gets = rb_io_gets;
-2461      lex_input = file;
-
-(parse.y)
-
-

rb_io_gets() is not a exclusive function for the parser -but one of the general-purpose library of Ruby. -It is the function to read a line from an IO object.

-

On the other hand, lex_get_str() is defined as follows:

-

lex_get_str()

-
-2398  static int lex_gets_ptr;
-
-2400  static VALUE
-2401  lex_get_str(s)
-2402      VALUE s;
-2403  {
-2404      char *beg, *end, *pend;
-2405
-2406      beg = RSTRING(s)->ptr;
-2407      if (lex_gets_ptr) {
-2408          if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
-2409          beg += lex_gets_ptr;
-2410      }
-2411      pend = RSTRING(s)->ptr + RSTRING(s)->len;
-2412      end = beg;
-2413      while (end < pend) {
-2414          if (*end++ == '\n') break;
-2415      }
-2416      lex_gets_ptr = end - RSTRING(s)->ptr;
-2417      return rb_str_new(beg, end - beg);
-2418  }
-
-(parse.y)
-
-

lex_gets_ptr remembers the place it have already read. -This moves it to the next \n, -and simultaneously cut out at the place and return it.

-

Here, let’s go back to nextc. -As described, by preparing the two functions with the same interface, -it switch the function pointer when initializing the parser, -and the other part is used in common. -It can also be said that the difference of the code is converted to the data -and absorbed. There was also a similar method of st_table.

-

pushback()

-

With the knowledge of the physical structure of the buffer and nextc, -we can understand the rest easily. -pushback() writes back a character. If put it in C, it is ungetc().

-

pushback()

-
-2501  static void
-2502  pushback(c)
-2503      int c;
-2504  {
-2505      if (c == -1) return;
-2506      lex_p--;
-2507  }
-
-(parse.y)
-
-

peek()

-

peek() checks the next character without moving the pointer forward.

-

peek()

-
-2509  #define peek(c) (lex_p != lex_pend && (c) == *lex_p)
-
-(parse.y)
-
-

The Token Buffer

-

The token buffer is the buffer of the next level. -It keeps the strings until a token will be able to cut out. -There are the five interfaces as follows:

- - - - - - - - - - - - - - - - - - - - - - - - - -
newtok begin a new token
tokadd add a character to the buffer
tokfix fix a token
tok the pointer to the beginning of the buffered string
toklen the length of the buffered string
toklast the last byte of the buffered string
-

Now, we’ll start with the data structures.

-

▼ The Token Buffer

-
-2271  static char *tokenbuf = NULL;
-2272  static int   tokidx, toksiz = 0;
-
-(parse.y)
-
-

tokenbuf is the buffer, tokidx is the end of the token -(since it is of int, it seems an index), -and toksiz is probably the buffer length. -This is also simply structured. If depicting it, -it would look like Figure 9.

-

-

(tbuffer)
-Figure 9: The token buffer

-

-

Let’s continuously go to the interface and -read newtok(), which starts a new token.

-

newtok()

-
-2516  static char*
-2517  newtok()
-2518  {
-2519      tokidx = 0;
-2520      if (!tokenbuf) {
-2521          toksiz = 60;
-2522          tokenbuf = ALLOC_N(char, 60);
-2523      }
-2524      if (toksiz > 4096) {
-2525          toksiz = 60;
-2526          REALLOC_N(tokenbuf, char, 60);
-2527      }
-2528      return tokenbuf;
-2529  }
-
-(parse.y)
-
-

The initializing interface of the whole buffer does not exist, -it’s possible that the buffer is not initialized. -Therefore, the first if checks it and initializes it. -ALLOC_N() is the macro ruby defines and is almost the same as calloc.

-

The initial value of the allocating length is 60, -and if it becomes too big (> 4096), -it would be returned back to small. -Since a token becoming this long is unlikely, -this size is realistic.

-

Next, let’s look at the tokadd() to add a character to token buffer.

-

tokadd()

-
-2531  static void
-2532  tokadd(c)
-2533      char c;
-2534  {
-2535      tokenbuf[tokidx++] = c;
-2536      if (tokidx >= toksiz) {
-2537          toksiz *= 2;
-2538          REALLOC_N(tokenbuf, char, toksiz);
-2539      }
-2540  }
-
-(parse.y)
-
-

At the first line, a character is added. -Then, it checks the token length and if it seems about to exceed the buffer end, -it performs REALLOC_N(). -REALLOC_N() is a realloc() which has the same way of specifying arguments -as calloc().

-

The rest interfaces are summarized below.

-

tokfix() tok() toklen() toklast()

-
-2511  #define tokfix() (tokenbuf[tokidx]='\0')
-2512  #define tok() tokenbuf
-2513  #define toklen() tokidx
-2514  #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
-
-(parse.y)
-
-

There’s probably no question.

-

yylex()

-

yylex() is very long. Currently, there are more than 1000 lines. -The most of them is occupied by a huge switch statement, -it branches based on each character. -First, I’ll show the whole structure that some parts of it are left out.

-

yylex outline

-
-3106  static int
-3107  yylex()
-3108  {
-3109      static ID last_id = 0;
-3110      register int c;
-3111      int space_seen = 0;
-3112      int cmd_state;
-3113
-3114      if (lex_strterm) {
-              /* ... string scan ... */
-3131          return token;
-3132      }
-3133      cmd_state = command_start;
-3134      command_start = Qfalse;
-3135    retry:
-3136      switch (c = nextc()) {
-3137        case '\0':                /* NUL */
-3138        case '\004':              /* ^D */
-3139        case '\032':              /* ^Z */
-3140        case -1:                  /* end of script. */
-3141          return 0;
-3142
-3143          /* white spaces */
-3144        case ' ': case '\t': case '\f': case '\r':
-3145        case '\13': /* '\v' */
-3146          space_seen++;
-3147          goto retry;
-3148
-3149        case '#':         /* it's a comment */
-3150          while ((c = nextc()) != '\n') {
-3151              if (c == -1)
-3152                  return 0;
-3153          }
-3154          /* fall through */
-3155        case '\n':
-              /* ... omission ... */
-
-            case xxxx:
-                :
-              break;
-                :
-            /* branches a lot for each character */
-                :
-                :
-4103        default:
-4104          if (!is_identchar(c) || ISDIGIT(c)) {
-4105              rb_compile_error("Invalid char `\\%03o' in expression", c);
-4106              goto retry;
-4107          }
-4108
-4109          newtok();
-4110          break;
-4111      }
-
-          /* ... deal with ordinary identifiers ... */
-      }
-
-(parse.y)
-
-

As for the return value of yylex(), -zero means that the input has finished, -non-zero means a symbol.

-

Be careful that a extremely concise variable named “c” is used all over this function. -space_seen++ when reading a space will become helpful later.

-

All it has to do as the rest is to keep branching for each character and processing it, -but since continuous monotonic procedure is lasting, it is boring for readers. -Therefore, we’ll narrow them down to a few points. -In this book not all characters will be explained, -but it is easy if you will amplify the same pattern.

-

'!'

-

Let’s start with what is simple first.

-

yylex'!'

-
-3205        case '!':
-3206          lex_state = EXPR_BEG;
-3207          if ((c = nextc()) == '=') {
-3208              return tNEQ;
-3209          }
-3210          if (c == '~') {
-3211              return tNMATCH;
-3212          }
-3213          pushback(c);
-3214          return '!';
-
-(parse.y)
-
-

I wroute out the meaning of the code, -so I’d like you to read them by comparing each other.

-
-case '!':
-  move to EXPR_BEG
-  if (the next character is '=' then) {
-      token is 「!=(tNEQ)」
-  }
-  if (the next character is '~' then) {
-      token is 「!~(tNMATCH)」
-  }
-  if it is neither, push the read character back
-  token is '!'
-
-

This case clause is short, but describes the important rule of the scanner. -It is “the longest match rule”. -The two characters "!=" can be interpreted in two ways: “! and =” or “!=”, -but in this case "!=" must be selected. -The longest match is essential for scanners of programming languages.

-

And, lex_state is the variable represents the state of the scanner. -This will be discussed too much -in the next chapter “Finite-State Scanner”, -you can ignore it for now. -EXPR_BEG indicates “it is clearly at the beginning”. -This is because -whichever it is ! of not or it is != or it is !~, -its next symbol is the beginning of an expression.

-

'<'

-

Next, we’ll try to look at '<' as an example of using yylval (the value of a symbol).

-

yylex'&gt;'

-
-3296        case '>':
-3297          switch (lex_state) {
-3298            case EXPR_FNAME: case EXPR_DOT:
-3299              lex_state = EXPR_ARG; break;
-3300            default:
-3301              lex_state = EXPR_BEG; break;
-3302          }
-3303          if ((c = nextc()) == '=') {
-3304              return tGEQ;
-3305          }
-3306          if (c == '>') {
-3307              if ((c = nextc()) == '=') {
-3308                  yylval.id = tRSHFT;
-3309                  lex_state = EXPR_BEG;
-3310                  return tOP_ASGN;
-3311              }
-3312              pushback(c);
-3313              return tRSHFT;
-3314          }
-3315          pushback(c);
-3316          return '>';
-
-(parse.y)
-
-

The places except for yylval can be ignored. -Concentrating only one point when reading a program is essential.

-

At this point, for the symbol tOP_ASGN of >>=, it set its value tRSHIFT. -Since the used union member is id, its type is ID. -tOP_ASGN is the symbol of self assignment, -it represents all of the things like += and -= and *=. -In order to distinguish them later, -it passes the type of the self assignment as a value.

-

The reason why the self assignments are bundled is, -it makes the rule shorter. -Bundling things that can be bundled at the scanner as much as possible -makes the rule more concise. -Then, why are the binary arithmetic operators not bundled? -It is because they differs in their precedences.

-

':'

-

If scanning is completely independent from parsing, this talk would be simple. -But in reality, it is not that simple. -The Ruby grammar is particularly complex, -it has a somewhat different meaning when there’s a space in front of it, -the way to split tokens is changed depending on the situation around. -The code of ':' shown below is an example that a space changes the behavior.

-

yylex':'

-
-3761        case ':':
-3762          c = nextc();
-3763          if (c == ':') {
-3764              if (lex_state == EXPR_BEG ||  lex_state == EXPR_MID ||
-3765                  (IS_ARG() && space_seen)) {
-3766                  lex_state = EXPR_BEG;
-3767                  return tCOLON3;
-3768              }
-3769              lex_state = EXPR_DOT;
-3770              return tCOLON2;
-3771          }
-3772          pushback(c);
-3773          if (lex_state == EXPR_END ||
-                  lex_state == EXPR_ENDARG ||
-                  ISSPACE(c)) {
-3774              lex_state = EXPR_BEG;
-3775              return ':';
-3776          }
-3777          lex_state = EXPR_FNAME;
-3778          return tSYMBEG;
-
-(parse.y)
-
-

Again, ignoring things relating to lex_state, -I’d like you focus on around space_seen.

-

space_seen is the variable that becomes true when there’s a space before a token. -If it is met, meaning there’s a space in front of '::', it becomes tCOLON3, -if there’s not, it seems to become tCOLON2. -This is as I explained at primary in the previous section.

-

Identifier

-

Until now, since there were only symbols, -it was just a character or 2 characters. -This time, we’ll look at a little long things. -It is the scanning pattern of identifiers.

-

First, the outline of yylex was as follows:

-
-yylex(...)
-{
-    switch (c = nextc()) {
-      case xxxx:
-        ....
-      case xxxx:
-        ....
-      default:
-    }
-
-   the scanning code of identifiers
-}
-
-

The next code is an extract from the end of the huge switch. -This is relatively long, so I’ll show it with comments.

-

yylex — identifiers

-
-4081        case '@':                 /* an instance variable or a class variable */
-4082          c = nextc();
-4083          newtok();
-4084          tokadd('@');
-4085          if (c == '@') {         /* @@, meaning a class variable */
-4086              tokadd('@');
-4087              c = nextc();
-4088          }
-4089          if (ISDIGIT(c)) {       /* @1 and such  */
-4090              if (tokidx == 1) {
-4091    rb_compile_error("`@%c' is not a valid instance variable name", c);
-4092              }
-4093              else {
-4094    rb_compile_error("`@@%c' is not a valid class variable name", c);
-4095              }
-4096          }
-4097          if (!is_identchar(c)) { /* a strange character appears next to @  */
-4098              pushback(c);
-4099              return '@';
-4100          }
-4101          break;
-4102
-4103        default:
-4104          if (!is_identchar(c) || ISDIGIT(c)) {
-4105              rb_compile_error("Invalid char `\\%03o' in expression", c);
-4106              goto retry;
-4107          }
-4108
-4109          newtok();
-4110          break;
-4111      }
-4112
-4113      while (is_identchar(c)) {   /* between characters that can be used as identifieres */
-4114          tokadd(c);
-4115          if (ismbchar(c)) {      /* if it is the head byte of a multi-byte character */
-4116              int i, len = mbclen(c)-1;
-4117
-4118              for (i = 0; i < len; i++) {
-4119                  c = nextc();
-4120                  tokadd(c);
-4121              }
-4122          }
-4123          c = nextc();
-4124      }
-4125      if ((c == '!' || c == '?') &&
-              is_identchar(tok()[0]) &&
-              !peek('=')) {      /* the end character of name! or name? */
-4126          tokadd(c);
-4127      }
-4128      else {
-4129          pushback(c);
-4130      }
-4131      tokfix();
-
-(parse.y)
-
-

Finally, I’d like you focus on the condition -at the place where adding ! or ?. -This part is to interpret in the next way.

-
-obj.m=1       # obj.m  =   1       (not obj.m=)
-obj.m!=1      # obj.m  !=  1       (not obj.m!)
-
-

((errata: this code is not relating to that condition))

-

This is “not” longest-match. -The “longest-match” is a principle but not a constraint. -Sometimes, you can refuse it.

-

The reserved words

-

After scanning the identifiers, there are about 100 lines of the code further -to determine the actual symbols. -In the previous code, instance variables, class variables and local variables, -they are scanned all at once, -but they are categorized here.

-

This is OK but, inside it there’s a little strange part. -It is the part to filter the reserved words. -Since the reserved words are not different from local variables in its -character type, scanning in a bundle and categorizing later is more efficient.

-

Then, assume there’s str that is a char* string, -how can we determine whether it is a reserved word? -First, of course, there’s a way of comparing a lot by if statements and strcmp(). -However, this is completely not smart. It is not flexible. -Its speed will also linearly increase. -Usually, only the data would be separated to a list or a hash -in order to keep the code short.

-
-/* convert the code to data */
-struct entry {char *name; int symbol;};
-struct entry *table[] = {
-    {"if",     kIF},
-    {"unless", kUNLESS},
-    {"while",  kWHILE},
-    /* …… omission …… */
-};
-
-{
-    ....
-    return lookup_symbol(table, tok());
-}
-
-

Then, how ruby is doing is that, it uses a hash table. -Furthermore, it is a perfect hash. -As I said when talking about st_table, -if you knew the set of the possible keys beforehand, -sometimes you could create a hash function that never conflicts. -As for the reserved words, -“the set of the possible keys is known beforehand”, -so it is likely that we can create a perfect hash function.

-

But, “being able to create” and actually creating are different. -Creating manually is too much cumbersome. -Since the reserved words can increase or decrease, -this kind of process must be automated.

-

Therefore, gperf comes in. gperf is one of GNU products, -it generates a perfect function from a set of values. -In order to know the usage of gperf itself in detail, -I recommend to do man gperf. -Here, I’ll only describe how to use the generated result.

-

In ruby the input file for gperf is keywords and the output is lex.c. -parse.y directly #include it. -Basically, doing #include C files is not good, -but performing non-essential file separation for just one function is worse. -Particularly, in ruby, there's the possibility that extern+ functions are -used by extension libraries without being noticed, thus -the function that does not want to keep its compatibility should be static.

-

Then, in the lex.c, a function named rb_reserved_word() is defined. -By calling it with the char* of a reserved word as key, you can look up. -The return value is NULL if not found, struct kwtable* if found -(in other words, if the argument is a reserved word). -The definition of struct kwtable is as follows:

-

kwtable

-
-   1  struct kwtable {char *name; int id[2]; enum lex_state state;};
-
-(keywords)
-
-

name is the name of the reserved word, id[0] is its symbol, -id[1] is its symbol as a modification (kIF_MOD and such). -lex_state is “the lex_state should be moved to after reading this reserved word”. -lex_state will be explained in the next chapter.

-

This is the place where actually looking up.

-

yylex() — identifier — call rb_reserved_word()

-
-4173                  struct kwtable *kw;
-4174
-4175                  /* See if it is a reserved word.  */
-4176                  kw = rb_reserved_word(tok(), toklen());
-4177                  if (kw) {
-
-(parse.y)
-
-

Strings

-

The double quote (") part of yylex() is this.

-

yylex'"'

-
-3318        case '"':
-3319          lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
-3320          return tSTRING_BEG;
-
-(parse.y)
-
-

Surprisingly it finishes after scanning only the first character. -Then, this time, when taking a look at the rule, -tSTRING_BEG is found in the following part:

-

▼ rules for strings

-
-string1         : tSTRING_BEG string_contents tSTRING_END
-
-string_contents :
-                | string_contents string_content
-
-string_content  : tSTRING_CONTENT
-                | tSTRING_DVAR string_dvar
-                | tSTRING_DBEG term_push compstmt '}'
-
-string_dvar     : tGVAR
-                | tIVAR
-                | tCVAR
-                | backref
-
-term_push       :
-
-

These rules are the part introduced to deal with embedded expressions inside of strings. -tSTRING_CONTENT is literal part, -tSTRING_DBEG is "#{". -tSTRING_DVAR represents “# that in front of a variable”. For example,

-
-".....#$gvar...."
-
-

this kind of syntax. -I have not explained but when the embedded expression is only a variable, -{ and } can be left out. -But this is often not recommended. -D of DVAR, DBEG seems the abbreviation of dynamic.

-

And, backref represents the special variables relating to regular expressions, -such as $1 $2 or $& $'.

-

term_push is “a rule defined for its action”.

-

Now, we’ll go back to yylex() here. -If it simply returns the parser, -since its context is the “interior” of a string, -it would be a problem if a variable and if and others are suddenly scanned in -the next yylex(). -What plays an important role there is …

-
-      case '"':
-        lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
-        return tSTRING_BEG;
-
-

lex_strterm. Let’s go back to the beginning of yylex().

-

▼ the beginning of yylex()

-
-3106  static int
-3107  yylex()
-3108  {
-3109      static ID last_id = 0;
-3110      register int c;
-3111      int space_seen = 0;
-3112      int cmd_state;
-3113
-3114      if (lex_strterm) {
-              /* scanning string */
-3131          return token;
-3132      }
-3133      cmd_state = command_start;
-3134      command_start = Qfalse;
-3135    retry:
-3136      switch (c = nextc()) {
-
-(parse.y)
-
-

If lex_strterm exists, it enters the string mode without asking. -It means, conversely speaking, if there’s lex_strterm, -it is while scanning string, -and when parsing the embedded expressions inside strings, -you have to set lex_strterm to 0. -And, when the embedded expression ends, you have to set it back. -This is done in the following part:

-

string_content

-
-1916  string_content  : ....
-1917                  | tSTRING_DBEG term_push
-1918                      {
-1919                          $<num>1 = lex_strnest;
-1920                          $<node>$ = lex_strterm;
-1921                          lex_strterm = 0;
-1922                          lex_state = EXPR_BEG;
-1923                      }
-1924                    compstmt '}'
-1925                      {
-1926                          lex_strnest = $<num>1;
-1927                          quoted_term = $2;
-1928                          lex_strterm = $<node>3;
-1929                          if (($$ = $4) && nd_type($$) == NODE_NEWLINE) {
-1930                              $$ = $$->nd_next;
-1931                              rb_gc_force_recycle((VALUE)$4);
-1932                          }
-1933                          $$ = NEW_EVSTR($$);
-1934                      }
-
-(parse.y)
-
-

In the embedded action, lex_stream is saved as the value of tSTRING_DBEG -(virtually, this is a stack push), -it recovers in the ordinary action (pop). -This is a fairly smart way.

-

But why is it doing this tedious thing? -Can’t it be done by, after scanning normally, -calling yyparse() recursively at the point when it finds #{ ? -There’s actually a problem. -yyparse() can’t be called recursively. -This is the well known limit of yacc. -Since the yyval that is used to receive or pass a value is a global variable, -careless recursive calls can destroy the value. -With bison (yacc of GNU), -recursive calls are possible by using %pure_parser directive, -but the current ruby decided not to assume bison. -In reality, byacc (Berkely yacc) is often used in BSD-derived OS and Windows and such, -if bison is assumed, it causes a little cumbersome.

-

lex_strterm

-

As we’ve seen, when you consider lex_stream as a boolean value, -it represents whether or not the scanner is in the string mode. -But its contents also has a meaning. -First, let’s look at its type.

-

lex_strterm

-
-  72  static NODE *lex_strterm;
-
-(parse.y)
-
-

This definition shows its type is NODE*. -This is the type used for syntax tree and will be discussed in detail -in Chapter 12: Syntax tree construction. -For the time being, it is a structure which has three elements, -since it is VALUE you don’t have to free() it, -you should remember only these two points.

-

NEW_STRTERM()

-
-2865  #define NEW_STRTERM(func, term, paren) \
-2866          rb_node_newnode(NODE_STRTERM, (func), (term), (paren))
-
-(parse.y)
-
-

This is a macro to create a node to be stored in lex_stream. -First, term is the terminal character of the string. -For example, if it is a " string, it is ", -and if it is a ' string, it is '.

-

paren is used to store the corresponding parenthesis when it is a % string. -For example,

-
-%Q(..........)
-
-

in this case, paren stores '('. And, term stores the closing parenthesis ')'. -If it is not a % string, paren is 0.

-

At last, func, this indicates the type of a string. -The available types are decided as follows:

-

func

-
-2775  #define STR_FUNC_ESCAPE 0x01  /* backslash notations such as \n are in effect  */
-2776  #define STR_FUNC_EXPAND 0x02  /* embedded expressions are in effect */
-2777  #define STR_FUNC_REGEXP 0x04  /* it is a regular expression */
-2778  #define STR_FUNC_QWORDS 0x08  /* %w(....) or %W(....) */
-2779  #define STR_FUNC_INDENT 0x20  /* <<-EOS(the finishing symbol can be indented) */
-2780
-2781  enum string_type {
-2782      str_squote = (0),
-2783      str_dquote = (STR_FUNC_EXPAND),
-2784      str_xquote = (STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
-2785      str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
-2786      str_sword  = (STR_FUNC_QWORDS),
-2787      str_dword  = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
-2788  };
-
-(parse.y)
-
-

Each meaning of enum string_type is as follows:

- - - - - - - - - - - - - - - - - - - - - - - - - -
str_squote ' string / %q
str_dquote " string / %Q
str_xquote command string (not be explained in this book)
str_regexp regular expression
str_sword %w
str_dword %W
-

String scan function

-

The rest is reading yylex() in the string mode, -in other words, the if at the beginning.

-

yylex− string

-
-3114      if (lex_strterm) {
-3115          int token;
-3116          if (nd_type(lex_strterm) == NODE_HEREDOC) {
-3117              token = here_document(lex_strterm);
-3118              if (token == tSTRING_END) {
-3119                  lex_strterm = 0;
-3120                  lex_state = EXPR_END;
-3121              }
-3122          }
-3123          else {
-3124              token = parse_string(lex_strterm);
-3125              if (token == tSTRING_END || token == tREGEXP_END) {
-3126                  rb_gc_force_recycle((VALUE)lex_strterm);
-3127                  lex_strterm = 0;
-3128                  lex_state = EXPR_END;
-3129              }
-3130          }
-3131          return token;
-3132      }
-
-(parse.y)
-
-

It is divided into the two major groups: here document and others. -But this time, we won’t read parse_string(). -As I previously described, there are a lot of conditions, -it is tremendously being a spaghetti code. -If I tried to explain it, -odds are high that readers would complain that “it is as the code is written!”. -Furthermore, although it requires a lot of efforts, it is not interesting.

-

But, not explaining at all is also not a good thing to do, -The modified version that functions are separately defined for each target to be scanned -is contained in the attached CD-ROM (doc/parse_string.html). -I’d like readers who are interested in to try to look over it.

-

Here Document

-

In comparison to the ordinary strings, here documents are fairly interesting. -That may be because, unlike the other elements, it deal with a line at a time. -Moreover, it is terrific that the starting symbol can exist in the middle of a program. -First, I’ll show the code of yylex() to scan the starting symbol of a here document.

-

yylex'&lt;'

-
-3260        case '<':
-3261          c = nextc();
-3262          if (c == '<' &&
-3263              lex_state != EXPR_END &&
-3264              lex_state != EXPR_DOT &&
-3265              lex_state != EXPR_ENDARG &&
-3266              lex_state != EXPR_CLASS &&
-3267              (!IS_ARG() || space_seen)) {
-3268              int token = heredoc_identifier();
-3269              if (token) return token;
-
-(parse.y)
-
-

As usual, we’ll ignore the herd of lex_state. -Then, we can see that it reads only “<<” here -and the rest is scanned at heredoc_identifier().
-Therefore, here is heredoc_identifier().

-

heredoc_identifier()

-
-2926  static int
-2927  heredoc_identifier()
-2928  {
-          /* ... omission ... reading the starting symbol */
-2979      tokfix();
-2980      len = lex_p - lex_pbeg;   /*(A)*/
-2981      lex_p = lex_pend;         /*(B)*/
-2982      lex_strterm = rb_node_newnode(NODE_HEREDOC,
-2983                          rb_str_new(tok(), toklen()),  /* nd_lit */
-2984                          len,                          /* nd_nth */
-2985          /*(C)*/       lex_lastline);                /* nd_orig */
-2986
-2987      return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
-2988  }
-
-(parse.y)
-
-

The part which reads the starting symbol (<<EOS) is not important, so it is totally left out. -Until now, the input buffer probably has become as depicted as Figure 10. -Let’s recall that the input buffer reads a line at a time.

-

-

(lexparams)
-Figure 10: scanning "printf\(<<EOS,n\)"

-

-

What heredoc_identifier() is doing is as follows:
-(A) len is the number of read bytes in the current line.
-(B) and, suddenly move lex_p to the end of the line.
-It means that in the read line, the part after the starting symbol is read but -not parsed. When is that rest part parsed? -For this mystery, a hint is that at (C) the lex_lastline (the currently -read line) and len (the length that has already read) are saved.

-

Then, the dynamic call graph before and after heredoc_identifier is simply -shown below:

-
-yyparse
-    yylex(case '<')
-        heredoc_identifier(lex_strterm = ....)
-    yylex(the beginning if)
-        here_document
-
-

And, this here_document() is doing the scan of the body of the here document. -Omitting invalid cases and adding some comments, -heredoc_identifier() is shown below. -Notice that lex_strterm remains unchanged after it was set at heredoc_identifier().

-

here_document()(simplified)

-
-here_document(NODE *here)
-{
-    VALUE line;                      /* the line currently being scanned */
-    VALUE str = rb_str_new("", 0);   /* a string to store the results */
-
-    /* ... handling invalid conditions, omitted ... */
-
-    if (embeded expressions not in effect) {
-        do {
-            line = lex_lastline;     /*(A)*/
-            rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len);
-            lex_p = lex_pend;        /*(B)*/
-            if (nextc() == -1) {     /*(C)*/
-                goto error;
-            }
-        } while (the currently read line is not equal to the finishing symbol);
-    }
-    else {
-        /* the embeded expressions are available ... omitted */
-    }
-    heredoc_restore(lex_strterm);
-    lex_strterm = NEW_STRTERM(-1, 0, 0);
-    yylval.node = NEW_STR(str);
-    return tSTRING_CONTENT;
-}
-
-

rb_str_cat() is the function to connect a char* at the end of a Ruby string. -It means that the currently being read line lex_lastline is connected to -str at (A). After it is connected, there’s no use of the current line. -At (B), suddenly moving lex_p to the end of line. -And (C) is a problem, in this place, it looks like doing the check whether -it is finished, but actually the next “line” is read. -I’d like you to recall that nextc() automatically reads the next line when -the current line has finished to be read. -So, since the current line is forcibly finished at (B), -lex_p moves to the next line at (C).

-

And finally, leaving the do ~ while loop, it is heredoc_restore().

-

heredoc_restore()

-
-2990  static void
-2991  heredoc_restore(here)
-2992      NODE *here;
-2993  {
-2994      VALUE line = here->nd_orig;
-2995      lex_lastline = line;
-2996      lex_pbeg = RSTRING(line)->ptr;
-2997      lex_pend = lex_pbeg + RSTRING(line)->len;
-2998      lex_p = lex_pbeg + here->nd_nth;
-2999      heredoc_end = ruby_sourceline;
-3000      ruby_sourceline = nd_line(here);
-3001      rb_gc_force_recycle(here->nd_lit);
-3002      rb_gc_force_recycle((VALUE)here);
-3003  }
-
-(parse.y)
-
-

here->nd_orig holds the line which contains the starting symbol.
-here->nd_nth holds the length already read in the line contains the starting -symbol.
-It means it can continue to scan from the just after the starting symbol -as if there was nothing happened. (Figure 11)

-

-

(heredoc)
-Figure 11: The picture of assignation of scanning Here Document

-

- - - -
- - diff --git a/htmls/preface.html b/htmls/preface.html deleted file mode 100644 index c2b0464..0000000 --- a/htmls/preface.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Preface

-

This book explores several themes with the following goals in mind:

-

To have knowledge of the structure of ruby -To gain knowledge about language processing systems in general -To acquire skills in reading source code

-

Ruby is an object-oriented language developed by Yukihiro Matsumoto. The -official implementation of the Ruby language is called ruby. It is actively -developed and maintained by the open source community. Our first goal is to -understand the inner-workings of the ruby implementation. This book is going -to investigate ruby as a whole.

-

Secondly, by knowing about the implementation of Ruby, we will be able to know -about other language processing systems. I tried to cover all topics necessary -for implementing a language, such as hash table, scanner and parser, evaluation -procedure, and many others. Although this book is not intended as a text book -and I don’t go through entire topics and schemes for a language processing -system, I tried to include adequate explanations about these concepts. For -those who are not familiar with the Ruby language yet, a brief summary is -included to help understand the topics.

-

The main themes of this book are the first and the second point above. Though, -what I want to emphasize the most is the third one: To acquire skill in reading -source code. I dare to say it’s a “hidden” theme. I will explain why we need -this.

-

It is often said “To be a skilled programmer, you should read source code -written by others.” This is certainly true. But I haven’t found a book that -explains how you can actually do it. There are many books that explain OS -kernels and the interior of language processing systems by showing the concrete -structure or “the answer,” but they don’t explain the way to reach that answer. -It’s clearly one-sided.

-

Can you, perhaps, naturally read code just because you know how to write a -program? Is it so easy to read code that all programmers are already able to -read any code by another programmer? I don’t think so. To be skilled in -reading code is certainly as difficult as writing code.

-

In light of such questions, this book doesn’t simply provide a general -explanation of the ruby language, but demonstrates procedures for analyzing -source code. When I started writing this book, I had some experience with the -Ruby language, but I did not fully understand the inner structure of the ruby -implementation. In other words, this book begins exploring ruby from the same -starting place as the reader. This book is the summary of the process and -results of my code analysis from that point.

-

I asked Yukihiro Matsumoto, the author of ruby, for supervision. But I -thought the spirit of this book would be lost if each analysis was monitored by -the author of the language himself. Therefore I limited his review to the final -stage of writing. In this way, I tried to assure the correctness of the -contents, keeping the goal of reading code alive at the same time.

-

To be honest, this book is not easy. In the very least, it is limited in its -simplicity by the inherent complexity of its aim. However, this complexity may -be what makes the book interesting to you. Do you find it interesting to be -chattering around a piece of cake? Do you take to your desk to solve a puzzle -that you know the answer to in a heartbeat? How about a suspense novel whose -criminal you can guess halfway through? If you really want to come to new -knowledge, you need to solve a problem engaging all your capacities. This is -the book that lets you practice such idealism exhaustively. “I think, -therefore it’s fun!” Everybody who finds it fun gives pleasure to the author.

-

Target audience

-

Firstly, knowledge about the Ruby language isn’t required. However, since the -knowledge of the Ruby language is absolutely necessary to understand certain -explanations of its structure, supplementary explanations of the language are -inserted here and there.

-

Knowledge about the C language is required, to some extent. I assume you have -experience calling malloc() to assign a list or stack, and have used function -pointer at least a few times.

-

This book doesn’t provide a proper introduction to an object-oriented language. -You will have a difficult time if you don’t know the basics of at least one -object-oriented language. Furthermore, some examples are given in Java and C++.

-

Structure of this book

-

This book has four main parts:

-

Part 1: Objects -Part 2: Syntactic analysis -Part 3: Evaluation -Part 4: Peripheral around the evaluator

-

Supplementary chapters are included at the beginning of each part when -necessary. These provide a basic introduction for those who are not familiar -with Ruby and the general mechanism of a language processing system.

-

Now, we are going through the overview of the four main parts. The symbol in -parentheses after the explanation indicates the difficulty gauge. They are ©, -(B), (A) in order of easy to hard, (S) being the highest.

-

Part 1: Object

-

Chapter 1: Focuses the basics of Ruby to get ready to accomplish Part 1. © -Chapter 2: Gives concrete inner structure of Ruby objects. © -Chapter 3: States about hash table. © -Chapter 4: Writes about Ruby class system. You may read through this chapter quickly at first, because it tells plenty of abstract stories. (A) -Chapter 5: Shows the garbage collector which is responsible for generating and releasing objects. The first story in low-level series. (B) -Chapter 6: Describes the implementation of global variables, class variables, and constants. © -Chapter 7: Outline of the security features of Ruby. ©

-

Part 2: Syntactic analysis

-

Chapter 8: Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. © -Chapter 9: Introduction to yacc required to read the syntax file at least. (B) -Chapter 10: Look through the rules and physical structure of the parser. (A) -Chapter 11: Explore around the peripherals of lex_state, which is the most difficult part of the parser. The most difficult part of this book. (S) -Chapter 12: Finalization of Part 2 and connection to Part 3. ©

-

Part 3: Evaluator

-

Chapter 13: Describe the basic mechanism of the evaluator. © -Chapter 14: Reads the evaluation stack that creates the main context of Ruby. (A) -Chapter 15: Talks about search and initialization of methods. (B) -Chapter 16: Defies the implementation of the iterator, the most characteristic feature of Ruby. (A) -Chapter 17: Describe the implementation of the eval methods. (B)

-

Part 4: Peripheral around the evaluator

-

Chapter 18: Run-time loading of libraries in C and Ruby. (B) -Chapter 19: Describes the implementation of thread at the end of the core part. (A)

-

Environment

-

This book describes on ruby 1.7.3 2002-09-12 version. It’s attached on the -CD-ROM. Choose any one of ruby-rhg.tar.gz, ruby-rhg.lzh, or ruby-rhg.zip -according to your convenience. Content is the same for all. Alternatively you -can obtain from the support site (footnote{@http://i.loveruby.net/ja/rhg/@}) of -this book.

-

For the publication of this book, the following build environment was prepared -for confirmation of compiling and testing the basic operation. The details of -this build test are given in @ doc/buildtest.html@ in the attached CD-ROM. -However, it doesn’t necessarily assume the probability of the execution even -under the same environment listed in the table. The author doesn’t guarantee -in any form the execution of ruby.

-

BeOS 5 Personal Edition/i386 -Debian GNU/Linux potato/i386 -Debian GNU/Linux woody/i386 -Debian GNU/Linux sid/i386 -FreeBSD 4.4-RELEASE/Alpha (Requires the local patch for this book) -FreeBSD 4.5-RELEASE/i386 -FreeBSD 4.5-RELEASE/PC98 -FreeBSD 5-CURRENT/i386 -HP-UX 10.20 -HP-UX 11.00 (32bit mode) -HP-UX 11.11 (32bit mode) -Mac OS X 10.2 -NetBSD 1.6F/i386 -OpenBSD 3.1 -Plamo Linux 2.0/i386 -Linux for PlayStation2 Release 1.0 -Redhat Linux 7.3/i386 -Solaris 2.6/Sparc -Solaris 8/Sparc -UX/4800 -Vine Linux 2.1.5 -Vine Linux 2.5 -VineSeed -Windows 98SE (Cygwin, MinGW+Cygwin, MinGW+MSYS) -Windows Me (Borland C++ Compiler 5.5, Cygwin, MinGW+Cygwin, MinGW+MSYS, Visual C++ 6) -Windows NT 4.0 (Cygwin, MinGW+Cygwin) -Windows 2000 (Borland C++ Compiler 5.5, Visual C++ 6, Visual C++.NET) -Windows XP (Visual C++.NET, MinGW+Cygwin)

-

These numerous tests aren’t of a lone effort by the author. Those test build -couldn’t be achieved without magnificent cooperations by the people listed -below.

-

I’d like to extend warmest thanks from my heart.

-

Tietew -kjana -nyasu -sakazuki -Masahiro Sato -Kenichi Tamura -Morikyu -Yuya Kato -Yasuhiro Kubo -Kentaro Goto -Tomoyuki Shimomura -Masaki Sukeda -Koji Arai -Kazuhiro Nishiyama -Shinya Kawaji -Tetsuya Watanabe -Naokuni Fujimoto

-

However, the author owes the responsibility for this test. Please refrain from -attempting to contact these people directly. If there’s any flaw in execution, -please be advised to contact the author by e-mail: @aamine@loveruby.net@.

-

Web site

-

The web site for this book is http://i.loveruby.net/ja/rhg/. -I will add information about related programs and additional documentation, as -well as errata. In addition, I’m going to publisize the first few chapters of -this book at the same time of the release. I will look for a certain -circumstance to publicize more chapters, and the whole contents of the book -will beat this website. at the end.

-

Acknowledgment

-

First of all, I would like to thank Mr. Yukihiro Matsumoto. He is the author of -Ruby, and he made it in public as an open source software. Not only he -willingly approved me to publish a book about analyzing ruby, but also he -agreed to supervise the content of it. In addition, he helped my stay in -Florida with simultaneous translation. There are plenty of things beyond -enumeration I have to say thanks to him. Instead of writing all the things, I -give this book to him.

-

Next, I would like to thank arton, who proposed me to publish this book. The -words of arton always moves me. One of the things I’m currently struggled due -to his words is that I have no reason I don’t get a .NET machine.

-

Koji Arai, the ‘captain’ of documentation in the Ruby society, conducted a -scrutiny review as if he became the official editor of this book while I was -not told so. I thank all his review.

-

Also I’d like to mention those who gave me comments, pointed out mistakes and -submitted proposals about the construction of the book throughout all my work.

-

Tietew, -Yuya, -Kawaji, -Gotoken, -Tamura, -Funaba, -Morikyu, -Ishizuka, -Shimomura, -Kubo, -Sukeda, -Nishiyama, -Fujimoto, -Yanagawa, -(I’m sorry if there’s any people missing), -I thank all those people contributed.

-

As a final note, I thank Otsuka , Haruta, and Kanemitsu who you for arranging -everything despite my broke deadline as much as four times, and that the -manuscript exceeded 200 pages than originally planned.

-

I cannot expand the full list here to mention the name of all people -contributed to this book, but I say that I couldn’t successfully publish this -book without such assistance. Let me take this place to express my -appreciation. Thank you very much.

-

p(=right).

-

If you want to send remarks, suggestions and reports of typographcal errors, -please address to " <aamine@loveruby.net>":mailto:aamine@loveruby.net.

-

""Rubyソースコード完全解説" can be reserved/ordered at ImpressDirect. “:http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721”(Jump to the introduction page)":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721

-

Copyright © 2002-2004 Minero Aoki, All rights reserved.

- - - -
- - diff --git a/htmls/security.html b/htmls/security.html deleted file mode 100644 index c68395d..0000000 --- a/htmls/security.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Security | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Clifford Escobar CAOILE & ocha-

-

Chapter 7: Security

-

Fundamentals

-

I say security but I don’t mean passwords or encryption. The Ruby security -feature is used for handling untrusted objects in a environment like CGI -programming.

-

For example, when you want to convert a string representing a number into a -integer, you can use the eval method. However. eval is a method that “runs -a string as a Ruby program.” If you eval a string from a unknown person from -the network, it is very dangerous. However for the programmer to fully -differentiate between safe and unsafe things is very tiresome and cumbersome. -Therefore, it is for certain that a mistake will be made. So, let us make it -part of the language, was reasoning for this feature.

-

So then, how Ruby protect us from that sort of danger? Causes of dangerous -operations, for example, opening unintended files, are roughly divided into two -groups:

-
    -
  • Dangerous data
  • -
  • Dangerous code
  • -
-

For the former, the code that handles these values is created by the -programmers themselves, so therefore it is (relatively) safe. For the latter, -the program code absolutely cannot be trusted.

-

Because the solution is vastly different between the two causes, it is important to -differentiate them by level. This are called security levels. The Ruby security -level is represented by the $SAFE global variable. The value ranges from -minimum value 0 to maximum value 4. When the variable is assigned, the level -increases. Once the level is raised it can never be lowered. And for each -level, the operations are limited.

-

I will not explain level 1 or 3. -Level 0 is the normal program environment and the security system is not -running. Level 2 handles dangerous values. Level 4 handles dangerous code. -We can skip 0 and move on to explain in detail levels 2 and 4.

-

((errata: Level 1 handles dangerous values. -“Level 2 has no use currently” is right.))

-

Level 1

-

This level is for dangerous data, for example, in normal CGI -applications, etc.

-

A per-object “tainted mark” serves as the basis for the Level 1 -implementation. All objects read in externally are marked tainted, and -any attempt to eval or File.open with a tainted object will cause an -exception to be raised and the attempt will be stopped.

-

This tainted mark is “infectious”. For example, when taking a part of a -tainted string, that part is also tainted.

-

Level 4

-

This level is for dangerous programs, for example, running external -(unknown) programs, etc.

-

At level 1, operations and the data it uses are checked, but at level -4, operations themselves are restricted. For example, exit, file -I/O, thread manipulation, redefining methods, etc. Of course, the -tainted mark information is used, but basically the operations are the -criteria.

-

Unit of Security

-

$SAFE looks like a global variable but is in actuality a thread -local variable. In other words, Ruby’s security system works on units -of thread. In Java and .NET, rights can be set per component (object), -but Ruby does not implement that. The assumed main target was probably -CGI.

-

Therefore, if one wants to raise the security level of one part of the -program, then it should be made into a different thread and have its -security level raised. I haven’t yet explained how to create a thread, -but I will show an example here:

-
-# Raise the security level in a different thread
-p($SAFE)   # 0 is the default
-Thread.fork {    # Start a different thread
-    $SAFE = 4    # Raise the level
-    eval(str)    # Run the dangerous program
-}
-p($SAFE)   # Outside of the block, the level is still 0
-
-

Reliability of $SAFE

-

Even with implementing the spreading of tainted marks, or restricting -operations, ultimately it is still handled manually. In other words, -internal libraries and external libraries must be completely -compatible and if they don’t, then the partway the “tainted” operations -will not spread and the security will be lost. And actually this kind -of hole is often reported. For this reason, this writer does not -wholly trust it.

-

That is not to say, of course, that all Ruby programs are dangerous. -Even at $SAFE=0 it is possible to write a secure program, and even -at $SAFE=4 it is possible to write a program that fits your whim. -However, one cannot put too much confidence on $SAFE (yet).

-

In the first place, functionality and security do not go together. It -is common sense that adding new features can make holes easier to -open. Therefore it is prudent to think that ruby can probably be -dangerous.

-

Implementation

-

From now on, we’ll start to look into its implementation. -In order to wholly grasp the security system of ruby, -we have to look at “where is being checked” rather than its mechanism. -However, this time we don’t have enough pages to do it, -and just listing them up is not interesting. -Therefore, in this chapter, I’ll only describe about the -mechanism used for security checks. -The APIs to check are mainly these below two:

-
    -
  • rb_secure(n) : If more than or equal to level n, it would raise SecurityError.
  • -
  • SafeStringValue() : - If more than or equal to level 1 and a string is tainted, - then it would raise an exception.
  • -
-

We won’t read SafeStringValue() here.

-

Tainted Mark

-

The taint mark is, to be concrete, the FL_TAINT flag, which is set to -basic->flags, and what is used to infect it is the OBJ_INFECT() macro. -Here is its usage.

-
-OBJ_TAINT(obj)            /* set FL_TAINT to obj */
-OBJ_TAINTED(obj)          /* check if FL_TAINT is set to obj */
-OBJ_INFECT(dest, src)     /* infect FL_TAINT from src to dest */
-
-

Since OBJ_TAINT() and OBJ_TAINTED() can be assumed not important, -let’s briefly look over only OBJ_INFECT().

-

OBJ_INFECT

-
- 441  #define OBJ_INFECT(x,s) do {                             \
-          if (FL_ABLE(x) && FL_ABLE(s))                        \
-              RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT; \
-      } while (0)
-
-(ruby.h)
-
-

FL_ABLE() checks if the argument VALUE is a pointer or not. -If the both objects are pointers (it means each of them has its flags member), -it would propagate the flag.

-

$SAFE

-

ruby_safe_level

-
- 124  int ruby_safe_level = 0;
-
-7401  static void
-7402  safe_setter(val)
-7403      VALUE val;
-7404  {
-7405      int level = NUM2INT(val);
-7406
-7407      if (level < ruby_safe_level) {
-7408          rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
-7409                   ruby_safe_level, level);
-7410      }
-7411      ruby_safe_level = level;
-7412      curr_thread->safe = level;
-7413  }
-
-(eval.c)
-
-

The substance of $SAFE is ruby_safe_level in eval.c. -As I previously wrote, $SAFE is local to each thread, -It needs to be written in eval.c where the implementation of threads is located. -In other words, it is in eval.c only because of the restrictions of C, -but it can essentially be located in another place.

-

safe_setter() is the setter of the $SAFE global variable. -It means, because this function is the only way to access it from Ruby level, -the security level cannot be lowered.

-

However, as you can see, from C level, -because static is not attached to ruby_safe_level, -you can ignore the interface and modify the security level.

-

rb_secure()

-

rb_secure()

-
- 136  void
- 137  rb_secure(level)
- 138      int level;
- 139  {
- 140      if (level <= ruby_safe_level) {
- 141          rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
- 142                   rb_id2name(ruby_frame->last_func), ruby_safe_level);
- 143      }
- 144  }
-
-(eval.c)
-
-

If the current safe level is more than or equal to level, -this would raise SecurityError. It’s simple.

- - - -
- - diff --git a/htmls/spec.html b/htmls/spec.html deleted file mode 100644 index 151ac38..0000000 --- a/htmls/spec.html +++ /dev/null @@ -1,1675 +0,0 @@ - - - - - Ruby Language Details | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 8 : Ruby Language Details

-

I’ll talk about the details of Ruby’s syntax and evaluation, -which haven’t been covered yet. I didn’t intend a complete exposition, -so I left out everything which doesn’t come up in this book. -That’s why you won’t be able to write Ruby programs just by -reading this. A complete exposition can be found in the -\footnote{Ruby reference manual: archives/ruby-refm.tar.gz in the attached CD-ROM}

-

Readers who know Ruby can skip over this chapter.

-

Literals

-

The expressiveness of Ruby’s literals is extremely high. -What distinguishes Ruby as a scripting language -is firstly the existence of -the toplevel, secondly it’s the expressiveness of its literals in my -opinion. Thirdly it might be the richness of its standard library.

-

The literals have already as elements enormous power, but even more -when combined. Especially that one can create complex literals from -hash and array literals is a great advantage of Ruby. One can simply -write down a hash of arrays of regular expressions for instance.

-

Let’s look at the valid expressions one by one.

-

Strings

-

Strings and regular expressions can’t be missing in a scripting language. -There is a great variety of string literals.

-

Single Quoted Strings

-
-'string'              # 「string」
-'\\begin{document}'   # 「\begin{document}」
-'\n'                  # 「\n」backslash and an n, no newline
-'\1'                  # 「\1」backslash and 1
-'\''                  # 「'」
-
-

This is the simplest form. In C everything enclosed in single quotes becomes a -string, it’s the same in Ruby. Let’s call this a '-string. The backslash escape -is in effect only for \ itself and '. If one puts a backslash -in front of another character the backslash remains as for example -in the fourth example.

-

And Ruby’s strings aren’t divided by newline characters. -If we write a string over several lines the newlines are contained -in the string.

-
-'multi
-    line
-        string'
-
-

And if the -K option is given to the ruby command multibyte strings -will be accepted. At present the three encodings EUC-JP (-Ke), -Shift JIS (-Ks), and UTF8 (-Ku) can be specified. (Translator’s note: --K option was removed in Ruby 1.9)

-
-'「漢字が通る」と「マルチバイト文字が通る」はちょっと違う'
-# 'There's a little difference between "Kanji are accepted" and "Multibyte characters are accepted".'
-
-

Double Quoted Strings

-
-"string"              # 「string」
-"\n"                  # newline
-"\x0f"               # a byte given in hexadecimal form
-"page#{n}.html"       # embedding a command
-
-

With double quotes we can use command expansion and backslash notation. -The backslash notation is classical, it was already supported in C, -\n is a newline, \b is a backspace, this kind of notation. -In Ruby also Ctrl-C and ESC can be expressed, that’s convenient. -It’s probably of no use to list the whole notation here.

-

On the other hand, expression expansion is even more fantastic. -We can write an arbitrary Ruby expression inside #{ } and it -will be evaluated at runtime and embedded into the string. There -are no limitations like only one variable or only one method. -This is not a mere literal anymore but a whole expression representing -a string.

-
-"embedded #{lvar} expression"
-"embedded #{@ivar} expression"
-"embedded #{1 + 1} expression"
-"embedded #{method_call(arg)} expression"
-"embedded #{"string in string"} expression"
-
-

Strings with %

-
-%q(string)            # same as 'string'
-%Q(string)            # same as "string"
-%(string)             # same as %Q(string) or "string"
-
-

If a lot of separator characters appear in a string, escaping all of them -becomes a burden. In that case the separator characters can be -changed. The string which contains the one character " can be -written with a % string as follows:

-
-"<a href=\"http://i.loveruby.net#{path}\">"
-%Q(")
-
-

The expression isn’t shorter, but nicer to look at. -When we have to escape more often, it even becomes more concise.

-

Here we have used parentheses as delimiters, but something else is fine, -too. Like brackets or braces or #. Almost every symbol is fine, even -%.

-
-%q#this is string#
-%q[this is string]
-%q%this is string%
-
-

Here Documents

-

Here documents are a syntactical device where one or more lines can -form a string. A normal string starts right after the delimiter " -and takes everything until the ending ". Here documents start -at the line after a <<EOS and end at the line before the ending EOS.

-
-
-<<EOS
-All lines between the starting and
-the ending line are in this
-here document
-EOS
-
-

Here we used EOS as identifier but any word is fine. -Precisely speaking all the character matching [a-zA-Z_0-9] can be used.

-

The characteristic of a here document is that every line between -the start symbol and the ending symbol will form a string. The line -which contains the start symbol delimits the string. -That’s why the position of the start symbol is not important. -It can even be in the middle of an expression:

-
-printf(<<EOS, count_n(str))
-count=%d
-EOS
-
-

In this case the string "count=%d\n" goes in the place of <<EOS. -So it’s the same as the following.

-
-printf("count=%d\n", count_n(str))
-
-

The start symbol can be somewhere in the line, but there are strict -rules for the ending symbol: It must be at the beginning of the line -and there must not be another letter in that line. However -if we write the start symbol with a minus like this <<-EOS we -can indent the line with the end symbol.

-
-     <<-EOS
-It would be convenient if one could indent the content
-of a here document. But that's not possible.
-If you want that, the best way is to write
-a method which delete the indent. But beware
-of tabs.
-     EOS
-
-

Furthermore, the start symbol can be enclosed in single or double quotes. -Then the properties of the whole here document change. -When we change <<EOS to <<"EOS" we can use command expression -imbedding and backslash notation.

-
-    <<"EOS"
-One day is #{24 * 60 * 60} seconds.
-Incredible.
-EOS
-
-

But <<'EOS' is not the same as a single quoted string. It starts -the complete literal mode. Everything even backslashes go -into the string as they are typed. This is useful for a string which -contains many backslashes.

-

In the second part we also explain how a here document is passed. -But I’d like you to guess it before. -(Translators Note: In Ruby 1.8 and 1.9 expression expansion and -backslash notation can be used in a normal here document. -There does not seem to be a difference anymore to a double quote enclosed -here document.)

-

Characters

-

Ruby strings are byte strings, there are no character objects. -Instead there are the following expressions which return the -integers which correspond a certain character in ASCII code.

-
-?a                    # the integer which corresponds to 「a」
-?.                    # the integer which corresponds to 「.」
-?\n                   # LF
-?\C-a                 # Ctrl-a
-
-

(Translator’s note: Strings in Ruby 1.9 are not byte strings anymore, -they have an attached encoding. ?a returns the string "a" in Ruby1.9)

-

Regular Expressions

-
-/regexp/
-/^Content-Length:/i
-/正規表現/
-/\/\*.*?\*\//m        # An expression which matches C comments
-/reg#{1 + 1}exp/      # the same as /reg2exp/
-
-

What is contained between slashes is a regular expression. -Regular expressions are a language to designate string patterns. -For example

-
-/abc/
-
-

This regular expression matches a string where there’s an a followed -by a b followed by a c. It matches “abc” or “fffffffabc” or -“abcxxxxx”.

-

One can designate more special patterns.

-
-/^From:/
-
-

This matches a string where there’s a From followed by a : at -the beginning. There are several more expressions of this kind, -such that one can create quite complex patterns.

-

The uses are infinite: -Changing the matched part to another string, deleting the matched part, -determining if there’s one match and and and…

-

A more concrete use case would be extracting the From: header -from a mail. Then changing the \n to an \r and -checking if the rest looks like a mail address.

-

The regular expressions form an independent language, it has -it’s own parser and evaluator within ruby. It can be found in regex.c -in the Ruby source. In effect from a grammar view point they are -treated the same as strings. Escapes, backslash notation and command -embedding can be used almost the same as in strings.

-

Of course regular expressions and strings are treated the same -in the Ruby syntax only. Regular expressions themselves are a language -of their own with own rules which have to be obeyed. This is a subject -of a whole other book. We won’t go deeper into that here. -Refer for instance to Jeffrey Friedl, Regular expressions.

-

Regular Expressions with %

-

Also as with strings, regular expressions also have a syntax for changing -delimiters. In this case it is %r. Here just some examples.

-
-%r(regexp)
-%r[/\*.*?\*/]            # matches a C comment
-%r("(?:[^"\\]+|\\.)*")   # matches a string in C
-%r{reg#{1 + 1}exp}       # imbedding a Ruby expression
-
-

Arrays

-

An array literal is contained in brackets [], elements are separated -by commas.

-
-[1, 2, 3]
-['This', 'is', 'an', 'array', 'of', 'string']
-
-[/regexp/, {'hash'=>3}, 4, 'string', ?\C-a]
-
-lvar = $gvar = @ivar = @@cvar = nil
-[lvar, $gvar, @ivar, @@cvar]
-[Object.new(), Object.new(), Object.new()]
-
-

Ruby’s arrays are a list of arbitrary objects. From a syntactical -standpoint it’s characteristic is, that -the elements can be arbitrary expressions. As mentioned earlier, -an array of hashes of regular expressions can easily be made. -Not just literals but also variables or method calls can also be -put together.

-

And as with the other literals note that this is really an “expression -which generates an array object”

-
-i = 0
-while i < 5
-  p([1,2,3].id)    # Each time another object id is shown.
-  i += 1
-end
-
-

Word Arrays

-

When writing scripts one uses arrays of strings a lot, hence -there is a special notation only for arrays of strings. -That is %w. With an example it’s immediately obvious.

-
-%w( alpha beta gamma delta )   # ['alpha','beta','gamma','delta']
-%w( 月 火 水 木 金 土 日 )
-%w( Jan Feb Mar Apr May Jun
-    Jul Aug Sep Oct Nov Dec )
-
-

There’s also %W where command embedding can be used. -It’s a relatively recent implementation.

-
-n = 5
-%w( list0 list#{n} )   # ['list0', 'list#{n}']
-%W( list0 list#{n} )   # ['list0', 'list5']
-
-

The author hasn’t come up with a good use yet.

-

Hashes

-

Hash tables are data structure which store a one-to-one relation between -arbitrary objects. The following expressions generate a table.

-
-{ 'key' => 'value', 'key2' => 'value2' }
-{ 3 => 0, 'string' => 5, ['array'] => 9 }
-{ Object.new() => 3, Object.new() => 'string' }
-
-# Of course we can put it in several lines.
-{ 0 => 0,
-  1 => 3,
-  2 => 6 }
-
-

We explained hashes in detail in the third chapter “Names and -Nametables”. They are fast lookup tables which allocate memory slots depending -on the hash values. In Ruby grammar, -both keys and values can be arbitrary expressions.

-

Furthermore inside the argument of a method call the {...} can be omitted.

-
-  some_method(arg, key => value, key2 => value2)
-# some_method(arg, {key => value, key2 => value2}) # same as above
-
-

With this we can imitate named arguments.

-
-button.set_geometry('x' => 80, 'y' => '240')
-
-

Of course in this case set_geometry must accept a hash as input. -Real keyword arguments will be transformed into parameter variables, though. -With a passed hash it is not quite the real thing.

-

Ranges

-

Range literals are oddballs which don’t appear in most other languages. -Here are some expressions which generate Range objects.

-
-0..5          # from 0 to 5 containing 5
-0...5         # from 0 to 5 not containing 5
-1+2 .. 9+0    # from 3 to 9 containing 9
-'a'..'z'      # strings from 'a' to 'z' containing 'z'
-
-

If there are two dots the last element is included. If there -are three dots it is not included. Not only integers but also floats -and strings can be made into ranges, even arbitrary objects can -be used in ranges. Syntactically arbitrary expressions can be -used as delimiters of a range object. If the returned object cannot -be made into a range there will be a runtime error.

-

Besides, the precedence of .. and ... is quite low. Here’s a surprising -interpretation.

-
-1..5.to_a()   # 1..(5.to_a())
-
-

I thinks the Ruby grammar is really intuitive, -but I do not like this.

-

Symbols

-

In the first part we talked about symbols at length. -They are something which corresponds one-to-one to strings. -In Ruby symbols are expressed with a : in front.

-
-:identifier
-:abcde
-
-

These are pretty standard examples. But all symbol and method -names become symbols with a : in front. Like this:

-
-:$gvar
-:@ivar
-:@@cvar
-:CONST
-
-

We haven’t shown any method names so far. Of course [] or attr= -can be used as symbols too.

-
-:[]
-:attr=
-
-

When one uses these symbols as values in an array, it’ll look quite -complicated.

-

Numerical Values

-

This is the least interesting. It might be added that

-
-1_000_000
-
-

becomes one million and that underscores can be used inside a number. -But that isn’t particularly interesting. This is it about numerical -values in this book. We’ll completely forget them from here on.

-

Methods

-

Let’s talk about the definition and calling of methods.

-

Definition and Calls

-
-def some_method( arg )
-  ....
-end
-
-class C
-  def some_method( arg )
-    ....
-  end
-end
-
-

Methods are defined with def. If they are defined at toplevel -they become function style methods, inside a class they become -methods of this class. To call a method which was defined in a class, -one usually has to create an instance with new as shown below.

-
-C.new().some_method(0)
-
-

The Return Value of Methods

-

The return value of a method is the value of a return statement -if it runs across one. -If there is none it’s the value of the last statement.

-
-def one()     # 1 is returned
-  return 1
-  999
-end
-
-def two()     # 2 is returned
-  999
-  2
-end
-
-def three()   # 3 is returned
-  if true then
-    3
-  else
-    999
-  end
-end
-
-

If the method body is empty nil is returned -and an expression without a value cannot put at the end. -Hence every method has a return value.

-

Optional Arguments

-

Optional arguments can also be defined. If the number of arguments -doesn’t suffice the parameters are automatically assigned to a -default value.

-
-def some_method( arg = 9 )  # default value is 9
-  p arg
-end
-
-some_method(0)    # 0 is shown.
-some_method()     # The default value 9 is shown.
-
-

There can also be several optional arguments. -But in that case they must all come at the end. It is not -possible to make an argument in the middle optional. -It would be unclear how this should be made sense of.

-
-def right_decl( arg1, arg2, darg1 = nil, darg2 = nil )
-  ....
-end
-
-# This is not possible
-def wrong_decl( arg, default = nil, arg2 )  # A middle argument cannot be optional
-  ....
-end
-
-

Omitting argument parantheses

-

The parentheses from a method call can be omitted.

-
-puts 'Hello, World!'   # puts("Hello, World")
-obj = Object.new       # obj = Object.new()
-
-

In Python leaving out parentheses gets the method object, but -there is no such thing in Ruby.

-

We can also omit parentheses within the arguments itself.

-
-  puts(File.basename fname)
-# puts(File.basename(fname)) same as the above
-
-

If we like we can even leave out more

-
-  puts File.basename fname
-# puts(File.basename(fname))  same as the above
-
-

In Ruby 2.0 such an expression will probably not pass anymore.

-

Actually let’s also leave out the parentheses in the definition

-
-def some_method param1, param2, param3
-end
-
-def other_method    # without arguments we see this a lot
-end
-
-

Parentheses are often left out in method calls, but leaving out -parentheses in the definition is not very popular. -Only if there are no arguments the parentheses are frequently omitted.

-

Arguments and Lists

-

Arguments form a list of objects. If we want to use the elements of a list as arguments we can do this as follows:

-
-def delegate(a, b, c)
-  p(a, b, c)
-end
-
-list = [1, 2, 3]
-delegate(*list)   # identical to delegate(1, 2, 3)
-
-

In this way we can distribute an array into arguments. -We call this device a *argument. Here we used a local variable -for demonstration, but of course there is no limitation. -We can also directly put a literal or a method call instead.

-
-m(*[1,2,3])    # We could have written the expanded form in the first place...
-m(*mcall())
-
-

The * argument can be used together with ordinary arguments, -but the * argument must come last.

-

In the definition on the other hand we can handle the arguments in -bulk when we put a * in front of the parameter variable.

-
-def some_method( *args )
-  p args
-end
-
-some_method()          # prints []
-some_method(0)         # prints [0]
-some_method(0, 1)      # prints [0,1]
-
-

The surplus arguments are gathered in an array. Only one *parameter -can be declared. It must also come after the default arguments.

-
-def some_method0( arg, *rest )
-end
-def some_method1( arg, darg = nil, *rest )
-end
-
-

If we combine list expansion and bulk reception together, the arguments -of one method can be passed as a whole to another method. This might -be the most practical use of the *parameter.

-
-# a method which passes its arguments to other_method
-def delegate(*args)
-  other_method(*args)
-end
-
-def other_method(a, b, c)
-  return a + b + c
-end
-
-delegate(0, 1, 2)      # same as other_method(0, 1, 2)
-delegate(10, 20, 30)   # same as other_method(10, 20, 30)
-
-

Various Method Call Expressions

-

There is only one mechanism for ‘method call’, but there still -can be several representations of the same mechanism. This is -colloquially called syntactic sugar.

-

In Ruby there is a ton of it, -and they are really attractive for a person who has a fetish for parsers. -For instance the examples below are all method calls.

-
-1 + 2                   # 1.+(2)
-a == b                  # a.==(b)
-~/regexp/               # /regexp/.~
-obj.attr = val          # obj.attr=(val)
-obj[i]                  # obj.[](i)
-obj[k] = v              # obj.[]=(k,v)
-<code>cvs diff abstract.rd</code>  # Kernel.`('cvs diff abstract.rd')
-
-

It’s hard to believe until you get used to it, but attr=, []=, \` -are all names of methods. They can appear as names in a method definition -and can also be used as symbols.

-
-class C
-  def []( index )
-  end
-  def +( another )
-  end
-end
-p(:attr=)
-p(:[]=)
-p(:`)
-
-

There are people who don’t like sweets and there are people who -hate syntactic sugar. Maybe because one cannot tell by the looks -that it’s really the same thing. It feels like a deception. -(Why’s everyone so serious?)

-

Let’s see some more details.

-

Symbol Appendices

-
-obj.name?
-obj.name!
-
-

First a small thing. It’s just appending a ? or a !. Call and Definition -do not differ, so it’s not too painful. There are convention for what -to use these method names, but there is no enforcement on language level. -It’s just a convention. -These method names are probably an influence from Lisp which has a great variety -of function names.

-

Binary Operators

-
-1 + 2    # 1.+(2)
-
-

Binary Operators will be converted to a method call to the object on the -left hand side. Here the method + from the object 1 is called. -As listed below there are many of them. There are the general operators -+ and -, also the equivalence operator == and the spaceship operator -`<=>’ as in Perl, all sorts. They are listed in order of their precedence.

-
-**
-* / %
-+ -
-<< >>
-&
-| ^
-> >= < <=
-<=> == === =~
-
-

The symbols & and | are methods, but the double symbols && and || -are built-in operators. Remember how it is in C.

-

Unary Operators

-
-+2
--1.0
-~/regexp/
-
-

These are the unary operators. There are only three of them: + - ~. -+ and - work as one would imagine ( in the default setting). -The operator ~ matches a string or a regular expression -with the variable $_. With an integer it stands for bit conversion.

-

To distinguish the unary + from the binary + the method names -for the unary operators are +@ and -@ respectively. -Of course they can be called by just writing +n or -n.

-

((errata: + or – as the prefix of a numeric literal is actually scanned as a -part of the literal. This is a kind of optimizations.))

-

Attribute Assignment

-
-obj.attr = val   # obj.attr=(val)
-
-

This is an attribute assignment statement. The above will be translated -into the method call attr=. When using this together with method calls whose -parentheses are omitted, we can write code which looks like attribute access.

-
-class C
-  def i() @i end          # We can write the definition in one line
-  def i=(n) @i = n end
-end
-
-c = C.new
-c.i = 99
-p c.i    # prints 99
-
-

However both are method calls. -They are similar to get/set property in Delphi or slot accessors in CLOS.

-

Besides, we cannot define a attribute assignment which takes an argument like -obj.attr(arg)=.

-

Index Notation

-
-obj[i]    # obj.[](i)
-
-

The above will be translated into a method call for []. -Array and hash access are also implemented with this device.

-
-obj[i] = val   # obj.[]=(i, val)
-
-

When assigning to an index the []= method is used.

-

super

-

Often we don’t want to replace a method, but we want to add a little -bit to the behaviour of an already existing method. Here it becomes -necessary to not just overwrite the method in the superclass but -to also call the method in the superclass. -That’s what Ruby’s super is for.

-
-class A
-  def test
-    puts 'in A'
-  end
-end
-class B < A
-  def test
-    super   # launches A#test
-  end
-end
-
-

Ruby’s `super differs from the one in Java. This one here -calls the method with the same name in the superclass. -In other words super is a reserved word.

-

When using super be careful about the difference between the difference -of the zero arguments super and the omitted arguments `super. -The super with omitted arguments passes all the parameter variables.

-
-class A
-  def test( *args )
-    p args
-  end
-end
-
-class B < A
-  def test( a, b, c )
-    # super with no arguments
-    super()    # shows []
-
-    # super with omitted arguments. Same result as super(a, b, c)
-    super      # shows [1, 2, 3]
-  end
-end
-
-B.new.test(1,2,3)
-
-

Visibility

-

Depending on the location ( the object self) a method can or -cannot be called. This function was usually called visibility. -In Ruby there are three kinds of methods.

-
    -
  • public
  • -
  • private
  • -
  • protected
  • -
-

public methods can be called from anywhere in any form. -private methods can syntactically only be called without a receiver. -In effect they can only be called by instances of the class -in which they were defined and in instances of its subclass. -protected methods can only be called by instances of the defining class -and its subclasses. -It differs from private that methods can still be called from other -instances of the same class.

-

The terms are the same as in C++ but the meaning is slightly different. -Be careful.

-

Usually we control visibility as shown below.

-
-class C
-  public
-  def a1() end   # becomes public
-  def a2() end   # becomes public
-
-  private
-  def b1() end   # becomes private
-  def b2() end   # becomes private
-
-  protected
-  def c1() end   # becomes protected
-  def c2() end   # becomes protected
-end
-
-

Here public, private and `protected are method calls without -parentheses. These aren’t reserved words.

-

public and private can also be used with an argument to set -the visibility of a particular method. But that’s not really relevant. -We’ll leave this out.

-

Module functions

-

Given a module ‘M’. If there are two methods with the exact same -content

-
    -
  • M.method_name
  • -
  • M#method_name(Visibility is private)
  • -
-

then we call this a module function.

-

It is not apparent why this should be useful. But let’s look -at the next example which is happily used.

-
-Math.sin(5)       # If used for a few times this is more convenient
-
-include Math
-sin(5)            # If used more often this is more practical
-
-

It’s important that both functions have the same content. -With a different self but with the same code the behavior should -still be the same. Instance variables become extremely difficult to use. -Hence these methods are probably only used -for procedures like sin. That’s why they are called module functions.

-

Iterators

-

Ruby’s iterators differ a bit from Java’s or C++’s iterator classes -or ‘Iterator’ design patterns. Precisely speaking those iterators -are exterior iterators. Ruby’s iterators are called interior iterators. -It’s difficult to understand from the definition so -let’s explain it with a concrete example.

-
-arr = [0,2,4,6.8]
-
-

This array is given and we want to access the elements in -order. In C style we would write the following.

-
-i = 0
-while i < arr.length
-  print arr[i]
-  i += 1
-end
-
-

Using an iterator we can write:

-
-arr.each do |item|
-  print item
-end
-
-

Everything from each do to end is the call to an iterator method. -More precisely each is the iterator method and between -do and end is the iterator block. -The part between the vertical bars are the block parameters. -They are the arguments passed from the iterator method to the block where -they become variables.

-

Saying it quite abstractly, an iterator is something like -a piece of code which has been cut out and passed. In our example the -piece print item has been cut out and is passed to the each method. -Then each takes all the elements of the array in order and passes them -to the cut out piece of code.

-

We can also think the other way round. The other parts except print item -are being cut out and inserted into the each method.

-
-i = 0
-while i < arr.length
-  print arr[i]
-  i += 1
-end
-
-arr.each do |item|
-  print item
-end
-
-

Comparison with higher order functions

-

What comes closest in C to iterators are functions which receive function pointers, -or higher order functions. But there are two points in which iterators in Ruby -and higher order functions in C differ.

-

Firstly, Ruby iterators can only take one block. For instance we can’t -do the following.

-
-# Mistake. Several blocks cannot be passed.
-array_of_array.each do |i|
-  ....
-end do |j|
-  ....
-end
-
-

Secondly, Ruby’s blocks can share local variables with the code outside.

-
-lvar = 'ok'
-[0,1,2].each do |i|
-  p lvar    # Can acces local variable outside the block.
-end
-
-

That’s where iterators are convenient.

-

But variables can only be shared with the outside. They cannot be shared -with the inside of the iterator method ( e.g. each). Putting it intuitively, -only the local variables can be seen, which are on the outside of the code.

-

Block Local Variables

-

Local variables which are assigned inside a block stay local to that block. -They become block local variables. Let’s check it out.

-
-[0].each do
-  i = 0
-  p i     # 0
-end
-
-

For the time being we apply each to an array of length 1. ( We can -leave out the block parameter.) The variable i is first assigned -and declared inside the block. So i becomes a block local variable.

-

Block local means that it cannot be accessed from the outside. -Let’s test it.

-
-% ruby -e '
-[0].each do
-  i = 0
-end
-p i     # Here occurs an error.
-'
--e:5: undefined local variable or method `i'
-for #<Object:0x40163a9c> (NameError)
-
-

When we referenced a block local variable from outside the block -an error occured. Without a doubt it stayed local to the block.

-

Iterators can also be nested repeatedly. Each time -the new block creates another scope.

-
-lvar = 0
-[1].each do
-  var1 = 1
-  [2].each do
-    var2 = 2
-    [3].each do
-      var3 = 3
-      #  Here lvar, var1, var2, var3 can be seen
-    end
-    # Here lvar, var1, var2 can be seen
-  end
-  # Here lvar, var1 can be seen
-end
-# Here only lvar can be seen
-
-

There’s one point which you have to keep in mind. Differing from -nowadays’ major languages Ruby’s block local variables don’t do shadowing. -Shadowing means for instance in C that in the code below the two declared -variables i are different.

-
-{
-    int i = 3;
-    printf("%d\n", i);         /* 3 */
-    {
-        int i = 99;
-        printf("%d\n", i);     /* 99 */
-    }
-    printf("%d\n", i);         /* 3 (元に戻った) */
-}
-
-

Inside the block the i inside overshadows the i outside. -That’s why it’s called shadowing.

-

But what happens in Ruby where there’s no shadowing. -Let’s look at this example.

-
-i = 0
-p i           # 0
-[0].each do
-  i = 1
-  p i         # 1
-end
-p i           # 1 the change is preserved
-
-

When we assign i inside the block and if there is a variable i -that same variable will be used. Hence if we assign to i inside -the value for i on the outside changes. On this point there -came many complains: “This is error prone. Please do shadowing.” -Each time there’s flaming but till now no conclusion was reached.

-

The syntax of iterators

-

There are some smaller topics left.

-

First, there are two ways to write an iterator. One is the -do ~ end as used above, the other one is the enclosing in braces. -The two expressions below have exactly the same meaning.

-
-arr.each do |i|
-  puts i
-end
-
-arr.each {|i|    # The author likes a four space indentation for
-    puts i       # an iterator with braces.
-}
-
-

But grammaticarly the precedence is different. -The braces bind much stronger than do~end.

-
-m m do .... end    # m(m) do....end
-m m { .... }       # m(m() {....})
-
-

And iterators are of course just methods so they also take -arguments.

-
-re = /^\d/                 # regular expression to match a digit at the beginning of the line
-$stdin.grep(re) do |line|  # look repeatedly for this regular expression
-  ....
-end
-
-

yield

-

Of course users can write their own iterators. Methods which have -a yield in their definition text are iterators. -Let’s try to write an iterator with the same effect as Array#each:

-
-# adding the definition to the Array class
-class Array
-  def my_each
-    i = 0
-    while i < self.length
-      yield self[i]
-      i += 1
-    end
-  end
-end
-
-# this is the original each
-[0,1,2,3,4].each do |i|
-  p i
-end
-
-# my_each works the same
-[0,1,2,3,4].my_each do |i|
-  p i
-end
-
-

yield calls the block. At this point control is passed to the block, -when the execution of the block finishes it returns back to the same -location. Think about it like calling a special function. When the -present method does not have a block a runtime error will occur.

-
-% ruby -e '[0,1,2].each'
--e:1:in `each': no block given (LocalJumpError)
-        from -e:1
-
-

Proc

-

I said, that iterators are like cut out code which is passed as an -argument. But we can even more directly make code to an object -and carry it around.

-
-twice = Proc.new {|n| n * 2 }
-p twice.call(9)   # 18 will be printed
-
-

In short, it is like a function. It can be created with new and -as might be expected, the return value of Proc.new is an instance -of the Proc class.

-

Proc.new looks surely like an iterator and it is indeed so. -It is an ordinary iterator. There’s only some mechanism inside Proc.new -which turns an iterator block into an object.

-

Besides there is a function style method lambda provided which -has the same effect as Proc.new. Choose whatever suits you.

-
-twice = lambda {|n| n * 2 }
-
-

Iterators and Proc

-

Why did we start talking all of a sudden about Proc? Because there -is a deep relationship between iterators and Proc. -In fact iterators and Proc objects are quite the same thing. -That’s why one can be transformed into the other.

-

First, to turn an iterator block into a Proc object -one has to put an & in front of the parameter name.

-
-def print_block( &block )
-  p block
-end
-
-print_block() do end   # Shows something like <Proc:0x40155884>
-print_block()          # Without a block nil is printed
-
-

With an & in front of the argument name, the block is transformed to -a Proc object and assigned to the variable. If the method is not an -iterator (there’s no block attached) nil is assigned.

-

And in the other direction, if we want to pass a Proc to an iterator -we also use &.

-
-block = Proc.new {|i| p i }
-[0,1,2].each(&block)
-
-

This code means exactly the same as the code below.

-
-[0,1,2].each {|i| p i }
-
-

If we combine these two, we can delegate an iterator -block to a method somewhere else.

-
-def each_item( &block )
-  [0,1,2].each(&block)
-end
-
-each_item do |i|    # same as [0,1,2].each do |i|
-  p i
-end
-
-

Expressions

-

Expressions in Ruby can be combined to build new expressions or statements. -For instance a method call can be another method call’s argument, -and so it would become an expression. -The same goes for literals. But literals and method calls are not combinations -of other elements. From here on the expressions introduced will always be used -in combination with other expressions.

-

if

-

We probably do not need to explain the if expression. If the conditional -expression is true the body expression is executed. As explained in the -first part in Ruby every object except nil and false is true.

-
-if cond0 then
-  ....
-elsif cond1 then
-  ....
-elsif cond2 then
-  ....
-else
-  ....
-end
-
-

elsif and else can be omitted. Each then can also be omitted -elsif・But there are some finer requirements concerning then. -It will be apparent by looking at the examples below. -All of them are valid.

-
-# 1                                    # 4
-if cond then ..... end                 if cond
-                                       then .... end
-# 2
-if cond; .... end                      # 5
-                                       if cond
-# 3                                    then
-if cond then; .... end                   ....
-                                       end
-
-

Furthermore, as every expression has a return value, there -is also a return value here. It is the return value of the -body expression which holds. For instance if the condition -at the beginning is true it is the return value of the -following expression.

-
-p(if true  then 1 else 2 end)   #=> 1
-p(if false then 1 else 2 end)   #=> 2
-p(if false then 1 elsif true then 2 else 3 end)   #=> 2
-
-

If there’s no match, or the match is empty nil is returned.

-
-p(if false then 1 end)    #=> nil
-p(if true  then   end)    #=> nil
-
-

unless

-

An if with a negated condition is the same as an unless. -The following two examples have the same meaning.

-
-unless cond then          if not (cond) then
-  ....                      ....
-end                       end
-
-

unless can also have an else clause but there cannot be an elsif. -Of course then can be omitted.

-

unless also has a value. Analogous to if it is the value of the of the -clause which matches. If there’s no match or the match is empty nil -is returned.

-

and && or ||

-

The most useful utilization of the and is probably as a boolean operator. -For instance in the conditional clause of an if.

-
-if cond1 and cond2
-  puts 'ok'
-end
-
-

But as in Perl, the Shell or Lisp it can also be used as a conditional -branch expression. -The two following expressions have the same meaning.

-
-                                        if invalid?(key)
-invalid?(key) and return nil              return nil
-                                        end
-
-

&& and and have the same meaning. Different is the binding order.

-
-method arg0 &&  arg1    # method(arg0 && arg1)
-method arg0 and arg1    # method(arg0) and arg1
-
-

Basically the symbolic operator is used in an expression which becomes an argument. -The alphabetical operator is used in an expression which will not become -an argument.

-

As for and, if the evaluation of the left hand side is true, -the right hand side will also be evaluated.

-

On the other hand or is the opposite of and. If the evaluation of the left hand -side is false, the right hand side will also be evaluated.

-
-valid?(key) or return nil
-
-

or and || have the same relationship as && and and. Only the precedence is -different.

-

The Conditional Operator

-

There is a conditional operator similar to C:

-
-cond ? iftrue : iffalse
-
-

The space between the symbols is important. -If they bump together the following weirdness happens.

-
-cond?iftrue:iffalse   # cond?(iftrue(:iffalse))
-
-

The value of the conditional operator is the value of the last executed expression. -Either the value of the true side or the value of the false side.

-

while until

-

Here’s a while expression.

-
-while cond do
-  ....
-end
-
-

This is the most basic loop construct. As long as cond is true -the body is executed. The do can be omitted.

-
-until io_ready?(id) do
-  sleep 0.5
-end
-
-

until comes to the exact opposite conclusion as the while. -As long as the body expression is false it is executed. -The do can be omitted.

-

There is also a jump construct which exits the loop. -As in C/C++/Java it is called break. Instead of continue there -is next. That seems to have come from Perl.

-
-i = 0
-while true
-  if i > 10
-    break   # exit the loop
-  elsif i % 2 == 0
-    i *= 2
-    next    # next loop iteration
-  end
-  i += 1
-end
-
-

And there is another Perlism: the redo.

-
-while cond
-  # (A)
-  ....
-  redo
-  ....
-end
-
-

It will return to (A) and repeat from there. With next there -is a condition check, with redo there is none.

-

I might come into the world top 100, if the amount of Ruby programs -would be counted, but I haven’t used redo yet. It does not seem to be -that necessary after all.

-

case

-

A special form of the if expression. It performs branching on a series of -conditions. The following left and right expressions are identical in meaning.

-
-case value
-when cond1 then                if cond1 === value
-  ....                           ....
-when cond2 then                elsif cond2 === value
-  ....                           ....
-when cond3, cond4 then         elsif cond3 === value or cond4 === value
-  ....                           ....
-else                           else
-  ....                           ....
-end                            end
-
-

The threefold equals === is, as the same as the ==, actually a method call. -Notice that the receiver is the object on the left hand side. Concretely, -if it is the === of an Array, it would check if it contains the value -as its element. -If it is a Hash, it tests whether it has the value as its key. -If its is an regular expression, it tests if the value matches. -And so on. -Since case has many grammatical elements, -to list them all would be tedious, thus we will not cover them in this book.

-

Exceptions

-

This is a control structure which can pass method boundaries and -transmit errors. Readers who are acquainted to C++ or Java -will know about exceptions. Ruby exceptions are basically the -same.

-

In Ruby exceptions come in the form of the function style method raise. -raise is not a reserved word.

-
-raise ArgumentError, "wrong number of argument"
-
-

In Ruby exception are instances of the Exception class and it’s -subclasses. This form takes an exception class as its first argument -and an error message as its second argument. In the above case -an instance of ArgumentError is created and “thrown”. Exception -object ditch the part after the raise and return upwards the -method call stack.

-
-def raise_exception
-  raise ArgumentError, "wrong number of argument"
-  # the code after the exception will not be executed
-  puts 'after raise'
-end
-raise_exception()
-
-

If nothing blocks the exception it will move to the top level. -When it reaches the top level, ruby gives out a message and ends -with a non-zero exit code.

-
-% ruby raise.rb
-raise.rb:2:in `raise_exception': wrong number of argument (ArgumentError)
-        from raise.rb:7
-
-

However, for this an exit would be sufficient, for an exception ther -should be ways to handle it. In Ruby there is the begin, rescue, end for this. -It resembles the try and catch in C++ and Java.

-
-def raise_exception
-  raise ArgumentError, "wrong number of argument"
-end
-
-begin
-  raise_exception()
-rescue ArgumentError => err then
-  puts 'exception catched'
-  p err
-end
-
-

rescue is a control structure which captures an exception, it catches -the exceptions of the declared class and its subclasses. If in the -above example an instance of ArgumentError comes flying this rescue -matches it. By =>err the exception object will be assigned to the local variable -err, after that the rescue part is executed.

-
-% ruby rescue.rb
-exception catched
-#<ArgumentError: wrong number of argument>
-
-

If the exception is resuced the execution carries on after the rescue -as if nothing happened. We can also make it retry the critical part -with retry.

-
-begin    # return here
-  ....
-rescue ArgumentError => err then
-  retry  # beginning anew
-end
-
-

We can omit the =>err and the then after rescue. We can also leave -out the exception class. In this case the class StandardError is matched.

-

If we want to add more exception classes we can just list them after rescue. -When we want to handle different errors differently we can use several rescues -in one begin~end block.

-
-begin
-  raise IOError, 'port not ready'
-rescue ArgumentError, TypeError
-rescue IOError
-rescue NameError
-end
-
-

In this case the exception class is checked in order until there is a match. -Only the one matched part is executed. For instance in the above case only -IOError is executed.

-

On the othor hand, when there is an else clause, it is executed -only when there is no exception.

-
-begin
-  nil    # Of course here will no error occur
-rescue ArgumentError
-  # This part will not be executed
-else
-  # This part will be executed
-end
-
-

Moreover an ensure clause will be executed in every case: -when there is no exception, when there is an exception, rescued or not.

-
-begin
-  f = File.open('/etc/passwd')
-  # do stuff
-ensure   # this part will be executed anyway
-  f.close
-end
-
-

Besides, this begin expression also has a value. The value of the -whole begin~end expression is the value of the part which was executed -last. The ensure part does not count as it is normally used for cleanup only.

-

Variables and Constants

-

Referring a variable or a constant. The value is the object the variable points to. -We already talked in too much detail about the various behaviors.

-
-lvar
-@ivar
-@@cvar
-CONST
-$gvar
-
-

I want to add one more thing. The variables starting with $ are -of a special kind. Some have strange names, but they are not -necessarily global.

-

First the Perlish variables $_ and $~. $_ saves the return -value of gets and other methods, $~ contains the last match -of a regular expression. They are called local and thread local. -Incredible variables.

-

And the variable $! which saves the exceptional object when -an exception has occurred as well as the variable $? which -saves the status of a child process and $SAFE which represents -the security level are all thread local.

-

Assignment

-

Variable assignment are all performed by =. All variables are -typeless. What is saved is a reference to an object. It is -implemented with VALUE (pointer).

-
-var = 1
-obj = Object.new
-@ivar = 'string'
-@@cvar = ['array']
-PI = 3.1415926535
-$gvar = {'key' => 'value'}
-
-

However, as mentioned earlier obj.attr=val is not an assignment. -It is a method call.

-

Self Assignment

-
-var += 1
-
-

This syntax is also in C/C++/Java. In Ruby,

-
-var = var + 1
-
-

it is a shortcut of this code. -Differing from C, the Ruby + is a method and thus part of the library. -In the whole meaning of += is built in the language processor itself. -And in C++, += and *= can be wholly overwritten, -but we cannot do this in Ruby. -In Ruby <code>= is always defined as an operation of the combination of </code> and assignment.

-

We can also combine self assignment and an attribute-access-flavor method. -The result more looks like an attribute.

-
-class C
-  def i() @i end          # A method definition can be written in one line.
-  def i=(n) @i = n end
-end
-
-obj = C.new
-obj.i = 1
-obj.i += 2    # obj.i = obj.i + 2
-p obj.i       # 3
-
-

If there is += there might also be ++ but this is not the case. -Why is that so? In Ruby assignment is dealt with on the language level. -But on the other hand methods are in the library. Keeping these two, -the world of variables and the world of objects, strictly apart is an -important peculiarity of Ruby. If ++ were introduced the separation -might easily be broken. That’s why there’s no ++

-

Some people don’t want to go without the brevity of ++. It has been -proposed again and again in the mailing list but was always turned down. -I also am in favor of ++ but I can do without, there has never been -a ++ in Ruby so let’s forget about it.

-

defined?

-

defined? is a strange construct in Ruby. It tells whether an -expression value is defined or not.

-
-var = 1
-defined?(var)   #=> true
-
-

In other words it tells whether the received argument (is it okay to call -it so?) returns a value after evaluation. But it won’t tell you if there’s -a parse error or an exception is raised.

-

I would have loved to tell you more about defined? -but it will not appear again in this book. What a pity.

-

Statements

-

A statement is a syntactic construct which basically -cannot be combined with something else and is written -in a separate line.

-

But it still can be evaluated. For instance there are return values -for class definition statements and method definition statements. -However this is only rarely used, not recommended and isn’t useful. -We stick with this informal criteria. -Here we also don’t mention the various return values.

-

The Ending of a statement

-

Up to now we just said “For now one line’s one statement”. -But Ruby’s statement ending’s aren’t that straightforward.

-

First a statement can be ended explicitly with a semicolon as in C. -Of course then we can write two and more statements in one line.

-
-puts 'Hello, World!'; puts 'Hello, World once more!'
-
-

On the other hand after opened parentheses, dyadic operators, or commas -when the command apparently continues the sentence continues automatically.

-
-# 1 + 3 * method(6, 7 + 8)
-1 +
-  3 *
-     method(
-            6,
-            7 + 8)
-
-

But it’s also no problem to connect lines explicitly with a backslash.

-
-p 1 + \
-  2
-
-

The Modifiers if and unless

-

The if modifier is an irregular version of the normal if -The programs on the left and right mean exactly the same.

-
-on_true() if cond                if cond
-                                   on_true()
-                                 end
-
-

The unless is the negative version. -Guard statements ( statements which exclude exceptions) can -be conveniently written with it.

-

The Modifiers while and until

-

while and until also have a back notation.

-
-process() while have_content?
-sleep(1) until ready?
-
-

Combining this with begin and end gives a do-while-loop like in C.

-
-begin
-  res = get_response(id)
-end while need_continue?(res)
-
-

Class Definition

-
-class C < SuperClass
-  ....
-end
-
-

Defines the class C which inherits from SuperClass

-

We talked quite extensively about classes in the first part. -This statement will be executed, within the definition the class will -become self, arbitrary expressions can be written within. Class -definitions can be nested. They form the foundation of Ruby execution -image.

-

Method Definition

-
-def m(arg)
-end
-
-

I’ve already written about method definition and won’t add more. -They also belong to statements.

-

Singleton method definition

-

We already talked a lot about singleton methods in the first part. -They do not belong to classes but to objects, in fact, they belong -to singleton classes. We define singleton methods by putting the -receiver in front of the method name. Parameter declaration is done -the same way like with ordinary methods.

-
-def obj.some_method
-end
-
-def obj.some_method2( arg1, arg2, darg = nil, *rest, &block )
-end
-
-

Definition of Singleton methods

-
-class << obj
-  ....
-end
-
-

From the viewpoint of purposes, -it is the statement to define some singleton methods in a bundle. -From the viewpoint of measures, -it is the statement in which the singleton class of obj becomes self when -executed. -In all over the Ruby program, -this is the only place where a singleton class is exposed.

-
-class << obj
-  p self  #=> #<Class:#<Object:0x40156fcc>>   # Singleton Class 「(obj)」
-  def a() end   # def obj.a
-  def b() end   # def obj.b
-end
-
-

Multiple Assignment

-

With a multiple assignment several assignments can be combined into one. -The following is a simple example:

-
-a, b, c = 1, 2, 3
-
-

It’s exactly the same as the following.

-
-a = 1
-b = 2
-c = 3
-
-

It’s not just for brevity’s sake. When we bind variables to an elements -of an array it becomes delightful.

-
-a, b, c = [1, 2, 3]
-
-

This also has the same result as the above. -Furthermore, the right handside does not need to be a literal. -It can also be a variable or a method call.

-
-tmp = [1, 2, 3]
-a, b, c = tmp
-ret1, ret2 = some_method()   # some_method might probably return several values
-
-

Precisely speaking it is as follows. We will write the value of the -left hand side as obj.

-
    -
  1. obj if it is an array
  2. -
  3. if its to_ary method is defined, it is used to convert obj to an array.
  4. -
  5. [obj]
  6. -
-

Decide the right-hand side by following this procedure and perform assignments. -It means the evaluation of the right-hand side and the operation of assignments -are totally independent from each other.

-

And it goes on, the left and right hand side can be infinitely nested.

-
-a, (b, c, d) = [1, [2, 3, 4]]
-a, (b, (c, d)) = [1, [2, [3, 4]]]
-(a, b), (c, d) = [[1, 2], [3, 4]]
-
-

As the result of the execution of this program, -each line will be a=1 b=2 c=3 d=4.

-

And it goes on. The left hand side can be index or parameter assignments.

-
-i = 0
-arr = []
-arr[i], arr[i+1], arr[i+2] = 0, 2, 4
-p arr    # [0, 2, 4]
-
-obj.attr0, obj.attr1, obj.attr2 = "a", "b", "c"
-
-

And like with method parameters, -* can be used to receive in a bundle.

-
-first, *rest = 0, 1, 2, 3, 4
-p first  # 0
-p rest   # [1, 2, 3, 4]
-
-

If all of them are used all at once, you will easily get confused.

-

Block parameter and multiple assignment

-

We brushed over block parameters when we were talking about iterators. -But there is a deep relationship between them and multiple assignment. -For instance in the following case.

-
-array.each do |i|
-  ....
-end
-
-

When the block is called with a yield, the provided parameters are multi-assigned to i. -Here there’s only one variable on the left hand side, so it does not look like multi assignment. -But if there are two or more variables we see what’s going on. For instance Hash#each -provides a key and a value we usually call it like that:

-
-hash.each do |key, value|
-  ....
-end
-
-

In this case an array with elements key and value are yielded -from the hash.

-

Hence we can also use nested multiple assignment as shown below.

-
-# [[key,value],index] are given to yield
-hash.each_with_index do |(key, value), index|
-  ....
-end
-
-

alias

-
-class C
-  alias new orig
-end
-
-

Defining another method new with the same body as the already -defined method orig. alias are similar to hardlinks in a unix -file system. They are a means of assigning multiple names to one method body. I other words, -because the names themselves are independent of each other, -if one method name is overwritten by a subclass method, the -other one still returns the method as before.

-

undef

-
-class C
-  undef method_name
-end
-
-

Prohibits the calling of C#method_name. It’s not just a simple -revoking of the definition. If there even were a method in the -superclass it would also be forbidden. In other words the method is -exchanged for a sign which says “This method must not be called”.

-

undef is extremely powerful, once it is set it cannot be -deleted on the Ruby level, because it is used to cover up contradictions -in the internal structure. One must define a method in the lower class. -Even then when one calls super an -error occurs.

-

By the way the method which corresponds to unlink in a file system -is Module#remove_method. While defining a class, self refers -to that class, we can call it as follows ( Remember that Class is a -subclass of Module.

-
-class C
-  remove_method(:method_name)
-end
-
-

But even with a remove_method one cannot cancel the undef. -It’s because the sign put up by undef prohibits any kind of searches.

-

((errata: It can be redefined by using def))

-

Some more small topics

-

Comments

-
-# examples of bad comments.
-1 + 1            # compute 1+1.
-alias my_id id   # my_id is an alias of id.
-
-

From a # to the end of line is a comment. -It doesn’t have a meaning for the program.

-

Embedded documents

-
-=begin
-This is an embedded document.
-It's so called because it is embedded in the program.
-Plain and simple.
-=end
-
-

An embedded document stretches from -an =begin outside a string at the beginning of a line -to a =end. The interior can be arbitrary. -The program reads and ignores it like a simple comment.

-

Multi-byte strings

-

When the global variable $KCODE is set to either EUC, SJIS -or UTF8, strings encoded in euc-jp, shift_jis, or utf8 respectively can be -used in a string of a data.

-

And if the option -Ke, -Ks or -Ku is given to the ruby -command multibyte strings can be used within the Ruby code. -String literals, regular expressions and even operator names -can contain multibyte characters. Hence it is possible to do -something like this:

-
-def 表示( arg )
-  puts arg
-end
-
-表示 'にほんご'
-
-

But I really cannot recommend doing things like that.

- - - -
- - diff --git a/htmls/syntree.html b/htmls/syntree.html deleted file mode 100644 index f572d14..0000000 --- a/htmls/syntree.html +++ /dev/null @@ -1,1615 +0,0 @@ - - - - - Chapter 12: Syntax tree construction | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 12: Syntax tree construction

-

Node

-

NODE

-

As I’ve already described, a Ruby program is first converted to a syntax tree. -To be more precise, a syntax tree is a tree structure made of structs called “nodes”. -In ruby , all nodes are of type NODE .

-

NODE

- -
- 128  typedef struct RNode {
- 129      unsigned long flags;
- 130      char *nd_file;
- 131      union {
- 132          struct RNode *node;
- 133          ID id;
- 134          VALUE value;
- 135          VALUE (*cfunc)(ANYARGS);
- 136          ID *tbl;
- 137      } u1;
- 138      union {
- 139          struct RNode *node;
- 140          ID id;
- 141          int argc;
- 142          VALUE value;
- 143      } u2;
- 144      union {
- 145          struct RNode *node;
- 146          ID id;
- 147          long state;
- 148          struct global_entry *entry;
- 149          long cnt;
- 150          VALUE value;
- 151      } u3;
- 152  } NODE;
-
-(node.h)
-
-

Although you might be able to infer from the struct name RNode , nodes are Ruby objects. -This means the creation and release of nodes are taken care of by the ruby ’s garbage collector.

-

Therefore, flags naturally has the same role as basic.flags of the object struct. -It means that T_NODE which is the type of a struct and flags such as FL_FREEZE are stored in it. -As for NODE , in addition to these, its node type is stored in flags .

-

What does it mean? Since a program could contain various elements -such as if and while and def and so on, there are also various corresponding node types. -The three available union are complicated, -but how these unions are used is decided to only one specific way for each node. -For example, the below table shows the case when it is NODE_IF that is the node of if .

- - - - - - - - - - - - - - - - - - - - - -
member union member role
u1 u1.node the condition expression
u2 u2.node the body of true
u3 u3.node the body of false
-

And, in node.h , the macros to access each union member are available.

-

▼ the macros to access NODE

- -
- 166  #define nd_head  u1.node
- 167  #define nd_alen  u2.argc
- 168  #define nd_next  u3.node
- 169
- 170  #define nd_cond  u1.node
- 171  #define nd_body  u2.node
- 172  #define nd_else  u3.node
- 173
- 174  #define nd_orig  u3.value
-                 :
-                 :
-
-(node.h)
-
-

For example, these are used as follows:

-
-NODE *head, *tail;
-head->nd_next = tail;    /* head->u3.node = tail */
-
-

In the source code, it’s almost certain that these macros are used. -A very few exceptions are only the two places where creating NODE in parse.y -and where marking NODE in gc.c .

-

By the way, what is the reason why such macros are used? -For one thing, it might be because it’s cumbersome to remember numbers like u1 -that are not meaningful by just themselves. -But what is more important than that is, there should be no problem if the -corresponding number is changed and it’s possible that it will actually be changed. -For example, since a condition clause of if does not have to be stored in u1 , -someone might want to change it to u2 for some reason. But if u1 is directly used, -he needs to modify a lot of places all over the source codes, it is inconvenient. -Since nodes are all declared as NODE , it’s hard to find nodes that represent if . -By preparing the macros to access, this kind of trouble can be avoided -and conversely we can determine the node types from the macros.

-

Node Type

-

I said that in the flags of a NODE struct its node type is stored. -We’ll look at in what form this information is stored. -A node type can be set by nd_set_type() and obtained by nd_type() .

-

nd_type nd_set_type

- -
- 156  #define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0xff)
- 157  #define nd_set_type(n,t) \
- 158      RNODE(n)->flags = ((RNODE(n)->flags & ~FL_UMASK) \
-                             | (((t)<<FL_USHIFT) & FL_UMASK))
-
-(node.h)
-
-

FL_USHIFT FL_UMASK

- -
- 418  #define FL_USHIFT    11
- 429  #define FL_UMASK  (0xff<<FL_USHIFT)
-
-(ruby.h)
-
-

It won’t be so much trouble if we’ll keep focus on around nd_type . -Fig.1 shows how it seems like.

-

-

(flagUsage)
-Fig.1: How RNode.flags is used

-

-

And, since macros cannot be used from debuggers, -the nodetype() function is also available.

-

nodetype

- -
-4247  static enum node_type
-4248  nodetype(node)                  /* for debug */
-4249      NODE *node;
-4250  {
-4251      return (enum node_type)nd_type(node);
-4252  }
-
-(parse.y)
-
-

File Name and Line Number

-

The nd_file of a NODE holds (the pointer to) the name of the file where the -text that corresponds to this node exists. Since there’s the file name, we -naturally expect that there’s also the line number, but the corresponding member -could not be found around here. Actually, the line number is being embedded to -flags by the following macro:

-

nd_line nd_set_line

- -
- 160  #define NODE_LSHIFT (FL_USHIFT+8)
- 161  #define NODE_LMASK  (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
- 162  #define nd_line(n) \
-          ((unsigned int)((RNODE(n)->flags >> NODE_LSHIFT) & NODE_LMASK))
- 163  #define nd_set_line(n,l) \
- 164      RNODE(n)->flags = ((RNODE(n)->flags & ~(-1 << NODE_LSHIFT)) \
-                             | (((l)&NODE_LMASK) << NODE_LSHIFT))
-
-(node.h)
-
-

nd_set_line() is fairly spectacular. -However, as the names suggest, it is certain that nd_set_line() and nd_line -works symmetrically. Thus, if we first examine the simpler nd_line() and grasp -the relationship between the parameters, there’s no need to analyze nd_set_line() -in the first place.

-

The first thing is NODE_LSHIFT , as you can guess from the description of the -node types of the previous section, it is the number of used bits in flags . -FL_USHIFT is reserved by system of ruby (11 bits, ruby.h ), 8 bits are for -its node type.

-

The next thing is NODE_LMASK .

-
-sizeof(NODE*) * CHAR_BIT - NODE_LSHIFT
-
-

This is the number of the rest of the bits. -Let’s assume it is restbits . This makes the code a lot simpler.

-
-#define NODE_LMASK  (((long)1 << restbits) - 1)
-
-

Fig.2 shows what the above code seems to be doing. Note that a borrow occurs -when subtracting 1. We can eventually understand that NODE_LMASK is a sequence -filled with 1 whose size is the number of the bits that are still available.

-

-

(lmask)
-Fig.2: NODE_LMASK

-

-

Now, let’s look at nd_line() again.

-
-(RNODE(n)->flags >> NODE_LSHIFT) & NODE_LMASK
-
-

By the right shift, the unused space is shifted to the LSB. The bitwise AND -leaves only the unused space. Fig.3 shows how flags is used. Since FL_USHIFT -is 11, in 32-bit machine 32-(11+8)=13 bits are available for the line number.

-

-

(flags)
-Fig.3: How flags are used at NODE

-

-

… This means, if the line numbers becomes beyond 2^13=8192, -the line numbers should wrongly be displayed. Let’s try.

-
-File.open('overflow.rb', 'w') {|f|
-    10000.times { f.puts }
-    f.puts 'raise'
-}
-
-

With my 686 machine, ruby overflow.rb properly displayed 1809 as a line number. -I’ve succeeded. However, if you use 64-bit machine, you need to create a little -bigger file in order to successfully fail.

-

rb_node_newnode()

-

Lastly let’s look at the function rb_node_newnode() that creates a node.

-

rb_node_newnode()

- -
-4228  NODE*
-4229  rb_node_newnode(type, a0, a1, a2)
-4230      enum node_type type;
-4231      NODE *a0, *a1, *a2;
-4232  {
-4233      NODE *n = (NODE*)rb_newobj();
-4234
-4235      n->flags |= T_NODE;
-4236      nd_set_type(n, type);
-4237      nd_set_line(n, ruby_sourceline);
-4238      n->nd_file = ruby_sourcefile;
-4239
-4240      n->u1.node = a0;
-4241      n->u2.node = a1;
-4242      n->u3.node = a2;
-4243
-4244      return n;
-4245  }
-
-(parse.y)
-
-

We’ve seen rb_newobj() in the Chapter 5: Garbage collection. It is the function to get a -vacant RVALUE . By attaching the T_NODE struct-type flag to it, -the initialization as a VALUE will complete. -Of course, it’s possible that some values that are not of type NODE* are -passed for u1 u2 u3, but received as NODE* for the time being. -Since the syntax trees of ruby does not contain double and such, -if the values are received as pointers, it will never be too small in size.

-

For the rest part, you can forget about the details you’ve learned so far, -and assume NODE is

-
    -
  • flags
  • -
  • nodetype
  • -
  • nd_line
  • -
  • nd_file
  • -
  • u1
  • -
  • u2
  • -
  • u3
  • -
-

a struct type that has the above seven members.

-

Syntax Tree Construction

-

The role of the parser is to convert the source code that is a byte sequence to a -syntax tree. Although the grammar passed, it does not finish even half of the task, -so we have to assemble nodes and create a tree. -In this section, we’ll look at the construction process of that syntax tree.

-

YYSTYPE

-

Essentially this chapter is about actions, -thus YYSTYPE which is the type of $$ or $1 becomes important. -Let’s look at the %union of ruby first.

-

%union declaration

- -
- 170  %union {
- 171      NODE *node;
- 172      ID id;
- 173      int num;
- 174      struct RVarmap *vars;
- 175  }
-
-(parse.y)
-
-

struct RVarmap is a struct used by the evaluator and holds a block local variable. -You can tell the rest. The most used one is of course node .

-

Landscape with Syntax Trees

-

I mentioned that looking at the fact first is a theory of code reading. -Since what we want to know this time is how the generated syntax tree is, -we should start with looking at the answer (the syntax tree).

-

It’s also nice using debuggers to observe every time, -but you can visualize the syntax tree more handily -by using the tool nodedump contained in the attached CD-ROM, -This tool is originally the NodeDump made by Pragmatic Programmers -and remodeled for this book. -The original version shows quite explanatory output, -but this remodeled version deeply and directly displays the appearance of the -syntax tree.

-

For example, in order to dump the simple expression m(a) , you can do as follows:

-
-% ruby -rnodedump -e 'm(a)'
-NODE_NEWLINE
-nd_file = "-e"
-nd_nth  = 1
-nd_next:
-    NODE_FCALL
-    nd_mid = 9617 (m)
-    nd_args:
-        NODE_ARRAY
-        nd_alen = 1
-        nd_head:
-            NODE_VCALL
-            nd_mid = 9625 (a)
-        nd_next = (null)
-
-

The -r option is used to specify the library to be load, -and the -e is used to pass a program. -Then, the syntax tree expression of the program will be dumped.

-

I’ll briefly explain about how to see the content. -NODE_NEWLINE and NODE_FCALL and such are the node types. -What are written at the same indent level of each node are the contents of its node members. -For example, the root is NODE_NEWLINE , and it has the three members: -nd_file nd_nth nd_next. nd_file points to the "-e" string of C, -and ng_nth points to the 1 integer of C, and nd_next holds the next node NODE_CALL . -But since these explanation in text are probably not intuitive, -I recommend you to also check Fig.4 at the same time.

-

-

(stree)
-Fig.4: Syntax Tree

-

-

I’ll explain the meaning of each node. NODE_CALL is a Function CALL. -NODE_ARRAY is as its name suggests the node of array, and here it expresses -the list of arguments. NODE_VCALL is a Variable or CALL, a reference to -undefined local variable will become this.

-

Then, what is NODE_NEWLINE ? This is the node to join the name of the currently -executed file and the line number at runtime and is set for each stmt . -Therefore, when only thinking about the meaning of the execution, this node can -be ignored. When you require nodedump-short instead of nodedump , -distractions like NODE_NEWLINE are left out in the first place. Since it is -easier to see if it is simple, nodedump-short will be used later on except for -when particularly written.

-

Now, we’ll look at the three type of composing elements in order to grasp how -the whole syntax tree is. The first one is the leaves of a syntax tree. Next, -we’ll look at expressions that are combinations of that leaves, this means they -are branches of a syntax tree. -The last one is the list to list up the statements that is the trunk of a syntax -tree in other words.

-

Leaf

-

First, let’s start with the edges that are the leaves of the syntax tree. -Literals and variable references and so on, among the rules, they are what -belong to primary and are particularly simple even among the primary rules.

-
-% ruby -rnodedump-short -e '1'
-NODE_LIT
-nd_lit = 1:Fixnum
-
-

1 as a numeric value. There’s not any twist. However, notice that what is -stored in the node is not 1 of C but 1 of Ruby (1 of Fixnum ). This is because …

-
-% ruby -rnodedump-short -e ':sym'
-NODE_LIT
-nd_lit = 9617:Symbol
-
-

This way, Symbol is represented by the same NODE_LIT when it becomes a syntax tree. -As the above example, VALUE is always stored in nd_lit so it can be handled -completely in the same way whether it is a Symbol or a Fixnum when executing. -In this way, all we need to do when dealing with it are retrieving the value -in nd_lit and returning it. Since we create a syntax tree in order to execute it, -designing it so that it becomes convenient when executing is the right thing to do.

-
-% ruby -rnodedump-short -e '"a"'
-NODE_STR
-nd_lit = "a":String
-
-

A string. This is also a Ruby string. -String literals are copied when actually used.

-
-% ruby -rnodedump -e '[0,1]'
-NODE_NEWLINE
-nd_file = "-e"
-nd_nth  = 1
-nd_next:
-    NODE_ARRAY
-    nd_alen = 2
-    nd_head:
-        NODE_LIT
-        nd_lit = 0:Fixnum
-    nd_next:
-        NODE_ARRAY
-        nd_alen = 1
-        nd_head:
-            NODE_LIT
-            nd_lit = 1:Fixnum
-        nd_next = (null)
-
-

Array. I can’t say this is a leaf, but let’s allow this to be here because it’s -also a literal. It seems like a list of NODE_ARRAY hung with each element node. -The reason why only in this case I didn’t use nodedump-short is … -you will understand after finishing to read this section.

-

Branch

-

Next, we’ll focus on “combinations” that are branches. -if will be taken as an example.

-

if

-

I feel like if is always used as an example, that’s because its structure is -simple and there’s not any reader who don’t know about if , so it is convenient -for writers.

-

Anyway, this is an example of if . -For example, let’s convert this code to a syntax tree.

-

▼The Source Program

- -
-if true
-  'true expr'
-else
-  'false expr'
-end
-
-

▼Its syntax tree expression

- -
-NODE_IF
-nd_cond:
-    NODE_TRUE
-nd_body:
-    NODE_STR
-    nd_lit = "true expr":String
-nd_else:
-    NODE_STR
-    nd_lit = "false expr":String
-
-

Here, the previously described nodedump-short is used, so NODE_NEWLINE -disappeared. nd_cond is the condition, nd_body is the body of the true case, -nd_else is the body of the false case.

-

Then, let’s look at the code to build this.

-

if rule

- -
-1373                  | kIF expr_value then
-1374                    compstmt
-1375                    if_tail
-1376                    kEND
-1377                      {
-1378                          $$ = NEW_IF(cond($2), $4, $5);
-1379                          fixpos($$, $2);
-1380                      }
-
-(parse.y)
-
-

It seems that NEW_IF() is the macro to create NODE_IF . Among the values of -the symbols, $2 $4 $5 are used, thus the correspondences between the symbols -of the rule and $n are:

-
-kIF    expr_value  then  compstmt  if_tail  kEND
- $1          $2      $3        $4       $5    $6
-NEW_IF(expr_value,       compstmt, if_tail)
-
-

this way. In other words, expr_value is the condition expression, compstmt -( $4 ) is the case of true, if_tail is the case of false.

-

On the other hand, the macros to create nodes are all named NEW_xxxx , and they -are defined node.h . Let’s look at NEW_IF() .

-

NEW_IF()

- -
- 243  #define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e)
-
-(node.h)
-
-

As for the parameters, -it seems that c represents condition, t represents then, and e represents -else respectively. As described at the previous section, the order of -members of a node is not so meaningful, so you don’t need to be careful about -parameter names in this kind of place.

-

And, the code() which processes the node of the condition expression in the -action is a semantic analysis function. This will be described later.

-

Additionally, fixpos() corrects the line number. NODE is initialized with -the file name and the line number of the time when it is “created”. However, -for instance, the code of if should already be parsed by end by the time -when creating NODE_IF . Thus, the line number would go wrong if it remains -untouched. Therefore, it needs to be corrected by fixpos() .

-
-fixpos(dest, src)
-
-

This way, the line number of the node dest is set to the one of the node src . -As for if , the line number of the condition expression becomes the line number -of the whole if expression.

-

elsif

-

Subsequently, let’s look at the rule of if_tail .

-

if_tail

- -
-1543  if_tail         : opt_else
-1544                  | kELSIF expr_value then
-1545                    compstmt
-1546                    if_tail
-1547                      {
-1548                          $$ = NEW_IF(cond($2), $4, $5);
-1549                          fixpos($$, $2);
-1550                      }
-
-1553  opt_else        : none
-1554                  | kELSE compstmt
-1555                      {
-1556                          $$ = $2;
-1557                      }
-
-(parse.y)
-
-

First, this rule expresses “a list ends with opt_else after zero or more -number of elsif clauses”. That’s because, if_tail appears again and again -while elsif continues, it disappears when opt_else comes in. We can -understand this by extracting arbitrary times.

-
-if_tail: kELSIF .... if_tail
-if_tail: kELSIF .... kELSIF .... if_tail
-if_tail: kELSIF .... kELSIF .... kELSIF .... if_tail
-if_tail: kELSIF .... kELSIF .... kELSIF .... opt_else
-if_tail: kELSIF .... kELSIF .... kELSIF .... kELSE compstmt
-
-

Next, let’s focus on the actions, surprisingly, elsif uses the same NEW_IF() as if . -It means, the below two programs will lose the difference after they become syntax trees.

-
-if cond1                  if cond1
-  body1                     body1
-elsif cond2               else
-  body2                     if cond2
-elsif cond3                   body2
-  body3                     else
-else                          if cond3
-  body4                         body3
-end                           else
-                                body4
-                              end
-                            end
-                          end
-
-

Come to think of it, in C language and such, there’s no distinction between -the two also at the syntax level. Thus this might be a matter of course. -Alternatively, the conditional operator ( a?b:c ) becomes indistinguishable -from if statement after they become syntax trees.

-

The precedences was very meaningful when it was in the context of grammar, -but they become unnecessary any more because the structure of a syntax tree -contains that information. And, the difference in appearance such as if and -the conditional operator become completely meaningless, -its meaning (its behavior) only matters. -Therefore, there’s perfectly no problem if if and the conditional operator -are the same in its syntax tree expression.

-

I’ll introduce a few more examples. add and && become the same. -or and || are also equal to each other. not and ! , if and modifier if , -and so on. These pairs also become equal to each other.

-

Left Recursive and Right Recursive

-

By the way, the symbol of a list was always written at the left side when expressing a list -in Chapter 9: yacc crash course. However, have you noticed it becomes opposite in if_tail ? -I’ll show only the crucial part again.

-
-if_tail: opt_else
-       | kELSIF ... if_tail
-
-

Surely, it is opposite of the previous examples. if_tail which is the symbol -of a list is at the right side.

-

In fact, there’s another established way of expressing lists,

-
-list: END_ITEM
-    | ITEM list
-
-

when you write in this way, it becomes the list that contains continuous zero -or more number of ITEM and ends with END_ITEM .

-

As an expression of a list, whichever is used it does not create a so much difference, -but the way that the actions are executed is fatally different. -With the form that list is written at the right, the actions are sequentially -executed from the last ITEM . We’ve already learned about the behavior of the -stack of when list is at the left, -so let’s try the case that list is at the right. -The input is 4 ITEM s and END_ITEM .

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
empty at first
ITEM shift ITEM
ITEM ITEM shift ITEM
ITEM ITEM ITEM shift ITEM
ITEM ITEM ITEM ITEM shift ITEM
ITEM ITEM ITEM ITEM END_ITEM shift END_ITEM
ITEM ITEM ITEM ITEM list reduce END_ITEM to list
ITEM ITEM ITEM list reduce ITEM list to list
ITEM ITEM list reduce ITEM list to list
ITEM list reduce ITEM list to list
list reduce ITEM list to list
accept.
-

When list was at the left, shifts and reductions were done in turns. -This time, as you see, there are continuous shifts and continuous reductions.

-

The reason why if_tail places “list at the right” is to create a syntax tree -from the bottom up. When creating from the bottom up, the node of if will be -left in hand in the end. But if defining if_tail by placing “list at the left”, -in order to eventually leave the node of if in hand, it needs to traverse all -links of the elsif and every time elsif -is found add it to the end. This is cumbersome. And, slow. -Thus, if_tail is constructed in the “list at the right” manner.

-

Finally, the meaning of the headline is, in grammar terms, -“the left is list " is called left-recursive, -“the right is list " is called right-recursive. -These terms are used mainly when reading papers about processing grammars or -writing a book of yacc .

-

Trunk

-

Leaf, branch, and finally, it’s trunk. -Let’s look at how the list of statements are joined.

-

▼The Source Program

- -
-7
-8
-9
-
-

The dump of the corresponding syntax tree is shown below. -This is not nodedump-short but in the perfect form.

-

▼Its Syntax Tree

- -
-NODE_BLOCK
-nd_head:
-    NODE_NEWLINE
-    nd_file = "multistmt"
-    nd_nth  = 1
-    nd_next:
-        NODE_LIT
-        nd_lit = 7:Fixnum
-nd_next:
-    NODE_BLOCK
-    nd_head:
-        NODE_NEWLINE
-        nd_file = "multistmt"
-        nd_nth  = 2
-        nd_next:
-            NODE_LIT
-            nd_lit = 8:Fixnum
-    nd_next:
-        NODE_BLOCK
-        nd_head:
-            NODE_NEWLINE
-            nd_file = "multistmt"
-            nd_nth  = 3
-            nd_next:
-                NODE_LIT
-                nd_lit = 9:Fixnum
-        nd_next = (null)
-
-

We can see the list of NODE_BLOCK is created and NODE_NEWLINE are attached -as headers. (Fig.5)

-

-

(blocklist)
-Fig.5: NODE_BLOCK and NODE_NEWLINE

-

-

It means, for each statement ( stmt ) NODE_NEWLINE is attached, -and when they are multiple, it will be a list of NODE_BLOCK . -Let’s also see the code.

-

stmts

- -
- 354  stmts           : none
- 355                  | stmt
- 356                      {
- 357                          $$ = newline_node($1);
- 358                      }
- 359                  | stmts terms stmt
- 360                      {
- 361                          $$ = block_append($1, newline_node($3));
- 362                      }
-
-(parse.y)
-
-

newline_node() caps NODE_NEWLINE , block_append() appends it to the list. -It’s straightforward. -Let’s look at the content only of the block_append() .

-

block_append()

-

It this function, the error checks are in the very middle and obstructive. -Thus I’ll show the code without that part.

-

block_append() (omitted)

- -
-4285  static NODE*
-4286  block_append(head, tail)
-4287      NODE *head, *tail;
-4288  {
-4289      NODE *end;
-4290
-4291      if (tail == 0) return head;
-4292      if (head == 0) return tail;
-4293
-4294      if (nd_type(head) != NODE_BLOCK) {
-4295          end = NEW_BLOCK(head);
-4296          end->nd_end = end;    /*(A-1)*/
-4297          fixpos(end, head);
-4298          head = end;
-4299      }
-4300      else {
-4301          end = head->nd_end;   /*(A-2)*/
-4302      }
-
-          /* ……omitted…… */
-
-4325      if (nd_type(tail) != NODE_BLOCK) {
-4326          tail = NEW_BLOCK(tail);
-4327          tail->nd_end = tail;
-4328      }
-4329      end->nd_next = tail;
-4330      head->nd_end = tail->nd_end;   /*(A-3)*/
-4331      return head;
-4332  }
-
-(parse.y)
-
-

According to the previous syntax tree dump, NEW_BLOCK was a linked list uses nd_next . -Being aware of it while reading, it can be read “if either head or tail is not NODE_BLOCK , -wrap it with NODE_BLOCK and join the lists each other.”

-

Additionally, on (A-1~3), the nd_end of the NODE_BLOCK of the head of the -list always points to the NODE_BLOCK of the tail of the list. This is probably -because in this way we don’t have to traverse all elements when adding an -element to the tail (Fig.6). -Conversely speaking, when you need to add elements later, NODE_BLOCK is suitable.

-

-

(append)
-Fig.6: Appending is easy.

-

-

The two types of lists

-

Now, I’ve explained the outline so far. -Because the structure of syntax tree will also appear in Part 3 in large amounts, -we won’t go further as long as we are in Part 2. -But before ending, there’s one more thing I’d like to talk about. -It is about the two general-purpose lists.

-

The two general-purpose lists mean BLOCK and LIST . -BLOCK is, as previously described, a linked list of NODE_BLOCK to join the statements. -LIST is, although it is called LIST , a list of NODE_ARRAY . -This is what is used for array literals. -LIST is used to store the arguments of a method or the list of multiple assignments.

-

As for the difference between the two lists, -looking at the usage of the nodes is helpful to understand.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NODE_BLOCK nd_head holding an element
nd_end pointing to the NODE_BLOCK of the end of the list
nd_next pointing to the next NODE_BLOCK
NODE_ARRAY nd_head holding an element
nd_alen the length of the list that follows this node
nd_next pointing to the next NODE_ARRAY
-

The usage differs only in the second elements that are nd_end and nd_alen . -And this is exactly the significance of the existence of each type of the two nodes. -Since its size can be stored in NODE_ARRAY , we use an ARRAY list -when the size of the list will frequently be required. -Otherwise, we use a BLOCK list that is very fast to join. -I don’t describe this topic in details because the codes that use them is -necessary to understand the significance but not shown here, -but when the codes appear in Part 3, -I’d like you to recall this and think “Oh, this uses the length”.

-

Semantic Analysis

-

As I briefly mentioned at the beginning of Part 2, there are two types of analysis -that are appearance analysis and semantic analysis. -The appearance analysis is mostly done by yacc , the rest is doing the semantic -analysis inside actions.

-

Errors inside actions

-

What does the semantic analysis precisely mean? -For example, there are type checks in a language that has types. -Alternatively, check if variables with the same name are not defined multiple times, -and check if variables are not used before their definitions, -and check if the procedure being used is defined, -and check if return is not used outside of procedures, and so on. -These are part of the semantic analysis.

-

What kind of semantic analysis is done in the current ruby ? -Since the error checks occupies almost all of semantic analysis in ruby , -searching the places where generating errors seems a good way. -In a parser of yacc , yyerror() is supposed to be called when an error occurs. -Conversely speaking, there’s an error where yyerror() exists. -So, I made a list of the places where calling yyerror() inside the actions.

-
    -
  • an expression not having its value (void value expression) at a place where a value is required
  • -
  • an alias of $n
  • -
  • BEGIN inside of a method
  • -
  • END inside of a method
  • -
  • return outside of methods
  • -
  • a local variable at a place where constant is required
  • -
  • a class statement inside of a method
  • -
  • an invalid parameter variable ($gvar and CONST and such)
  • -
  • parameters with the same name appear twice
  • -
  • an invalid receiver of a singleton method (def ().method and such)
  • -
  • a singleton method definition on literals
  • -
  • an odd number of a list for hash literals
  • -
  • an assignment to self/nil/true/false/__FILE__/__LINE__
  • -
  • a constant assignment inside of a method
  • -
  • a multiple assignment inside of a conditional expression
  • -
-

These checks can roughly be categorized by each purpose as follows:

-
    -
  • for the better error message
  • -
  • in order not to make the rule too complex
  • -
  • the others (pure semantic analysis)
  • -
-

For example, “return outside of a method” is a check in order not to make the -rule too complex. Since this error is a problem of the structure, it can be -dealt with by grammar. -For example, it’s possible by defining the rules separately for both inside and -outside of methods and making the list of all what are allowed and what are not -allowed respectively. But this is in any way cumbersome and rejecting it in an -action is far more concise.

-

And, "an assignment to self " seems a check for the better error message. -In comparison to “return outside of methods”, rejecting it by grammar is much easier, -but if it is rejected by the parser, the output would be just "parse error". -Comparing to it, the current

-
-% ruby -e 'self = 1'
--e:1: Can't change the value of self
-self = 1
-      ^
-
-

this error is much more friendly.

-

Of course, we can not always say that an arbitrary rule is exactly “for this purpose”. -For example, as for “return outside of methods”, -this can also be considered that this is a check “for the better error message”. -The purposes are overlapping each other.

-

Now, the problem is “a pure semantic analysis”, -in Ruby there are few things belong to this category. -In the case of a typed language, the type analysis is a big event, but -because variables are not typed in Ruby, it is meaningless. -What is standing out instead is the cheek of an expression that has its value.

-

To put “having its value” precisely, -it is “you can obtain a value as a result of evaluating it”. -return and break do not have values by themselves. Of course, a value is -passed to the place where return to, but not any values are left at the place -where return is written. -Therefore, for example, the next expression is odd,

-
-i = return(1)
-
-

Since this kind of expressions are clearly due to misunderstanding or simple mistakes, -it’s better to reject when compiling. -Next, we’ll look at value_expr which is one of the functions to check if it takes a value.

-

value_expr()

-

value_expr() is the function to check if it is an expr that has a value.

-

value_expr()

- -
-4754  static int
-4755  value_expr(node)
-4756      NODE *node;
-4757  {
-4758      while (node) {
-4759          switch (nd_type(node)) {
-4760            case NODE_CLASS:
-4761            case NODE_MODULE:
-4762            case NODE_DEFN:
-4763            case NODE_DEFS:
-4764              rb_warning("void value expression");
-4765              return Qfalse;
-4766
-4767            case NODE_RETURN:
-4768            case NODE_BREAK:
-4769            case NODE_NEXT:
-4770            case NODE_REDO:
-4771            case NODE_RETRY:
-4772              yyerror("void value expression");
-4773              /* or "control never reach"? */
-4774              return Qfalse;
-4775
-4776            case NODE_BLOCK:
-4777              while (node->nd_next) {
-4778                  node = node->nd_next;
-4779              }
-4780              node = node->nd_head;
-4781              break;
-4782
-4783            case NODE_BEGIN:
-4784              node = node->nd_body;
-4785              break;
-4786
-4787            case NODE_IF:
-4788              if (!value_expr(node->nd_body)) return Qfalse;
-4789              node = node->nd_else;
-4790              break;
-4791
-4792            case NODE_AND:
-4793            case NODE_OR:
-4794              node = node->nd_2nd;
-4795              break;
-4796
-4797            case NODE_NEWLINE:
-4798              node = node->nd_next;
-4799              break;
-4800
-4801            default:
-4802              return Qtrue;
-4803          }
-4804      }
-4805
-4806      return Qtrue;
-4807  }
-
-(parse.y)
-
-

Algorithm

-

Summary: It sequentially checks the nodes of the tree, if it hits “an expression -certainly not having its value”, it means the tree does not have any value. -Then it warns about that by using rb_warning() and return Qfalse . If it -finishes to traverse the entire tree without hitting any “an expression not -having its value”, it means the tree does have a value. Thus it returns Qtrue .

-

Here, notice that it does not always need to check the whole tree. -For example, let’s assume value_expr() is called on the argument of a method. -Here:

-

▼ check the value of arg by using value_expr()

- -
-1055  arg_value       : arg
-1056                      {
-1057                          value_expr($1);
-1058                          $$ = $1;
-1059                      }
-
-(parse.y)
-
-

Inside of this argument $1 , there can also be other nesting method calls again. -But, the argument of the inside method must have been already checked with -value_expr() , so you don’t have to check it again.

-

Let’s think more generally. Assume an arbitrary grammar element A exists, -and assume value_expr() is called against its all composing elements, -the necessity to check the element A again would disappear.

-

Then, for example, how is if ? Is it possible to be handled as if value_expr() -has already called for all elements? If I put only the bottom line, it isn’t. -That is because, since if is a statement (which does not use a value), -the main body should not have to return a value. -For example, in the next case:

-
-def method
-  if true
-    return 1
-  else
-    return 2
-  end
-  5
-end
-
-

This if statement does not need a value.
-But in the next case, its value is necessary.

-
-def method( arg )
-  tmp = if arg
-        then 3
-        else 98
-        end
-  tmp * tmp / 3.5
-end
-
-

So, in this case, the if statement must be checked when checking the entire -assignment expression. This kind of things are laid out in the switch -statement of value_expr() .

-

Removing Tail Recursion

-

By the way, when looking over the whole value_expr , we can see that there’s -the following pattern appears frequently:

-
-while (node) {
-    switch (nd_type(node)) {
-      case NODE_XXXX:
-        node = node->nd_xxxx;
-        break;
-         :
-         :
-    }
-}
-
-

This expression will also carry the same meaning after being modified to the below:

-
-return value_expr(node->nd_xxxx)
-
-

A code like this which does a recursive call just before return is called a -tail recursion. It is known that this can generally be converted to goto . -This method is often used when optimizing. -As for Scheme, it is defined in specifications that tail recursions must be -removed by language processors. This is because recursions are often used -instead of loops in Lisp-like languages.

-

However, be careful that tail recursions are only when "calling just before return ". -For example, take a look at the NODE_IF of value_expr() ,

-
-if (!value_expr(node->nd_body)) return Qfalse;
-node = node->nd_else;
-break;
-
-

As shown above, the first time is a recursive call. -Rewriting this to the form of using return ,

-
-return value_expr(node->nd_body) && value_expr(node->nd_else);
-
-

If the left value_expr() is false, the right value_expr() is also executed. -In this case, the left value_expr() is not “just before” return . -Therefore, it is not a tail recursion. -Hence, it can’t be extracted to goto .

-

The whole picture of the value check

-

As for value checks, we won’t read the functions further. -You might think it’s too early, but all of the other functions are, as the same -as value_expr() , step-by-step one-by-one only traversing and checking nodes, -so they are completely not interesting. -However, I’d like to cover the whole picture at least, -so I finish this section by just showing the call graph of the relevant functions (Fig.7).

-

-

(callgraph)
-Fig.7: the call graph of the value check functions

-

-

Local Variables

-

Local Variable Definitions

-

The variable definitions in Ruby are really various. -As for constants and class variables, these are defined on the first assignment. -As for instance variables and global variables, as all names can be considered -that they are already defined, you can refer them without assigning beforehand -(although it produces warnings).

-

The definitions of local variables are again completely different from the above all. -A local variable is defined when its assignment appears on the program. -For example, as follows:

-
-lvar = nil
-p lvar      # being defined
-
-

In this case, as the assignment to lvar is written at the first line, -in this moment lvar is defined. -When it is undefined, it ends up with a runtime exception NameError as follows:

-
-% ruby lvar.rb
-lvar.rb:1: undefined local variable or method `lvar'
-for #<Object:0x40163a9c> (NameError)
-
-

Why does it say "local variable or method"? -As for methods, the parentheses of the arguments can be omitted when calling, -so when there’s not any arguments, it can’t be distinguished from local variables. -To resolve this situation, ruby tries to call it as a method when it finds -an undefined local variable. Then if the corresponding method is not found, it -generates an error such as the above one.

-

By the way, it is defined when “it appears”, this means it is defined even -though it was not assigned. The initial value of a defined variable is nil.

-
-if false
-  lvar = "this assigment will never be executed"
-end
-p lvar   # shows nil
-
-

Moreover, since it is defined “when” it “appears”, the definition has to be -before the reference in a symbol sequence. -For example, in the next case, it is not defined.

-
-p lvar       # not defined !
-lvar = nil   # although appearing here ...
-
-

Be careful about the point of “in the symbol sequence”. -It has completely nothing to do with the order of evaluations. -For example, for the next code, naturally the condition expression is evaluated first, -but in the symbol sequence, at the moment when p appears the assignment -to lvar has not appeared yet. -Therefore, this produces NameError .

-
-p(lvar) if lvar = true
-
-

What we’ve learned by now is that the local variables are extremely influenced -by the appearances. When a symbol sequence that expresses an assignment appears, -it will be defined in the appearance order. Based on this information, we can -infer that ruby seems to define local variables while parsing because the -order of the symbol sequence does not exist after leaving the parser. -And in fact, it is true. In ruby , the parser defines local variables.

-

Block Local Variables

-

The local variables newly defined in an iterator block are called block local -variables or dynamic variables. Block local variables are, in language -specifications, identical to local variables. However, these two differ in -their implementations. -We’ll look at how is the difference from now on.

-

The data structure

-

We’ll start with the local variable table struct local_vars.

-

struct local_vars

- -
-5174  static struct local_vars {
-5175      ID *tbl;                    /* the table of local variable names */
-5176      int nofree;                 /* whether it is used from outside */
-5177      int cnt;                    /* the size of the tbl array */
-5178      int dlev;                   /* the nesting level of dyna_vars */
-5179      struct RVarmap* dyna_vars;  /* block local variable names */
-5180      struct local_vars *prev;
-5181  } *lvtbl;
-
-(parse.y)
-
-

The member name prev indicates that the struct local_vars is a -opposite-direction linked list. … Based on this, we can expect a stack. -The simultaneously declared global variable lvtbl points to local_vars that -is the top of that stack.

-

And, struct RVarmap is defined in env.h , -and is available to other files and is also used by the evaluator. -This is used to store the block local variables.

-

struct RVarmap

- -
-  52  struct RVarmap {
-  53      struct RBasic super;
-  54      ID id;                  /* the variable name */
-  55      VALUE val;              /* its value */
-  56      struct RVarmap *next;
-  57  };
-
-(env.h)
-
-

Since there’s struct RBasic at the top, this is a Ruby object. -It means it is managed by the garbage collector. -And since it is joined by the next member, it is probably a linked list.

-

Based on the observation we’ve done and the information that will be explained, -Fig.8 illustrates the image of both structs while executing the parser.

-

-

(localvars)
-Fig.8: The image of local variable tables at runtime

-

-

Local Variable Scope

-

When looking over the list of function names of parse.y , -we can find functions such as local_push() local_pop() local_cnt() are laid out. -In whatever way of thinking, they appear to be relating to a local variable. -Moreover, because the names are push pop, it is clearly a stack. -So first, let’s find out the places where using these functions.

-

local_push() local_pop() used examples

- -
-1475                  | kDEF fname
-1476                      {
-1477                          $<id>$ = cur_mid;
-1478                          cur_mid = $2;
-1479                          in_def++;
-1480                          local_push(0);
-1481                      }
-1482                    f_arglist
-1483                    bodystmt
-1484                    kEND
-1485                      {
-1486                          /* NOEX_PRIVATE for toplevel */
-1487                          $$ = NEW_DEFN($2, $4, $5,
-                                  class_nest?NOEX_PUBLIC:NOEX_PRIVATE);
-1488                          if (is_attrset_id($2))
-                                  $$->nd_noex = NOEX_PUBLIC;
-1489                          fixpos($$, $4);
-1490                          local_pop();
-1491                          in_def--;
-1492                          cur_mid = $<id>3;
-1493                      }
-
-(parse.y)
-
-

At def , I could find the place where it is used. It can also be found in class -definitions and singleton class definitions, and module definitions. -In other words, it is the place where the scope of local variables is cut. -Moreover, as for how they are used, -it does push where the method definition starts and does pop when the definition ends. -This means, as we expected, it is almost certain that the functions start with -local_ are relating to local variables. And it is also revealed that the part -between push and pop is probably a local variable scope.

-

Moreover, I also searched local_cnt() .

-

NEW_LASGN()

- -
- 269  #define NEW_LASGN(v,val) rb_node_newnode(NODE_LASGN,v,val,local_cnt(v))
-
-(node.h)
-
-

This is found in node.h . Even though there are also the places where using in parse.y , -I found it in the other file. Thus, probably I’m in desperation.

-

This NEW_LASGN is “new local assignment”. This should mean the node of an -assignment to a local variable. And also considering the place where using it, -the parameter v is apparently the local variable name. val is probably -(a syntax tree that represents). the right-hand side value

-

Based on the above observations, local_push() is at the beginning of the local variable, -local_cnt() is used to add a local variable if there’s a local variable assignment in the halfway, -local_pop() is used when ending the scope. -This perfect scenario comes out. (Fig.9)

-

-

(localtbl)
-Fig.9: the flow of the local variable management

-

-

Then, let’s look at the content of the function.

-

push and pop

-

local_push()

- -
-5183  static void
-5184  local_push(top)
-5185      int top;
-5186  {
-5187      struct local_vars *local;
-5188
-5189      local = ALLOC(struct local_vars);
-5190      local->prev = lvtbl;
-5191      local->nofree = 0;
-5192      local->cnt = 0;
-5193      local->tbl = 0;
-5194      local->dlev = 0;
-5195      local->dyna_vars = ruby_dyna_vars;
-5196      lvtbl = local;
-5197      if (!top) {
-5198          /* preserve the variable table of the previous scope into val  */
-5199          rb_dvar_push(0, (VALUE)ruby_dyna_vars);
-5200          ruby_dyna_vars->next = 0;
-5201      }
-5202  }
-
-(parse.y)
-
-

As we expected, it seems that struct local_vars is used as a stack. -Also, we can see lvtbl is pointing to the top of the stack. -The lines relates to rb_dvar_push() will be read later, so it is left untouched for now.

-

Subsequently, we’ll look at local_pop() and local_tbl() at the same time.

-

local_tbl local_pop

- -
-5218  static ID*
-5219  local_tbl()
-5220  {
-5221      lvtbl->nofree = 1;
-5222      return lvtbl->tbl;
-5223  }
-
-5204  static void
-5205  local_pop()
-5206  {
-5207      struct local_vars *local = lvtbl->prev;
-5208
-5209      if (lvtbl->tbl) {
-5210          if (!lvtbl->nofree) free(lvtbl->tbl);
-5211          else lvtbl->tbl[0] = lvtbl->cnt;
-5212      }
-5213      ruby_dyna_vars = lvtbl->dyna_vars;
-5214      free(lvtbl);
-5215      lvtbl = local;
-5216  }
-
-(parse.y)
-
-

I’d like you to look at local_tbl() . -This is the function to obtain the current local variable table ( lvtbl->tbl ). -By calling this, the nofree of the current table becomes true. -The meaning of nofree seems naturally "Don’t free() ". -In other words, this is like reference counting, "this table will be used, so -please don’t free() ". Conversely speaking, -when local_tbl() was not called with a table even once, -that table will be freed at the moment when being popped and be discarded. -For example, this situation probably happens when a method without any local variables.

-

However, the “necessary table” here means lvtbl->tbl . -As you can see, lvtbl itself will be freed at the same moment when being popped. -It means only the generated lvtbl->tbl is used in the evaluator. -Then, the structure of lvtbl->tbl is becoming important. -Let’s look at the function local_cnt() (which seems) to add variables -which is probably helpful to understand how the structure is.

-

And before that, I’d like you to remember that lvtbl->cnt is stored -at the index 0 of the lvtbl->tbl .

-

Adding variables

-

The function (which seems) to add a local variable is local_cnt() .

-

local_cnt()

- -
-5246  static int
-5247  local_cnt(id)
-5248      ID id;
-5249  {
-5250      int cnt, max;
-5251
-5252      if (id == 0) return lvtbl->cnt;
-5253
-5254      for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
-5255          if (lvtbl->tbl[cnt] == id) return cnt-1;
-5256      }
-5257      return local_append(id);
-5258  }
-
-(parse.y)
-
-

This scans lvtbl->tbl and searches what is equals to id . -If the searched one is found, it straightforwardly returns cnt-1 . -If nothing is found, it does local_append() . -local_append() must be, as it is called append , the procedure to append. -In other words, local_cnt() checks if the variable was already registered, -if it was not, adds it by using local_append() and returns it.

-

What is the meaning of the return value of this function? lvtbl->tbl seems an -array of the variables, so there’re one-to-one correspondences between the -variable names and “their index – 1 ( cnt-1 )”. (Fig.10)

-

-

(lvtbltbl)
-Fig.10: The correspondences between the variable names and the return values

-

-

Moreover, this return value is calculated so that the start point becomes 0, -the local variable space is probably an array. -And, this returns the index to access that array. -If it is not, like the instance variables or constants, -(the ID of) the variable name could have been used as a key in the first place.

-

You might want to know why it is avoiding index 0 (the loop start -from cnt=1 ) for some reasons, it is probably to store a value at local_pop() .

-

Based on the knowledge we’ve learned, we can understand the role of local_append() -without actually looking at the content. -It registers a local variable and returns -“(the index of the variable in lvtbl->tbl ) – 1”. -It is shown below, let’s make sure.

-

local_append()

- -
-5225  static int
-5226  local_append(id)
-5227      ID id;
-5228  {
-5229      if (lvtbl->tbl == 0) {
-5230          lvtbl->tbl = ALLOC_N(ID, 4);
-5231          lvtbl->tbl[0] = 0;
-5232          lvtbl->tbl[1] = '_';
-5233          lvtbl->tbl[2] = '~';
-5234          lvtbl->cnt = 2;
-5235          if (id == '_') return 0;
-5236          if (id == '~') return 1;
-5237      }
-5238      else {
-5239          REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
-5240      }
-5241
-5242      lvtbl->tbl[lvtbl->cnt+1] = id;
-5243      return lvtbl->cnt++;
-5244  }
-
-(parse.y)
-
-

It seems definitely true. lvtbl->tbl is an array of the local variable names, -and its index – 1 is the return value (local variable ID).

-

Note that it increases lvtbl->cnt . -Since the code to increase lvtbl->cnt only exists here, -from only this code its meaning can be decided. -Then, what is the meaning? It is, -since “lvtbl->cnt increases by 1 when a new variable is added”, -“lvtbl->cnt holds the number of local variables in this scope”.

-

Finally, I’ll explain about tbl[1] and tbl[2] . These '_' and '~' are, -as you can guess if you are familiar with Ruby, -the special variables named $_ and $~ . -Though their appearances are identical to global variables, -they are actually local variables. -Even If you didn’t explicitly use it, when the methods such as Kernel#gets are called, -these variables are implicitly assigned, -thus it’s necessary that the spaces are always allocated.

-

Summary of local variables

-

Since the description of local variables were complex in various ways, -let’s summarize it.

-

First, It seems the local variables are different from the other variables -because they are not managed with st_table . -Then, where are they stored in? It seems the answer is an array. -Moreover, it is stored in a different array for each scope.

-

The array is lvtbl->tbl , and the index 0 holds the lvtbl->cnt which is set -at local_pop() . In other words, it holds the number of the local variables. -The index 1 or more hold the local variable names defined in the scope. -Fig.11 shows the final appearance we expect.

-

-

(tbl)
-Fig.11: correspondences between local variable names and the return values

-

-

Block Local Variables

-

The rest is dyna_vars which is a member of struct local_vars. -In other words, this is about the block local variables. -I thought that there must be the functions to do something with this, -looked over the list of the function names, -and found them as expected. -There are the suspicious functions named dyna_push() dyna_pop() dyna_in_block(). -Moreover, here is the place where these are used.

-

▼ an example using dyna_push dyna_pop

- -
-1651  brace_block     : '{'
-1652                      {
-1653                          $<vars>$ = dyna_push();
-1654                      }
-1655                    opt_block_var
-1656                    compstmt '}'
-1657                      {
-1658                          $$ = NEW_ITER($3, 0, $4);
-1659                          fixpos($$, $4);
-1660                          dyna_pop($<vars>2);
-1661                      }
-
-(parse.y)
-
-

push at the beginning of an iterator block, pop at the end. -This must be the process of block local variables.

-

Now, we are going to look at the functions.

-

dyna_push()

- -
-5331  static struct RVarmap*
-5332  dyna_push()
-5333  {
-5334      struct RVarmap* vars = ruby_dyna_vars;
-5335
-5336      rb_dvar_push(0, 0);
-5337      lvtbl->dlev++;
-5338      return vars;
-5339  }
-
-(parse.y)
-
-

Increasing lvtbl->dlev seems the mark indicates the existence of the block -local variable scope. -Meanwhile, rb_dvar_push() is …

-

rb_dvar_push()

- -
- 691  void
- 692  rb_dvar_push(id, value)
- 693      ID id;
- 694      VALUE value;
- 695  {
- 696      ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
- 697  }
-
-(eval.c)
-
-

It creates a struct RVarmap that has the variable name id and the value -val as its members, adds it to the top of the global variable ruby_dyna_vars . -This is again and again the form of cons. -In dyna_push() , ruby_dyan_vars is not set aside, -it seems it adds directly to the ruby_dyna_vars of the previous scope.

-

Moreover, the value of the id member of the RVarmap to be added here is 0. -Although it was not seriously discussed in this book, -the ID of ruby will never be 0 while it is normally created by rb_intern() . -Thus, we can infer that this RVarmap , as it is like NUL or NULL , -probably has a role as sentinel. -If we think based on this assumption, we can describe the reason why the holder -of a variable ( RVarmap ) is added even though not any variables are added.

-

Next, dyna_pop() .

-

dyna_pop()

- -
-5341  static void
-5342  dyna_pop(vars)
-5343      struct RVarmap* vars;
-5344  {
-5345      lvtbl->dlev--;
-5346      ruby_dyna_vars = vars;
-5347  }
-
-(parse.y)
-
-

By reducing lvtbl->dlev , it writes down the fact that the block local -variable scope ended. -It seems that something is done by using the argument, -let’s see this later at once.

-

The place to add a block local variable has not appeared yet. -Something like local_cnt() of local variables is missing. -So, I did plenty of grep with dvar and dyna , and this code was found.

-

assignable() (partial)

- -
-4599  static NODE*
-4600  assignable(id, val)
-4601      ID id;
-4602      NODE *val;
-4603  {
-                            :
-4634              rb_dvar_push(id, Qnil);
-4635              return NEW_DASGN_CURR(id, val);
-
-(parse.y)
-
-

assignable() is the function to create a node relates to assignments, -this citation is the fragment of that function only contains the part to deal -with block local variables. -It seems that it adds a new variable (to ruby_dyna_vars ) -by using rb_dvar_push() that we’ve just seen.

-

ruby_dyna_vars in the parser

-

Now, taking the above all into considerations, let’s imagine the appearance of -ruby_dyna_vars at the moment when a local variable scope is finished to be -parsed.

-

First, as I said previously, -the RVarmap of id=0 which is added at the beginning of a block scope is a -sentinel which represents a break between two block scopes. -We’ll call this "the header of ruby_dyna_vars ".

-

Next, among the previously shown actions of the rule of the iterator block, -I’d like you to focus on this part:

-
-$<vars>$ = dyna_push();    /* what assigned into $<vars>$ is ... */
-        :
-        :
-dyna_pop($<vars>2);        /* …… appears at $<vars>2 */
-
-

dyna_push() returns the ruby_dyna_vars at the moment. -dyna_pop() put the argument into ruby_dyna_vars . -This means ruby_dyna_vars would be saved and restored for each the block local -variable scope. -Therefore, when parsing the following program,

-
-iter {
-    a = nil
-    iter {
-        b = nil
-        iter {
-            c = nil
-            # nesting level 3
-        }
-        bb = nil
-        # nesting level 2
-        iter {
-            e = nil
-        }
-    }
-    # nesting level 1
-}
-
-

Fig.12 shows the ruby_dyna_vars in this situation.

-

-

(dynavars)
-Fig.12: ruby_dyna_vars when all scopes are finished to be parsed

-

-

This structure is fairly smart. -That’s because the variables of the higher levels can naturally be accessed by -traversing over all of the list even if the nesting level is deep. -This way has the simpler searching process than creating a different table for -each level.

-

Plus, in the figure, it looks like bb is hung at a strange place, -but this is correct. -When a variable is found at the nest level which is decreased after increased once, -it is attached to the subsequent of the list of the original level. -Moreover, in this way, the specification of local variable that -“only the variables which already exist in the symbol sequence are defined” -is expressed in a natural form.

-

And finally, at each cut of local variable scopes (this is not of block local -variable scopes), this link is entirely saved or restored to lvtbl->dyna_vars . -I’d like you to go back a little and check local_push() and local_pop() .

-

By the way, although creating the ruby_dyna_vars list was a huge task, -it is by itself not used at the evaluator. This list is used only to check the -existence of the variables and will be garbage collected at the same moment -when parsing is finished. And after entering the evaluator, another chain is -created again. -There’s a quite deep reason for this, … we’ll see around this once again in -Part 3.

- - - -
- - diff --git a/htmls/thread.html b/htmls/thread.html deleted file mode 100644 index c361e1f..0000000 --- a/htmls/thread.html +++ /dev/null @@ -1,1153 +0,0 @@ - - - - - Chapter 19: Threads | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Chapter 19: Threads

-

Outline

-

Ruby Interface

-

Come to think of it, I feel I have not introduced an actual code to use Ruby threads. -This is not so special, but here I’ll introduce it just in case.

-
-Thread.fork {
-    while true
-      puts 'forked thread'
-    end
-}
-while true
-  puts 'main thread'
-end
-
-

When executing this program, -a lot of "forked thread" and "main thread" are printed in the properly mixed -state.

-

Of course, other than just creating multiple threads, there are also various -ways to control. There’s not the synchronize as a reserved word like Java, -common primitives such as Mutex or Queue or Monitor are of course available, -and the below APIs can be used to control a thread itself.

-

▼ Thread API

- - - - - - - - - - - - - - - - - - - - - - - - - -
Thread.pass transfer the execution to any other thread
Thread.kill(th) terminates the th thread
Thread.exit terminates the thread itself
Thread.stop temporarily stop the thread itself
Thread#join waiting for the thread to finish
Thread#wakeup to wake up the temporarily stopped thread
-

ruby Thread

-

Threads are supposed to “run all together”, -but actually they are running for a little time in turns. -To be precise, by making some efforts on a machine of multi CPU, -it’s possible that, for instance, two of them are running at the same time. -But still, if there are more threads than the number of CPU, -they have to run in turns.

-

In other words, in order to create threads, someone has to switch the threads -in somewhere. There are roughly two ways to do it: -kernel-level threads and user-level threads. -They are respectively, as the names suggest, to create a thread in kernel or at -user-level. If it is kernel-level, by making use of multi-CPU, -multiple threads can run at the same time.

-

Then, how about the thread of ruby? It is user-level thread. -And (Therefore), the number of threads that are runnable at the same time is -limited to one.

-

Is it preemptive?

-

I’ll describe about the traits of ruby threads in more detail. -As an alternative point of view of threads, -there’s the point that is “is it preemptive?”.

-

When we say “thread (system) is preemptive”, -the threads will automatically be switched without being explicitly switched by -its user. -Looking this from the opposite direction, the user can’t control the timing of -switching threads.

-

On the other hand, in a non-preemptive thread system, -until the user will explicitly say -“I can pass the control right to the next thread”, -threads will never be switched. -Looking this from the opposite direction, -when and where there’s the possibility of switching threads is obvious.

-

This distinction is also for processes, -in that case, preemptive is considered as “superior”. -For example, if a program had a bug and it entered an infinite loop, -the processes would never be able to switch. -This means a user program can halt the whole system and is not good. -And, switching processes was non-preemptive on Windows 3.1 -because its base was MS-DOS, -but Windows 95 is preemptive. Thus, the system is more robust. -Hence, it is said that Windows 95 is “superior” to 3.1.

-

Then, how about the ruby thread? It is preemptive at Ruby-level, -and non-preemptive at C level. In other words, when you are writing C code, -you can determine almost certainly the timings of switching threads.

-

Why is this designed in this way? Threads are indeed convenient, -but its user also need to prepare certain minds. -It means that it is necessary the code is compatible to the threads. -(It must be multi-thread safe). In other words, in order to make it preemptive -also in C level, the all C libraries have to be thread safe.

-

But in reality, there are also a lot of C libraries that are still not thread safe. -A lot of efforts were made to ease to write extension libraries, -but it would be brown if the number of usable libraries is decreased by -requiring thread safety. -Therefore, non-preemptive at C level is a reasonable choice for ruby.

-

Management System

-

We’ve understand ruby thread is non-preemptive at C level. -It means after it runs for a while, it voluntarily let go of the controlling -right. Then, I’d like you to suppose that now a currently being executed thread -is about to quit the execution. Who will next receive the control right? -But before that, it’s impossible to guess it without knowing how threads are -expressed inside ruby in the first place. -Let’s look at the variables and the data types to manage threads.

-

▼ the structure to manage threads

- -
- 864  typedef struct thread * rb_thread_t;
- 865  static rb_thread_t curr_thread = 0;
- 866  static rb_thread_t main_thread;
-
-7301  struct thread {
-7302      struct thread *next, *prev;
-
-(eval.c)
-
-

Since struct thread is very huge for some reason, -this time I narrowed it down to the only important part. -It is why there are only the two. These next and prev are member names, -and their types are rb_thread_t, -thus we can expect rb_thread_t is connected by a dual-directional link list. -And actually it is not an ordinary dual-directional list, -the both ends are connected. It means, it is circular. -This is a big point. Adding the static main_thread and curr_thread variables -to it, the whole data structure would look like Figure 1.

-

-

(thread)
-Figure 1: the data structures to manage threads

-

-

main_thread (main thread) means the thread existed at the time when a program -started, meaning the “first” thread. curr_thread is obviously current thread, -meaning the thread currently running. -The value of main_thread will never change while the process is running, -but the value of curr_thread will change frequently.

-

In this way, because the list is being a circle, the procedure to chose “the -next thread” becomes easy. It can be done by merely following the next link. -Only by this, we can run all threads equally to some extent.

-

What does switching threads mean?

-

By the way, what is a thread in the first place? -Or, what makes us to say threads are switched?

-

These are very difficult questions. Similar to what a program is or what an -object is, when asked about what are usually understood by feelings, -it’s hard to answer clearly. -Especially, “what is the difference between threads and processes?” -is a good question.

-

Still, in a realistic range, we can describe it to some extent. -What necessary for threads is the context of executing. -As for the context of ruby, as we’ve seen by now, -it consists of ruby_frame and ruby_scope and ruby_class and so on. -And ruby allocates the substance of ruby_frame on the machine stack, -and there are also the stack space used by extension libraries, -therefore the machine stack is also necessary as a context of a Ruby program. -And finally, the CPU registers are indispensable. -These various contexts are the elements to enable threads, -and switching them means switching threads. -Or, it is called “context-switch”.

-

The way of context-switching

-

The rest talk is how to switch contexts. -ruby_scope and ruby_class are easy to replace: -allocate spaces for them somewhere such as the heap and -set them aside one by one. -For the CPU registers, we can make it -because we can save and write back them by using setjmp(). -The spaces for both purposes are respectively prepared in rb_thread_t.

-

struct thread (partial)

- -
-7301  struct thread {
-7302      struct thread *next, *prev;
-7303      jmp_buf context;
-
-7315      struct FRAME *frame;        /* ruby_frame */
-7316      struct SCOPE *scope;        /* ruby_scope */
-7317      struct RVarmap *dyna_vars;  /* ruby_dyna_vars */
-7318      struct BLOCK *block;        /* ruby_block */
-7319      struct iter *iter;          /* ruby_iter */
-7320      struct tag *tag;            /* prot_tag */
-7321      VALUE klass;                /* ruby_class */
-7322      VALUE wrapper;              /* ruby_wrapper */
-7323      NODE *cref;                 /* ruby_cref */
-7324
-7325      int flags;  /* scope_vmode / rb_trap_immediate / raised */
-7326
-7327      NODE *node;                 /* rb_current_node */
-7328
-7329      int tracing;                /* tracing */
-7330      VALUE errinfo;              /* $! */
-7331      VALUE last_status;          /* $? */
-7332      VALUE last_line;            /* $_ */
-7333      VALUE last_match;           /* $~ */
-7334
-7335      int safe;                   /* ruby_safe_level */
-
-(eval.c)
-
-

As shown above, there are the members that seem to correspond to ruby_frame -and ruby_scope. There’s also a jmp_buf to save the registers.

-

Then, the problem is the machine stack. -How can we substitute them?

-

The way which is the most straightforward for the mechanism is directly writing -over the pointer to the position (end) of the stack. -Usually, it is in the CPU registers. -Sometimes it is a specific register, -and it is also possible that a general-purpose register is allocated for it. -Anyway, it is in somewhere. -For convenience, we’ll call it the stack pointer from now on. -It is obvious that the different space can be used as the stack by modifying it. -But it is also obvious in this way we have to deal with it for each CPU -and for each OS, thus it is really hard to serve the potability.

-

Therefore, ruby uses a very violent way to implement the substitution of the -machine stack. That is, if we can’t modify the stack pointer, let’s modify the -place the stack pointer points to. We know the stack can be directly modified -as we’ve seen in the description about the garbage collection, -the rest is slightly changing what to do. -The place to store the stack properly exists in struct thread.

-

struct thread (partial)

- -
-7310      int   stk_len;      /* the stack length */
-7311      int   stk_max;      /* the size of memory allocated for stk_ptr */
-7312      VALUE*stk_ptr;      /* the copy of the stack */
-7313      VALUE*stk_pos;      /* the position of the stack */
-
-(eval.c)
-
-

How the explanation goes

-

So far, I’ve talked about various things, but the important points can be -summarized to the three:

-
    -
  • When
  • -
  • To which thread
  • -
  • How
  • -
-

to switch context. These are also the points of this chapter. -Below, I’ll describe them using a section for each of the three points -respectively.

-

Trigger

-

To begin with, it’s the first point, when to switch threads. -In other words, what is the cause of switching threads.

-

Waiting I/O

-

For example, when trying to read in something by calling IO#gets or IO#read, -since we can expect it will take a lot of time to read, -it’s better to run the other threads in the meantime. -In other words, a forcible switch becomes necessary here. -Below is the interface of getc.

-

rb_getc()

- -
-1185  int
-1186  rb_getc(f)
-1187      FILE *f;
-1188  {
-1189      int c;
-1190
-1191      if (!READ_DATA_PENDING(f)) {
-1192          rb_thread_wait_fd(fileno(f));
-1193      }
-1194      TRAP_BEG;
-1195      c = getc(f);
-1196      TRAP_END;
-1197
-1198      return c;
-1199  }
-
-(io.c)
-
-

READ_DATA_PENDING(f) is a macro to check if the content of the buffer of the -file is still there. If there’s the content of the buffer, -it means it can move without any waiting time, -thus it would read it immediately. -If it was empty, it means it would take some time, -thus it would rb_thread_wait_fd(). -This is an indirect cause of switching threads.

-

If rb_thread_wait_fd() is “indirect”, there also should be a “direct” cause. -What is it? Let’s see the inside of rb_thread_wait_fd().

-

rb_thread_wait_fd()

- -
-8047  void
-8048  rb_thread_wait_fd(fd)
-8049      int fd;
-8050  {
-8051      if (rb_thread_critical) return;
-8052      if (curr_thread == curr_thread->next) return;
-8053      if (curr_thread->status == THREAD_TO_KILL) return;
-8054
-8055      curr_thread->status = THREAD_STOPPED;
-8056      curr_thread->fd = fd;
-8057      curr_thread->wait_for = WAIT_FD;
-8058      rb_thread_schedule();
-8059  }
-
-(eval.c)
-
-

There’s rb_thread_schedule() at the last line. -This function is the “direct cause”. -It is the heart of the implementation of the ruby threads, -and does select and switch to the next thread.

-

What makes us understand this function has such role is, -in my case, I knew the word “scheduling” of threads beforehand. -Even if you didn’t know, because you remembers now, -you’ll be able to notice it at the next time.

-

And, in this case, it does not merely pass the control to the other thread, -but it also stops itself. -Moreover, it has an explicit deadline that is “by the time when it becomes readable”. -Therefore, this request should be told to rb_thread_schedule(). -This is the part to assign various things to the members of curr_thread. -The reason to stop is stored in wait_for, -the information to be used when waking up is stored in fd, -respectively.

-

Waiting the other thread

-

After understanding threads are switched at the timing of rb_thread_schedule(), -this time, conversely, from the place where rb_thread_schedule() appears, -we can find the places where threads are switched. -Then by scanning, I found it in the function named rb_thread_join().

-

rb_thread_join() (partial)

- -
-8227  static int
-8228  rb_thread_join(th, limit)
-8229      rb_thread_t th;
-8230      double limit;
-8231  {
-
-8243          curr_thread->status = THREAD_STOPPED;
-8244          curr_thread->join = th;
-8245          curr_thread->wait_for = WAIT_JOIN;
-8246          curr_thread->delay = timeofday() + limit;
-8247          if (limit < DELAY_INFTY) curr_thread->wait_for |= WAIT_TIME;
-8248          rb_thread_schedule();
-
-(eval.c)
-
-

This function is the substance of Thread#join, -and Thread#join is a method to wait until the receiver thread will end. -Indeed, since there’s time to wait, running the other threads is economy. -Because of this, the second reason to switch is found.

-

Waiting For Time

-

Moreover, also in the function named rb_thread_wait_for(), -rb_thread_schedule() was found. -This is the substance of (Ruby’s) sleep and such.

-

rb_thread_wait_for (simplified)

- -
-8080  void
-8081  rb_thread_wait_for(time)
-8082      struct timeval time;
-8083  {
-8084      double date;
-
-8124      date = timeofday() +
-                 (double)time.tv_sec + (double)time.tv_usec*1e-6;
-8125      curr_thread->status = THREAD_STOPPED;
-8126      curr_thread->delay = date;
-8127      curr_thread->wait_for = WAIT_TIME;
-8128      rb_thread_schedule();
-8129  }
-
-(eval.c)
-
-

timeofday() returns the current time. -Because the value of time is added to it, -date indicates the time when the waiting time is over. -In other words, this is the order “I’d like to stop until it will be the -specific time”.

-

Switch by expirations

-

In the above all cases, -because some manipulations are done from Ruby level, -consequently it causes to switch threads. -In other words, by now, the Ruby-level is also non-preemptive. -Only by this, if a program was to single-mindedly keep calculating, -a particular thread would continue to run eternally. Therefore, -we need to let it voluntary dispose the control right after running -for a while. -Then, how long a thread can run by the time when it will have to stop, -is what I’ll talk about next.

-

setitimer

-

Since it is the same every now and then, -I feel like lacking the skill to entertain, -but I searched the places where calling rb_thread_schedule() further. -And this time it was found in the strange place. -It is here.

-

catch_timer()

- -
-8574  static void
-8575  catch_timer(sig)
-8576      int sig;
-8577  {
-8578  #if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
-8579      signal(sig, catch_timer);
-8580  #endif
-8581      if (!rb_thread_critical) {
-8582          if (rb_trap_immediate) {
-8583              rb_thread_schedule();
-8584          }
-8585          else rb_thread_pending = 1;
-8586      }
-8587  }
-
-(eval.c)
-
-

This seems something relating to signals. -What is this? -I followed the place where this catch_timer() function is used, -then it was used around here:

-

rb_thread_start_0() (partial)

- -
-8620  static VALUE
-8621  rb_thread_start_0(fn, arg, th_arg)
-8622      VALUE (*fn)();
-8623      void *arg;
-8624      rb_thread_t th_arg;
-8625  {
-
-8632  #if defined(HAVE_SETITIMER)
-8633      if (!thread_init) {
-8634  #ifdef POSIX_SIGNAL
-8635          posix_signal(SIGVTALRM, catch_timer);
-8636  #else
-8637          signal(SIGVTALRM, catch_timer);
-8638  #endif
-8639
-8640          thread_init = 1;
-8641          rb_thread_start_timer();
-8642      }
-8643  #endif
-
-(eval.c)
-
-

This means, catch_timer is a signal handler of SIGVTALRM.

-

Here, “what kind of signal SIGVTALRM is” becomes the question. -This is actually the signal sent when using the system call named setitimer. -That’s why there’s a check of HAVE_SETITIMER just before it. -setitimer is an abbreviation of “SET Interval TIMER” -and a system call to tell OS to send signals with a certain interval.

-

Then, where is the place calling setitimer? It is the rb_thread_start_timer(), -which is coincidently located at the last of this list.

-

To sum up all, it becomes the following scenario. -setitimer is used to send signals with a certain interval. -The signals are caught by catch_timer(). -There, rb_thread_schedule() is called and threads are switched. Perfect.

-

However, signals could occur anytime, -if it was based on only what described until here, -it means it would also be preemptive at C level. -Then, I’d like you to see the code of catch_timer() again.

-
-if (rb_trap_immediate) {
-    rb_thread_schedule();
-}
-else rb_thread_pending = 1;
-
-

There’s a required condition that is doing rb_thread_schedule() only when -it is rb_trap_immediate. This is the point. rb_trap_immediate is, as the -name suggests, expressing “whether or not immediately process signals”, -and it is usually false. -It becomes true only while the limited time such as while doing I/O on a single -thread. In the source code, it is the part between TRAP_BEG and TRAP_END.

-

On the other hand, since rb_thread_pending is set when it is false, -let’s follow this. -This variable is used in the following place.

-

CHECK_INTSHAVE_SETITIMER

- -
-  73  #if defined(HAVE_SETITIMER) && !defined(__BOW__)
-  74  EXTERN int rb_thread_pending;
-  75  # define CHECK_INTS do {\
-  76      if (!rb_prohibit_interrupt) {\
-  77          if (rb_trap_pending) rb_trap_exec();\
-  78          if (rb_thread_pending && !rb_thread_critical)\
-  79              rb_thread_schedule();\
-  80      }\
-  81  } while (0)
-
-(rubysig.h)
-
-

This way, inside of CHECK_INTS, rb_thread_pending is checked and -rb_thread_schedule() is done. -It means, when receiving SIGVTALRM, rb_thread_pending becomes true, -then the thread will be switched at the next time going through CHECK_INTS.

-

This CHECK_INTS has appeared at various places by now. -For example, rb_eval() and rb_call0() and rb_yeild_0. -CHECK_INTS would be meaningless if it was not located where the place -frequently being passed. -Therefore, it is natural to exist in the important functions.

-

tick

-

We understood the case when there’s setitimer. -But what if setitimer does not exist? -Actually, the answer is in CHECK_INTS, which we’ve just seen. -It is the definition of the #else side.

-

CHECK_INTSnot HAVE_SETITIMER

- -
-  84  EXTERN int rb_thread_tick;
-  85  #define THREAD_TICK 500
-  86  #define CHECK_INTS do {\
-  87      if (!rb_prohibit_interrupt) {\
-  88          if (rb_trap_pending) rb_trap_exec();\
-  89          if (!rb_thread_critical) {\
-  90              if (rb_thread_tick-- <= 0) {\
-  91                  rb_thread_tick = THREAD_TICK;\
-  92                  rb_thread_schedule();\
-  93              }\
-  94          }\
-  95      }\
-  96  } while (0)
-
-(rubysig.h)
-
-

Every time going through CHECK_INTS, decrement rb_thread_tick. -When it becomes 0, do rb_thread_schedule(). -In other words, the mechanism is that the thread will be switched -after THREAD_TICK (=500) times going through CHECK_INTS.

-

Scheduling

-

The second point is to which thread to switch. -What solely responsible for this decision is rb_thread_schedule().

-

rb_thread_schedule()

-

The important functions of ruby are always huge. -This rb_thread_schedule() has more than 220 lines. -Let’s exhaustively divide it into portions.

-

rb_thread_schedule() (outline)

- -
-7819  void
-7820  rb_thread_schedule()
-7821  {
-7822      rb_thread_t next;           /* OK */
-7823      rb_thread_t th;
-7824      rb_thread_t curr;
-7825      int found = 0;
-7826
-7827      fd_set readfds;
-7828      fd_set writefds;
-7829      fd_set exceptfds;
-7830      struct timeval delay_tv, *delay_ptr;
-7831      double delay, now;  /* OK */
-7832      int n, max;
-7833      int need_select = 0;
-7834      int select_timeout = 0;
-7835
-7836      rb_thread_pending = 0;
-7837      if (curr_thread == curr_thread->next
-7838          && curr_thread->status == THREAD_RUNNABLE)
-7839          return;
-7840
-7841      next = 0;
-7842      curr = curr_thread;         /* starting thread */
-7843
-7844      while (curr->status == THREAD_KILLED) {
-7845          curr = curr->prev;
-7846      }
-
-          /* ……prepare the variables used at select …… */
-          /* ……select if necessary        …… */
-          /* ……decide the thread to invoke next …… */
-          /* ……context-switch     …… */
-8045  }
-
-(eval.c)
-
-

(A) When there’s only one thread, this does not do anything and returns immediately. -Therefore, the talks after this can be thought based on the assumption that -there are always multiple threads.

-

(B) Subsequently, the initialization of the variables. -We can consider the part until and including the while is the initialization. -Since cur is following prev, -the last alive thread (status != THREAD_KILLED) will be set. -It is not “the first” one -because there are a lot of loops that “start with the next of curr then -deal with curr and end”.

-

After that, we can see the sentences about select. -Since the thread switch of ruby is considerably depending on select, -let’s first study about select in advance here.

-

select

-

select is a system call to wait until the preparation for reading or writing a -certain file will be completed. -Its prototype is this:

-
-int select(int max,
-           fd_set *readset, fd_set *writeset, fd_set *exceptset,
-           struct timeval *timeout);
-
-

In the variable of type fd_set, a set of fd that we want to check is stored. -The first argument max is “(the maximum value of fd in fd_set) + 1”. -The timeout is the maximum waiting time of select. -If timeout is NULL, it would wait eternally. -If timeout is 0, without waiting for even just a second, -it would only check and return immediately. -As for the return value, I’ll talk about it at the moment when using it.

-

I’ll talk about fd_set in detail. -fd_set can be manipulated by using the below macros:

-

fd_set maipulation

- -
-fd_set set;
-
-FD_ZERO(&set)       /* initialize */
-FD_SET(fd, &set)    /* add a file descriptor fd to the set */
-FD_ISSET(fd, &set)  /* true if fd is in the set */
-
-

fd_set is typically a bit array, -and when we want to check n-th file descriptor, the n-th bit is set (Figure 2).

-
-

(fdset)
-Figure 2: fd_set

-
    -
  • インデックス index -
- -

I’ll show a simple usage example of select.

-

▼ a usage exmple of select

- -
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-int
-main(int argc, char **argv)
-{
-    char *buf[1024];
-    fd_set readset;
-
-    FD_ZERO(&readset);              /* initialize readset */
-    FD_SET(STDIN_FILENO, &readset); /* put stdin into the set */
-    select(STDIN_FILENO + 1, &readset, NULL, NULL,  NULL);
-    read(STDIN_FILENO, buf, 1024);  /* success without delay */
-    exit(0);
-}
-
-

This code assume the system call is always success, -thus there are not any error checks at all. -I’d like you to see only the flow that is FD_ZEROFD_SETselect. -Since here the fifth argument timeout of select is NULL, -this select call waits eternally for reading stdin. -And since this select is completed, -the next read does not have to wait to read at all. -By putting print in the middle, -you will get further understandings about its behavior. -And a little more detailed example code is put in the attached CD-ROM -{see also doc/select.html}.

-

Preparations for select

-

Now, we’ll go back to the code of rb_thread_schedule(). -Since this code branches based on the reason why threads are waiting. -I’ll show the content in shortened form.

-

rb_thread_schedule() − preparations for select

- -
-7848    again:
-          /* initialize the variables relating to select */
-7849      max = -1;
-7850      FD_ZERO(&readfds);
-7851      FD_ZERO(&writefds);
-7852      FD_ZERO(&exceptfds);
-7853      delay = DELAY_INFTY;
-7854      now = -1.0;
-7855
-7856      FOREACH_THREAD_FROM(curr, th) {
-7857          if (!found && th->status <= THREAD_RUNNABLE) {
-7858              found = 1;
-7859          }
-7860          if (th->status != THREAD_STOPPED) continue;
-7861          if (th->wait_for & WAIT_JOIN) {
-                  /* ……join wait…… */
-7866          }
-7867          if (th->wait_for & WAIT_FD) {
-                  /* ……I/O wait…… */
-7871          }
-7872          if (th->wait_for & WAIT_SELECT) {
-                  /* ……select wait…… */
-7882          }
-7883          if (th->wait_for & WAIT_TIME) {
-                  /* ……time wait…… */
-7899          }
-7900      }
-7901      END_FOREACH_FROM(curr, th);
-
-(eval.c)
-
-

Whether it is supposed to be or not, -what stand out are the macros named FOREACH-some. -These two are defined as follows:

-

FOREACH_THREAD_FROM

- -
-7360  #define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
-7361  #define END_FOREACH_FROM(f,x) } while (x != f)
-
-(eval.c)
-
-

Let’s extract them for better understandability.

-
-th = curr;
-do {
-    th = th->next;
-    {
-        .....
-    }
-} while (th != curr);
-
-

This means: follow the circular list of threads from the next of curr -and process curr at last and end, -and meanwhile the th variable is used. -This makes me think about the Ruby’s iterators -… is this my too much imagination?

-

Here, we’ll go back to the subsequence of the code, it uses -this a bit strange loop and checks if there’s any thread which needs select. -As we’ve seen previously, since select can wait for -reading/writing/exception/time all at once, -you can probably understand I/O waits and time waits can be centralized by single select. -And though I didn’t describe about it in the previous section, -select waits are also possible. -There’s also a method named IO.select in the Ruby’s library, -and you can use rb_thread_select() at C level. -Therefore, we need to execute that select at the same time. -By merging fd_set, multiple select can be done at once.

-

The rest is only join wait. -As for its code, let’s see it just in case.

-

rb_thread_schedule()select preparation − join wait

- -
-7861          if (th->wait_for & WAIT_JOIN) {
-7862              if (rb_thread_dead(th->join)) {
-7863                  th->status = THREAD_RUNNABLE;
-7864                  found = 1;
-7865              }
-7866          }
-
-(eval.c)
-
-

The meaning of rb_thread_dead() is obvious because of its name. -It determines whether or not the thread of the argument has finished.

-

Calling select

-

By now, we’ve figured out whether select is necessary or not, -and if it is necessary, its fd_set has already prepared. -Even if there’s a immediately invocable thread (THREAD_RUNNABLE), -we need to call select beforehand. -It’s possible that there’s actually a thread that it has already been while -since its I/O wait finished and has the higher priority. -But in that case, tell select to immediately return -and let it only check if I/O was completed.

-

rb_thread_schedule()select

- -
-7904      if (need_select) {
-7905          /* convert delay into timeval */
-7906          /* if theres immediately invocable threads, do only I/O checks */
-7907          if (found) {
-7908              delay_tv.tv_sec = 0;
-7909              delay_tv.tv_usec = 0;
-7910              delay_ptr = &delay_tv;
-7911          }
-7912          else if (delay == DELAY_INFTY) {
-7913              delay_ptr = 0;
-7914          }
-7915          else {
-7916              delay_tv.tv_sec = delay;
-7917              delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec)*1e6;
-7918              delay_ptr = &delay_tv;
-7919          }
-7920
-7921          n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr);
-7922          if (n < 0) {
-                  /* …… being cut in by signal or something …… */
-7944          }
-7945          if (select_timeout && n == 0) {
-                  /* …… timeout …… */
-7960          }
-7961          if (n > 0) {
-                  /* …… properly finished …… */
-7989          }
-7990          /* In a somewhere thread, its I/O wait has finished.
-7991             roll the loop again to detect the thread */
-7992          if (!found && delay != DELAY_INFTY)
-7993              goto again;
-7994      }
-
-(eval.c)
-
-

The first half of the block is as written in the comment. -Since delay is the usec until the any thread will be next invocable, -it is converted into timeval form.

-

In the last half, it actually calls select and branches based on its result. -Since this code is long, I divided it again. -When being cut in by a signal, it either goes back to the beginning -then processes again or becomes an error. -What are meaningful are the rest two.

-

Timeout

-

When select is timeout, a thread of time wait or select wait may become -invocable. Check about it and search runnable threads. -If it is found, set THREAD_RUNNABLE to it.

-

Completing normally

-

If select is normally completed, -it means either the preparation for I/O is completed or select wait ends. -Search the threads that are no longer waiting by checking fd_set. -If it is found, set THREAD_RUNNABLE to it.

-

Decide the next thread

-

Taking all the information into considerations, -eventually decide the next thread to invoke. -Since all what was invocable and all what had finished waiting and so on became -RUNNABLE, you can arbitrary pick up one of them.

-

rb_thread_schedule() − decide the next thread

- -
-7996      FOREACH_THREAD_FROM(curr, th) {
-7997          if (th->status == THREAD_TO_KILL) {              /*(A)*/
-7998              next = th;
-7999              break;
-8000          }
-8001          if (th->status == THREAD_RUNNABLE && th->stk_ptr) {
-8002              if (!next || next->priority < th->priority)  /*(B)*/
-8003                 next = th;
-8004          }
-8005      }
-8006      END_FOREACH_FROM(curr, th);
-
-(eval.c)
-
-

(A) if there’s a thread that is about to finish, -give it the high priority and let it finish.

-

(B) find out what seems runnable. -However it seems to consider the value of priority. -This member can also be modified from Ruby level -by using Tread#priority Thread#priority=. -ruby itself does not especially modify it.

-

If these are done but the next thread could not be found, -in other words if the next was not set, what happen? -Since select has already been done, -at least one of threads of time wait or I/O wait should have finished waiting. -If it was missing, the rest is only the waits for the other threads, -and moreover there’s no runnable threads, -thus this wait will never end. -This is a dead lock.

-

Of course, for the other reasons, a dead lock can happen, -but generally it’s very hard to detect a dead lock. -Especially in the case of ruby, Mutex and such are implemented at Ruby -level, the perfect detection is nearly impossible.

-

Switching Threads

-

The next thread to invoke has been determined. -I/O and select checks has also been done. -The rest is transferring the control to the target thread. -However, for the last of rb_thread_schedule() and the code to switch threads, -I’ll start a new section.

-

Context Switch

-

The last third point is thread-switch, -and it is context-switch. -This is the most interesting part of threads of ruby.

-

The Base Line

-

Then we’ll start with the tail of rb_thread_schedule(). -Since the story of this section is very complex, -I’ll go with a significantly simplified version.

-

rb_thread_schedule() (context switch)

- -
-if (THREAD_SAVE_CONTEXT(curr)) {
-    return;
-}
-rb_thread_restore_context(next, RESTORE_NORMAL);
-
-

As for the part of THREAD_SAVE_CONTEXT(), -we need to extract the content at several places in order to understand.

-

THREAD_SAVE_CONTEXT()

- -
-7619  #define THREAD_SAVE_CONTEXT(th) \
-7620      (rb_thread_save_context(th),thread_switch(setjmp((th)->context)))
-
-7587  static int
-7588  thread_switch(n)
-7589      int n;
-7590  {
-7591      switch (n) {
-7592        case 0:
-7593          return 0;
-7594        case RESTORE_FATAL:
-7595          JUMP_TAG(TAG_FATAL);
-7596          break;
-7597        case RESTORE_INTERRUPT:
-7598          rb_interrupt();
-7599          break;
-            /* …… process various abnormal things …… */
-7612        case RESTORE_NORMAL:
-7613        default:
-7614          break;
-7615      }
-7616      return 1;
-7617  }
-
-(eval.c)
-
-

If I merge the three then extract it, here is the result:

-
-rb_thread_save_context(curr);
-switch (setjmp(curr->context)) {
-  case 0:
-    break;
-  case RESTORE_FATAL:
-    ....
-  case RESTORE_INTERRUPT:
-    ....
-  /* ……process abnormals…… */
-  case RESTORE_NORMAL:
-  default:
-    return;
-}
-rb_thread_restore_context(next, RESTORE_NORMAL);
-
-

At both of the return value of setjmp() and rb_thread_restore_context(), -RESTORE_NORMAL appears, -this is clearly suspicious. -Since it does longjmp() in rb_thread_restore_context(), -we can expect the correspondence between setjmp() and longjmp(). -And if we will imagine the meaning also from the function names,

-
-save the context of the current thread
-setjmp
-restore the context of the next thread
-longjmp
-
-

The rough main flow would probably look like this. -However what we have to be careful about here is, -this pair of setjmp() and longjmp() is not completed in this thread. -setjmp() is used to save the context of this thread, -longjmp() is used to restore the context of the next thread. -In other words, there’s a chain of setjmp/longjmp() as follows. (Figure 3)

-
-

(setjmploop)
-Figure 3: the backstitch by chaining of setjmp

-
    -
  • 外側 outside
  • -
  • 退避 set aside
  • -
  • 復元 restore
  • -
  • スレッド thread -
- -

We can restore around the CPU registers with setjmp()/longjmp(), -so the remaining context is the Ruby stacks in addition to the machine stack. -rb_thread_save_context() is to save it, -and rb_thread_restore_context() is to restore it. -Let’s look at each of them in sequential order.

-

rb_thread_save_context()

-

Now, we’ll start with rb_thread_save_context(), which saves a context.

-

rb_thread_save_context() (simplified)

- -
-7539  static void
-7540  rb_thread_save_context(th)
-7541      rb_thread_t th;
-7542  {
-7543      VALUE *pos;
-7544      int len;
-7545      static VALUE tval;
-7546
-7547      len = ruby_stack_length(&pos);
-7548      th->stk_len = 0;
-7549      th->stk_pos = (rb_gc_stack_start<pos)?rb_gc_stack_start
-7550                                           :rb_gc_stack_start - len;
-7551      if (len > th->stk_max) {
-7552          REALLOC_N(th->stk_ptr, VALUE, len);
-7553          th->stk_max = len;
-7554      }
-7555      th->stk_len = len;
-7556      FLUSH_REGISTER_WINDOWS;
-7557      MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
-
-          /* …………omission………… */
-      }
-
-(eval.c)
-
-

The last half is just keep assigning the global variables such as ruby_scope -into th, so it is omitted because it is not interesting. -The rest, in the part shown above, it attempts to copy the entire machine stack -into the place where th->stk_ptr points to.

-

First, it is ruby_stack_length() which writes the head address of the stack -into the parameter pos and returns its length. -The range of the stack is determined by using this value -and the address of the bottom-end side is set to th->stk_ptr. -We can see some branches, -it is because both a stack extending higher and a stack extending lower are -possible. (Figure 4)

-
-

(twodirection)
-Fig.4: a stack extending higher and a stack extending lower

-
    -
  • 下にのびるスタック a stack extending lower
  • -
  • 上にのびるスタック a stack extending higher -
- -

After that, the rest is allocating a memory in where th->stkptr points to and -copying the stack: allocate the memory whose size is th->stk_max then copy the -stack by the len length.

-

FLUSH_REGISTER_WINDOWS was described in Chapter 5: Garbage collection, -so its explanation might no longer be necessary. -This is a macro (whose substance is written in Assembler) -to write down the cache of the stack space to the memory. -It must be called when the target is the entire stack.

-

rb_thread_restore_context()

-

And finally, -it is rb_thread_restore_context(), -which is the function to restore a thread.

-

rb_thread_restore_context()

- -
-7635  static void
-7636  rb_thread_restore_context(th, exit)
-7637      rb_thread_t th;
-7638      int exit;
-7639  {
-7640      VALUE v;
-7641      static rb_thread_t tmp;
-7642      static int ex;
-7643      static VALUE tval;
-7644
-7645      if (!th->stk_ptr) rb_bug("unsaved context");
-7646
-7647      if (&v < rb_gc_stack_start) {
-7648          /* the machine stack extending lower */
-7649          if (&v > th->stk_pos) stack_extend(th, exit);
-7650      }
-7651      else {
-7652          /* the machine stack extending higher */
-7653          if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
-7654      }
-
-          /* omission …… back the global variables */
-
-7677      tmp = th;
-7678      ex = exit;
-7679      FLUSH_REGISTER_WINDOWS;
-7680      MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
-7681
-7682      tval = rb_lastline_get();
-7683      rb_lastline_set(tmp->last_line);
-7684      tmp->last_line = tval;
-7685      tval = rb_backref_get();
-7686      rb_backref_set(tmp->last_match);
-7687      tmp->last_match = tval;
-7688
-7689      longjmp(tmp->context, ex);
-7690  }
-
-(eval.c)
-
-

The th parameter is the target to give the execution back. -MEMCPY() and longjmp() in the last half are at the heart. -The closer MEMCPY() to the last, the better it is, because -after this manipulation, the stack is in a destroyed state until longjmp().

-

Nevertheless, there are rb_lastline_set() and rb_backref_set(). -They are the restorations of $_ and $~. -Since these two variables are not only local variables but also thread local variables, -even if it is only a single local variable slot, -there are its as many slots as the number of threads. -This must be here because the place actually being written back is the stack. -Because they are local variables, their slot spaces are allocated with alloca().

-

That’s it for the basics. But if we merely write the stack back, -in the case when the stack of the current thread is shorter than the stack of -the thread to switch to, -the stack frame of the very currently executing function -(it is rb_thread_restore_context) would be overwritten. -It means the content of the th parameter will be destroyed. -Therefore, in order to prevent this from occurring, -we first need to extend the stack. -This is done by the stack_extend() in the first half.

-

stack_extend()

- -
-7624  static void
-7625  stack_extend(th, exit)
-7626      rb_thread_t th;
-7627      int exit;
-7628  {
-7629      VALUE space[1024];
-7630
-7631      memset(space, 0, 1);        /* prevent array from optimization */
-7632      rb_thread_restore_context(th, exit);
-7633  }
-
-(eval.c)
-
-

By allocating a local variable (which will be put at the machine stack space) -whose size is 1K, forcibly extend the stack. -However, though this is a matter of course, doing return from stack_extend() -means the extended stack will shrink immediately. -This is why rb_thread_restore_context() is called again immediately in the -place.

-

By the way, the completion of the task of rb_thread_restore_context() -means it has reached the call of longjmp(), -and once it is called it will never return back. -Obviously, the call of stack_extend() will also never return. -Therefore, rb_thread_restore_context() does not have to think about -such as possible procedures after returning from stack_extend().

-

Issues

-

This is the implementation of the ruby thread switch. -We can’t think it is lightweight. -Plenty of malloc() realloc() and plenty of memcpy() and doing setjmp() longjmp() -then furthermore calling functions to extend the stack. -There’s no problem to express “It is deadly heavy”. -But instead, there’s not any system call depending on a particular OS, -and there are just a few assembly only for the register windows of Sparc. -Indeed, this seems to be highly portable.

-

There’s another problem. It is, because the stacks of all threads are allocated to the -same address, there’s the possibility that the code using the pointer to the -stack space is not runnable. Actually, Tcl/Tk excellently matches this -situation, in order to bypass, Ruby’s Tcl/Tk interface reluctantly choses -to access only from the main thread.

-

Of course, this does not go along with native threads. -It would be necessary to restrict ruby threads to run only on a particular -native thread in order to let them work properly. -In UNIX, there are still a few libraries that use a lot of threads. -But in Win32, because threads are running every now and then, -we need to be careful about it.

- - - -
- - diff --git a/htmls/variable.html b/htmls/variable.html deleted file mode 100644 index 99e66fa..0000000 --- a/htmls/variable.html +++ /dev/null @@ -1,589 +0,0 @@ - - - - - Variables and constants | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Vincent ISAMBART

-

Chapter 6: Variables and constants

-

Outline of this chapter

-

Ruby variables

-

In Ruby there are quite a lot of different types of variables and -constants. Let’s line them up, starting from the largest scope.

-
    -
  • Global variables
  • -
  • Constants
  • -
  • Class variables
  • -
  • Instance variables
  • -
  • Local variables
  • -
-

Instance variables were already explained in chapter 2 “Objects”. In -this chapter we’ll talk about:

-
    -
  • Global variables
  • -
  • Class variables
  • -
  • Constants
  • -
-

We will talk about local variables in the third part of the book.

-

API for variables

-

The object of this chapter’s analysis is variable.c. Let’s first -look at the available API.

-
-VALUE rb_iv_get(VALUE obj, char *name)
-VALUE rb_ivar_get(VALUE obj, ID name)
-VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
-VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
-
-

We’ve already spoken about those functions, but must mention them again -as they are in variable.c. They are of course used for accessing instance -variables.

-
-VALUE rb_cv_get(VALUE klass, char *name)
-VALUE rb_cvar_get(VALUE klass, ID name)
-VALUE rb_cv_set(VALUE klass, char *name, VALUE val)
-VALUE rb_cvar_set(VALUE klass, ID name, VALUE val)
-
-

These functions are the API for accessing class variables. Class -variables belong directly to classes so the functions take a class as -parameter. There are in two groups, depending if their name starts -with rb_Xv or rb_Xvar. The difference lies in the type of the -variable “name”. The ones with a shorter name are generally easier to -use because they take a char*. The ones with a longer name are more -for internal use as they take a ID.

-
-VALUE rb_const_get(VALUE klass, ID name)
-VALUE rb_const_get_at(VALUE klass, ID name)
-VALUE rb_const_set(VALUE klass, ID name, VALUE val)
-
-

These functions are for accessing constants. Constants also belong to -classes so they take classes as parameter. rb_const_get() follows -the superclass chain, whereas rb_const_get_at() does not (it just -looks in klass).

-
-struct global_entry *rb_global_entry(ID name)
-VALUE rb_gv_get(char *name)
-VALUE rb_gvar_get(struct global_entry *ent)
-VALUE rb_gv_set(char *name, VALUE val)
-VALUE rb_gvar_set(struct global_entry *ent, VALUE val)
-
-

These last functions are for accessing global variables. They are a -little different from the others due to the use of `struct -global_entry`. We’ll explain this while describing the implementation.

-

Important points

-

The most important topic of this chapter is “Where and how are variables -stored?”, in other words: data structures.

-

The second most important matter is how we search for the values. The scopes -of Ruby variables and constants are quite complicated because -variables and constants are sometimes inherited, sometimes looked for -outside of the local scope… To have a better understanding, you -should first try to guess from the behavior how it could be -implemented, then compare that with what is really done.

-

Class variables

-

Class variables are variables that belong to classes. In Java or C++ -they are called static variables. They can be accessed from both the -class or its instances. But “from an instance” or “from the class” is -information only available in the evaluator, and we do not have one -for the moment. So from the C level it’s like having no access -range. We’ll just focus on the way these variables are stored.

-

Reading

-

The functions to get a class variable are rb_cvar_get() and -rb_cv_get(). The function with the longer name takes ID as -parameter and the one with the shorter one takes char*. Because the -one taking an ID seems closer to the internals, we’ll look at it.

-

rb_cvar_get() -

-1508  VALUE
-1509  rb_cvar_get(klass, id)
-1510      VALUE klass;
-1511      ID id;
-1512  {
-1513      VALUE value;
-1514      VALUE tmp;
-1515
-1516      tmp = klass;
-1517      while (tmp) {
-1518          if (RCLASS→iv_tbl) {
-1519              if (st_lookup(RCLASS→iv_tbl,id,&value)) {
-1520                  if (RTEST) {
-1521                      cvar_override_check(id, tmp);
-1522                  }
-1523                  return value;
-1524              }
-1525          }
-1526          tmp = RCLASS→super;
-1527      }
-1528
-1529      rb_name_error(id,“uninitialized class variable %s in %s”,
-1530                    rb_id2name(id), rb_class2name(klass));
-1531      return Qnil;                /* not reached */
-1532  }

-

(variable.c) -

-

This function reads a class variable in klass.

-

Error management functions like rb_raise() can be simply ignored -like I said before. The rb_name_error() that appears this time is a -function for raising an exception, so it can be ignored for the same -reasons. In ruby, you can assume that all functions ending with -_error raise an exception.

-

After removing all this, we can see that while following the klass‘s -superclass chain we only search in iv_tbl. At this point you should -say "What? iv_tbl is the instance variables table, isn’t it?" As a -matter of fact, class variables are stored in the instance variable -table.

-

We can do this because when creating IDs, the whole name of the -variables is taken into account, including the prefix: rb_intern() -will return different IDs for “@var” and “@@var”. At the Ruby -level, the variable type is determined only by the prefix so there’s -no way to access a class variable called @var from Ruby.

-

Constants

-

It’s a little abrupt but I’d like you to remember the members of -struct RClass. If we exclude the basic member, struct RClass -contains:

-
    -
  • VALUE super
  • -
  • struct st_table *iv_tbl
  • -
  • struct st_table *m_tbl
  • -
-

Then, considering that:

-
    -
  1. constants belong to a class
  2. -
  3. we can’t see any table dedicated to constants in struct RClass
  4. -
  5. class variables and instance variables are both in iv_tbl
  6. -
-

Could it mean that the constants are also…

-

Assignment

-

rb_const_set() is a function to set the value of constants: it sets -the constant id in the class klass to the value val.

-

rb_const_set() -

-1377  void
-1378  rb_const_set(klass, id, val)
-1379      VALUE klass;
-1380      ID id;
-1381      VALUE val;
-1382  {
-1383      mod_av_set(klass, id, val, Qtrue);
-1384  }

-

(variable.c) -

-

mod_av_set() does all the hard work:

-

mod_av_set() -

-1352  static void
-1353  mod_av_set(klass, id, val, isconst)
-1354      VALUE klass;
-1355      ID id;
-1356      VALUE val;
-1357      int isconst;
-1358  {
-1359      char *dest = isconst ? “constant” : “class variable”;
-1360
-1361      if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
-1362          rb_raise(rb_eSecurityError, “Insecure: can’t set %s”, dest);
-1363      if (OBJ_FROZEN(klass)) rb_error_frozen(“class/module”);
-1364      if (!RCLASS→iv_tbl) {
-1365          RCLASS→iv_tbl = st_init_numtable();
-1366      }
-1367      else if (isconst) {
-1368          if (st_lookup(RCLASS→iv_tbl, id, 0) ||
-1369              (klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) {
-1370              rb_warn(“already initialized %s %s”, dest, rb_id2name(id));
-1371          }
-1372      }
-1373
-1374      st_insert(RCLASS→iv_tbl, id, val);
-1375  }

-

(variable.c) -

-

You can this time again ignore the warning checks (rb_raise(), -rb_error_frozen() and rb_warn()). Here’s what’s left:

-

mod_av_set() (only the important part) -

-    if (!RCLASS→iv_tbl) {
-        RCLASS→iv_tbl = st_init_numtable();
-    }
-    st_insert(RCLASS→iv_tbl, id, val);
-

-

We’re now sure constants also reside in the instance table. It means -in the iv_tbl of struct RClass, the following are mixed together:

-
    -
  1. the class’s own instance variables
  2. -
  3. class variables
  4. -
  5. constants
  6. -
-

Reading

-

We now know how the constants are stored. We’ll now check how they -really work.

-

rb_const_get()

-

We’ll now look at rconst_get(), the function to read a -constant. This functions returns the constant referred to by id from the class -klass.

-

rb_const_get() -

-1156  VALUE
-1157  rb_const_get(klass, id)
-1158      VALUE klass;
-1159      ID id;
-1160  {
-1161      VALUE value, tmp;
-1162      int mod_retry = 0;
-1163
-1164      tmp = klass;
-1165    retry:
-1166      while (tmp) {
-1167          if (RCLASS→iv_tbl &&
-                  st_lookup(RCLASS→iv_tbl,id,&value)) {
-1168              return value;
-1169          }
-1170          if (tmp == rb_cObject && top_const_get(id, &value))
-                  return value;
-1171          tmp = RCLASS→super;
-1172      }
-1173      if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
-1174          mod_retry = 1;
-1175          tmp = rb_cObject;
-1176          goto retry;
-1177      }
-1178
-1179      /* Uninitialized constant /
-1180      if (klass && klass != rb_cObject) {
-1181          rb_name_error(id, “uninitialized constant %s at %s”,
-1182                        rb_id2name(id),
-1183                        RSTRING)→ptr);
-1184      }
-1185      else { / global_uninitialized /
-1186          rb_name_error(id, “uninitialized constant %s”,rb_id2name(id));
-1187      }
-1188      return Qnil;                / not reached */
-1189  }

-

(variable.c) -

-

There’s a lot of code in the way. First, we should at least remove the -rb_name_error() in the second half. In the middle, what’s around -mod_entry seems to be a special handling for modules. Let’s also -remove that for the time being. The function gets reduced to this:

-

rb_const_get (simplified) -

-VALUE
-rb_const_get(klass, id)
-    VALUE klass;
-    ID id;
-{
-    VALUE value, tmp;

-tmp = klass; -while (tmp) { -if (RCLASS→iv_tbl && st_lookup(RCLASS→iv_tbl,id,&value)) { -return value; -} -if (tmp == rb_cObject && top_const_get(id, &value)) return value; -tmp = RCLASS→super; -} -

} -

-

Now it should be pretty easy to understand. The function searches for the -constant in iv_tbl while climbing klass’s superclass chain. That -means:

-
-class A
-  Const = "ok"
-end
-class B < A
-  p(Const)    # can be accessed
-end
-
-

The only problem remaining is top_const_get(). This function is only -called for rb_cObject so top must mean “top-level”. If you don’t -remember, at the top-level, the class is Object. This means the same -as “in the class statement defining C, the class becomes C”, -meaning that “the top-level’s class is Object”.

-
-# the class of the top-level is Object
-class A
-  # the class is A
-  class B
-    # the class is B
-  end
-end
-
-

So top_const_get() probably does something specific to the top -level.

-

top_const_get()

-

Let’s look at this top_const_get function. It looks up the id -constant writes the value in klassp and returns.

-

top_const_get() -

-1102  static int
-1103  top_const_get(id, klassp)
-1104      ID id;
-1105      VALUE klassp;
-1106  {
-1107      / pre-defined class /
-1108      if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue;
-1109
-1110      / autoload */
-1111      if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
-1112          rb_autoload_load(id);
-1113          *klassp = rb_const_get(rb_cObject, id);
-1114          return Qtrue;
-1115      }
-1116      return Qfalse;
-1117  }

-

(variable.c) -

-

rb_class_tbl was already mentioned in chapter 4 “Classes and -modules”. It’s the table for storing the classes defined at the -top-level. Built-in classes like String or Array have for example -an entry in it. That’s why we should not forget to search in this -table when looking for top-level constants.

-

The next block is related to autoloading. This allows us to automatically -load a library when accessing a top-level constant for the first -time. This can be used like this:

-
-autoload(:VeryBigClass, "verybigclass")   # VeryBigClass is defined in it
-
-

After this, when VeryBigClass is accessed for the first time, the -verybigclass library is loaded (with require). As long as -VeryBigClass is defined in the library, execution can continue smoothly. It’s -an efficient approach, when a library is too big and a lot of time is spent on loading.

-

This autoload is processed by rb_autoload_xxxx(). We won’t discuss -autoload further in this chapter because there will probably be a big -change in how it works soon (The way autoload works did change in -1.8: autoloaded constants do not need to be defined at top-level -anymore).

-

Other classes?

-

But where did the code for looking up constants in other classes end up? -After all, constants are first looked up in the outside classes, then -in the superclasses.

-

In fact, we do not yet have enough knowledge to look at that. The -outside classes change depending on the location in the program. In -other words it depends of the program context. So we need first to -understand how the internal state of the -evaluator is handled. Specifically, this search in other classes is done in the -ev_const_get() function of eval.c. We’ll look at it and finish -with the constants in the third part of the book.

-

Global variables

-

General remarks

-

Global variables can be accessed from anywhere. Or put the other way -around, there is no need to restrict access to them. Because they are -not attached to any context, the table only has to be at one place, and -there’s no need to do any check. Therefore implementation is very -simple.

-

But there is still quite a lot of code. The reason for this is that global -variables are quite different from normal variables. Functions like -the following are only available for global variables:

-
    -
  • you can “hook” access of global variables
  • -
  • you can alias them with alias
  • -
-

Let’s explain this simply.

-

Aliases of variables

-
-alias $newname $oldname
-
-

After this, you can use $newname instead of $oldname. alias for -variables is mainly a counter-measure for “symbol variables”. “symbol -variables” are variables inherited from Perl like $= or $0. $= -decides if during string comparison upper and lower case letters -should be differentiated. $0 shows the name of the main Ruby -program. There are some other symbol variables but anyway as their -name is only one character long, they are difficult to remember for -people who don’t know Perl. So, aliases were created to make them a little -easier to understand.

-

That said, currently symbol variables are not recommended, and are -moved one by one in singleton methods of suitable modules. The current -school of thought is that $= and others will be abolished in 2.0.

-

Hooks

-

You can “hook” read and write of global variables.

-

Hooks can be also be set at the Ruby level, but I was thinking: why not -instead look at C level special variables for system use like -$KCODE? $KCODE is the variable containing the encoding the -interpreter currently uses to handle strings. It can only be set to -special values like "EUC" or "UTF8". But this is too bothersome so -it can also be set it to "e" or "u".

-
-p($KCODE)      # "NONE" (default)
-$KCODE = "e"
-p($KCODE)      # "EUC"
-$KCODE = "u"
-p($KCODE)      # "UTF8"
-
-

Knowing that you can hook assignment of global variables, you should -understand easily how this can be done. By the way, $KCODE’s K comes -from “kanji” (the name of Chinese characters in Japanese).

-

You might say that even with alias or hooks, -global variables just aren’t used much, so it’s functionality that doesn’t -really mater. It’s adequate not to talk much about unused -functions, and I need some pages for the analysis of the parser and -evaluator. That’s why I’ll proceed with the explanation below throwing -away what’s not really important.

-

Data structure

-

When we were looking at how variables work, I said that the way they -are stored is important. That’s why I’d like you to firmly grasp the -structure used by global variables.

-

▼ Data structure for global variables -

-  21  static st_table *rb_global_tbl;

-334 struct global_entry { -335 struct global_variable *var; -336 ID id; -337 }; -324 struct global_variable { -325 int counter; /* reference counter */ -326 void data; / value of the variable */ -327 VALUE (getter)(); / function to get the variable */ -328 void (setter)(); / function to set the variable */ -329 void (marker)(); / function to mark the variable */ -330 int block_trace; -331 struct trace_var *trace; -332 }; -

(variable.c) -

-

rb_global_tbl is the main table. All global variables are stored in -this table. The keys of this table are of course variable names -(ID). A value is expressed by a struct global_entry and a `struct -global_variable` (figure 1).

-

-

(gvar)
-Figure 1: Global variables table at execution time

-

-

The structure representing the variables is split in two to be able to -create aliases. When an alias is established, two global_entrys -point to the same struct global_variable.

-

It’s at this time that the reference counter (the counter member of -struct global_variable) is necessary. I explained the general idea of -a reference counter in the previous section “Garbage -collection”. Reviewing it briefly, when a new reference to the -structure is made, the counter in incremented by 1. When the reference -is not used anymore, the counter is decreased by 1. When the counter -reaches 0, the structure is no longer useful so free() can be -called.

-

When hooks are set at the Ruby level, a list of struct trace_vars is -stored in the trace member of struct global_variable, but I won’t -talk about it, and omit struct trace_var.

-

Reading

-

You can have a general understanding of global variables just by looking at how -they are read. The functions for reading them are rb_gv_get() and -rb_gvar_get().

-

rb_gv_get() rb_gvar_get() -

- 716  VALUE
- 717  rb_gv_get(name)
- 718      const char *name;
- 719  {
- 720      struct global_entry *entry;
- 721
- 722      entry = rb_global_entry(global_id(name));
- 723      return rb_gvar_get(entry);
- 724  }

-649 VALUE -650 rb_gvar_get(entry) -651 struct global_entry *entry; -652 { -653 struct global_variable *var = entry→var; -654 return (*var→getter)(entry→id, var→data, var); -655 } -

(variable.c) -

-

A substantial part of the content seems to turn around the -rb_global_entry() function, but that does not prevent us -understanding what’s going on. global_id is a function that converts a -char* to ID and checks if it’s the ID of a global -variable. (*var->getter)(...) is of course a function call using the -function pointer var->getter. If p is a function pointer, -(*p)(arg) calls the function.

-

But the main part is still rb_global_entry().

-

rb_global_entry() -

- 351  struct global_entry*
- 352  rb_global_entry(id)
- 353      ID id;
- 354  {
- 355      struct global_entry *entry;
- 356
- 357      if (!st_lookup(rb_global_tbl, id, &entry)) {
- 358          struct global_variable *var;
- 359          entry = ALLOC;
- 360          st_add_direct(rb_global_tbl, id, entry);
- 361          var = ALLOC;
- 362          entry→id = id;
- 363          entry→var = var;
- 364          var→counter = 1;
- 365          var→data = 0;
- 366          var→getter = undef_getter;
- 367          var→setter = undef_setter;
- 368          var→marker = undef_marker;
- 369
- 370          var→block_trace = 0;
- 371          var→trace = 0;
- 372      }
- 373      return entry;
- 374  }

-

(variable.c) -

-

The main treatment is only done by the st_lookup() at the beginning. -What’s done afterwards is just creating (and storing) a new entry. As, when -accessing a non existing global variable, an entry is automatically -created, rb_global_entry() will never return NULL.

-

This was mainly done for speed. When the parser finds a global -variable, it gets the corresponding struct global_entry. When -reading the value of the variable, the parser just has to get the -value from the entry (using rb_gv_get()), and has no need to do any -check.

-

Let’s now continue a little with the code that follows. var->getter -and others are set to undef_xxxx. undef means that the global -setter/getter/marker for the variable are currently undefined.

-

undef_getter() just shows a warning and returns nil, as even -undefined global variables can be read. undef_setter() is quite -interesting so let’s look at it.

-

undef_setter() -

- 385  static void
- 386  undef_setter(val, id, data, var)
- 387      VALUE val;
- 388      ID id;
- 389      void data;
- 390      struct global_variable *var;
- 391  {
- 392      var→getter = val_getter;
- 393      var→setter = val_setter;
- 394      var→marker = val_marker;
- 395
- 396      var→data = (void)val;
- 397  }

-

(variable.c) -

-

val_getter() takes the value from entry->data and returns -it. val_getter() just puts a value in entry->data. Setting -handlers this way allows us not to need special handling for undefined -variables (figure 2). Skillfully done, isn’t it?

-

-

(gaccess)
-Figure 2: Setting and consultation of global variables

-

- - - -
- - diff --git a/htmls/yacc.html b/htmls/yacc.html deleted file mode 100644 index 7feb6e9..0000000 --- a/htmls/yacc.html +++ /dev/null @@ -1,1013 +0,0 @@ - - - - - YACC crash course | Ruby Hacking Guide - - - - -
- -
-

Ruby Hacking Guide

-
- - - -

Translated by Vincent ISAMBART & ocha-

-

Chapter 9: yacc crash course

-

Outline

-

Parser and scanner

-

How to write parsers for programming languages has been an active area -of research for a long time, and there is a quite firm established -tactic for doing it. If we limit ourselves to a grammar not too -strange (or ambiguous), we can solve this problem by following this -method.

-

The first part consists in splitting a string in a list of words (or -tokens). This is called a scanner or lexer. The term “lexical -analyzer” is also used, but is too complicated to say so we’ll use the -name scanner.

-

When speaking about scanners, the common sense first says “there are -generally spaces at the end of a word”. And in practice, it was made -like this in most programming languages, because it’s the easiest way.

-

There can also be exceptions. For example, in the old Fortran, white -spaces did not have any meaning. This means a white space did not end -a word, and you could put spaces in the name of a variable. However -that made the parsing very complicated so the compiler vendors, one by -one, started ignoring that standard. Finally Fortran 90 followed this -trend and made the fact that white spaces have an impact the standard.

-

By the way, it seems the reason white spaces had not meaning in -Fortran 77 was that when writing programs on punch cards it was easy -to make errors in the number of spaces.

-

List of symbols

-

I said that the scanner spits out a list of words (tokens), but, to be -exact, what the scanner creates is a list of “symbols”, not words.

-

What are symbols? Let’s take numbers as an example. In a programming -language, 1, 2, 3, 99 are all “numbers”. They can all be handled the -same way by the grammar. Where we can write 1, we can also write 2 or -3. That’s why the parser does not need to handle them in different -ways. For numbers, “number” is enough.

-

“number”, “identifier” and others can be grouped together as -“symbol”. But be careful not to mix this with the Symbol class.

-

The scanner first splits the string into words and determines what -these symbols are. For example, NUMBER or DIGIT for numbers, -IDENTIFIER for names like “name”, IF for the reserved word -if. These symbols are then given to the next phase.

-

Parser generator

-

The list of words and symbols spitted out by the scanner are going to -be used to form a tree. This tree is called a syntax tree.

-

The name “parser” is also sometimes used to include both the scanner -and the creation of the syntax tree. However, we will use the narrow -sense of “parser”, the creation of the syntax tree. How does this -parser make a tree from the list of symbols? In other words, on what -should we focus to find the tree corresponding to a piece of code?

-

The first way is to focus on the meaning of the words. For example, -let’s suppose we find the word var. If the definition of the local -variable var has been found before this, we’ll understand it’s the -reading of a local variable.

-

An other ways is to only focus on what we see. For example, if after -an identified comes a ‘=’, we’ll understand it’s an assignment. If -the reserved word if appears, we’ll understand it’s the start of an -if statement.

-

The later method, focusing only on what we see, is the current -trend. In other words the language must be designed to be analyzed -just by looking at the list of symbols. The choice was because -this way is simpler, can be more easily generalized and can therefore -be automatized using tools. These tools are called parser generators.

-

The most used parser generator under UNIX is yacc. Like many others, -ruby‘s parser is written using yacc. The input file for this tool -is parser.y. That’s why to be able to read ruby’s parser, we need -to understand yacc to some extent. (Note: Starting from 1.9, ruby -requires bison instead of yacc. However, bison is mainly yacc -with additional functionality, so this does not diminish the interest -of this chapter.)

-

This chapter will be a simple presentation of yacc to be able to -understand parse.y, and therefore we will limit ourselves to what’s -needed to read parse.y. If you want to know more about parsers and -parser generators, I recommend you a book I wrote called “Rubyを256倍使 -うための本 無道編” (The book to use 256 times more of Ruby - -Unreasonable book). I do not recommend it because I wrote it, but -because in this field it’s the easiest book to understand. And besides -it’s cheap so stakes will be low.

-

Nevertheless, if you would like a book from someone else (or can’t -read Japanese), I recommend O’Reilly’s “lex & yacc programming” by -John R. Levine, Tony Mason and Doug Brown. And if your are still not -satisfied, you can also read “Compilers” (also known as the “dragon -book” because of the dragon on its cover) by Alfred V. Aho, Ravi Sethi -and Jeffrey D. Ullman.

-

Grammar

-

Grammar file

-

The input file for yacc is called “grammar file”, as it’s the file -where the grammar is written. The convention is to name this grammar -file *.y. It will be given to yacc who will generate C source -code. This file can then be compiled as usual (figure 1 shows the full -process).

-

-

(build)
-Figure 1: File dependencies

-

-

The output file name is always y.tab.c and can’t be changed. The -recent versions of yacc usually allow to change it on the command -line, but for compatibility it was safer to keep y.tab.c. By the -way, it seems the tab of y.tab.c comes from table, as lots of -huge tables are defined in it. -It’s good to have a look at the file once.

-

The grammar file’s content has the following form:

-

▼ General form of the grammar file -

-%{
-Header
-%}
-%union ….
-%token ….
-%type ….

-

% -Rules part -% -User defined part -

-

yacc‘s input file is first divided in 3 parts by %%. The first -part if called the definition part, has a lot of definitions and -setups. Between %{ and %} we can write anything we want in C, like -for example necessary macros. After that, the instructions starting -with % are special yacc instructions. Every time we use one, we’ll -explain it.

-

The middle part of the file is called the rules part, and is the most -essential part for yacc. It’s where is written the grammar we want -to parse. We’ll explain it in details in the next section.

-

The last part of the file, the user defined part, can be used freely -by the user. yacc just copies this part verbatim in the output -file. It’s used for example to put auxiliary routines needed by the -parser.

-

What does yacc do.

-

What yacc takes care of is mainly this rules part in the -middle. yacc takes the grammar written there and use it to make a -function called yyparse(). It’s the parser, in the narrow sense of -the word.

-

In the narrow sense, so it means a scanner is needed. However, yacc -won’t take care of it, it must be done by the user. -The scanner is the function named yylex().

-

Even if yacc creates yyparse(), it only takes care of its core -part. The “actions” we’ll mention later is out of its scope. You can -think the part done by yacc is too small, but that’s not the -case. That’s because this “core part” is overly important that yacc -survived to this day even though we keep complaining about it.

-

But what on earth is this core part? That’s what we’re going to see.

-

BNF

-

When we want to write a parser in C, its code will be “cut the string -this way, make this an if statement…” When using parser -generators, we say the opposite, that is “I would like to parse this -grammar.” Doing this creates for us a parser to handle the -grammar. This means telling the specification gives us the -implementation. That’s the convenient point of yacc.

-

But how can we tell the specification? With yacc, the method of -description used is the BNF (Backus-Naur Form). Let’s look at a very -simple example.

-
-if_stmt: IF expr THEN stmt END
-
-

Let’s see separately what’s at the left and at the right of the -“:”. The part on the left side, if_stmt, is equal to the right -part… is what I mean here. In other words, I’m saying that:

-

if_stmt and IF expr THEN stmt END are equivalent.

-

Here, if_stmt, IF, expr… are all “symbols”. expr is the -abbreviation of expression, stmt of statement. It must be for -sure the declaration of the if statement.

-

One definition is called a rule. The part at the left of “:” is -called the left side and the right part called the right side. This is -quite easy to remember.

-

But something is missing. We do not want an if statement without -being able to use else. And even if we could write else, having -to always write the else even when it’s useless would be -cumbersome. In this case we could do the following:

-
-if_stmt: IF expr THEN stmt END
-       | IF expr THEN stmt ELSE stmt END
-
-

|” means “or”.

-

if_stmt is either “IF expr THEN stmt END” or “`IF expr THEN stmt -ELSE stmt END`”.

-

That’s it.

-

Here I would like you to pay attention to the split done with -|. With just this, one more rule is added. In fact, punctuating with -| is just a shorter way to repeat the left side. The previous -example has exactly the same meaning as the following:

-
-if_stmt: IF expr THEN stmt END
-if_stmt: IF expr THEN stmt ELSE stmt END
-
-

This means two rules are defined in the example.

-

This is not enough to complete the definition of the if -statement. That’s because the symbols expr and stmt are not sent -by the scanner, their rules must be defined. To be closer to Ruby, let’s -boldly add some rules.

-
-stmt   : if_stmt
-       | IDENTIFIER '=' expr   /* assignment */
-       | expr
-
-if_stmt: IF expr THEN stmt END
-       | IF expr THEN stmt ELSE stmt END
-
-expr   : IDENTIFIER       /* reading a variable */
-       | NUMBER           /* integer constant */
-       | funcall          /* FUNction CALL */
-
-funcall: IDENTIFIER '(' args ')'
-
-args   : expr             /* only one parameter */
-
-

I used two new elements. First, comments of the same form as in C, and -character expressed using '='. This '=' is also of course a -symbol. Symbols like “=” are different from numbers as there is only -one variety for them. That’s why for symbols where can also use '='. -It would be great to be able to use for strings for, for example, -reserved words, but due to limitations of the C language this cannot -be done.

-

We add rules like this, to the point we complete writing all the -grammar. With yacc, the left side of the first written rule is “the -whole grammar we want to express”. So in this example, stmt -expresses the whole program.

-

It was a little too abstract. Let’s explain this a little more -concretely. By “stmt expresses the whole program”, I mean stmt and -the rows of symbols expressed as equivalent by the rules, are all -recognized as grammar. For example, stmt and stmt are -equivalent. Of course. Then expr is equivalent to stmt. That’s -expressed like this in the rule. Then, NUMBER and stmt are -equivalent. That’s because NUMBER is expr and expr is stmt.

-

We can also say that more complicated things are equivalent.

-
-              stmt
-               ↓
-             if_stmt
-               ↓
-      IF expr THEN stmt END
-          ↓        ↓
-IF IDENTIFIER THEN expr END
-                    ↓
-IF IDENTIFIER THEN NUMBER END
-
-

When it has expanded until here, -all elements become the symbols sent by the scanner. -It means such sequence of symbols is correct as a program. -Or putting it the other way around, if this sequence of symbols is sent -by the scanner, the parser can understand it in the opposite order of expanding.

-
-IF IDENTIFIER THEN NUMBER END
-                    ↓
-IF IDENTIFIER THEN expr END
-          ↓        ↓
-      IF expr THEN stmt END
-               ↓
-             if_stmt
-               ↓
-              stmt
-
-

And stmt is a symbol expressing the whole program. That’s why this -sequence of symbols is a correct program for the parser. When it’s the -case, the parsing routine yyparse() ends returning 0.

-

By the way, the technical term expressing that the parser succeeded is -that it “accepted” the input. The parser is like a government office: -if you do not fill the documents in the boxes exactly like he asked -you to, he’ll refuse them. The accepted sequences of symbols are the -ones for which the boxes where filled correctly. Parser and government -office are strangely similar for instance in the fact that they care -about details in specification and that they use complicated terms.

-

Terminal symbols and nonterminal symbols

-

Well, in the confusion of the moment I used without explaining it the -expression “symbols coming from the scanner”. So let’s explain this. I -use one word “symbol” but there are two types.

-

The first type of the symbols are the ones sent by the scanner. They -are for example, IF, THEN, END, '=', … They are called -terminal symbols. That’s because like before when we did the quick -expansion we find them aligned at the end. In this chapter terminal -symbols are always written in capital letters. However, symbols like -'=' between quotes are special. Symbols like this are all terminal -symbols, without exception.

-

The other type of symbols are the ones that never come from the -scanner, for example if_stmt, expr or stmt. They are called -nonterminal symbols. As they don’t come from the scanner, they only -exist in the parser. Nonterminal symbols also always appear at one -moment or the other as the left side of a rule. In this chapter, -nonterminal symbols are always written in lower case letters.

-

How to test

-

I’m now going to tell you the way to process the grammar file with -yacc.

-
-%token A B C D E
-%%
-list: A B C
-    | de
-
-de  : D E
-
-

First, put all terminal symbols used after %token. However, you do -not have to type the symbols with quotes (like '='). Then, put %% -to mark a change of section and write the grammar. That’s all.

-

Let’s now process this.

-
-% yacc first.y
-% ls
-first.y  y.tab.c
-%
-
-

Like most Unix tools, “silence means success”.

-

There’s also implementations of yacc that need semicolons at the end -of (groups of) rules. When it’s the case we need to do the following:

-
-%token A B C D E
-%%
-list: A B C
-    | de
-    ;
-
-de  : D E
-    ;
-
-

I hate these semicolons so in this book I’ll never use them.

-

Void rules

-

Let’s now look a little more at some of the established ways of -grammar description. I’ll first introduce void rules.

-
-void:
-
-

There’s nothing on the right side, this rule is “void”. For example, -the two following targets means exactly the same thing.

-
-target: A B C
-
-target: A void B void C
-void  :
-
-

What is the use of such a thing? It’s very useful. For example in the -following case.

-
-if_stmt : IF expr THEN stmts opt_else END
-
-opt_else:
-        | ELSE stmts
-
-

Using void rules, we can express cleverly the fact that “the else -section may be omitted”. Compared to the rules made previously using -two definitions, this way is shorter and we do not have to disperse -the burden.

-

Recursive definitions

-

The following example is still a little hard to understand.

-
-list: ITEM         /* rule 1 */
-    | list ITEM    /* rule 2 */
-
-

This expresses a list of one or more items, in other words any of the -following lists of symbols:

-
-ITEM
-ITEM ITEM
-ITEM ITEM ITEM
-ITEM ITEM ITEM ITEM
-      :
-
-

Do you understand why? First, according to rule 1 list can be read -ITEM. If you merge this with rule 2, list can be ITEM ITEM.

-
-list: list ITEM
-    = ITEM ITEM
-
-

We now understand that the list of symbols ITEM ITEM is similar to -list. By applying again rule 2 to list, we can say that 3 ITEM -are also similar to list. By quickly continuing this process, the -list can grow to any size. -This is something like mathematical induction.

-

I’ll now show you the next example. The following example expresses -the lists with 0 or more ITEM.

-
-list:
-    | list ITEM
-
-

First the first line means “list is equivalent to (void)”. By void I -mean the list with 0 ITEM. Then, by looking at rule 2 we can say -that “list ITEM” is equivalent to 1 ITEM. That’s because list is -equivalent to void.

-
-list: list   ITEM
-    = (void) ITEM
-    =        ITEM
-
-

By applying the same operations of replacement multiple times, we can -understand that list is the expression a list of 0 or more items.

-

With this knowledge, “lists of 2 or more ITEM” or “lists of 3 or -more ITEM” are easy, and we can even create “lists of an even number -of elements”.

-
-list:
-    | list ITEM ITEM
-
-

Construction of values

-

This abstract talk lasted long enough so in this section I’d really -like to go on with a more concrete talk.

-

Shift and reduce

-

Up until now, various ways to write grammars have been explained, -but what we want is being able to build a syntax tree. -However, I’m afraid to say, only telling it the rules is not enough to be able -to let it build a syntax tree, as might be expected. -Therefore, this time, I’ll tell you the way to build a syntax tree by adding -something to the rules.

-

We’ll first see what the parser does during the execution. We’ll use -the following simple grammar as an example.

-
-%token A B C
-%%
-program: A B C
-
-

In the parser there is a stack called the semantic stack. The parser -pushes on it all the symbols coming from the scanner. This move is -called “shifting the symbols”.

-
-[ A B ] ← C   shift
-
-

And when any of the right side of a rule is equal to the end of the -stack, it is “interpreted”. When this happens, -the sequence of the right-hand side is replaced by the symbol of the left-hand -side.

-
-[ A B C ]
-    ↓         reduction
-[ program ]
-
-

This move is called “reduce A B C” to program". This term -is a little presumptuous, but in short it is like, -when you have enough number of tiles of haku and hatsu and chu respectively, -it becomes “Big three dragons” in Japanese Mahjong, -… this might be irrelevant.

-

And since program expresses the whole program, -if there’s only a program on the stack, it probably means the whole program is -found out. Therefore, if the input is just finished here, it is accepted.

-

Let’s try with a little more complicated grammar.

-
-%token IF E S THEN END
-%%
-program : if
-
-if      : IF expr THEN stmts END
-
-expr    : E
-
-stmts   : S
-        | stmts S
-
-

The input from the scanner is this.

-
-IF  E  THEN  S  S  S  END
-
-

The transitions of the semantic stack in this case are shown below.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Stack Move
empty at first
IF shift IF
IF E shift E
IF expr reduce E to expr
IF expr THEN shift THEN
IF expr THEN S shift S
IF expr THEN stmts reduce S to stmts
IF expr THEN stmts S shift S
IF expr THEN stmts reduce stmts S to stmts
IF expr THEN stmts S shift S
IF expr THEN stmts reduce stmts S to stmts
IF expr THEN stmts END shift END
if reduce IF expr THEN stmts END to if
program reduce if to program
accept.
-

As the end of this section, there’s one thing to be cautious with. -a reduction does not always means decreasing the symbols. -If there’s a void rule, it’s possible that a symbol is generated out of “void”.

-

Action

-

Now, I’ll start to describe the important parts. -Whichever shifting or reducing, -doing several things only inside of the semantic stack is not meaningful. -Since our ultimate goal was building a syntax tree, -it cannot be sufficient without leading to it. -How does yacc do it for us? -The answer yacc made is that “we shall enable to hook the moment when the -parser performing a reduction.” The hooks are called actions of the parser. -An action can be written at the last of the rule as follows.

-
-program: A B C { /* Here is an action */ }
-
-

The part between { and } is the action. If you write like this, -at the moment reducing A B C to program this action will be executed. -Whatever you do as an action is free. -If it is a C code, almost all things can be written.

-

The value of a symbol

-

This is further more important but, -each symbol has “its value”. -Both terminal and nonterminal symbols do. -As for terminal symbols, since they come from the scanner, -their values are also given by the scanner. -For example, 1 or 9 or maybe 108 for a NUMBER symbol. -For an IDENTIFIER symbol, it might be "attr" or "name" or "sym". -Anything is fine. -Each symbol and its value are pushed together on the semantic stack. -The next figure shows the state just the moment S is shifted with its value.

-
-IF     expr    THEN    stmts   S
-value  value   value   value   value
-
-

According to the previous rule, stmts S can be reduced to stmts. -If an action is written at the rule, it would be executed, -but at that moment, the values of the symbols corresponding to the right-hand -side are passed to the action.

-
-IF    expr   THEN   stmts  S      /* Stack */
-v1    v2     v3     v4     v5
-                    ↓     ↓
-            stmts:  stmts  S      /* Rule */
-                    ↓     ↓
-                  { $1  +  $2; }  /* Action */
-
-

This way an action can take the value of each symbol corresponding to the -right-hand side of a rule through $1, $2, $3, … -yacc will rewrite the kinds of $1 and $2 to the notation to point to the stack. -However because it is written in C language it needs to handle, for instance, -types, but because it is tiresome, let’s assume their types are of int for the moment.

-

Next, instead it will push the symbol of the left-hand side, but because all -symbols have their values the left-hand side symbol must also have its value. -It is expressed as $$ in actions, the value of $$ when leaving an action -will be the value of the left-hand side symbol.

-
-IF    expr   THEN   stmts  S      /* the stack just before reducing */
-v1    v2     v3     v4     v5
-                    ↓     ↓
-            stmts:  stmts  S      /* the rule that the right-hand side matches the end */
-              ↑    ↓     ↓
-            { $$  = $1  +  $2; }  /* its action */
-
-
-IF    expr   THEN   stmts         /* the stack after reducing */
-v1    v2     v3     (v4+v5)
-
-

As the end of this section, this is just an extra. -The value of a symbol is sometimes called “semantic value”. -Therefore the stack to put them is the “semantic value stack”, -and it is called “semantic stack” for short.

-

yacc and types

-

It’s really cumbersome but without talking about types we cannot finish this -talk. What is the type of the value of a symbol? -To say the bottom line first, it will be the type named YYSTYPE. -This must be the abbreviation of either YY Stack TYPE or Semantic value TYPE. -And YYSTYPE is obviously the typedef of somewhat another type. -The type is the union defined with the instruction named %union in the definition part.

-

We have not written %union before but it did not cause an error. Why? -This is because yacc considerately process with the default value without asking. -The default value in C should naturally be int. -Therefore, YYSTYPE is int by default.

-

As for an example of a yacc book or a calculator, int can be used unchanged. -But in order to build a syntax tree, -we want to use structs and pointers and the other various things. -Therefore for instance, we use %union as follows.

-
-%union {
-    struct node {
-        int type;
-        struct node *left;
-        struct node *right;
-    } *node;
-    int num;
-    char *str;
-}
-
-

Because this is not for practical use, -the arbitrary names are used for types and members. -Notice that it is different from the ordinal C but there’s no semicolon at the -end of the %unicon block.

-

And, if this is written, it would look like the following in y.tab.c.

-
-typedef union {
-    struct node {
-        int type;
-        struct node *left;
-        struct node *right;
-    } *node;
-    int num;
-    char *str;
-} YYSTYPE;
-
-

And, as for the semantic stack,

-
-YYSTYPE yyvs[256];       /* the substance of the stack(yyvs = YY Value Stack) */
-YYSTYPE *yyvsp = yyvs;   /* the pointer to the end of the stack */
-
-

we can expect something like this. -Therefore, the values of the symbols appear in actions would be

-
-/* the action before processed by yacc */
-target: A B C { func($1, $2, $3); }
-
-/* after converted, its appearance in y.tab.c */
-{ func(yyvsp[-2], yyvsp[-1], yyvsp[0]); ;
-
-

naturally like this.

-

In this case, because the default value int is used, -it can be accessed just by referring to the stack. -If YYSTYPE is a union, it is necessary to also specify one of its members. -There are two ways to do that, one way is associating with each symbol, -another way is specifying every time.

-

Generally, the way of associating with each type is used. -By using %token for terminal symbols and -using %type for nonterminal symbols, -it is written as follows.

-
-%token<num> A B C    /* All of the values of A B C is of type int */
-%type<str> target    /* All of the values of target is of type char* */
-
-

On the other hand, if you’d like to specify everytime, -you can write a member name into next to $ as follows.

-
-%union { char *str; }
-%%
-target: { $<str>$ = "In short, this is like typecasting"; }
-
-

You’d better avoid using this method if possible.
-Defining a member for each symbol is basic.

-

Coupling the parser and the scanner together

-

After all, I’ve finished to talk all about this and that of the values inside the parser. -For the rest, I’ll talking about the connecting protocol with the scanner, -then the heart of this story will be all finished.

-

First, we’d like to make sure that I mentioned that the scanner was the yylex() function. -each (terminal) symbol itself is returned (as int) as a return value of the function. -Since the constants with the same names of symbols are defined (#define) by -yacc, we can write NUMBER for a NUMBER. -And its value is passed by putting it into a global variable named yylval. -This yylval is also of type YYSTYPE, -and the exactly same things as the parser can be said. -In other words, if it is defined in %union it would become a union. -But this time the member is not automatically selected, -its member name has to be manually written. -The very simple examples would look like the following.

-
-static int
-yylex()
-{
-    yylval.str = next_token();
-    return STRING;
-}
-
-

Figure 2 summarizes the relationships described by now. -I’d like you to check one by one. -yylval, $$, $1, $2 … -all of these variables that become the interfaces are of type YYSTYPE.

-
-

(yaccvars)
-Figure 2: Relationships among yacc related variables & functions

-
-

Embedded Action

-

An action is written at the last of a rule, is how it was explained. -However, actually it can be written in the middle of a rule.

-
-target: A B { puts("embedded action"); } C D
-
-

This is called “embedded action”.
-An embedded action is merely a syntactic sugar of the following definition:

-
-target: A B dummy C D
-
-dummy :     /* void rule */
-        {
-            puts("embedded action");
-        }
-
-

From this example, you might be able to tell everything including -when it is executed. -The value of a symbol can also be taken. -In other words, in this example, -the value of the embedded action will come out as $3.

-

Practical Topics

-

Conflicts

-

I’m not afraid of yacc anymore.

-

If you thought so, it is too naive. -Why everyone is afraid so much about yacc, -the reason is going to be revealed.

-

Up until now, I wrote not so carefully “when the right-hand side of the rule -matches the end of the stack”, -but what happens if there’s a rule like this:

-
-target  : A B C
-        | A B C
-
-

When the sequence of symbols A B C actually comes out, -it would be hard to determine which is the rule to match. -Such thing cannot be interpreted even by humans. -Therefore yacc also cannot understand this. -When yacc find out an odd grammar like this, -it would complain that a reduce/reduce conflict occurs. -It means multiple rules are possible to reduce at the same time.

-
-% yacc rrconf.y
-conflicts:  1 reduce/reduce
-
-

But usually, I think you won’t do such things except as an accident.
-But how about the next example? -The described symbol sequence is completely the same.

-
-target  : abc
-        | A bc
-
-abc     : A B C
-
-bc      :   B C
-
-

This is relatively possible. Especially when each part is complicatedly moved -while developing rules, it is often the case that this kind of rules are made -without noticing.

-

There’s also a similar pattern, as follows:

-
-target  : abc
-        | ab C
-
-abc     : A B C
-
-ab      : A B
-
-

When the symbol sequence A B C comes out, -it’s hard to determine whether -it should choose one abc or the combination of ab and C. -In this case, yacc will complain that a shift/reduce conflict occurs. -This means there’re both a shift-able rule and a reduce-able rule -at the same time.

-
-% yacc srconf.y
-conflicts:  1 shift/reduce
-
-

The famous example of shift/reduce conflicts is “the hanging else problem”. -For example, the if statement of C language causes this problem. -I’ll describe it by simplifying the case:

-
-stmt     : expr ';'
-         | if
-
-expr     : IDENTIFIER
-
-if       : IF '(' expr ')' stmt
-         | IF '(' expr ')' stmt  ELSE stmt
-
-

In this rule, -the expression is only IDENTIFIER (variable), -the substance of if is only one statement. -Now, what happens if the next program is parsed with this grammar?

-
-if (cond)
-    if (cond)
-        true_stmt;
-    else
-        false_stmt;
-
-

If it is written this way, we might feel like it’s quite obvious. -But actually, this can be interpreted as follows.

-
-if (cond) {
-    if (cond)
-        true_stmt;
-}
-else {
-    false_stmt;
-}
-
-

The question is -“between the two ifs, inside one or outside oue, -which is the one to which the else should be attached?”.

-

However shift/reduce conflicts are relatively less harmful than reduce/reduce -conflicts, because usually they can be solved by choosing shift. -Choosing shift is almost equivalent to “connecting the elements closer to each -other” and it is easy to match human instincts. -In fact, the hanging else can also be solved by shifting it. -Hence, the yacc follows this trend, -it choses shift by default when a shift/reduce conflict occurs.

-

Look-ahead

-

As an experiment, -I’d like you to process the next grammar with yacc.

-
-%token A B C
-%%
-target  : A B C   /* rule 1 */
-        | A B     /* rule 2 */
-
-

We can’t help expecting there should be a conflict. -At the time when it has read until A B, -the rule 1 would attempt to shift, -the rule 2 would attempt to reduce. -In other words, this should cause a shift/reduce conflict. However, ….

-
-% yacc conf.y
-%
-
-

It’s odd, there’s no conflict. Why?

-

In fact, the parser created with yacc can look ahead only one symbol. -Before actually doing shift or reduce, -it can decide what to do by peeking the next symbol.

-

Therefore, it is also considered for us when generating the parser, -if the rule can be determined by a single look-ahead, -conflicts would be avoided. -In the previous rules, for instance, if C comes right after A B, -only the rule 1 is possible and it would be chose (shift). -If the input has finished, the rule 2 would be chose (reduce).

-

Notice that the word “look-ahead” has two meanings: -one thing is the look-ahead while processing *.y with yacc. -The other thing is the look-ahead while actually executing the generated parser. -The look-ahead during the execution is not so difficult, -but the look-ahead of yacc itself is pretty complicated. -That’s because -it needs to predict all possible input patterns and decides its behaviors -from only the grammar rules.

-

However, because “all possible” is actually impossible, -it handles “most of” patterns. -How broad range over all patterns it can cover up shows -the strength of a look-ahead algorithm. -The look-ahead algorithm that yacc uses when processing grammar files is -LALR, which is relatively powerful among -currently existing algorithms to resolve conflicts.

-

A lot things have been introduced, -but you don’t have to so worry because what to do in this book is only reading -and not writing. What I wanted to explain here is not the look-ahead of grammars -but the look-ahead during executions.

-

Operator Precedence

-

Since abstract talks have lasted for long, I’ll talk more concretely. -Let’s try to define the rules for infix operators such as + or *. -There are also established tactics for this, we’d better tamely follow it. -Something like a calculator for arithmetic operations is defined below:

-
-expr    : expr '+' expr
-        | expr '-' expr
-        | expr '*' expr
-        | expr '/' expr
-        | primary
-
-primary : NUMBER
-        | '(' expr ')'
-
-

primary is the smallest grammar unit. -The point is that expr between parentheses becomes a primary.

-

Then, if this grammar is written to an arbitrary file and compiled, -the result would be this.

-
-% yacc infix.y
-16 shift/reduce conflicts
-
-

They conflict aggressively. Thinking for 5 minutes is enough to see that -this rule causes a problem in the following and simialr cases:

-
-1 - 1 - 1
-
-

This can be interpreted in both of the next two ways.

-
-(1 - 1) - 1
-1 - (1 - 1)
-
-

The former is natural as an numerical expression. -But what yacc does is the process of their appearances, -there does not contain any meanings. -As for the things such as the meaning the - symbol has, -it is absolutely not considered at all. -In order to correctly reflect a human intention, -we have to specify what we want step by step.

-

Then, what we can do is -writing this in the definition part.

-
-%left '+' '-'
-%left '*' '/'
-
-

These instructions specifies both the precedence and the associativity -at the same time.
-I’ll explain them in order.

-

I think that the term “precedence” often appears when talking about the grammar -of a programming language. -Describing it logically is complicated, so if I put it instinctively, -it is about to which operator parentheses are attached -in the following and similar cases.

-
-1 + 2 * 3
-
-

If * has higher precedence, it would be this.

-
-1 + (2 * 3)
-
-

If + has higher precedence, it would be this.

-
-(1 + 2) * 3
-
-

As shown above, resolving shift/reduce conflicts -by defining the stronger ones and weaker ones among operators -is operator precedence.

-

However, if the operators has the same precedence, how can it be resolved? -Like this, for instance,

-
-1 - 2 - 3
-
-

because both operators are -, their precedences are the completely same. -In this case, it is resolved by using the associativity. -Associativity has three types: left right nonassoc, -they will be interpreted as follows:

- - - - - - - - - - - - - - - - - -
Associativity Interpretation
left (left-associative) (1 – 2) – 3
right (right-associative) 1 – (2 – 3)
nonassoc (non-associative) parse error
-

Most of the operators for numerical expressions are left-associative. -The right-associative is used mainly for = of assignment and not of denial.

-
-a = b = 1    # (a = (b = 1))
-not not a    # (not (not a))
-
-

The representatives of non-associative are probably the comparison operators.

-
-a == b == c   # parse error
-a <= b <= c   # parse error
-
-

However, this is not the only possibility. -In Python, for instance, comparisons between three terms are possible.

-

Then, the previous instructions named %left %right %noassoc are used to -specify the associativities of their names. -And, precedence is specified as the order of the instructions. -The lower the operators written, the higher the precedences they have. -If they are written in the same line, they have the same level of precedence.

-
-%left  '+' '-'    /* left-associative and third precedence  */
-%left  '*' '/'    /* left-associative and second precedence */
-%right '!'        /* right-associative and first precedence */
-
- - - -
- - From e2b2c711e984b825df75ae70faf04b8a27d6d338 Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 19 Aug 2013 03:58:59 +0900 Subject: [PATCH 010/121] bring back the original settings This reverts the most of changes made at commit 6936c628eca42a51f540d1682c4370bb97015557 --- README.md | 4 ++-- _config.htmls.yml | 4 ---- _config.local.yml | 3 --- _config.yml | 1 - script/publish | 2 +- 5 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 _config.htmls.yml delete mode 100644 _config.local.yml diff --git a/README.md b/README.md index b1696c9..8111490 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Running the site locally $ git clone https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com $ gem install jekyll $ gem install RedCloth -$ jekyll serve --config _config.local.yml # this compiles files and starts a server on localhost:4000. +$ jekyll serve # this compiles files and starts a server on localhost:4000. ``` @@ -33,7 +33,7 @@ For Bundler users ```sh $ git clone https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com $ bundle install -$ jekyll serve --config _config.local.yml # this compiles files and starts a server on localhost:4000. +$ jekyll serve # this compiles files and starts a server on localhost:4000. ``` diff --git a/_config.htmls.yml b/_config.htmls.yml deleted file mode 100644 index ff58ad1..0000000 --- a/_config.htmls.yml +++ /dev/null @@ -1,4 +0,0 @@ -redcloth: - hard_breaks: false -exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] -destination: htmls diff --git a/_config.local.yml b/_config.local.yml deleted file mode 100644 index b4d19e5..0000000 --- a/_config.local.yml +++ /dev/null @@ -1,3 +0,0 @@ -redcloth: - hard_breaks: false -exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] diff --git a/_config.yml b/_config.yml index 6acff37..b4d19e5 100644 --- a/_config.yml +++ b/_config.yml @@ -1,4 +1,3 @@ redcloth: hard_breaks: false exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] -source: htmls diff --git a/script/publish b/script/publish index a1ed71a..8ea6758 100755 --- a/script/publish +++ b/script/publish @@ -14,7 +14,7 @@ require 'date' require 'fileutils' today = Date.today -system("jekyll build --config _config.local.yml") +system("jekyll build") GUIDE_DIR = File.expand_path("../..", __FILE__) ORIGINAL_DIR = "#{GUIDE_DIR}/_site" From fc445124483a8154846f801c2a879df2bd5bd1a9 Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 19 Aug 2013 05:32:04 +0900 Subject: [PATCH 011/121] forgot to remove ./htmls from the excluded directories --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index b4d19e5..972afec 100644 --- a/_config.yml +++ b/_config.yml @@ -1,3 +1,3 @@ redcloth: hard_breaks: false -exclude: ["ebooks", "script", "original_repo", "htmls", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] +exclude: ["ebooks", "script", "original_repo", "Gemfile", "Gemfile.lock", "dictionary.txt", "README.md"] From 3f017b5661efd6142710b5ad92cc73d1d2386583 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 20 Aug 2013 11:05:08 +0900 Subject: [PATCH 012/121] update the converter to fix improper markups --- _plugins/rhg_textile_converter.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/_plugins/rhg_textile_converter.rb b/_plugins/rhg_textile_converter.rb index df521d9..80d9180 100644 --- a/_plugins/rhg_textile_converter.rb +++ b/_plugins/rhg_textile_converter.rb @@ -17,11 +17,17 @@ def convert(content) skips << "cvs diff parse.y" # chapter 11 skips << "69 EXPR_DOT, /*" # chapter 11 content = lines.map do |line| - if skips.any? {|s| line.include? s } - line - else - line.gsub(RHG_CODE_RE) { "#{$1}" } + unless skips.any? {|s| line.include? s } + line = line.gsub(RHG_CODE_RE) { "#{$1}" } end + + # this applies the markup of the original book and + # fixes improper markups of the generated htmls at the same time. + if line =~ /^▼ / + line = %{

#{line.rstrip}

\n} + end + + line end.join # try to apply the style for images of the original book From 9c96e04011b44b4391a4a68321ef2f9bea067f35 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 22 Aug 2013 05:06:51 +0900 Subject: [PATCH 013/121] This workaround is no longer necessary --- contextual.textile | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/contextual.textile b/contextual.textile index 6732057..2802096 100644 --- a/contextual.textile +++ b/contextual.textile @@ -86,8 +86,8 @@ Thus, it is a variable which shows the scanner’s state. What states are there? Let’s look at the definitions. ▼ `enum lex_state` - -pre(longlist).   61 static enum lex_state { +
+  61  static enum lex_state {
   62      EXPR_BEG,      /* ignore newline, +/- is a sign. */
   63      EXPR_END,      /* newline significant, +/- is a operator. */
   64      EXPR_ARG,      /* newline significant, +/- is a operator. */
@@ -98,7 +98,9 @@ pre(longlist).   61  static enum lex_state {
   69      EXPR_DOT,      /* right after `.' or `::', no reserved words. */
   70      EXPR_CLASS,    /* immediate after `class', no here document. */
   71  } lex_state;
+
 (parse.y)
+
The EXPR prefix stands for “expression”. `EXPR_BEG` is “Beginning of expression” and `EXPR_DOT` is “inside the expression, after the dot”. @@ -617,8 +619,8 @@ operators. In all, there are five - `kUNLESS_MOD kUNTIL_MOD kWHILE_MOD` `kRESCUE_MOD` and `kIF_MOD` The distinction is made here: ▼ `yylex`-Reserved word - -pre(longlist). 4173 struct kwtable *kw; +
+4173                  struct kwtable *kw;
 4174
 4175                  /* See if it is a reserved word.  */
 4176                  kw = rb_reserved_word(tok(), toklen());
@@ -644,7 +646,9 @@ pre(longlist). 4173                  struct kwtable *kw;
 4196                          return kw->id[1];
 4197                      }
 4198                  }
+
 (parse.y)
+
This is located at the end of `yylex` after the identifiers are scanned. The part that handles modifiers is the last (innermost) `if`〜`else` Whether @@ -657,9 +661,11 @@ structure defined in `keywords` and the hash function `rb_reserved_word()` is created by `gperf`. I’ll show the structure here again. ▼ `keywords` - `struct kwtable` +
+   1  struct kwtable {char *name; int id[2]; enum lex_state state;};
 
-pre(longlist).    1  struct kwtable {char *name; int id[2]; enum lex_state state;};
 (keywords)
+
I’ve already explained about `name` and `id[0]` - they are the reserved word name and its symbol. Here I will speak about the remaining members. @@ -789,8 +795,8 @@ It’s the only part tasked with processing `do` so looking at this code should be enough to understand the criteria for making the distinction. ▼ `yylex`-Identifier-Reserved word - -pre(longlist). 4183 if (kw->id[0] == kDO) { +
+4183                      if (kw->id[0] == kDO) {
 4184                          if (COND_P()) return kDO_COND;
 4185                          if (CMDARG_P() && state != EXPR_CMDARG)
 4186                              return kDO_BLOCK;
@@ -798,7 +804,9 @@ pre(longlist). 4183                      if (kw->id[0] == kDO) {
 4188                              return kDO_BLOCK;
 4189                          return kDO;
 4190                      }
+
 (parse.y)
+
It’s a little messy, but you only need the part associated with `kDO_COND`. That is because only two comparisons are meaningful. @@ -1384,8 +1392,8 @@ This is the important part. As shown previously, you can avoid a conflict by changing the `do` and `'{'` symbols. ▼ `yylex`-`'{'` - -pre(longlist). 3884 case '{': +
+3884        case '{':
 3885          if (IS_ARG() || lex_state == EXPR_END)
 3886              c = '{';          /* block (primary) */
 3887          else if (lex_state == EXPR_ENDARG)
@@ -1396,7 +1404,9 @@ pre(longlist). 3884        case '{':
 3892          CMDARG_PUSH(0);
 3893          lex_state = EXPR_BEG;
 3894          return c;
+
 (parse.y)
+
`IS_ARG()` is defined as From 3ce945206d3a66cf00ec5b35fdad09179526eaf4 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 22 Aug 2013 09:44:29 +0900 Subject: [PATCH 014/121] The errata for chapter 11 --- contextual.textile | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/contextual.textile b/contextual.textile index 2802096..c7c64aa 100644 --- a/contextual.textile +++ b/contextual.textile @@ -175,6 +175,17 @@ which case suits best (see image 1) !images/ch_contextual_transittobeg.jpg(Transition to `EXPR_BEG`)! +((errata:
+1. Actually when the state is `EXPR_DOT`, the state after reading a +`tIDENTIFIER` would be either `ARG` or `CMDARG`. +However, because the author wanted to roughly group them as `FNAME/DOT` and the +others here, these two are shown together. +Therefore, to be precise, `EXPR_FNAME` and `EXPR_DOT` should have also been +separated.
+2. '`)`' does not cause the transition from "everything else" to `EXPR_BEG`. +)) + + This does indeed look like the head of statement. Especially the `'\n'` and the `';'` The open parentheses and the comma also suggest that it’s the head not just of the statement, but of the expression as well. @@ -224,7 +235,7 @@ For more information, see the section “The `do` conflict” * `EXPR_END` Used when there is a possibility that the statement is terminal. For example, -after a literal or brackets. Except for cases when `EXPR_ENDARG` is used +after a literal or a closing parenthesis. Except for cases when `EXPR_ENDARG` is used * `EXPR_ENDARG` @@ -882,6 +893,14 @@ MSB← →LSB ...0000000010 COND_LEXPOP() +((errata:
+It leaves `COND_P()` only when it is 1. +When `COND_P()` is 0 and the second bottom bit is 1, +it would become 1 after doing LEXPOP, +thus `COND_P()` is not left in this case. +)) + + Now I will explain what that means. h4. Investigating the function @@ -1680,6 +1699,17 @@ The decision-making part using `EXPR_ENDARG` is the same as `tLBRACE_ARG` so priorities shouldn’t be an issue here. Similarly to `'{'` the right course of action is probably to make it `kDO_BLOCK` +((errata:
+In the following case, priorities should have an influence. +(But it does not in the actual code. It means this is a bug.) + +
+m m (a) { ... } # This should be interpreted as m(m(a) {...}), 
+                # but is interpreted as m(m(a)) {...}
+m m (a) do ... end # as the same as this: m(m(a)) do ... end 
+
+)) + The problem lies with `CMDARG_P()` and `EXPR_CMDARG`. Let’s look at both. h4. `CMDARG_P()` @@ -1868,6 +1898,10 @@ m(m _ m m _ +((errata:
+The third one "m m _" is not `EXPR_CMDARG`. (It is `EXPR_ARG`.) +)) + h4. Conclusion Let us now return to the `do` decision code. @@ -2011,6 +2045,14 @@ tell you everything. It can’t tell anything other than what the reader infers. And with this very useful sermon, I close the chapter. +((errata:
+This confidently written conclusion was wrong. +Without `EXPR_CMDARG`, for instance, this program "`m (m do end)`" cannot be +parsed. This is an example of the fact that correctness is not proved even if +dynamic analyses are done so many times. +)) + + h4. Still not the end Another thing I forgot. I can’t end the chapter without explaining why From 0476632e250a4ef7be980b2c8dd7b2b49f34a977 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 22 Aug 2013 11:04:07 +0900 Subject: [PATCH 015/121] edit chapter 11 a little --- contextual.textile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contextual.textile b/contextual.textile index c7c64aa..961cdae 100644 --- a/contextual.textile +++ b/contextual.textile @@ -196,8 +196,8 @@ There are other easy methods to observe the functioning. For example, you can use a debugger to “hook” the `yylex()` and look at the `lex_state` Another way is to rewrite the source code to output state transitions. In the -case of `lex_state` we only have numerical patterns for assignment and -comparison, so the solution would be to treat them as text patterns and rewrite +case of `lex_state` we only have a few patterns for assignment and +comparison, so the solution would be to grasp them as text patterns and rewrite the code to output state transitions. The CD that comes with this book contains the `rubylex-analyser` tool. When necessary, I will refer to it in this text. @@ -246,13 +246,13 @@ Refer to the section “First parameter enclosed in parentheses” * `EXPR_FNAME` Comes before the method name, usually after `def`, `alias`, `undef` or the -symbol `':'` In an independent position ` is the method name. +symbol `':'` A single "`" can be a name. * `EXPR_DOT` Comes after the dot in a method call. Handled similarly to `EXPR_FNAME` Various reserved words are treated as simple identifiers. -In an independent position '`' is the name. +A single '`' can be a name. * `EXPR_CLASS` @@ -1494,7 +1494,7 @@ The problem here are parts of single lines that come out as `+EXPR_ENDARG`. This indicates a transition occurring during parser action. According to this, for some reason an action is executed after reading the `')'` a transition to `EXPR_ENDARG` occurs and `'{'` is nicely changed into `tLBRACE_ARG` This is -actually a pretty high-level technique – indiscriminately (ab)using +actually a pretty high-level technique – generously (ab)using the LALR(1) up to the (1). h4. Abusing the lookahead From 7a6aabaa8c94f7ce1626d520ac8b0a7d94c2fbdb Mon Sep 17 00:00:00 2001 From: ocha- Date: Sat, 24 Aug 2013 08:12:01 +0900 Subject: [PATCH 016/121] the rest of chapter 18 --- images/ch_load_link.jpg | Bin 0 -> 12093 bytes images/ch_load_loadwait.jpg | Bin 0 -> 25118 bytes load.textile | 543 +++++++++++++++++++++--------------- 3 files changed, 311 insertions(+), 232 deletions(-) create mode 100644 images/ch_load_link.jpg create mode 100644 images/ch_load_loadwait.jpg diff --git a/images/ch_load_link.jpg b/images/ch_load_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54fdc93a8ce23695024150d291cf9e6f697725bf GIT binary patch literal 12093 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 literal 0 HcmV?d00001 diff --git a/images/ch_load_loadwait.jpg b/images/ch_load_loadwait.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0cda54375103da2641e50e20173641b466be7c7f GIT binary patch literal 25118 zcmeFZ2Ut_t);As?5D-F9P#_6J1JaS+0!pNV^d?O~g46(^7g0$R1t9`blqS7{5PB$r zbdcVAl_pICeE$ZJf@@%G?Cs$8cCL0FHePmU_zi!!nvOAC&B4vn%hT4w(cKHqi?;J| zw6#-kcg1+v`0}0jJ_S$$P*YKXs3@sHAP@}=^$9v=FdZ!|9oxxM49qZgP7WA56bk1O z=7FCRL_ndu(tLs>1crD z03hh+vw@UMR431hf=;3InOV-9lQyyO@-7>oJ}oApYK#qzE^Qt}NL@CHdJ+>`E^dHJ z8D?hTL}P**_>%Z20oE9#Ii6M z3~A{jo6m*b-@$&33y#(c!udJnE#=}&wCExj(BbZ$mV;u{h=-^sGEnICo|cbNmRoU8 zhy&5se)(J(gST4Drvs3M6?QQdQJ($rs`HC|lSrAq0D4_L;4UzAM@&@rg&mYm9Ux7YEUXMpJ?6w6X0dwZ;8puP9w#)9oB~w*|_jG}@n2jJUe}c0`(iHgofcJGW3tiN+Mcz|a^_L&_HtKzw?mMU zbt;Imn5pWf25W%%>M}iH9}z|;cPQQMTA{|=8=_{l)@ZW4IKo!%~a&BoMNb#$+%ov zZ7p$H?uak6y38zS#&su*g;Twu*+TkI%!OMbR?iseQi@tcv-&=$!lmx|?`ZYG8Y9bH z6N^}$e^dGn_?86}p30p$A4eSb+RwdlZ3e|G=u?]r`7u19bA=VLl493XPZ6G8Sqb=@n|aB>`p=jDK-K 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 l$Ot3NBYev>UZ| -The are two reasons for adding the missing extension. The first one is +There are two reasons for adding the missing extension. The first one is not to load it twice if the same file is later `require`d with its extension. The second one is to be able to load both `nkf.rb` and `nkf.so`. In fact the extensions are disparate (`.so .dll .bundle` @@ -179,9 +178,11 @@ end h3. Highlights of this chapter -Here the mechanism is a lot about details, so it's a little difficult -to enumerate it simply. That's why we will work a little differently -on it, and we are going to reduce the target to 3 points: +With the above knowledge in our mind, we are going to read. +But because this time its specification is defined very particularly, +if we simply read it, it could be just a enumeration of the codes. +Therefore, in this chapter, +we are going to reduce the target to the following 3 points: * loading serialisation * the repartition of the functions in the different source files @@ -190,12 +191,13 @@ on it, and we are going to reduce the target to 3 points: Regarding the first point, you will understand it when you see it. For the second point, the functions that appear in this chapter come -from 4 different files, `eval.c ruby.c file.c dln.c`. We'll look at -the reason they are stretched in different places. +from 4 different files, `eval.c ruby.c file.c dln.c`. +Why is this in this way? +We'll try to think about the realistic situation behind it. The third point is just like its name says. We will see how the currently popular trend of execution time loading, more commonly -referred to as plug-ins, works. This is the most important part of this +referred to as plug-ins, works. This is the most interesting part of this chapter, so I'd like to use as many pages as possible to talk about it. h2. Searching the library @@ -267,7 +269,7 @@ actually like subroutines, and the two variables `feature` and `fname` are more or less their parameters. These variables have the following meaning. -|variable|meaning|example| +|_. variable|_. meaning|_. example| |`feature`|the library file name that will be put in `$"`|`uri.rb`、`nkf.so`| |`fname`|the full path to the library|`/usr/lib/ruby/1.7/uri.rb`| @@ -444,7 +446,15 @@ returned back to the thread where it was called. When the file name disappears from `loading_tbl`, the loading is finished so the function can end. The `curr_thread` check is not to lock itself (figure 1). -!images/ch_load_loadwait.png(Serialisation of loads)! +
+(loadwait)
+Figure 1: Serialisation of loads +* スレッド thread +* ロック lock +* ロード開始 loading is started +* ロード完了 loading is completed +* アンロック unlock +
h2. Loading of Ruby programs @@ -466,11 +476,12 @@ part inside `rb_f_require()`'s `load_rb` loading Ruby programs. The `rb_load()` which is called here is actually the "meat" of the Ruby-level `load`. -ということは探索がもう一回必要になるわけで、同じ作業をもう一回見るなん -てやっていられない。そこでその部分は以下では省略してある。 +This means it needs to search once again, +but looking at the same procedure once again is too much trouble. +Therefore, that part is omitted in the below codes. -And since the second argument (`wrap`) passed to `rb_load` in the above code is 0, the call is wrapped in 0. (*** What is this supposed to mean??? That the nesting level is 0?) -また第二引数の`wrap`も、上記の呼び出しコードで0なので、0で畳み込んである。 +And the second argument `wrap` is folded with 0 +because it is 0 in the above calling code. ▼ `rb_load()` (simplified edition)
@@ -487,13 +498,13 @@ rb_load(fname, /* wrap=0 */)
     PUSH_VARS();
     PUSH_CLASS();
     ruby_class = rb_cObject;
-    ruby_cref = top_cref;           /* (A-1) CREFを変える */
+    ruby_cref = top_cref;           /* (A-1) change CREF */
     wrapper = ruby_wrapper;
     ruby_wrapper = 0;
     PUSH_FRAME();
     ruby_frame->last_func = 0;
     ruby_frame->last_class = 0;
-    ruby_frame->self = self;        /* (A-2) ruby_frame->cbaseを変える */
+    ruby_frame->self = self;        /* (A-2) change ruby_frame->cbase */
     ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0);
     PUSH_SCOPE();
     /* at the top-level the visibility is private by default */
@@ -505,7 +516,7 @@ rb_load(fname, /* wrap=0 */)
     if (state == 0) {
         NODE *node;
 
-        /* (B)なぜかevalと同じ扱い */
+        /* (B) this is dealt with as eval for some reasons */
         ruby_in_eval++;
         rb_load_file(RSTRING(fname)->ptr);
         ruby_in_eval--;
@@ -532,32 +543,46 @@ rb_load(fname, /* wrap=0 */)
 }
 
-やっとスタック操作の嵐から抜けられたと思った瞬間また突入するというのも -精神的に苦しいものがあるが、気を取りなおして読んでいこう。 +Just after we thought we've been through the storm of stack manipulations +we entered again. Although this is tough, +let's cheer up and read it. + + +As the long functions usually are, +almost all of the code are occupied by the idioms. +`PUSH`/`POP`, tag protecting and re-jumping. +Among them, what we want to focus on is the things on (A) which relate to `CREF`. +Since a loaded program is always executed on the top-level, +it sets aside (not push) `ruby_cref` and brings back `top_cref`. +`ruby_frame->cbase` also becomes a new one. + + +And one more place, at (B) somehow `ruby_in_eval` is turned on. +What is the part influenced by this variable? +I investigated it and it turned out that it seems only `rb_compile_error()`. +When `ruby_in_eval` is true, the message is stored in the exception object, +but when it is not true, the message is printed to `stderr`. +In other words, when it is a parse error of the main program of the command, +it wants to print directly to `stderr`, but when inside of the evaluator, +it is not appropriate so it stops to do it. +It seems the "eval" of `ruby_in_eval` means neither the `eval` method nor the +`eval()` function but "evaluate" as a general noun. +Or, it's possible it indicates `eval.c`. + -長い関数の常で、コードのほとんどがイディオムで占められている。 -`PUSH`/`POP`、タグプロテクトと再ジャンプ。その中でも注目したいのは -(A)の`CREF`関係だ。ロードしたプログラムは常にトップレベル上で -実行されるので、`ruby_cref`を(プッシュではなく)退避し`top_cref`に戻す。 -`ruby_frame->cbase`も新しいものにしている。 -それともう一ヶ所、(B)でなぜか`ruby_in_eval`をオンにしている。そもそも -この変数はいったい何に影響するのか調べてみると、`rb_compile_error()`とい -う関数だけのようだ。`ruby_in_eval`が真のときは例外オブジェクトにメッセージを -保存、そうでないときは`stderr`にメッセージを出力、となっている。つまりコ -マンドのメインプログラムのパースエラーのときはいきなり`stderr`に出力した -いのだが評価器の中ではそれはまずいので止める、という仕組みらしい。すると -`ruby_in_eval`のevalはメソッド`eval`や関数`eval()`ではなくて一般動詞の -evaluateか、はたまた`eval.c`のことを指すのかもしれない。 h3. `rb_load_file()` -ここでソースファイルは突然`ruby.c`へと移る。と言うよりも実際のところは -こうではないだろうか。即ち、ロード関係のファイルは本来`ruby.c`に置きたい。 -しかし`rb_load()`では`PUSH_TAG()`などを使わざるを得ない。だから仕方なく -`eval.c`に置く。でなければ最初から全部`eval.c`に置くだろう。 +Then, all of a sudden, the source file is `ruby.c` here. +Or to put it more accurately, +essentially it is favorable if the entire loading code was put in `ruby.c`, +but `rb_load()` has no choice but to use `PUSH_TAG` and such. +Therefore, putting it in `eval.c` is inevitable. +If it were not the case, +all of them would be put in `eval.c` in the first place. -それで、`rb_load_file()`だ。 +Then, it is `rb_load_file()`. ▼ `rb_load_file()`
@@ -571,12 +596,15 @@ h3. `rb_load_file()`
 (ruby.c)
 
-まるごと委譲。`load_file()`の第二引数`script`は真偽値で、`ruby`コマンドの -引数のファイルをロードしているのかどうかを示す。今はそうではなく -ライブラリのロードと考えたいので`script=0`で疊み込もう。 -さらに以下では意味も考え本質的でないものを削ってある。 +Delegated entirely. The second argument `script` of `load_file()` is a boolean +value and it indicates whether it is loading the file of the argument of the +`ruby` command. Now, because we'd like to assume we are loading a library, +let's fold it by replacing it with `script=0`. +Furthermore, in the below code, also thinking about the meanings, +non essential things have already been removed. + -▼ `load_file()` (simplified edition) +

▼ `load_file()` (simplified edition)

 static void
 load_file(fname, /* script=0 */)
@@ -591,7 +619,7 @@ load_file(fname, /* script=0 */)
         fclose(fp);
     }
     f = rb_file_open(fname, "r");       (B)
-    rb_compile_file(fname, f, 1);       ==(C)==
+    rb_compile_file(fname, f, 1);       (C)
     rb_io_close(f);
 }
 
@@ -603,8 +631,8 @@ highly portable and reliable way to do it. (B) The file is opened once again, this time using the Ruby level library `File.open`. The file was not opened with `File.open` from the -beginning so as not to raise any Ruby exception if the file cannot be -opened. Here if any exception occurred we would like to have a +beginning so as not to raise any Ruby exception. +Here if any exception occurred we would like to have a loading error, but getting the errors related to `open`, for example `Errno::ENOENT`, `Errno::EACCESS`..., would be problematic. We are in `ruby.c` so we cannot stop a tag jump. @@ -615,7 +643,7 @@ tree is added to `ruby_eval_tree` so there is no need to get the result. That's all for the loading code. Finally, the calls were quite deep so -let's look at the callgraph of `rb_f_require()` bellow. +the callgraph of `rb_f_require()` is shown bellow.
 rb_f_require           ....eval.c
@@ -629,19 +657,23 @@ rb_f_require           ....eval.c
         eval_node
 
-We've seen a lot of callgraphs, they are now common sense. + +You must bring callgraphs on a long trip. It's common knowledge. + + h4. The number of `open` required for loading -Like we've seen before, there are `open` used just to check if a file -can be open, but in fact during the loading process other functions -like for example `rb_find_file_ext()` also do checks using `open`. How +Previously, there was `open` used just to check if a file can be open, +but in fact, during the loading process of `ruby`, additionally other functions +such as `rb_find_file_ext()` also internally do checks by using `open`. How many times is `open()` called in the whole process? -If you're wondering that, it's just a matter of having the right program available to count and see. You can easily find out using a system call tracer. On Linux, the tool to use would be `strace`; on Solaris, `truss`; or on BSD, `ktrace` or `truss`. - -というように -OSによって名前がてんでバラバラなのだが、Googleで検索すればすぐ見付かる +If you're wondering that, just actually counting it is the right attitude as a +programmer. We can easily count it by using a system call tracer. +The tool to use would be `strace` on Linux, `truss` on Solaris, `ktrace` or +`truss` on BSD. Like this, for each OS, the name is different +and there's no consistency, but you can find them by googling. If you're using Windows, probably your IDE will have a tracer built in. Well, as my main environment is Linux, I looked using `strace`. @@ -661,8 +693,9 @@ open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3 open("/usr/lib/ruby/1.7/rational.rb", O_RDONLY|O_LARGEFILE) = 3 -`libc.so.6`の`open`まではダイナミックリンクの実装で使っている`open`なので -残りの`open`は計四回。つまり三回は無駄になっているようだ。 +Until the `open` of `libc.so.6`, it is the `open` used in the implementation of +dynamic links, and there are the other four `open`s. +Thus it seems the three of them are useless. h2. Loading of extension libraries @@ -693,189 +726,222 @@ part about locking anymore so it was removed. (eval.c) -By now, there is very little here which is novel. タグはイディオム通りの使いかた -しかしていないし、可視性スコープの退避・復帰も見慣れた手法だ。 +By now, there is very little here which is novel. +The tags are used only in the way of the idiom, +and to save/restore the visibility scope is done in the way we get used to see. All that remains is `dln_load()`. What on earth is that for? For the answer, continue to the next section. -h3. リンクについて復習 +h3. Brush up about links -`dln_load()`は拡張ライブラリをロードしているわけだが、拡張ライブラリを -ロードするとはどういうことなのだろうか。それを話すにはまず話を思い切り -物理世界方向に巻き戻し、リンクのことから始めなければならない。 +`dln_load()` is loading an extension library, +but what does loading an extension library mean? +To talk about it, we need to dramatically roll back the talk to the physical world, +and start with about links. + +I think compiling C programs is, of course, not a new thing for you. +Since I'm using `gcc` on Linux, I can create a runnable program in the following +manner. -Cのプログラムをコンパイルしたことはもちろんあると思う。筆者は -Linuxで`gcc`を使っているので、次のようにすれば動くプログラムが -作成できる。
 % gcc hello.c
 
-ファイル名からするときっとこれはHello, World!プログラムなんだろう。 -`gcc`はUNIXではデフォルトで`a.out`というファイルにプログラムを -出力するので続いて次のように実行できる。 + +According to the file name, this is probably an "Hello, World!" program. +In UNIX, `gcc` outputs a program into a file named `a.out` by default, +so you can subsequently execute it in the following way:
 % ./a.out
 Hello, World!
 
-It prints out just as expected. - -By the way, what is `gcc` actually doing here? Usually we just say is "compiles", but actually it... - -# Preprocesses (`cpp`) -# Compiles C into assembly (`cc`) -# Assembles the assembly language into machine code (`as`) -# Links (`ld`) - -という四つの段階を通っている。このうちプリプロセス・コンパイル・アセン -ブルまではいろいろなところで説明を見掛けるのだが、なぜかリンクの段階だ -けは明文化されずに終わることが多いようだ。学校の歴史の授業では絶対に -「現代」まで行き着かない、というのと同じようなものだろうか。そこで本書 -ではその断絶を埋めるべく、まずリンクとは何なのか簡単にまとめておくこと -にする。 - -アセンブルまでの段階が完了したプログラムはなんらかの形式の -「オブジェクトファイル」 -になっている。そのような形式でメジャーなものには以下のよう -なものがある。 - -* ELF, Executable and Linking Format(新しめのUNIX) -* `a.out`, assembler output(比較的古いUNIX) -* COFF, Common Object File Format(Win32) - -念のため言っておくが、オブジェクトファイル形式の`a.out`と`cc`の -デフォルト出力ファイル名の`a.out`は全然別物である。例えば今時のLinuxで -普通に作ればELF形式のファイル`a.out`ができる。 - -それで、このオブジェクトファイル形式がどう違うのか、という話はこのさい -どうでもいい。今認識しなければならないのは、これらのオブジェクトファイ -ルはどれも「名前の集合」と考えられるということだ。例えばこのファイルに -存在する関数名や変数名など。 - -またオブジェクトファイルに含まれる名前の集合には二種類がある。即ち - -* 必要な名前の集合(例えば内部から呼んでいる外部関数。例:`printf`) -* 提供する名前の集合(例えば内部で定義している関数。例:`hello`) - -である。そしてリンクとは、複数のオブジェクトファイルを集めてきたときに -全てのオブジェクトファイルの「必要な名前の集合」が「提供する名前の集合」 -の中に含まれることを確認し、かつ互いに結び付けることだ。つまり全ての -「必要な名前」から線をひっぱって、どこかのオブジェクトファイルが「提供 -する名前」につなげられるようにしなければいけない(図2)。 -このことを用語を使って -言えば、未定義シンボルを解決する(resolving undefined symbol)、となる。 - -!images/ch_load_link.png(オブジェクトファイルとリンク)! - -論理的にはそういうことだが、現実にはそれだけではプログラムは走らないわ -けだ。少なくともCのプログラムは走らない。名前をアドレス(数)に変換し -てもらわなければ動けないからだ。 - -そこで論理的な結合の次には物理的な結合が必要になる。オブジェクトファイ -ルを現実のメモリ空間にマップし、全ての名前を数で置き換えないといけない。 -具体的に言えば関数呼び出し時のジャンプ先アドレスを調節したりする。 - -そしてこの二つの結合をいつやるかによってリンクは二種類に分かれる。即ち -スタティックリンクとダイナミックリンクである。スタティックリンクはコン -パイル時に全段階を終了してしまう。一方ダイナミックリンクは結合のうちい -くらかをプログラムの実行時まで遅らせる。そしてプログラムの実行時になっ -て初めてリンクが完了する。 - -もっともここで説明したのは非常に単純な理想的モデルであって現実をかなり -歪曲している面がある。論理結合と物理結合はそんなにキッパリ分かれるもの -ではないし、「オブジェクトファイルは名前の集合」というのもナイーブに過 -ぎる。しかしなにしろこのあたりはプラットフォームによってあまりに動作が -違いすぎるので、真面目に話していたら本がもう一冊書けてしまう。 -現実レベルの知識を得るためにはさらに -『エキスパートCプログラミング』\footnote{『エキスパートCプログラミング』Peter van der Linden著、梅原系訳、アスキー出版局、1996} -『Linkers&Loaders』@footnote{『Linkers&Loaders』John R.Levine著、榊原一矢監訳 ポジティブエッジ訳、オーム社、2001} -あたりも読んでおくとよい。 - -h3. 真にダイナミックなリンク +It is created properly. + +By the way, what is `gcc` actually doing here? +Usually we just say "compile" or "compile", but actually + +# preprocess (`cpp`) +# compile C into assembly (`cc`) +# assemble the assembly language into machine code (`as`) +# link (`ld`) + +there are these four steps. Among them, preprocessing and compiling and +assembling are described in a lot of places, but the description often ends +without clearly describing about the linking phase. +It is like a history class in school which would never reach "modern age". +Therefore, in this book, trying to provide the extinguished part, +I'll briefly summarize what is linking. + +A program finished the assembling phase becomes an "object file" in +somewhat format. The following formats are some of such formats which are major. + +* ELF, Executable and Linking Format (recent UNIX) +* `a.out`, assembler output (relatively old UNIX) +* COFF, Common Object File Format (Win32) + +It might go without saying that the `a.out` as an object file format and +the `a.out` as a default output file name of `cc` are totally different things. +For example, on modern Linux, when we create it ordinarily, the `a.out` file +in ELF format is created. + +And, how these object file formats differ each other is not important now. +What we have to recognize now is, all of these object files +can be considered as "a set of names". +For example, the function names and the variable names which exist in this file. + +And, sets of names contained in the object file have two types. + +* set of necessary names +(for instance, the external functions called internally. e.g. `printf`) + +* set of providing names +(for instance, the functions defined internally. e.g. `hello`) + + +And linking is, when gathering multiple object files, +checking if "the set of providing names" contains "the set of necessary names" +entirely, and connecting them each other. +In other words, pulling the lines from all of "the necessary names", +each line must be connected to one of "the providing names" of a particular +object file. (Figure. 2) +To put this in technical terms, +it is resolving undefined symbols. + +
+(link)
+Figure 2: object files and linking +* 提供する名前 the providing names +* 必要な名前 the necessary names +* オブジェクトファイル object file +
+ +Logically this is how it is, but in reality a program can't run only because of +this. At least, C programs cannot run without converting the names to the +addresses (numbers). + +So, after the logical conjunctions, the physical conjunctions become necessary. +We have to map object files into the real memory space +and substitute the all names with numbers. +Concretely speaking, for instance, the addresses to jump to on function calls +are adjusted here. + +And, based on the timing when to do these two conjunctions, +linking is divided into two types: +static linking and dynamic linking. +Static linking finishes the all phases during the compile time. +On the other hand, dynamic linking defers some of the conjunctions to the +executing time. And linking is finally completed when executing. + +However, what explained here is a very simple idealistic model, +and it has an aspect distorting the reality a lot. +Logical conjunctions and physical conjunctions are not so completely separated, +and "an object file is a set of names" is too naive. +But the behavior around this considerably differs depending on each platform, +describing seriously would end up with one more book. +To obtain the realistic level knowledge, additionally, +"Expert C Programming: Deep C Secrets" by Peter van der Linden, +"Linkers and Loaders" by John R.Levine +I recommend to read these books. + + + +h3. Linking that is truly dynamic And finally we get into our main topic. The "dynamic" in "dynamic linking" naturally means it "occurs at execution time", but what people usually refer to as "dynamic linking" is pretty much decided already at compile time. For example, the names of the needed functions, and which library they can be found in, are already known. For instance, if you need `cos()`, you know it's in `libm`, so you use `gcc -lm`. If you didn't specify the correct library at compile time, you'd get a link error. But extension libraries are different. Neither the names of the needed functions, or the name of the library which defines them are known at compile time. -文字列をプログラムの実 -行中に組み立ててロード・リンクしなければいけないのである。つまり先程の -言葉で言う「論理結合」すらも全て実行時に行わなければならない。そのため -には普通に言うところのダイナミックリンクとはまた少し違う仕組みが必要に -なる。 - -この操作、つまり実行時に全てを決めるリンク、のことを普通は -「動的ロード(dynamic load)」と呼ぶ。本書の用語遣いからいくと -「ダイナミックロード」と片仮名にひらくべきなのだろうが、 -ダイナミックリンクと -ダイナミックロードだと紛らわしいのであえて漢字で「動的ロード」とする。 - -h3. 動的ロードAPI - -概念の説明は以上だ。あとはその動的ロードをどうやればいいかである。とは -言っても難しいことはなくて、普通はシステムに専用APIが用意されているの -でこちらは単にそれを呼べばいい。 - -例えばUNIXならわりと広範囲にあるのが`dlopen`というAPIである。ただし -「UNIXならある」とまでは言えない。例えばちょっと前のHP-UXには全く違う -インターフェイスがあるしMac OS XだとNeXT風のAPIを使う。また同じ -`dlopen`でもBSD系だと`libc`にあるのにLinuxだと`libdl`として外付けになっ -ている、などなど、壮絶なまでに移植性がない。いちおうUNIX系と並び称され -ていてもこれだけ違うわけだから、他のOSになれば全然違うのもあたりまえで -ある。同じAPIが使われていることはまずありえない。 - -そこで`ruby`はどうしているかというと、その全然違うインターフェイスを吸収 -するために`dln.c`というファイルを用意している。`dln`はdynamic linkの略だろ -う。`dln_load()`はその`dln.c`の関数の一つなのである。 - -そんなふうに全くバラバラの動的ロードAPIだが、せめてもの救 -いはAPIの使用パターンが全く同じだということだ。どのプラットフォームだ -ろうと - -# ライブラリをプロセスのアドレス空間にマップする -# ライブラリに含まれる関数へのポインタを取る -# ライブラリをアンマップ - -という三段階で構成されている。例えば`dlopen`系APIならば +We need to construct a string at execution time and load and link. +It means that even "the logical conjunctions" in the sense of the previous words +should be done entirely at execution time. +In order to do it, another mechanism that is a little different form the ordinal +dynamic linkings is required. + +This manipulation, linking that is entirely decided at runtime, +is usually called "dynamic load". + + + +h3. Dynamic load API + +I've finished to explain the concept. The rest is how to do that dynamic loading. +This is not a difficult thing. Usually there's a specific API prepared in the +system, we can accomplish it by merely calling it. + +For example, what is relatively broad for UNIX is the API named `dlopen`. +However, I can't say "It is always available on UNIX". +For example, for a little previous HP-UX has a totally different interface, +and a NeXT-flavor API is used on Mac OS X. +And even if it is the same `dlopen`, +it is included in `libc` on BSD-derived OS, +and it is attached from outside as `libdl` on Linux. +Therefore, it is desperately not portable. +It differs even among UNIX-based platforms, +it is obvious to be completely different in the other Operating Systems. +It is unlikely that the same API is used. + +Then, how `ruby` is doing is, in order to absorb the totally different +interfaces, the file named `dln.c` is prepared. +`dln` is probably the abbreviation of "dynamic link". +`dln_load()` is one of functions of `dln.c`. + +Where dynamic loading APIs are totally different each other, +the only saving is the usage pattern of API is completely the same. +Whichever platform you are on, + +# map the library to the address space of the process +# take the pointers to the functions contained in the library +# unmap the library + +it consists of these there steps. +For example, if it is `dlopen`-based API, # `dlopen` # `dlsym` # `dlclose` -が対応する。Win32 APIならば +are the correspondences. If it is Win32 API, -# `LoadLibrary`(または`LoadLibraryEx`) +# `LoadLibrary` (or `LoadLibraryEx`) # `GetProcAddress` # `FreeLibrary` -が対応する。 +are the correspondences. + +At last, I'll talk about what `dln_load()` is doing by using these APIs. +It is, in fact, calling `Init_xxxx()`. +By reaching here, we finally become to be able to illustrate the entire process +of `ruby` from the invocation to the completion without any lacks. +In other words, when `ruby` is invoked, it initializes the evaluator and starts +evaluating a program passed in somewhat way. +If `require` or `load` occurs during the process, +it loads the library and transfers the control. +Transferring the control means parsing and evaluating if it is a Ruby library +and it means loading and linking and finally calling `Init_xxxx()` +if it is an extension library. -最後に、このAPI群を使って`dln_load()`が何をするかを話そう。これが実は、 -`Init_xxxx()`の呼び出しなのだ。ここに至ってついに`ruby`起動から終了までの全 -過程が欠落なく描けるようになる。即ち、`ruby`は起動すると評価器を初期化し -なんらかの方法で受け取ったメインプログラムの評価を開始する。その途中で -`require`か`load`が起こるとライブラリをロードし制御を移す。制御を移す、と -は、Rubyライブラリならばパースして評価することであり、拡張ライブラリな -らばロード・リンクして`Init_xxxx()`を呼ぶことである。 h3. `dln_load()` -ようやく`dln_load()`の中身にたどりつけた。`dln_load()`も長い関数だが、これ -また理由があって構造は単純である。まず概形を見てほしい。 +Finally, we've reached the content of `dln_load()`. +`dln_load()` is also a long function, +but its structure is simple because of some reasons. +Take a look at the outline first. -▼ `dln_load()`(概形) +▼ `dln_load()` (outline)
 void*
 dln_load(file)
     const char *file;
 {
 #if defined _WIN32 && !defined __CYGWIN__
-    Win32 APIでロード
+    load with Win32 API
 #else
-    プラットフォーム独立の初期化
-#ifdef 各プラットフォーム
-    ……プラットフォームごとのルーチン……
+    initialization depending on each platform
+#ifdef each platform
+    ……routines for each platform……
 #endif
 #endif
 #if !defined(_AIX) && !defined(NeXT)
@@ -886,19 +952,20 @@ dln_load(file)
 }
 
-このようにメインとなる部分がプラットフォームごとに完璧に分離しているため、 -考えるときは一つ一つのプラットフォームのことだけを考えていればいい。 -サポートされているAPIは以下の通りだ。 +This way, the part connecting to the main is completely separated based on each +platform. When thinking, we only have to think about one platform at a time. +Supported APIs are as follows: + +* `dlopen` (Most of UNIX) +* `LoadLibrary` (Win32) +* `shl_load` (a bit old HP-UX) +* `a.out` (very old UNIX) +* `rld_load` (before `NeXT4`) +* `dyld` (`NeXT` or Mac OS X) +* `get_image_symbol` (BeOS) +* `GetDiskFragment` (Mac Os 9 and before) +* `load` (a bit old AIX) -* `dlopen`(多くのUNIX) -* `LoadLibrary`(Win32) -* `shl_load`(少し古いHP-UX) -* `a.out`(かなり古いUNIX) -* `rld_load`(`NeXT4`未満) -* `dyld`(`NeXT`またはMac OS X) -* `get_image_symbol`(BeOS) -* `GetDiskFragment`(Mac OS 9以前) -* `load`(少し古いAIX) h3. `dln_load()`-`dlopen()` @@ -914,7 +981,7 @@ First, let's start with the API code for the `dlopen` series. 1260 #define DLN_ERROR() (error = dln_strerror(),\ strcpy(ALLOCA_N(char, strlen(error) + 1), error)) 1298 char *buf; -1299 /* Init_xxxxという文字列をbufに書き込む(領域はalloca割り当て) */ +1299 /* write a string "Init_xxxx" to buf (the space is allocated with alloca) */ 1300 init_funcname(&buf, file); 1304 { @@ -928,21 +995,21 @@ First, let's start with the API code for the `dlopen` series. 1312 # define RTLD_GLOBAL 0 1313 #endif 1314 -1315 /* (A)ライブラリをロード */ +1315 /* (A) load the library */ 1316 if ((handle = (void*)dlopen(file, RTLD_LAZY | RTLD_GLOBAL)) == NULL) { 1317 error = dln_strerror(); 1318 goto failed; 1319 } 1320 - /* (B)Init_xxxx()へのポインタを取る */ + /* (B) get the pointer to Init_xxxx() */ 1321 init_fct = (void(*)())dlsym(handle, buf); 1322 if (init_fct == NULL) { 1323 error = DLN_ERROR(); 1324 dlclose(handle); 1325 goto failed; 1326 } -1327 /* ==(C)==Init_xxxx()を呼ぶ */ +1327 /* (C) call Init_xxxx() */ 1328 (*init_fct)(); 1329 1330 return handle; @@ -955,22 +1022,34 @@ First, let's start with the API code for the `dlopen` series. (dln.c) -(A)`dlopen()`の引数の`RTLD_LAZY`は「実際に関数を要求したときに -未解決シンボルを解決する」ことを示す。返り値はライブラリを識別する -ための印(ハンドル)で、`dl*()`には常にこれを渡さないといけない。 -(B)`dlsym()`はハンドルの示すライブラリから関数ポインタを取る。返り値が -`NULL`なら失敗だ。ここで`Init_xxxx()`へのポインタを取り、呼ぶ。 +(A) the `RTLD_LAZY` as the argument of `dlopen()` indicates "resolving the +undefined symbols when the functions are actually demanded" +The return value is the mark (handle) to distinguish the library and +we always need to pass it when using `dl*()`. -`dlclose()`の呼び出しはない。`Init_xxxx()`の中でロードした -ライブラリの関数ポインタを -返したりしているはずだが、`dlclose()`するとライブラリ全体が使えなくなって -しまうのでまずいのだ。つまりプロセスが終了するまで`dlclose()`は呼べない。 -h3. `dln_load()`-Win32 +(B) `dlsym()` gets the function pointer from the library specified by the +handle. If the return value is `NULL`, it means failure. +Here, getting the pointer to `Init_xxxx()` +If the return value is `NULL`, it means failure. Here, the pointer to +`Init_xxxx()` is obtained and called. -Win32では`LoadLibrary()`と`GetProcAddress()`を使う。 -MSDNにも載っているごく一般的なWin32 APIである。 + +`dlclose()` is not called here. Since the pointers to the +functions of the loaded library are possibly returned inside `Init_xxx()`, +it is troublesome if `dlclose()` is done +because the entire library would be disabled to use. +Thus, we can't call `dlclose()` until the process will be finished. + + + + +h3. `dln_load()` -- Win32 + + +As for Win32, `LoadLibrary()` and `GetProcAddress()` are used. +It is very general Win32 API which also appears on MSDN. ▼ `dln_load()`-Win32
@@ -986,12 +1065,12 @@ MSDNにも載っているごく一般的なWin32 APIである。
 1268
 1269      if (strlen(file) >= MAXPATHLEN) rb_loaderror("filename too long");
 1270
-1271      /* "Init_xxxx"という文字列をbufに書き込む(領域はalloca割り当て) */
+1271      /* write the "Init_xxxx" string to buf (the space is allocated with alloca) */
 1272      init_funcname(&buf, file);
 1273
 1274      strcpy(winfile, file);
 1275
-1276      /* ライブラリをロード */
+1276      /* load the library */
 1277      if ((handle = LoadLibrary(winfile)) == NULL) {
 1278          error = dln_strerror();
 1279          goto failed;
@@ -1001,7 +1080,7 @@ MSDNにも載っているごく一般的なWin32 APIである。
 1283          rb_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
 1284      }
 1285
-1286      /* Init_xxxx()を呼ぶ */
+1286      /* call Init_xxxx() */
 1287      (*init_fct)();
 1288      return handle;
 
@@ -1012,6 +1091,6 @@ MSDNにも載っているごく一般的なWin32 APIである。
 (dln.c)
 
-`LoadLibrary()`して`GetProcAddress()`。ここまでパターンが同じだと -言うこともないので、終わってしまうことにしよう。 - +Doing `LoadLibrary()` then `GetProcAddress()`. +The pattern is so equivalent that nothing is left to say, +I decided to end this chapter. From 0c92ca68cc9f1dc5affe61a596d24fb4b914938e Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Sat, 24 Aug 2013 21:56:56 +0900 Subject: [PATCH 017/121] Translate about 2/5 in Intro --- intro.textile | 249 +++++++++++++++++++++++--------------------------- 1 file changed, 116 insertions(+), 133 deletions(-) diff --git a/intro.textile b/intro.textile index e0e845e..4cfdad1 100644 --- a/intro.textile +++ b/intro.textile @@ -272,192 +272,175 @@ p(=emlist). result = if cond then process(val) else nil end -大雑把に言うと、関数やメソッドの引数にできるものは式だと思っていい。 +Roughly, you can assume any element which can be fed as an argument for a function +or a method is a formula. +Of course, there are other languages whose syntactic elements are mostly a formula. +Namely, Lisp is the best example. For this characteristic, many people seem to +regard Ruby is similar to Lisp. -もちろん「ほとんどの文法要素が式」という言語は他にもいろいろある。例えば -Lispはその最たるものだ。このあたりの特徴からなんとなく「RubyはLispに似 -てる」と感じる人が多いようである。 +h4. Iterators -h4. イテレータ +Ruby has iterators. What is an iterator? Before getting into iterators, I should +mention the necessity of using an alternative term, because the word "iterator" is +disliked recently. However, I don't have a good alternation. So let us keep calling +it "iterator" for the time being. -Rubyにはイテレータがある。イテレータとは何か。いやその前にイテレータと -いう言葉は最近嫌われているので別の言葉を使うべきかもしれない。だがい -い言葉を思いつかないので当面イテレータと呼ぶことにする。 +Well again, what is an iterator? If you are already familiar with a high level +function which is similar, you can assume it for now. C-language example is the way +you feed function pointer as an argument. C++ example is a way to envelope the +operation part of STL's @Iterator@ into a method. If you are familiar with sh and +Perl, you can imagine it like a custom defined @for@ statement. +Yet, the above are merely examples of "similar" concepts. All of them are similar, +but they are not identical to Ruby's iterator. I will expand the precise story +when it's a good time later. -それでイテレータとは何か。高階の関数を知っているなら、とりあえずはそれ -と似たようなものだと思っておけばいい。Cで言えば関数ポインタを引数 -に渡すやつである。C++で言えばSTLにある@Iterator@の操作部分までをメソッド -に封入したものである。shやPerlを知っているのなら、独自に定義できる -@for@文みたいなもんだと思って見てみるといい。 +h4. Written in C-language +Being written in C-language is not distinctive these days, but it's still a notable +characteristic for sure. Unlike being written in Haskell or PL/I, it should possibly +be readable for a wide range of people generally. (I want you to confirm it in the +later in this book.) -もっともあくまでここに挙げたのは全て「似たようなもの」であって、どれも -Rubyのイテレータと似てはいるが、同じでは、全くない。いずれその時が来た -らもう少し厳密な話をしよう。 +Well, I just said it's in C-language, but the actual language version which ruby is +targetting is basically K&R C. Until a little while ago, there were a decent number +of - not plenty though - K&R-only-environment. Considering the trend of ANSI C being +a popular environment that seems to pass most of programs, there appears to be no +problem to port to ANSI C. However, the K&R style code is still maintained, with the +author Matsumoto's preference being one aspect. -h4. C言語で書いてある +For this reason, the function definition is all in K&R style, and the prototype +declarations are not strictly written. Looking at the mailing list, I can see a lot +of topics in which @gcc@ with @-Wall@ option outputs a huge dump of errors, and C++ +compiler warns prototype mismatch that fails to finish compiling. -Cで書いたプログラムなどいまどき珍しくもないが、特徴であることは間違い -ない。少なくともHaskellやPL/Iで書いてあるわけではないので一般人にも -読める可能性が高い(本当にそうかどうかはこれから自分で確かめてほしい)。 +h4. Extension library +Ruby library can be written in C. It can be loaded at execution without recompiling Ruby. +This type of library is called "Ruby extension library" or just "Extension library". -それからC言語と言っても@ruby@が対象としているのは基本的にK&R Cだ。 -少し前まではK&R onlyの環境が、たくさんとは言わないが、それなりにあったからだ。 -しかしさすがに最近はANSI Cが通らない環境はなくなってきており技術的には -ANSI Cに移っても特に問題はない。だが作者のまつもとさん個人の趣味もあっ -てまだK&Rスタイルを通している。 - - -そんなわけで関数定義は全てK&Rスタイルだし、プロトタイプ宣言もあまり真面 -目に書かれていない。@gcc@でうっかり@-Wall@を付けると大量に警告が出て -くるとか、 -C++コンパイラでコンパイルするとプロトタイプが合わないと怒られてコンパ -イルできない......なんて話がポロポロとメーリングリストに流れている。 - -h4. 拡張ライブラリ - -RubyのライブラリをCで書くことができ、Rubyを再コンパイルすることなく -実行時にロードできる。このようなライブラリを「Ruby拡張ライブラリ」 -または単に「拡張ライブラリ」と言う。 - - -単にCで書けるだけでなくRubyレベルとCレベルでのコードの表現の差が小さい -のも大きな特徴である。Rubyで使える命令はほとんどそのままCでも使うこと -ができる。例えば以下のように。 +In addition to the fact that's written in C, one of the important feature is that Ruby +level and C level code differences are very small. Most commands available in Ruby are +also available in C. See following example. p(=emlist). -# メソッド呼び出し +# Method call obj.method(arg) # Ruby rb_funcall(obj, rb_intern("method"), 1, arg); # C -# ブロック呼び出し + +# Block call yield arg # Ruby rb_yield(arg); # C -# 例外送出 + +# Raising exception raise ArgumentError, 'wrong number of arguments' # Ruby rb_raise(rb_eArgError, "wrong number of arguments"); # C -# オブジェクトの生成 + +# Generating an object arr = Array.new # Ruby VALUE arr = rb_ary_new(); # C -拡張ライブラリを書くうえでは非常に楽をできていいし、現実に -このことが代えがたい@ruby@の長所にもなっている。しかしそのぶん -@ruby@の実装にとっては非常に重い足枷となっており、随所にその -影響を見ることができる。特にGCやスレッドへの影響は顕著である。 +It's good because it provides easiness in composing an extension library, and actually +it makes an indispensable prominence of @ruby@. However, it's also a burden for @ruby@ +implementation. You can see the affects of it in many places. The affects to GC and +thread-processing is eminent. -h4. スレッド +h4. Thread -Rubyにはスレッドがある。さすがに最近はスレッドを知らない人はほとんどい -ないと思うのでスレッド自体に関する説明は省略する。以下はもう少し細かい -話だ。 +Ruby is equipped with thread. Assuming a very few people knowing none about thread these +days, I will omit an explanation about the thread itself. I will start a story in detail. +The thread level of @ruby@ belongs to the user level of origin. The characteristic of +this implementation is a very high portability in both specification and implementation. +Surprisingly a MS-DOS can run the thread. Furthermore, you can expect the same response +in any environment. Many people mention that this point is the best feature of @ruby@. -@ruby@のスレッドはオリジナルのユーザレベルスレッドである。この実装の -特徴は、仕様と実装、両方の移植性が非常に高いことである。なにしろDOS上で -さえスレッドが動き、どこでも同じ挙動で使えるのだ。この点を@ruby@の最大の -長所として挙げる人も多い。 +However, as a trade off for such an extremeness of portability, @ruby@ abandons the speed. +It's, say, probably the slowest of all user-level thread implementations in this world. +The trend of @ruby@ implementation may be seen here the most clearly. +h2. Technique to read source code -しかし@ruby@スレッドは凄まじい移植性を実現した反面で速度をおもいきり犠牲 -にしている。どのくらい遅いかというと、世の中に数あるユーザレベルスレッ -ドの実装の中でも一番遅いのではないか、というくらい遅い。これほど@ruby@の -実装の傾向を明確に表しているところもないだろう。 +Well. After an introduction of @ruby@, we are about to start reading source code. But wait. -h2. ソースコードを読む技術 +Any programmer has to read a source code somewhere, but I guess there are not many occasions +that someone teaches you the concrete ways how to read. Why? Is it because writing a program +naturally assumes reading a program? -さて。@ruby@の紹介も終わっていよいよソースコード読みに入ろうか、というと -ころだが、ちょっと待ってほしい。 +I don't think so. It's not easy to actually read a code written by other people. +In the same way as writing programs, there must be techniques and theories in reading programs. +And they are necessary. Therefore, before starting to ready @ruby@, I'd like to expand a general +summary of an approach you need to take in reading a source code. +h3. Principles -ソースコードを読む、というのはプログラマならば誰しもやらなければいけな -いことだが、その具体的な方法を教えてもらえることはあまりないのではない -だろうか。どうしてだろう。プログラムが書けるなら読むのも当然できるとい -うのだろうか。 +At first, I mention the principle. +h4. Decide a goal -しかし筆者には人の書いたプログラムを読むことがそんなに簡単なことだとは -思えない。プログラムを書くのと同じくらい、読むことにも技術や定石がある -はずだし、必要だと考える。そこで@ruby@を読んでいく前にもう少し一般的に、 -ソースコードを読むにはどういう考えかたをすればいいのか、整理することに -しよう。 -h3. 原則 - -まずは原則について触れる。 - -h4. 目的の決定 bq. -「ソースコードを読むための極意」は『目的をもって読む』ことです。 - - -これはRuby作者のまつもとさんの言だ。なるほど、この言葉には非常にうなず -けるものがある。「カーネルくらいは読んどかなきゃいかんかなあ」と思って -ソースコードを展開したり解説本を買ったりしてはみたものの、いったいどう -していいのかわからないまま放ってしまった、という経験のある人は多いので -はないだろうか。その一方で、「このツールのどこかにバグがある、とにかく -これを速攻で直して動かさないと納期に間に合わない」......というときには他 -人のプログラムだろうとなんだろうと瞬く間に直せてしまうこともあるのでは -ないだろうか。 - - -この二つのケースで違うのは、意識の持ちかたである。自分が何を知ろうと -しているのかわからなければ「わかる」ことはありえない。だからまず自分が -何を知りたいのか、それを明確に言葉にすることが全ての第一歩である。 - - -だがこれだけではもちろん「技術」たりえない。「技術」とは、意識すれば誰に -でもできるものでなければならないからだ。続いて、この第一歩から最終的に -目的を達成するところまで敷衍する方法について延べる。 +An important key to reading the source code is to set a concrete goal. -h4. 目的の具体化 -いま「@ruby@全部を理解する」を最終目標に決めたとしよう。これでも「目的を -決めた」とは言えそうだが、しかし実際にソースコードを読む役に立たないこ -とは明らかである。具体的な作業には何にもつながっていないからだ。従って -まずはこの曖昧な目標を具体的なところまで引きずり下ろさなければならない。 +This is a word by the author of Ruby, Matsumoto. Indeed, his word is very convincing for me. +When the motivation is a spontaneous idea "May be I should read a kernel, at least...", +you would get source code expanded or explanatory books ready on the desk. But not knowing +what to do, the studies are to be left untouched. Haven't you? On the other hand, when you +have in mind "I'm sure there is a bug somewhere in this tool. I need to quickly fix it and +make it work. Otherwise I will not be able to make the deadline...", you will probably be +able to fix the code in a blink, even if it's written by someone else. Haven't you? +The difference in these two cases is motivation you have. In order to know something, +you at least have to know what you want to know. Therefore, the first step of all is +to figure out what you want to know in explicit words. -どうすればいいだろうか。まず第一に、そのプログラムを書いた人間になった -つもりで考えてみることだ。そのときにはプログラムを作るときの知識が流用 -できる。例えば伝統的な「構造化」プログラムを読むとしたら、こちらも -構造化プログラムの手法に則って考えるようにする。即ち目的を徐々に徐々に分割 -していく。あるいはGUIプログラムのようにイベントループに入ってグルグル -するものならば、とりあえず適当にイベントループを眺めてからイベントハン -ドラの役割を調べてみる。あるいはMVC(Model View Controler)のMをまず調 -べてみる。 +However, of course this is not all needed to make it your own "technique". +Because "technique" needs to be a common method that anybody can make use of it by following it. +In the following section, I will explain how to bring the first step into the landing place +where you achieve the goal finally. +h4. Visualising the goal -第二に解析の手法を意識することだ。誰しも自分なりの解析方法というのはそ -れなりに持っていると思うが、それは経験と勘に頼って行われていることが多 -い。どうしたらうまくソースコードを読めるのか、そのこと自体を考え、意識 -することが非常に重要である。 +Now let us suppose that our final goal is set "Understand all about @ruby@". This is certainly +considered as "one set goal", but apparently it will not be useful for reading the source code +actually. It will not be a trigger of any concrete action. Therefore, your first job will be to +drag down the vague goal to the level of a concrete thing. +Then, what will the method be? Firstly, it's good if you pretend that you are the composer of +the program. You can utilize your knowledge in writing a program, in this case. For example, +when you are reading a traditional "structured" programming by somebody, you will analyze it +hiring the strategies of structured programming too. That is, you will divide the target into +pieces, little by little. For another example, suppose you are reading a GUI program that walks +around in an event loop, you can just start looking at the event loop before studying the roles +of the event handlers. In another case, you will look up what "M" is for in MVC (Model View Controller). -ではそのような手法にはどんなものがあるだろうか。それを次に説明する。 +Secondly, keep in mind the methods of analysis. Everybody might have certain analysis methods, +but they are often done based on experience and relying inspiration. It's crucially important +to give it to the notion how to read source code well. -h3. 解析の手法 +Well, what are such methods like? I will explain it in the next section. -ソースコードを読む手法は大雑把に言って静的な手法と動的な手法の二つに分 -類できる。静的な手法とはプログラムを動かさずソースコードを読んだり解析 -したりすること。動的な手法とはデバッガなどのツールを使って実際の動きを -見ることだ。 +h3. Analysis methods +The methods to read source code can be roughly divided into two; one is a static method and +the other is dynamic method. Static method is to read and analyze the source code without +running the program. Dynamic method is to watch the actual behavior using tools like a debugger. -プログラムを調査するときはまず動的な解析から始めたほうがよい。なぜなら -それは「事実」だからだ。静的な解析では現実にプログラムを動かしていない -のでその結果は多かれ少なかれ「予想」になってしまう。真実を知りたいのな -らばまず事実から始めるべきなのだ。 +It's better to start studying a program by dynamic analysis. That is because what you can see +there is the "fact". The results from static analysis, due to the fact of not running the program +actually, may well be "prediction" to a greater or lesser extent. If you want to know the truth, +you should start from watching the fact. +Of course, you don't know whether the results of dynamic analysis are the fact really. +The debugger could run with a bug, or the CPU may not be working properly due to overheat. +The conditions of your configuration could be wrong. However, the results of static analysis +should at least be closer to the fact than dynamic analysis. -もちろん動的な解析の結果が本当に事実であるかどうかはわからない。デバッガがバ -グっているかもしれないし、CPUが熱暴走しているかもしれない。自分が設定 -した条件が間違っているかもしれない。しかし少なくとも静的解析よりは動的 -な解析の結果のほうが事実に近いはずである。 +h3. Dynamic analysis -h3. 動的な解析 h4. 対象プログラムを使う これがなければ始まらない。そもそもそのプログラムがどういうものなのか、 From 7a0d359822cff7f7314707a6750ab95c236a85b9 Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Sun, 25 Aug 2013 10:37:01 +0900 Subject: [PATCH 018/121] Ignore vim/emacs buffer files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 37171ec..aa71241 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ _site rgh-*.epub +*# +*~ From c94299a7de5a8147259f1e979d425278a765782b Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Sun, 25 Aug 2013 10:37:20 +0900 Subject: [PATCH 019/121] Add images for Intro --- images/ch_abstract_build.jpg | Bin 0 -> 4733 bytes images/ch_abstract_ci.jpg | Bin 0 -> 6556 bytes images/ch_abstract_repo.jpg | Bin 0 -> 8826 bytes images/ch_abstract_syntree.jpg | Bin 0 -> 11207 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/ch_abstract_build.jpg create mode 100644 images/ch_abstract_ci.jpg create mode 100644 images/ch_abstract_repo.jpg create mode 100644 images/ch_abstract_syntree.jpg diff --git a/images/ch_abstract_build.jpg b/images/ch_abstract_build.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a9d7a6d47ac5cdc63e0f5ad3e1b86878e5c450b6 GIT binary patch literal 4733 zcmbtXc{r49+n=$^Iw@fcgF$Lgw!v5$dMpu=$XE)43WJ$Jnh?_yk!kQ)lB6sT+1Ihh zV;M_A#Mrk%7>WlK;j8z3JHBV>Iga-`zTZFRegCfWI?wYskNbCC*L^@gm<9-*Gcq*- z0KWnXgaQBu`v487sgH}NJJi!1>yC3FxMQHM!BAt1OHku$zIX!O4R_s-06mUz54`T? zuIq>O!MOw}96A^S7y`IBI5;`jxi~pFxw*Lx@gCvh<>BEKJuD<}1R^FW0TB}yhr*QP zq0(>}aq;5_1^B7cYHDhd@>;r@DmqH4YAWA?0J*ujd3kt6`1nLrq{O9E{?9mQ0)V&x zNkAAY5CmWW0a-!7gH`|-00gkG0)c@41v>{T8z+$E>!O|@0LTVpWnp3G;$~z0=JU;& zjhzE@Sn9M8>c~;)3yGY+twvFxQB$`;Yu7?!Pj8V?lq+ z_HT9+!22~m3y2j2&!=>%%698M15}lOEJ! z71IijC3_j7-<*Nf%;hmTvAHr?-OIsc)jeuUc{ZJ<>@l`Qv|~{NyuQ3HZrpUOFX7Mx zS}_6Czry#^jeP_U_+8oO?$Nf<5*JxA$Z)pGh?;EJTCqMJyW?BN<>VQJhGxWx0rmy;FqD;(G7qem19uE03~Xsp}-!CL*;=Ah*m;4-jGt1-$_GW5<8@ z$3LuEy#wB4M)W=}-^SDHENYrJ-d63*w)$(!*}N;7s35Xr2`}>|nzl06cM)xQO1YjS-}l&bFk2nubT4Jz2w^tSr#xHtS7F z2!evTu}=hQ*t5S$?T28~aI-)qHCXQ|j%HGFCFq5h@P^g;SaYc!yyHL#64V#_8`l9K z;c<`caLiV+R9^?z#}bBkU2EcK0l(+z>4` zL6xWChY8?hLZO#=do540f&=ZR>1J$QDs1`;dlCP2ukhJ{Qb>~wM)bzg!oV}gWt_d> z`ZaV?OAdd05N^D(HMaUmmEtv4ED0laNli~9{aoR@#R~UAN+sng{&8u1liy8UeH$Dy zc()TJZ^-EYN$z4izg_fL9)>d?j%&+~i=s)SFOYY)P;&pMpKl8h`Hyyf8j$>LYQHa| z68c}@#X@Ktf%buV0H`>wXz~}O|LFBZ&C@KW(_a)10IP?1tiOuU&+B*L>| z6D3&~(8Dwrji#qMuDM~Jy*3q}l&yj(z7u#_PCEef>6yS*SHPzx(i3%#<`3oBVLo#h z!mrvfc??Jk8Q8S@m5Xv%Rfi#ajS_tLV zp6`&|Y&F zCf{}!n?I`_$-bq2LlF^lUrKzs-Xi-P~OtmsQ z<5-#g*<=riMg@MQv6ts*XCa7TZ5lIC@_|6tnXT8QyRyb}tQ!y&6_D{c33 z=HcnqlV-g!S#vcEofe}>#^KQH!3w;nd5%KL>)@2&;M|UvORE=EgF~1EQbjFB&L#j-0iiIv0gngm@G*xL|=f)ANpv|hm5A089KrRRiYUxMpDkLy1RcAp5z zDOuk(S*i*0)8O;&P#J%lh{L%&qLlmZlXowi+ijF+vJ3E=EMk4;D=<10rY3nSl~U|5 zFWxEc(f3>5I?UT8yEjPX_X7Y78;0YHwdhvrzA?pJ5ODf&d+mqBB7zan{_dyn1~VBQZqU)G@&>yTUg zxnMSaDBm40k)lar2og)a_TWDvV>{~D`$j2cU-$s9{WE*s56^FQ+bh}Vuuk~{fR4$Z z=e?Fj-e;4hIlYVP0p2kY-gtPkD%dgJ>3B?}j{(c(B6{rRgk4HhsaYCoLaB0b%`a<2l3^4>1nw>6AanrpP9zr zp@e*)?!7_{w2uX$mN{mAQ2rl_mwTMn_ELE{33C!D)l@&^eWycAW1NBvg7leu?{2Oq zbE3n`+#@YwFZw9vSKX2MB123vDW$!ASTGP=U%fhh*}}oRn}ux4#M;2zSmw zk9dMihE$}dxxAVJ-_u!4HkKn)8u7Y#dIxJRC+Q znaK!4Fz>EfV?ECHuuerBRbH6FJ(W+nb_3psx17h{q^nZpi_tlH=mqNmn1@-cTeBaa zI%!S&GibNZV!2@L9GPg-X3L19S(3kH2A{pKxh=y!mhg5e%tp9}kEnnb#pz^}IicrfiWPIz6HNJg6jeAj`N2u) zV@&=DE41L>fZw}#=b`n==%*21=N#IMryTlX%G3Rd5bob0M2V=AVxA0*5UuUt)UG9sOp6k%gN9)_JzHO}kKa#`$d8uU~ zuWfdRLp-+=T*I?LAzgYJ$oGq;Rv|P1z$C#_Re`c%0bt{1cX_R?r)<5^CTZ`7q>ZYP zLBU%qi?zI!gdE{Gn%Jg;D9sdB8RNV<`dJM9QKGS5iiTU=T?_X*=Tfvod!z9C)`PxY zugzi!nc2CS^vIlX@R-l`as!_-jJx+lNNrSt|;)ub2P0?Z_h2Hl^@@b_D) zUe;cVkm1gNmiwyuYQ}yx#hp@{6-uBU>z<_ zg8c+1K*8Ma?zGSz^2?s`hW!$B2C8H--9)gabf2OgQV0!v2Tn zf6)7P)&1R0kHGiKAI@)!!&Qd2U!r&$$^3(pGbbNTp79vl{f&R)Z=cv-h>HOnRmq%1 zA5!FP+?J+XR4+3OpUKW@5LQcxsrvJrLzzQ3mrC-}rshlKx7wXGVE!`AUeuYYiB5Rf z-Z^gDWhU#!vpJbXsA6=Bs$0tWzgb-0U>+^#HQKdYT=Coz;$^)giNS0Ml8W=LI1)suY2%u zLt*Kt#DQ@leL%qYt-$MEW2CNigQk)PbUd-(W|F5lldt%bsYs`AmU%Wn5XeyQYbxd~#@7JHB>>#R-zU#7v?MM)sSB-5+FV1h~@b&zL@SZh!*QqiwYEf+Y_jxV?ucEkLJ+B7^y$Y)r? zEJBimVa*TK)-$al+M{j(aEL{(-V;u#^<*`X6z1X>a;z0 zompvH`0Pkr#2H}s*uF7_b9ji&DGu)D)#w87`gQmZ4R{ZGZ($< k9Ty1?m>Uk=SPRz1mNK5M?|&vgwj3SbTlvpc|6t^Q09N%56#xJL literal 0 HcmV?d00001 diff --git a/images/ch_abstract_ci.jpg b/images/ch_abstract_ci.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cec9498f55021540caf4725974c7e8d6e4cf209 GIT binary patch literal 6556 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 NGNu0q4gO@}zW{Rj(PjVu literal 0 HcmV?d00001 diff --git a/images/ch_abstract_repo.jpg b/images/ch_abstract_repo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..af55ec8507e6a53390e1dbdff895cce116acd006 GIT binary patch literal 8826 zcmb7pXH=8T)^>nE=tzw8DghFjQlz&~6A*|= z5Q+o@L_k5L>&Nq)_MEfM_pbMyU$bUr?S0>~XJ6Mfdw$RUUItv!(L!kfNG=)=2@e49 z`xii(2jyYw+k5mV;91st#8bu?d;{}?`QAp;_c4^b8rlFv3FGR_Vn@NJ+^lXn+(n7b`9%fBwakVV2|A>Dl!U2yBu-`l43oVdCB-V0a!HYZ80j_aMvgHi--ii9FJZ3x$5&N zZD0Vxri(wYu&GAJ2$8 z7BR4%7&HQ!TbFC~sI*+S^k^W~HX1c5rAK0XL#J3~4(i`;(|@2RuOBeod~uN3bM(Hj zVIseE;1-fVv3l&J$U)>SZ*`@VrW{{rsp@+>w22uG;$;7xcRvmqOjOzsPOGlcDWJYq zyl_dNjm2@@V^n%B6T#zYsGWKW6RDO7_iCB56_O_~GiMH2>clKhWlpX090GZ*+86z= ze9%Mgj_Td{`s|6sa-xDLw%XiDc2Ew$ab}P-i75Fm0k{{Q!$1>2mssV3Jm-sNh@^epGSg{$x1}N1AD2 zqgI1G5g;I#68A!0XzGRMqi-)@Fmh{t#uQ)KFKC0do)#UKLbn1gzPP*9Wh)2K;sm{LXs{*U&`P1$45QVG zH=;`5;D{_wlBv-4tw~Y3^$Fn;(5&LAE_CmMM6i!0zqqugHY;$~F!vz`q2RQ4+R$0Ka?TDIPXjHn;3wFr=UAq3@w|(ocI+XgK=Apd zr9S(JJK5YCmV~#u)4>DlYhM{z`jVPCLK(mee&29)Et^MKaUv?b$J=mx`ijU0GaArd z1I&pF!p)MSKTq!`$$tNHV>Yz7$}i)tTL)U+}zDh(G0B zC)GJ0%1}8+lzM&u7C0V`@z!cTTlX$frjp{^bbA-mDA4chVfm>v@9D~; zdWhhT6z2)AU%I5vjA?)JYOkoK!5&}GKHC2*-{nyIu*)Z>c)_sRmt%CwG`S^WLRnwR zRqjN_^Ul6c{`&E21m6Z%3fZrBcOHkiojA)@krmHe_ixYr5;^-Dz>8qLE6^fmJrXUf zJ@RCPyB>=6J}a1;`wb``?NI#wJ*LzcVnfRd<^yQH$X(=iw;Zm*<-O6V2|k3(7~g!OoCSJxtM6WP(V<;2O9Pv3kR zJJj)o@{Qi~wFIr4HwL4%pAt4k3g&`~lPe>hWmm8J_EwI#Y3DWTV&5!yz_~{d-*WK* z7Mf>f^qeXqfc>z&eu|M9b;d6Pw9BB`RGG3Z~qD}{^h2^ zrL-u;{VM!Fahc*jp!(L*4XcK}eIF*PEZ<E zX7=&ag*`U*Ort@9ya8Fz~m! zYZWsrqRl%_7*NM@lSwc+?_`0EjrGtWi(0=^;adg^h{qJuUiFQWja>mLN@HKew^N}_ZLbl%b!!gvOVbOeTk zX;Jn=F0bg`Y<(apEt)PrXF0dgjinr|T6I=YGI{mp1X_`(`6I#O{qob95Z+bZ&Ww~W z944a4LDc4X3+OQ$-2+iecX=;YV}a8f&jK@e>s!+XP`COh^hx7nS)hlwlGZQh>MnHy z%?fxOGh1F=-46oY0|OkuDAJI9TQA@8yg)=hH z^u?dRrq|I~R(dlOQG$wH{8>yYXP&2A#-*AOLJt$O?+|5rTG3`{wgrrY9~!aKm{1XA z*U5H9Kxq{s_N;C5(MaTQ=`nPf{+B;f`X8i)NNKX(k=aW7X?18UKR3wcp-h$TIYqwK|I-!}#Y zFe!=*I_6TQY3B|iqMWMVmcxBszT@KC!WBk1W&3o92es734y&Q`S{AVk8mSm!q_=6~ zG{6CRc~CH{t?9%&Y<&bHo+&;F)`@U>hJdg7JPW}MS#RI(K6bNeAGdR4-#;pWk5I#^Y~1%&=oyKlPm#~L#%1|WOA zs3giGt`$t+vv$dH_gkLsg?cgApt?6MWh8L(E4w=3pbIJS#|gVgh1D@bgBf$zS!C{` zhT58=cRy1|V+kSc!4CZX=El;x8*$?bZp z?R<(psXhB`nh4Vr_h~6-dd)!vk~;vT9A~x0@Lkj?*zX5#;nRv=Mpqu+0BH~Q<#0mep_$AHqk14d2)c~E|91f!!Ea|!>UMrhY1FLuhnpYtmyo*cwEaq1$oVZq)t_r< z_ZCA{U^lNrm}5w}Qy40_6o2$* zQ>`95(4R*zJpb&PEuNp8%YKjlJy);9)=+@L64E_2>~cy7i8e<23HeNR{MU0`pB4ht zVlf|bay5;y(fqa!XE(N<14E7E!_bH9A|&LRP&3I@V#ASBMv-q=dk*-9JrGth?4~Os zj8P zvFi_bVIR@H94)UMhFrir2wIP)9tSg|O-l)WX5^E4QLf-r5 zNpq;{4y7@5edkKS@*~rUCxkio;Ma6R@j(t9e>eC0OI)!I$mD7L#TQP}vIX~zmz^bx zSBZMExaM)FW!`t=Zu<$z15u68DQ2{Y^aB%R&w4~$@|mJP-&quS(!WR)0%2P;Dwh}d zE&<8t%U}~)a+$J+8!Fj$Ehk;qPL*QaHYWWI@R*n=6Eq{Vi;_^;@WyVa<(XsCF=Qcf zLS#+24}_iZuim+-G82{vb8{g(iA59QYS+xYCY)5)kO=H)hh>n2JEbe+Ic1)r z&8!{u5*R7S(D@;5^RDgaO^ zUeptGMHdXK*d#UsTtBgjn~DXiyXnknc}E^l52A%{A%Ql9)GRmx!ES-r700dL?ByV# z28pX`TDfmy;{iv@aRj}0hJ8j(2cAyHHSWyxr^jibYvsYJPCokiK=I^-&NHnHx>dPJB`4zC~ zVa9}YSw0}za^VK8uv9clI$=$8HA80OTmD0iAnpjASC6DF?grJskHbCpM5jb2R4p2s z>3C&X57O}f*fp4hwBvoykU%kJ{rTode^bqgDv!kaEIN4+!uI7)*n59h>h*_&sgUi( zd#Y-D)sh3T;Ea|ixKO7z=GKrle0?CECc&eYvuJUcl5wo(p4O$ghl(h{<_q9lO-n=M zXBSNoV~s3cL>_p?HtB7Jty}Uto1+yx<|ow*wQW=U^2V$s9pkvp#lDT1^Xu9+Sd&;+ zc2mb2X|K`sI1OP+Kb7q^-q~YIE&sqZT<@SA-RW@v4Nr%E%@dSc;}Hh6lb^AOd!*cn zqKckP>?UP*sfjG%>qMK5)U^v5nODbI*gkbfy12*@bn_MM59uFO(n#Bjb61QxHnb#& zU9(dQf*s!K_kFkl-~EX)?HdLTX;}D2uDH0UM29LR*jiyJm!Ij&vg{)KC!HPf4RdOj z!ocZx8-M}{V&_k}At8Uux}YM!cmX6%$Rr3DtWhx5YdmPIu>XRaGzdK!v%W8)`7V@d zh(&Dz^J$MU{=Q!=pb1gk<5Y#Cqooh3Cz=(HB?KRHv!7gGd;PV~ z8oNZ|V=J;vrjoOP{IiE%Te#4xQ*W{_ze#>_?$3ZX&)UBl^!@vr>hK>4hQA#2e<{lx zj4A)iH01|Qy^4_Y$HPrShRxn}9^oLdqQ&5o)c#=lL^I^TT-AVVV0ih1w`x zTl7F{>&5c~pA<5%-n1T1*{q=zY5dd5tIhk&(^;Yf&j3{$T6%DL5;(P!%Ly7Yw?*o(D#5#epU;c}mq^UJE#?LC zy6_Er##FGGnC~)eC5~t+o8x55*gV`{rDO3Bj%`(?xbL{!@~^HPU5=%t&D1wtDATyq zE@gc6k?S+8hFnMX0u@5D47H!VoxEXQqJhdRo~*W%e)@WojKg@)GPJ^>2Wy>nCzYy_dX5v$=*$Swp6RUbG@3 z!v4Qi>4v{NU(KYE7KZEWHUd*dSs8P`R?zI}JXC?3k@aEb2A!YS*7nr*P;Y3t^IYMm z&~Co955*d^<)~bf~~9)2T-f{0nP7pDzcR zKTOYyK!pCMMKUQ?_(}a%WWR^JUgpl_u|O43?Nhwui5u6%8-(KVHm-JZ&L@}MtEG{U z>zj#dPJ2dHz8B*OqC$R6PXe5bkS_q;qB=xp$i|$mXAu?itEH=lAgphSnAx4G$^xJp z<(x$ZzfSrTqxYwfM`95L$Qz<%2{XAy4KX1mrt)uB?pQOaI0caB7n{y{c`@-2vW*J2 zHG@PI3liK&)W70d|0(nSrUm~(m4DmEiVl}n>q5smOFmDZ;^sKI@`in(eYMFb=ouY3 zkCU0pBCAikE{RggUK*DxXzMqi*l&wcc^@Ih)K-JUKK0`YoK~_bvYZ#6d2IB2`tH{> zLPyw!s$3TAt6^Pbk18Pu(6JxFFc4hrKpKnZl;n5`NUU?|Je6nOr!I^)jeEM-q_r2-*lIw(~0)@8N!gMgY?JG6E zLKvT{sp1jZ!z{DnXXGH}Oxx0@t+0>qMZ$RYlX}y8O`x0A-0jRk!)s`|nt=p!E5e3_ ztB%(FSW{L6mklFEycc+cofKOf9!YSdZ^)8vxsJz3ZiTQhj2geV_A5@vo-y?5ykC>R zjc3RZN^gD#9vBa9hn2=mXeWHBFT(nrDLZ}cTn4IR#3{c7>EXG$2R8BvPYWy3r=U{W zfP0?2LC<+ei0N;FGg**^69SeZAqLT<%%|I66>P*C z71x1&@Q)x%!Iteq0m5jP7?2G#newrxO0vS9*et!WacVAv+x_{Z?2-!Yc2~p-SN$OB zbRM_|XLLBVuWrdSIO~yLHGkjVVs(H{csNh~jnn zuiG?8SHX;B%OryTd9?_4OGJU(R!D@qhnz?FiQf*t)1f)yH(*WmIL4U3aFqF+(ZaND zq!etf@|{Ci#RkId+(Kp`$qO#&@m&{H!dosHl|+1&!CpQfL6qtkrbprdfKIaRKhrzn zM&S7OH3Q?BN&a`5tI6h;HrEfEKaW-}AMGhp;^O%02tIzwv z`rCHUF4OUdB~DU2?2AQ+0+!Q5@5O_7BN7n789L_ZG*_1EGMNc0n)iZ>%H8NEjb}Fr zqDaH)H1i2{vX093lAlV?CeGzHP+Th4tL2L}k%2Z`Zgc@P^+OobN?#z6I_@*8cv`^K z1^~AsFl&2Q$-|Q3u+O2`?xv%E`cf*2vj&lvf#Yecbbp<}_^#4>U(&j%$sxalJ*9{_ z<$B#RFpOfqm!ezU)1r#Lbeud&c7i%Pp3;Rz>E|k~pmOkzv*gC>yEiU>ZLKh75^b-K z(JZ~15Z+6cevmJ_NV0CHisEs|p_AHpp%-@MB62VrKrVLU*uE#!A9CG&UreS??9k*E zYb*-hXfc7Mp!A zyDRF}*dn4Q-NtV+)YgR{2Ljq(#lR*TRDDG+k?j94 zdOU=A|8Lc=>oB=^3K+}LSP+EvU;IH18u`hF?Vb(A%TLC^&6!g05CiI<;H{99VN-P#Uwn7)`*5>^?FKuwA7m%0zz#@;( zcgHS>@IvB?D7wgE@YEt2Aen=MNp3SOCMZQ^7Fd0rf+xcwy$`+e=tr==`h)me9hV2-Vc)H z9Kf~ymv^*(`ura|DqP3f$6U>>+ek0zRy>RAY)WPVd98^Gr>?$EMgfO6;Np>`(1oPj zyygb`ZT=`rvokjQ_0OvVNRDf-c#ac;*84EOBCfZ4K=g9yT8-BZKed_pi<9dMdIJ(g z?zfeo6jQuIdV$+Y<+D>Bx)#?z_gJDR6sq1i^CE0{t$|5HTvE)eT>hK`ea;fMAEDh} z-2gst!x9yzVz&asdV{L#Dr66Ioq>Dwi0@qxHg?C})~fdACzAZ>a(P#EsU5p8+Hf>5 z@D#>paRW$$A4Hqqexjd%IWwIXZ3=rJ44OlILk}E|nKhgmT#3$8d*=$Xp3JZ00xb>T zMhNwFG+L#;lX61p$Y^M#u8T!DwERiDj-j_Vb&OItE~9K$vO4f^=XS9;7ini8`x99c zONYcAKF-)K&Lnzj1V^OCS<$BUC8pj_&3vrCzD_1{*HB3@2fk}lm@drCuU|sNpUBkJ zVe*NoAI zn7Ikg0)%nDNPZ+CE5+1&u|faq0Mkw^MwHxb>Db>vrTV39>Z#jS?ZTo{7N_vOp-Jli zr#yQp?ohaAHpRqNBZR+sAKxneGo`Al=ykUwv7Q$`8b^VV@OO=VyeU?sh?P`$HR|Q` zwz1%uvzVyKXinkN75BlAJ9iE3d#4kR9F888tEfy#TWq)IhK>(rzVo{zCW_6y$rF{{ zQXNm=4`H4A9JtN5=na#}OhDDu?HT(t>EC|7Xez#3OD`U|3`pG}gRrjOu*fQ@XotH# z(&(j+uLcw0PrttkA()Wn!Q~DZpFK!jjL>y%xH{?KdDY6|9qa9v*X9CxIVxNav8dB> zacosbPF#-X)PAjXQ=4&UD|e5!qckNk1WBm_dX<-!d}%SVNCcgkqrj$hY2GG~EKFr6 zLgMGkVP++^uE+G5(~}f)btkh#Wy>*x@$sz7njiUO-@cHa5=bHHm$_nJr8Y6H=Z)Fa z5py1myC$%mI<&U?MVFMI0_O#EJ)Yl>6+Nj`e%_On z<%6RSS0ys8Lx%;9}UvK1s5_*k6DG1GudZo^uH)3oaoJ|FO=myGn0T z15%|+uhK!}$8+92{~hO@d+xjU8yP!$&9%qgbIrBp{N`NiY~*Yj1ih)Mp$Z~62aEs) z0-gN?iNiFUt?X=JcD63I9#)>VHn97?Ff|=xm>SX*<%zQPuy^x>@!HsW+gsbpxw$xd zSovHfKN|-rgCHa%q$I=;Qc_YfG6*>(9Tg=71trski!^j>%pB}&%&e?1PC*{n6#+Oa zE3d>=f$Kt|qM{r;QgV{QvVtO_!oOZZKt@JJNkPd-Ma3w5nf0>pe~hzFAX*3k1Hlpz z0WFA-mVk(s;H(+M3L*dz5}l6{^aqGZ2#LT1q>%I88&D7d5fLGnh?s4e>b>6Hxb$7V9XMLckv=wic5qBo4J8&FxLjs5tU^S99b^V@&_ z%r7bJKYjCmq+=jTqH}#{iD*Fzpp#?5{}adqlF{pVE3aM+U~;ioo}`63W6=+Smy4YQ zz$kS&3w0#ChU#s9xd*lMSIaz}q-a{~!|4Zs%&i~=Pv$AB!Tsn(({k2Cl1h|{ueAlo z61TN-a-h1~E^sw>k5i&pPWJitzKLasvnA!>TtwOv+R`L{NvB7?5bi$ce+Of+w|n&3 zmG(6ncPWQoq|%jMpXoOgsxy>iZ^m3_Z#e>Nva@q5`IryHU##$mtoCx5yM018J*Ul74{r-d8dkcBhS-okC4P;OiBm4zBd&V$nHyLbsp;D?lsA znnKya;-Qs`?cW|(HtmXY35S~Up~h47%oec+AyQxZ(^Q&cy@@gv#2UPLt@9P}rI zkYUg~9?FzSTj4kY`5arYS9p-=6(_y#%9K&l3pHBM1EN{)d7FzhkX2dwq4MuvZk4Bz zzc8cp@>pY@?UTIDtorqM53mL3Jy0(_%M(AfwQMq4H}^Ou?Xa{yRBQ?pzOEavM*uE> ztPYKsE`Gv3KJ`KO z3I(e-&641iE6j{{<&2Z9MKbSoz0O5Fd~lDgmnMQn9DH#%-qYuqjhAR?h2PDjsu!Ft zFsU3bu#3VxY*^z#R%R;Rutc@KIq{O#0iik(=Ow64)8iZLhNgLWE7~^%;!7@Fx?mUk z33pwCctqxLBl*wrJP9k3=xlc}6X0iF=^2Pdm1gHoKvj6~2iwU|;u>*r$+1>Zu|h_W zCjp5%71;t(T0_Er%3=fN~krx-mEQ6vGDWRT9<}(E~H)1;KYc!;`Dq0 z`xALJsq!I@@*dPg2W#WNB5PbJu!2?rJA36$6~L2*jaxe1{8=t0f!x4$-f7JlF;QWX zNsR}xWgv@<+`$CiQit})*aJvxw-)j(_6|pPGN?yYwa*>Hpqr52q^xNms6Dd+LSX! z8t9$pEUFLRDMsXcAZ82G9{fxzpN7Zh2PljPJ! z)d4L(nnIfJ&paMk>tohcR_LEBJ5K2$r7*D& zolNGekbCv5P|vnNx!0Z!&6}b;SeHz=*4(}RKGAyw{ou~Oq6SF%tTavOx55@(?yJ=_ zXCSSgupe7<;Y_QQH`wTX9Q*{BMh#dRS{Ex)HylY{MliB}P?xK+%v*O?Ls*1K+PEPT zpCpLlKpiZUI8Y~5nOE$W*2UJ2B<76^+@bwxFP5f-C00VDBO{irJWJfSsOu;~P&Wao1LVLs?os4(t$k6&1IAPx_sd<^XLxiWoU~KV`p;+5 zVWm~CU)SIVyOB#=_%l`uSjwYz@g@P&@>2t6)jaE50Nc(2+V@v>^1nf>wEeKCe&QQG*~9wctgHmfOH~y{1@}};v-eVe z^%Mbd7~Vd+#B91!uca$Dv6e6ZM5mz&if776b%f_*%5r&g2aYonUOa zuyRP8jCmtXf>6i~l2_^)vtPkCgj+XfRGyWS!JvB;9!t$CmhDn4)h@G{0$YEVQ*G4O zf1`a_Dz<~QB)omi7E4X=fo%ty3*owY)JlRHYwe1LMm1N;KM4xf*JU#jjMR}Q8V=sD zKLv!$N01wF8(8xl~*t^x0oI zc?Jz>zf252O6ytirhbHbak8ONUYGteSYi6{HO1QE_1GwXR@PxkG&KMbR{S%72!G9o zA;GRmGBDCI98oYlulELPB}<6&pobA-Ixogu4uhDb+VFvAQ8$DC4d^LaW@`>mi8}Tj z7~P1i2^VK3x_hUs-XgT)*{X{HUCQ#)&vh7 zLxN!Q>`!2Oe_C{4`Byn_-&Tk{PZMOy4k)&k9ckE>U}8G5v18moGb9AhRGM1nCJCF7 zsxG|%+Oa0C(FE>--t$hDFNY#YAcA)XDUmr$#3yEL`>Aa4f!|yc23D&&eK@woN))E(20I0oLOB1{VuT?x@sCFM zHjejeZ}trea?Bz11F z#f#PMGB_VDQomoZj|$a5uXO>CbxOF(e0yImqr6)N3amf_5)D>G)*fRA8@uA^`k4^V zdtM$5zMM<=v2lO3(GSD0L82I_+UuEHKf1KxiJi?Y2ra#SOq;@?-%slBr;tiQNCLh7 zw|OEkS?>J0O|Mhq8_xep)GRg($D=LNmSpXrxF^Y;C#jlW-;NiMzOr?H{d3xjX!wcN z3y65%>N8svPfz--FQ%)nBqJ%F%NE&xxBh;6XNmPD*-Fi0|Lo-Smz)+O6FoL+)Gn&R zH22YP9ppI4^W1Nyg)#UljI@Qj`Wa}$cj64xNH+hwv7u&hsv}~y65Kn^VL8EJU05cj z(|0VDv{&X#FA}qIzN26-99VaVwo&c|GCymFSvdX_}qN@vB z&llJtvdk^880DXx>lrocM2Y+yC+R~4zUSkP+z2UZc)cXLCo-xv+@UWtm;WYdTU+nv zhJQ`ma-Sy%mefeC8DA2%2_UE%6Zn!%RXOMiXYJ2GC#!?7!jToe-SyL&J2Qq{+ML@p z=GsO*v%ZdxB-tPBBtu|(h}9}y#2+*acdhKyR&WaRvSSH{VtKP%>EhJq!dhDo++_&P zKqcfq%pUFKgYpN5cKQuJdXFLSNn;J)1iG8%ebUJs9|h`pJ|3-z{^k}Ka`Um!tl$|) zU{S${nQP!c6C}obYf;KtLi`P8Bbkgej(zO|d>%mTK)82Lf2Ql{Nk7cSkr!ZjmDjIfCFC|7 zZ}(}Y%mslq^i=vM**w!E#+NbANl~{C+=}N|Jlag6Eni}vWF!Cv`{;gREOzDV>k5l} z2gX3k!l=2G4pykS(m&QRc>v|5DdZ4JOETYyR+!nFJ#B~o;d$ou(pmudeb$2lO-M){ z`W4+$R4DN<0Qxm`-x;N*CM(t(e7Hkg^dKNj7ESTk=5IavpF8Q9?I=vjj+bo5WQHgW zKh5wm!7ryS-!{KZDMqjl{ZZ((NZk9Q^8ys#I@@<>?39M`$7E-@5ZXC7# z8fRiOVKc@O$h%;4Gmuf5#xO|cIctq~_nlSDapVui@j|Wpy!qKa7kM*!e6@Wh-DRr3 zwu77qDWw0HYwwI}cxIfO(UtDvyF$o0OjA0SpHYA*Xslsq6z z=3^4j0bKthR)w^Qy|Z@=Lcqba#em+=3socY0m(NP+1O;Bx|e@ZwS5KN`!*e}GW7sA z)fwXY(J`Z+sdyyi$6T@?E-c{CR|?19m~Oi!upo~%oc5u?!q{M8GO5J zxN3CWdR?E!Z2`|3zrjxCI}(Q&T=(VAaqa70;k`Z=&p>k-0H-3HG>hD_EcH?zlTDl> zeW#LhwA|I#Qi8ei+TI&>CokvGD}UG_2wj@LNuN~|r#s3?RXhCfb4z9;E`@`&ht&Ge zjK+imre~`9$@Mw&iZ#y6-a67w89rh*YDOTy=`>B&N^w$=?nHVa z*(J{yux@=8mrN2q%5iUkBR3W=fPjWq0`a2IL5q!+cl8q~TyIc1=8PO*fgczazm&8k z0d>e_FYYw#sRk|9$H2n=ZckPr#&%0%ab-XprPCY;wa5E~Y39m*^$0CX>=Y0$O5z|R z%_)xCR^7orWVzF4Bj?1IP?|s}QL9j^tt(#3I zf>|HRKROMG1iuey9%DqsQqZ9Ks;7J>gJ7i@=fS9Or50gqXurwuh+%R)=R{yM8|Sym}5Tgm_g-Vet8t{e^P^q0g7AQqfI z?6qmb7m59qt6@%qf+z%SY+3K&T?4hmTcvox4XEX>`8L_(PQxv?SB*b#=KB6jFee}0 z2&~ct1?bmivQ@y{LcCuN3Qgs6T~J)njN(5MD>GpIKqgynrn>Gn5?w%+^UrMYukKlg znU@d=W68&fVSx6R;c7 zG=@aB?-BYpmH>`c$F#kR2ADV3BkXOm@dLxkhL^KrYWTuSiG+V%lB%VBFUdj61RRqy znaTBMn4ZcL7({=-L=hO3ooTo&(*b&eDdk{I2XXnz=Z!b?#Y zT*#^(Krbfi2C!I1iiZhd7^#qqAQ~9d>6Ze4>7X}rHQ(&V+t04l<3&P37sI66OXDch zQpYxH0?7b8a;V~EIfB1M*}lMm%S)kp5IXuo1h^Jaxh+bx+pwfWHu$e>^M{SHrOo-^6j0uoayT5zy<_ z@W{4#-$7+8TG(}`jkI{~Gi@ZSE9-t<=CZ zyh&RjNqNaF@nu=V5^wxg#H)J`uJ@7jGBWPS=gE%)x5rk!Kwb`jrn;Js6^EGGhX!76(5k9x$TouHEYXXjGFKe z39d3nB6huNB$s)wTD^LWv5Hmt)LOX&^<)SqgtW`W7`m8w2TF)mcJq)Trg!)eLWfpw zT_*)xRW-3#4%(4LDFVB4i)B~w8pn9blun1F=GfZTZJ)j6BG&Z0e@h{XR%G^!=~WO} zy_8;;YNqEXIC&Dm*0aeLuAhWSq^n{`J&06lmBz26mJeelH*$S$nUpC!Ia1?jVhIRQ z`}~}NiT5gZNGw8t<{9I(=e^3^M)LYQ81Z}#xBl8V)dL_~1DDJqDIQ&XX3 z^}1j!$ut6z5R?H4qnYI{n+LFOzi~ksC2sCJ)4fCEuIZ9dKR>RTJ_55*@4IGeDJjf! z`MdXbKMS3jmpJW1Y36Q9Bbif0%;lU#Bm&cBq+;K>J{PVPjG6?R%Z|MOtK!L}&Hbv? zrIeqf7uwq34{e^VOQP7PYNov}gCl=MC-U-zQ@8wD1>NNerIQfm;h~`(ip)&w8h3*2 zcGdLoa2seTTO``j~voM#r6&;PEjOC&N zXL`EQ>VCpjT)zNXJkk1|g`ds(b0)m{QT~0Ls#x^--iz3~Sx{^hY1JN3mXWs%LL7Y6 zwRzBIXd+%fvTx0E&lkyVabI~4aQWpeynNDP=sCBK4p##VjE6Neh@!vd=DJ5^_+5I+ zw&Ov;S}D!TKa+`jEk2}uDp@)!a}i&uJlsLjS<}v&b-_p>w8)1-5uC^YBbnb@o)3}a ziF{3>O&Nugz?64OfnfzY{mA{78Up4j0ok~#W7161O-Y+CqIz9BvO9?D35dCS^|jr; zTza+_ctgJ=!P>s^=^bWfrVx=Z|LR5dhZtC;{~nLDdf)=PllE+EN<(wQf~q$}IQLEN z8!Io-ZLK~xEmvyLDb&%qHFQ>Q`o)&_`|2&8MZNTkUfZ+(NQL}k(Ay|Ut*2i~9xz5hmOCIk64cShcW%lhX1`jvr@2Hsm<*SR7_m_H|Z{zq_R@eyI&%i&pT0n?64N6%5ea}X` zHh4GAu!B-7s__n6JCc-<$0-8`=nvSKI9M9{L_g$udw$CI=rY)<2#$~H<+#Bxe@+U7 z=-jo_i8ox%)l);2U-_mV9(`VBepDEnyMk6ax~ryb?qsv4cVpX#Re9b~owZtGVizcx zlf7<Fu9aD(R7RBl~(?Vd9cEfCa&hOLs{pUdu-|~{x_gil-vjXf-T=xJf zKcBjj8w0z=hpF0ZmQERgUp$(X_dL@}DDD%Iv%ky`8*|xH>Y+8)@P8ZN>efryXf5EP zaDCyFoGih>g3Yz4ido09v3!mC$(Gc1Bg7TdF~ceGbUekjo#7!r?1Pae0%2F%t<_qh zaU?bCn5KR?skMi(=TQVhq-tRPUD18hEH7;}v69Y_c7notu4=3<1Kw;tKzF{b$nB*S z?=z6zEhD3g^R4*$+~vfwKt1zcyk>lwt;{*uv)OoE!3@Tt`a)-MQ9pv0dt8l}hTl5u$1=$>!5cq@0__ zuz0`#|FL`6?}N816o*TPXZl~B^;z40!tl4mP4}Q@({7k-T(2#a-}q{>)X2b$bNr&9 z) zF86?6n6@^hZUX*xYnwM#JW={WLzq#J1dN8_)6^5913feQh3qQ4iiysl11vtXzq65j zxNH}80FkCJGjCKxd~a=sZ%Wh#qQ{O`F|)j8%4R}|>T~^Xkzae{g1&-v;wy$VjLq}j zL6cl0*cnQaQj%|aFQNs0BDzvn*1Q2bML@Hv>j%dhuDY(7;;+^2!x{(n4$P9K{B=nS zGf(yr_Hud_W7E?RSV-R!_KYDzLt-}3axvjHN?Oqm8k}y9xBII((}IZ&wMs03!2F@o z=ELQ?G&N?~v2}v;c25Ul{Fqn?*bdF6L@)iylo++?P>qMS_X1q)9mh7X;CoN#*|=`6 zvZ-x3cPjB+Wq#BhzxeauraUYA=Dj8h=`|W9^lT8C#lV44^t9^c?Ul%m)Xwbe=;L_d zGz{_#6xTXWgmLiDPQcEEmWD_g;%8^ymUgb@&WauXQ0lIOH0yzICJ+8QyWl@NU}FwaJTPQ zV4tItDX1!jmF==@>1%N0Hy;EDDSi49Z9)ArPrC27^bOKUo-=lZ&*24M*?Lb&i)fJ` zPWsLzeEZyB(j5w5&y`G3-17cH7~9>Otp@?#-r=VrmtEIFvWByfNEfQ=FN4OGMNwek zlKPpAXL2{3LBc|(85~9o=NU1hHl;E215>t5top!k@j7u4>3xWt5_z0w`D{Z)d~F*W zM9GR&SwBj0|9mm8jp(jXww;iPGD|#xAHx$u$VXKYoN-S0YcL^J9-Ma3! z1L1d;F2Z{_zs4Te*D2uaY$UjA$YY_GtFK`gs%(POKsTu?YwrxjvE0Y+e__MajTWTH zDL=I4$Oqza9Zr=~-vVvB541JfFKEaah6}|?#{Q_F6c@ih-OVAaXBP9DA^(eu>eM^W znn%5It#6)oM^o8oF$KKip|V!e5|$5_&g9Y%A+Om#g~ea<2z!uv?n- zYSmT&p65)f^|3)PzD~iouXVAnlgL%{GZR+ly(pi}etxCc%2bC8^^iD;U3A^h64h2pk}^sV={-WK2na+LrJQW02wMXH&5F1z*WyvG_V*K<3J=u%3_g2k z3n@I=Fx_*-Q55_u@BBMCP11?`hc9Mj&SGpO8l!Gix7t|mY^cXkZKtuiri4YE@8F#9 zRjg1vN{T;Dz%jbe8&l``H+8*!Uc0F|B9j4P3nC(dTtoiam4Lsi=wxY0D2SY6N!Nsv zJtlehGOFqP7Yss6v_s^LGvtblro>)}C%mCd;8qsUF7&71%8w66xZ58Jx29BX`+5TV zHorpKe+G7`hC;4p5Q&CdjIpDacZBW0)s=VN;kO3LyQ3Do<@!mjpMmYdC7A#*$B$;$ z+!M!&JiQ8$UGK87z4jGrI;|Kbm@*W`)A`+>-pg#mQ2k~6POrt6MGz1(-1c;$V3 zA0*aK@$S*HCF-f5a#G{e+;U1kgBx<)w#+0On3!4v_3j{;TU-1JL_Omh$}?;Rj8vC+ zh|WM^Tda@n!BT&({r>M)pvAk!z|`4Tf^XT^b8zii>`2EE!9-jTsfQAIy?E-|p{go} z*7i=d!~8X?c@-AF5P5~XGtl(_#B#_GaS0BModTh;IC7+Fqog$@@)(5X+s=OLllXKo z%So(oQhLm=BM);_p*np^t(F9|*wtD%nd)w>UsKwm#y0izly4V_?Y|t} zYT3vf()Dyn9>23iRFLJ`+&1UpC@iej43S47&RyU?0-yBLbVo-yIorpP3GB`TnW^cW z2q(p3_l}n6cBpxbyS9a?XKpq|@u#)LGD^~M1T+%n<;LSO0*s-H-{qwn=J507Z;g#3 zPn2R$#|7>P9S4~Ovg+yf4Yl2M&3*gq7}Y##n$81K`;oDv2p9xsEv~B;X~=4oj^D>J zq}Ot8xci5{qjcghK#!pX=TP|>i&}^c9F7FVnV9kgC!NM{@M#B*=j9wzPKGS`0EYWd z`gQNWt}C@)7aQEua$9X`Wr7_sPHv&c{vwS0oe2HvjtWOPi|FPde_^>OM&URrz$17M z`S>uSA|s?mLr-wfK*h1(McH?$-h}I)q1JAUUBN3#WEE-LXuw6)&F=}+Z=gD1o!+nD z@kG{hQR`WEdq=gQW|{)(ar%qvHIK%X&Oq4Y1YXM>N6;B)6pSV$j~5B89Sil;9Zhs} zGH9NwxJ#5WT;{jc-grKC!Xq8Q0He6k+`Mlw$M$3UB;|*rqqAM=^5MCj7d_YGpKn+A zgm*F%O^^_!M)k-e`6l}&c<@_hOmzolV}9ymvY6mr1z4->Db!r=KO`<-(qxoDLtvyj7pDJfzT4Os8O;vN=M03RxmD$)wuJT~ z#kwImV?a!t`+!EEve&nbWNGEkc<<3>yiqi|CNum~>m%NgORewHs zJZQDHu)Y{lLP4TLP0_M3Zk6d}+fyWs1U_ApsoQrnlR!n^BjAO-^)w#tnjSpxv%kv3 z>Jm8&2=)eJ4`0Q2#~u=Kc-4Aw5tsjpVgCuhh)vD$YrTFcQ!8 z_rUv!ix{uG4vlGGxpKZ|Sd2kBnvp7kmVVna1TOjFE2033D>Zs525_mU4Y0h(LK{XZ zcMyu^IHboA$2e$fQd(v^cl3aK3AZdyGS Date: Sun, 25 Aug 2013 10:38:57 +0900 Subject: [PATCH 020/121] Add a favicon.ico --- favicon.ico | Bin 0 -> 318 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 favicon.ico diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..81fe0b26c27da4f1316eb2968a8b2eeb9e6d0df2 GIT binary patch literal 318 zcmZQzU<5(|0RaXO&|qX>5ChRb3=&ZQVnzlQAj!aR08C;M|NsAISYTj)DM5sY(f|V@ IoQPKm05DJ%i~s-t literal 0 HcmV?d00001 From e93ca619816fec57733c4595a52bf45eece22893 Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Sun, 25 Aug 2013 10:45:29 +0900 Subject: [PATCH 021/121] Fix syntax bugs in intro.textile --- intro.textile | 55 ++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/intro.textile b/intro.textile index 4cfdad1..33596e3 100644 --- a/intro.textile +++ b/intro.textile @@ -4,6 +4,7 @@ layout: default h1. Preface: Introduction + h2. Characteristics of Ruby Some of the readers may have already been familiar with Ruby, some may be not. @@ -96,7 +97,7 @@ avoid gaining disagreement of calling it so. That's the definition I suggest. To fulfill this definition, I would define the meaning of "script language" as follows. -p(=center). + Whether the author of the language calls it "script language" or not. @@ -252,13 +253,13 @@ This topic is probably difficult to understand it instantly without needs supplemental explanation. For example, the following C-language program contains a syntactic error. -p(=emlist). +
 
 result = if (cond) { process(val); } else { 0; }
 
Because the C-language syntax defines @if@ as a statement. See following rewrite. -p(=emlist). +
 
 result = cond ? process(val) : 0;
 
@@ -268,7 +269,7 @@ as an expression. On the other hand, Ruby acceps a following expression because @if@ is an expression. -p(=emlist). +
 
 result = if cond then process(val) else nil end
 
@@ -324,7 +325,7 @@ In addition to the fact that's written in C, one of the important feature is tha level and C level code differences are very small. Most commands available in Ruby are also available in C. See following example. -p(=emlist). +
 
 # Method call
 obj.method(arg)                                 # Ruby
 rb_funcall(obj, rb_intern("method"), 1, arg);   # C
@@ -487,6 +488,7 @@ h4. 書き換えて動かす
 同じことを両方にやってみるべきである。
 
 h3. 静的な解析
+
 h4. 名前の大切さ
 
 静的解析とはつまりソースコードの解析だ。そしてソースコードの解析とは名
@@ -619,7 +621,7 @@ h3. 静的解析用ツール
 @gctags@は本当はタグファイルを作るためのツールなのだが、
 これを使ってファイルに含まれる関数名のリストを取ることもできる。
 
-p(=screen). 
+
 ~/src/ruby % gctags class.c | awk '{print $1}'
 SPECIAL_SINGLETON
 SPECIAL_SINGLETON
@@ -643,6 +645,7 @@ method_list
 関数クロスリファレンス
 
 h2. ビルド
+
 h3. 対象バージョン
 
 本書で解説している@ruby@のバージョンは1.7の2002-09-12版である。@ruby@はマ
@@ -664,7 +667,7 @@ h3. ソースコードを入手する
 添付CD-ROMに解説対象の版のアーカイブを収録した。
 CD-ROMのトップディレクトリに
 
-p(=emlist). 
+
 
 ruby-rhg.tar.gz
 ruby-rhg.zip
 ruby-rhg.lzh
@@ -674,11 +677,12 @@ ruby-rhg.lzh
 もちろん中身はどれも同じだ。例えば@tar.gz@のアーカイブなら
 次のように展開すればいいだろう。
 
-p(=screen). 
+
 ~/src % mount /mnt/cdrom
 ~/src % gzip -dc /mnt/cdrom/ruby-rhg.tar.gz | tar xf -
 ~/src % umount /mnt/cdrom
 
+ h3. コンパイルする ソースコードを見るだけでも「読む」ことはできる。しかしプログラムを知る @@ -698,7 +702,7 @@ h4. UNIX系OSでのビルド たいがい通ってしまう。 @~/src/ruby@にソースコードが展開されているとする。 -p(=screen). +
 ~/src/ruby % ./configure
 ~/src/ruby % make
 ~/src/ruby % su
@@ -713,7 +717,7 @@ Cygwin、UX/4800など一部のプラットフォームでは@configure@の段
 @--enable-shared@というのは@ruby@のほとんどを共有ライブラリ
 (@libruby.so@)としてコマンドの外に出すオプションである。
 
-p(=screen). 
+
 ~/src/ruby % ./configure --enable-shared
 
@@ -771,14 +775,14 @@ Visual C++と言っても普通はIDEは使わず、DOSプロンプトからビ しなければいけない。Visual C++にそのためのバッチファイルが付いてくるの で、まずはそれを実行しよう。 -p(=screen). +
 C:> cd "Program FilesMicrosoft Visual Studio .NETVc7bin"
 C:Program FilesMicrosoft Visual Studio .NETVc7bin> vcvars32
 
これはVisual C++.NETの場合だ。バージョン6なら以下の場所にある。 -p(=emlist). +
 
 C:Program FilesMicrosoft Visual StudioVC98bin
 
@@ -786,7 +790,7 @@ C:Program FilesMicrosoft Visual StudioVC98bin @win32@に移動してビルドすればいい。以下、ソースツリーは@C:src@に あるとしよう。 -p(=screen). +
 C:> cd srcruby
 C:srcruby> cd win32
 C:srcrubywin32> configure
@@ -817,7 +821,7 @@ CygwinとMinGWは添付CD-ROMにも収録した
 footnote{CygwinとMinGW......添付CD-ROMの@doc/win.html@を参照}。
 あとはCygwinの@bash@プロンプトから以下のように打てばよい。
 
-p(=screen). 
+
 ~/src/ruby % ./configure --with-gcc='gcc -mno-cygwin' 
                                  --enable-shared i386-mingw32
 ~/src/ruby % make
@@ -862,7 +866,7 @@ h3. @configure@
 ように埋め込んだ@Makefile.in@を置いておくと、それを実際の値に変換
 した@Makefile@を生成してくれる。例えば次のように。
 
-p(=emlist). 
+
 
 Makefile.in:  CFLAGS = @CFLAGS@
                      ↓
 Makefile   :  CFLAGS = -g -O2
@@ -874,8 +878,8 @@ Makefile   :  CFLAGS = -g -O2
 @configure@を実行した後にこのファイルができていることを確かめてほしい。
 中身はこんな感じだ。
 
-p(=caption). ▼@config.h@
-p(=longlist). 
+▼@config.h@
+
          :
          :
 #define HAVE_SYS_STAT_H 1
@@ -908,8 +912,9 @@ p(=longlist).
 使って差を埋めるのはあくまで各プログラマの仕事である。例えば次の
 ように。
 
-p(=caption). ▼@HAVE_@マクロの典型的な使いかた
-p(=longlist). 
+
+▼@HAVE_@マクロの典型的な使いかた
+
   24  #ifdef HAVE_STDLIB_H
   25  # include 
   26  #endif
@@ -931,7 +936,6 @@ h3. @autoconf@
 
 ここまでを絵にすると図1のようになる。
 
-p(=image). 
 !images/ch_abstract_build.jpg([build])!
 図1: @Makefile@ができるまで
 
@@ -1011,7 +1015,6 @@ CVSはエディタのundoリストのようなものと言ったが、そのた
 「ワーキングコピー」だ。レポジトリは一つだけだがワーキングコピーは
 いくつあってもいい(図2)。
 
-p(=image). 
 !images/ch_abstract_repo.jpg([repo])!
 図2: レポジトリとワーキングコピー
 
@@ -1024,7 +1027,6 @@ p(=image).
 または「コミット(commit)」と言う(図3)。チェックインするとレ
 ポジトリに変更が記録されて、いつでもそれを取り出せるようになる。
 
-p(=image). 
 !images/ch_abstract_ci.jpg([ci])!
 図3: チェックインとチェックアウト
 
@@ -1066,7 +1068,7 @@ footnote{@cvs@:@archives/cvs-1.11.2.tar.gz@}。
 インストールしたら試しに@ruby@のソースコードをチェックアウトしてみよう。
 インターネットに接続中に次のように打つ。
 
-p(=screen). 
+
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
 CVS Password: anonymous
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby
@@ -1080,7 +1082,7 @@ CVS Password: anonymous
 ばいい。次のように打てば本書が解説しているバージョンのワーキングコピー
 が取り出せる。
 
-p(=screen). 
+
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout -D2002-09-12 ruby
 
@@ -1112,7 +1114,7 @@ h3. 物理構造 トップディレクトリの様子だ。 スラッシュで終わっているのはサブディレクトリである。 -p(=emlist). +
 
 COPYING        compar.c       gc.c           numeric.c      sample/
 COPYING.ja     config.guess   hash.c         object.c       signal.c
 CVS/           config.sub     inits.c        pack.c         sprintf.c
@@ -1263,7 +1265,7 @@ h4. プラットフォーム依存ファイル
 各プラットフォーム特有のコードが入っている。
 
 h4. フォールバック関数
-p(=emlist). 
+
 
 missing/
 
@@ -1308,7 +1310,6 @@ h4. パーサ ツリー構造で表現したもので、例えば@if@文ならば図4のように 表現される。 -p(=image). !images/ch_abstract_syntree.jpg([syntree])! 図4: @if@文と、それに対応する構文木 From 82c41458219917caf5d27593d48e054a3dafb27a Mon Sep 17 00:00:00 2001 From: Johnny Mukai & Yohei Yasukawa Date: Sun, 25 Aug 2013 09:46:09 -0400 Subject: [PATCH 022/121] A little rough progress on intro. --- intro.textile | 55 +++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/intro.textile b/intro.textile index 33596e3..c1ecd4e 100644 --- a/intro.textile +++ b/intro.textile @@ -442,59 +442,40 @@ should at least be closer to the fact than dynamic analysis. h3. Dynamic analysis -h4. 対象プログラムを使う +h4. Use the target program -これがなければ始まらない。そもそもそのプログラムがどういうものなのか、 -どういう動作をすべきなのか、あらかじめ知っておく。 +You can't start without the target program. First of all, you need to know in advance what the program is like, and what are expected behaviors. -h4. デバッガで動きを追う +h4. Follow the behavior using the debugger -例えば実際にコードがどこを通ってどういうデータ構造を作るか、なんていう -ことは頭の中で考えているよりも実際にプログラムを動かしてみてその結果を -見たほうが早い。それにはデバッガを使うのが簡単だ。 +If you want to see the paths of code execution and the data structure produced as a result, it's quicker to look at the result by running the program actually than to emulate the behavior in your brain. In order to do so easily, use the debugger. +However, there is not adequate tools unfortunately, especially in free software, that can generate the picture of the data structure at execution. A snapshot of the comparatively simpler structure may be obtained by converting text data obtained instantly into a picture using graphviz\footnote{graphviz……See doc/graphviz.html in the attached CD-ROM}. But it's very difficult to find a way for general purpose and real time analysis. -実行時のデータ構造を絵にして見られるとさらに嬉しいのだが、そういうツー -ルはなかなかない(特にフリーのものは少ない)。比較的単純な構造のスナッ -プショットくらいならテキストでさらっと書き出し -@graphviz@footnote{@graphviz@......添付CD-ROMの@doc/graphviz.html@参照}の -ようなツールを使って絵にすることもできそうだが、汎用・リアルタイムを -目指すとかなり難しい。 +h4. Tracer -h4. トレーサ +You can use the tracer if you want to trace the procedures that code goes through. In case of C-language, there is a tool named ctrace\footnote{ctrace……http://www.vicente.org/ctrace}. For tracing a system call, you can use tools like strace\footnote{strace……http://www.wi.leidenuniv.nl/~wichert/strace/}, truss, and ktrace. -コードがどの手続きを通っているか調査したければトレーサを使えばいい。 -C言語なら -@ctrace@footnote{@ctrace@......@http://www.vicente.org/ctrace@}と -いうツールがある。 -またシステムコールのトレースには -@strace@footnote{@strace@......@http://www.wi.leidenuniv.nl/~wichert/strace/@}、 -@truss@、@ktrace@と言ったツールがある。 +h4. Print everywhere -h4. printしまくる +There is a word "printf debugging". This method also works for analysis other than debugging. If you are watching the history of one variable, for example, it may be easier to understand to look at the dump of the result of the print statements embed, than to track the variable with a debugger. -@printf@デバッグという言葉があるが、この手法はデバッグでなくても役に立つ。 -特定の変数の移り変わりなどはデバッガでチマチマ辿ってみるよりもprint文を -埋め込んで結果だけまとめて見るほうがわかりやすい。 +h4. Understanding code by modifying it -h4. 書き換えて動かす +Say for example, you do not understand some part of the code or a particular parameter, just make a small change and then re-run the program. +By trying out small changes and seeing how they affect the code you will understand how it works. -例えば動作のわかりにくいところでパラメータやコードを少しだけ変えて動 -かしてみる。そうすると当然動きが変わるから、コードがどういう意味なのか -類推できる。 +It goes without saying, you should have an original binary to compare your changes to. +h3. Static analysis -言うまでもないが、オリジナルのバイナリは残しておいて -同じことを両方にやってみるべきである。 +h4. The importance of naming -h3. 静的な解析 +Static analysis is simply source code analysis. Therefore, source code analysis is really an analysis of names. File names, function names, variable names, type names, member names -- A program is just a bunch of names. -h4. 名前の大切さ +One of the most powerful tools for creating abstractions in programming is naming. This may seem obvious but keeping this in mind will make reading much more efficient. -静的解析とはつまりソースコードの解析だ。そしてソースコードの解析とは名 -前の調査である。ファイル名・関数名・変数名・型名・メンバ名など、プログ -ラムは名前のかたまりだ。名前はプログラムを抽象化する最大の武器なのであ -たりまえと言えばあたりまえだが、この点を意識して読むとかなり効率が違う。 +Also, I'd like to mention something about coding rules. またコーディングルールについてもあたりをつけておきたい。例えばCの関数 From 2b9b5237383a89a4b96f9f68b41b897427a2cdb7 Mon Sep 17 00:00:00 2001 From: Johnny Mukai & Yohei Yasukawa Date: Sun, 25 Aug 2013 09:47:28 -0400 Subject: [PATCH 023/121] Quick re-wording on this sentence. --- object.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/object.textile b/object.textile index 7a32ddd..0c739df 100644 --- a/object.textile +++ b/object.textile @@ -572,7 +572,7 @@ all right but how is it in practice? Let's look at the function necessary, but it's not the main part of the treatment, so you should ignore them at first read. -After removing error treatment, only the `switch` remains, but this +If we ignore the error handling, only the `switch` remains, but this
 switch (TYPE(obj)) {

From 69d486032e03163ee6116c9075b3036fbc032635 Mon Sep 17 00:00:00 2001
From: Yohei YASUKAWA 
Date: Sun, 25 Aug 2013 22:59:06 +0900
Subject: [PATCH 024/121] Add new lines to be easier to review, and translate
 the rest of section

---
 intro.textile | 42 ++++++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/intro.textile b/intro.textile
index c1ecd4e..5ff8f43 100644
--- a/intro.textile
+++ b/intro.textile
@@ -444,13 +444,20 @@ h3. Dynamic analysis
 
 h4. Use the target program
 
-You can't start without the target program. First of all, you need to know in advance what the program is like, and what are expected behaviors. 
+You can't start without the target program. First of all, you need to know in advance what
+the program is like, and what are expected behaviors. 
 
 h4. Follow the behavior using the debugger
 
-If you want to see the paths of code execution and the data structure produced as a result, it's quicker to look at the result by running the program actually than to emulate the behavior in your brain. In order to do so easily, use the debugger. 
+If you want to see the paths of code execution and the data structure produced as a result,
+it's quicker to look at the result by running the program actually than to emulate the behavior
+in your brain. In order to do so easily, use the debugger. 
 
-However, there is not adequate tools unfortunately, especially in free software, that can generate the picture of the data structure at execution. A snapshot of the comparatively simpler structure may be obtained by converting text data obtained instantly into a picture using graphviz\footnote{graphviz……See doc/graphviz.html in the attached CD-ROM}. But it's very difficult to find a way for general purpose and real time analysis. 
+However, there is not adequate tools unfortunately, especially in free software,
+that can generate the picture of the data structure at execution. A snapshot of the comparatively
+simpler structure may be obtained by converting text data obtained instantly into a picture using
+graphviz\footnote{graphviz……See doc/graphviz.html in the attached CD-ROM}.
+But it's very difficult to find a way for general purpose and real time analysis. 
 
 h4. Tracer
 
@@ -458,33 +465,36 @@ You can use the tracer if you want to trace the procedures that code goes throug
 
 h4. Print everywhere
 
-There is a word "printf debugging". This method also works for analysis other than debugging.  If you are watching the history of one variable, for example, it may be easier to understand to look at the dump of the result of the print statements embed, than to track the variable with a debugger.
+There is a word "printf debugging". This method also works for analysis other than debugging.
+If you are watching the history of one variable, for example, it may be easier to understand
+to look at the dump of the result of the print statements embed, than to track the variable
+with a debugger.
 
 h4. Understanding code by modifying it
 
-Say for example, you do not understand some part of the code or a particular parameter, just make a small change and then re-run the program.
+Say for example, you do not understand some part of the code or a particular parameter,
+just make a small change and then re-run the program.
 By trying out small changes and seeing how they affect the code you will understand how it works.
 
 It goes without saying, you should have an original binary to compare your changes to.
 
 h3. Static analysis
 
-h4. The importance of naming
+h4. The importance of names
 
-Static analysis is simply source code analysis. Therefore, source code analysis is really an analysis of names. File names, function names, variable names, type names, member names -- A program is just a bunch of names.
+Static analysis is simply source code analysis. Therefore, source code analysis is
+really an analysis of names. File names, function names, variable names, type names,
+member names -- A program is just a bunch of names.
 
-One of the most powerful tools for creating abstractions in programming is naming. This may seem obvious but keeping this in mind will make reading much more efficient.
+One of the most powerful tools for creating abstractions in programming is naming.
+This may seem obvious but keeping this in mind will make reading much more efficient.
 
 Also, I'd like to mention something about coding rules.
+For example, in C language, @extern@ function often uses prefix to distinguish the type of functions.
+And in object-oriented programs, the name of member fields in a function often includes prefix,
+which is really important information (e.g. @rb_str_length@).
 
-
-またコーディングルールについてもあたりをつけておきたい。例えばCの関数
-名なら@extern@関数にはプリフィクスを使っていることが多く、関数の種類を見
-分けるのに使える。またオブジェクト指向様式のプログラムだと関数の所属情
-報がプリフィクスに入っていることがあり、貴重な情報になる。
-(例:@rb_str_length@)
-
-h4. ドキュメントを読む
+h4. Read documents
 
 内部構造を解説したドキュメントが入っていることもある。
 特に「@HACKING@」といった名前のファイルには注意だ。

From d2d7de8b169cdd8e0c264477cba93ccc0a7c8da5 Mon Sep 17 00:00:00 2001
From: ocha- 
Date: Mon, 26 Aug 2013 08:22:11 +0900
Subject: [PATCH 025/121] edit intro

---
 intro.textile | 75 +++++++++++++++++++++++++++++----------------------
 1 file changed, 43 insertions(+), 32 deletions(-)

diff --git a/intro.textile b/intro.textile
index 5ff8f43..d5d92ec 100644
--- a/intro.textile
+++ b/intro.textile
@@ -273,25 +273,26 @@ On the other hand, Ruby acceps a following expression because @if@ is an express
 result = if cond then process(val) else nil end
 
-Roughly, you can assume any element which can be fed as an argument for a function -or a method is a formula. +Roughly speaking, if it can be an argument of a function or a method, +you can consider it as an expression. -Of course, there are other languages whose syntactic elements are mostly a formula. -Namely, Lisp is the best example. For this characteristic, many people seem to -regard Ruby is similar to Lisp. +Of course, there are other languages whose syntactic elements are mostly expressions. +Lisp is the best example. Because of the characteristic around this, +there seems many people who feel like "Ruby is similar to Lisp". h4. Iterators Ruby has iterators. What is an iterator? Before getting into iterators, I should mention the necessity of using an alternative term, because the word "iterator" is -disliked recently. However, I don't have a good alternation. So let us keep calling +disliked recently. However, I don't have a good alternative. So let us keep calling it "iterator" for the time being. -Well again, what is an iterator? If you are already familiar with a high level -function which is similar, you can assume it for now. C-language example is the way -you feed function pointer as an argument. C++ example is a way to envelope the -operation part of STL's @Iterator@ into a method. If you are familiar with sh and -Perl, you can imagine it like a custom defined @for@ statement. +Well again, what is an iterator? If you know higher-order function, +for the time being, you can regard it as something similar to it. +In C-language, the counterpart would be passing a function pointer as an argument. +In C++, it would be a method to which the operation part of STL's @Iterator@ is enclosed. +If you know @sh@ or @Perl@, +it's good to imagine something like a custom @for@ statement which we can define. Yet, the above are merely examples of "similar" concepts. All of them are similar, but they are not identical to Ruby's iterator. I will expand the precise story @@ -299,31 +300,40 @@ when it's a good time later. h4. Written in C-language -Being written in C-language is not distinctive these days, but it's still a notable -characteristic for sure. Unlike being written in Haskell or PL/I, it should possibly -be readable for a wide range of people generally. (I want you to confirm it in the -later in this book.) +Being written in C-language is not notable these days, but it's still a +characteristic for sure. +At least it is not written in Haskell or PL/I, +thus there's the high possibility that the ordinary people can read it. +(Whether it is truly so, I'd like you confirm it by yourself.) Well, I just said it's in C-language, but the actual language version which ruby is targetting is basically K&R C. Until a little while ago, there were a decent number -of - not plenty though - K&R-only-environment. Considering the trend of ANSI C being -a popular environment that seems to pass most of programs, there appears to be no -problem to port to ANSI C. However, the K&R style code is still maintained, with the -author Matsumoto's preference being one aspect. +of - not plenty though - K&R-only-environment. +But recently, there are a few environments which do not accept programs +written in ANSI C, technically there's no problem to move on to ANSI C. +However, also because of the author Matsumoto's personal preference, +it is still written in K&R style. For this reason, the function definition is all in K&R style, and the prototype -declarations are not strictly written. Looking at the mailing list, I can see a lot -of topics in which @gcc@ with @-Wall@ option outputs a huge dump of errors, and C++ -compiler warns prototype mismatch that fails to finish compiling. +declarations are not so seriously written. +If you carelessly specify @-Wall@ option of @gcc@, +there would be plenty of warnings shown. +If you try to compile it with a C++ compiler, +it would warn prototype mismatch and could not compile. +... These kind of stories are often reported to the mailing list. + h4. Extension library -Ruby library can be written in C. It can be loaded at execution without recompiling Ruby. +We can write a Ruby library in C and load it at runtime without recompiling Ruby. This type of library is called "Ruby extension library" or just "Extension library". -In addition to the fact that's written in C, one of the important feature is that Ruby -level and C level code differences are very small. Most commands available in Ruby are -also available in C. See following example. +Not only the fact that we can write it in C, +but the very small difference in the code expression between Ruby-level and +C-level is also a significant trait. +As for the operations available in Ruby, +we can also use them in C in the almost same way. +See the following example.
 
 # Method call
@@ -353,24 +363,24 @@ h4. Thread
 Ruby is equipped with thread. Assuming a very few people knowing none about thread these
 days, I will omit an explanation about the thread itself. I will start a story in detail. 
 
-The thread level of @ruby@ belongs to the user level of origin. The characteristic of
++ruby+'s thread is a user-level thread that is originally written. The characteristic of
 this implementation is a very high portability in both specification and implementation.
 Surprisingly a MS-DOS can run the thread. Furthermore, you can expect the same response
 in any environment. Many people mention that this point is the best feature of @ruby@.
 
 However, as a trade off for such an extremeness of portability, @ruby@ abandons the speed.
 It's, say, probably the slowest of all user-level thread implementations in this world.
-The trend of @ruby@ implementation may be seen here the most clearly. 
+The tendency of @ruby@ implementation may be seen here the most clearly.
 
 h2. Technique to read source code
 
 Well. After an introduction of @ruby@, we are about to start reading source code. But wait. 
 
 Any programmer has to read a source code somewhere, but I guess there are not many occasions
-that someone teaches you the concrete ways how to read. Why? Is it because writing a program
-naturally assumes reading a program? 
+that someone teaches you the concrete ways how to read. Why?
+Does it mean you can naturally read a program if you can write a program?
 
-I don't think so. It's not easy to actually read a code written by other people.
+But I can't think reading the program written by other people is so easy.
 In the same way as writing programs, there must be techniques and theories in reading programs.
 And they are necessary. Therefore, before starting to ready @ruby@, I'd like to expand a general
 summary of an approach you need to take in reading a source code. 
@@ -382,8 +392,9 @@ At first, I mention the principle.
 h4. Decide a goal
 
 
-bq. 
+
An important key to reading the source code is to set a concrete goal. +
This is a word by the author of Ruby, Matsumoto. Indeed, his word is very convincing for me. From caf9c21005060f7ec2f8378ca410bfd1edd532dc Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 26 Aug 2013 09:19:14 +0900 Subject: [PATCH 026/121] fix syntax --- intro.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intro.textile b/intro.textile index d5d92ec..dd679fd 100644 --- a/intro.textile +++ b/intro.textile @@ -363,7 +363,7 @@ h4. Thread Ruby is equipped with thread. Assuming a very few people knowing none about thread these days, I will omit an explanation about the thread itself. I will start a story in detail. -+ruby+'s thread is a user-level thread that is originally written. The characteristic of +`ruby`'s thread is a user-level thread that is originally written. The characteristic of this implementation is a very high portability in both specification and implementation. Surprisingly a MS-DOS can run the thread. Furthermore, you can expect the same response in any environment. Many people mention that this point is the best feature of @ruby@. From 1ea453a993a861200b118e7d3be37930f16f896c Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 26 Aug 2013 13:00:23 +0900 Subject: [PATCH 027/121] edit the first half of chapter 02 mainly the parts that were different from the original book. --- object.textile | 107 +++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/object.textile b/object.textile index 0c739df..a8bc834 100644 --- a/object.textile +++ b/object.textile @@ -10,11 +10,13 @@ h2. Structure of Ruby objects h3. Guideline -In this chapter we will begin exploring the `ruby` source code, starting by -studying the declaration of object structures. +From this chapter, we will begin actually exploring the `ruby` source code. +First, as declared at the beginning of this book, +we'll start with the object structure. -What do objects need to exist? There are many answers to this question, but for -our purposes an object only needs three things: +What are the necessary conditions for objects to be objects? +There could be many ways to explain about object itself, +but there are only three conditions that are truly indispensable. # The ability to differentiate itself from other objects (an identity) # The ability to respond to messages (methods) @@ -22,13 +24,13 @@ our purposes an object only needs three things: In this chapter, we are going to confirm these three features one by one. -The most interesting file in this quest will be `ruby.h`, but we will also +The target file is mainly `ruby.h`, but we will also briefly look at other files such as `object.c`, `class.c` or `variable.c`. -h3. Structure of `VALUE` and objects +h3. `VALUE` and object struct -In `ruby`, the contents of an object are expressed by a `C` structure, always -handled via a pointer. A different kind of structure is used for each class, but +In `ruby`, the body of an object is expressed by a struct and always +handled via a pointer. A different struct type is used for each class, but the pointer type will always be `VALUE` (figure 1). !images/ch_object_value.png(`VALUE` and structure)! @@ -43,13 +45,15 @@ Here is the definition of `VALUE`: (ruby.h)
-In practice, a `VALUE` must be cast to different types of structure pointer. +In practice, when using a `VALUE`, we cast it to the pointer to each object struct. Therefore if an `unsigned long` and a pointer have a different size, `ruby` -will not work well. Strictly speaking, it will not work for pointer types -bigger than `sizeof(unsigned long)`. Fortunately, no recent machine feature -this capability, even if some time ago there were quite a few of them. +will not work well. Strictly speaking, it will not work if there's a pointer +type that is bigger than `sizeof(unsigned long)`. Fortunately, systems which +could not meet this requirement is unlikely recently, +but some time ago it seems there were quite a few of them. -Several structures are available according to object classes: +The structs, on the other hand, have several variations, +a different struct is used based on the class of the object. | `struct RObject` | all things for which none of the following applies | @@ -110,7 +114,8 @@ Before looking at every one of them in detail, let's begin with something more general. First, as `VALUE` is defined as `unsigned long`, it must be cast before -being used. That's why `Rxxxx()` macros have been made for each object +being used when it is used as a pointer. +That's why `Rxxxx()` macros have been made for each object structure. For example, for `struct RString` there is `RSTRING()`, for `struct RArray` there is `RARRAY()`, etc... These macros are used like this: @@ -129,8 +134,9 @@ of the type of structure pointed to by `VALUE`. !images/ch_object_rbasic.png(`struct RBasic`)! -You probably guessed that `struct RBasic` has been designed to contain some -important information shared by all object structures. Here is the definition +Because it is purposefully designed this way, +`struct RBasic` must contain very important information for Ruby objects. +Here is the definition for `struct RBasic`: ▼ `struct RBasic` @@ -154,8 +160,9 @@ str = rb_str_new(); /* creates a Ruby string (its structure is RString) */ TYPE(str); /* the return value is T_STRING */
-The names of these `T_xxxx` flags are directly linked to the corresponding type -name, like `T_STRING` for `struct RString` and `T_ARRAY` for `struct RArray`. +The all flags are named as `T_xxxx`, +like `T_STRING` for `struct RString` and `T_ARRAY` for `struct RArray`. +They are very straightforwardly corresponded to the type names. The other member of `struct RBasic`, `klass`, contains the class this object belongs to. As the `klass` member is of type `VALUE`, what is stored is (a @@ -199,10 +206,11 @@ easier and faster to put the information about the type in the structure. h4. The use of `basic.flags` -As limiting myself to saying that `basic.flags` is used for different things -including the type of structure makes me feel bad, here's a general -illustration for it (figure 5). There is no need to understand everything -right away, I just wanted to show its uses while it was bothering me. +Regarding the use of `basic.flags`, +because I feel bad to say it is the structure type "and such", +I'll illustrate it entirely here. (Figure 5) +There is no need to understand everything right away, +because this is prepared for the time when you will be wondering about it later. !images/ch_object_flags.png(Use of `flags`)! @@ -229,13 +237,14 @@ I'll explain them one by one. h4. Small integers -Just like in Ruby itself, all data are objects. Likewise, integers are objects. -However during normal program execution, lots of instances of integers are -created. Using structures to express them would risk slowing down execution. For -example, if we created 50000 objects when incrementing from 0 to 50000 we'd -definitely have to consider the performance issues. +All data are objects in Ruby, thus integers are also objects. +But since there are so many kind of integer objects, +if each of them is expressed as a structure, +it would risk slowing down execution significantly. +For example, when incrementing from 0 to 50000, +we would hesitate to create 50000 objects for only that purpose. -That's why in `ruby`, to some extent, small integers are treated specially and +That's why in `ruby`, integers that are small to some extent are treated specially and embedded directly into `VALUE`. "Small" means signed integers that can be held in `sizeof(VALUE)*8-1` bits. In other words, on 32 bits machines, the integers have 1 bit for the sign, and 30 bits for the integer part. Integers in this @@ -277,8 +286,8 @@ h4. Symbols What are symbols? As this question is quite troublesome to answer, let's start with the reasons -why symbols were necessary. First, let's start with the `ID` type used inside -`ruby`. It's like this: +why symbols were necessary. +In the first place, there's a type named `ID` used inside `ruby`. Here it is. ▼ `ID` @@ -289,13 +298,13 @@ why symbols were necessary. First, let's start with the `ID` type used inside
This `ID` is a number having a one-to-one association with a string. However, -in this world it's not possible to have an association between all strings and -a numerical value. That's why they are limited to the one to one relationships +it's not possible to have an association between all strings in this world and +numerical values. It is limited to the one to one relationships inside one `ruby` process. I'll speak of the method to find an `ID` in the next chapter "Names and name tables". -In language implementations, there are a lot of names to handle. Method names -or variable names, constant names, file names in class names... It's +In language processor, there are a lot of names to handle. Method names +or variable names, constant names, file names, class names... It's troublesome to handle all of them as strings (`char*`), because of memory management and memory management and memory management... Also, lots of comparisons would certainly be necessary, but comparing strings character by @@ -304,14 +313,14 @@ directly, something will be associated and used instead. And generally that "something" will be integers, as they are the simplest to handle. These `ID` are found as symbols in the Ruby world. Up to `ruby 1.4`, the -values of `ID` were converted to `Fixnum`, but used as symbols. Even today +values of `ID` converted to `Fixnum` were used as symbols. Even today these values can be obtained using `Symbol#to_i`. However, as real use results came piling up, it was understood that making `Fixnum` and `Symbol` the same was not a good idea, so since 1.6 an independent class `Symbol` has been created. `Symbol` objects are used a lot, especially as keys for hash tables. That's -why `Symbol`, like `Fixnum`, was made stored in `VALUE`. Let's look at the +why `Symbol`, like `Fixnum`, was made embedded in `VALUE`. Let's look at the `ID2SYM()` macro converting `ID` to `Symbol` object. ▼ `ID2SYM` @@ -358,7 +367,7 @@ values at the C level are defined like this: (ruby.h)
This time it's even numbers, but as 0 or 2 can't be used by pointers, they -can't overlap with other `VALUE`. It's because usually the first bloc of +can't overlap with other `VALUE`. It's because usually the first block of virtual memory is not allocated, to make the programs dereferencing a `NULL` pointer crash. @@ -382,10 +391,10 @@ function returning a boolean value. In other words, `NIL_P` means "is the argument `nil`?". It seems the "`p`" character comes from "predicate." This naming rule is used at many different places in `ruby`. -Also, in Ruby, `false` and `nil` are falsy (that is, they count as false in -conditional statements) and all the other objects are truthy. -However, in C, `nil` (`Qnil`) is true. That's why in C a Ruby-style macro, -`RTEST()`, has been created. +Also, in Ruby, `false` and `nil` are false (in conditional statements) +and all the other objects are true. +However, in C, `nil` (`Qnil`) is true. +That's why there's the `RTEST()` macro to do Ruby-style test in C. ▼ `RTEST()` @@ -417,7 +426,7 @@ h4. `Qundef`
This value is used to express an undefined value in the interpreter. It can't -be found at all at the Ruby level. +(must not) be found at all at the Ruby level. h2. Methods @@ -432,7 +441,7 @@ In Ruby, classes exist as objects during the execution. Of course. So there must be a structure for class objects. That structure is `struct RClass`. Its structure type flag is `T_CLASS`. -As class and modules are very similar, there is no need to differentiate their +As classes and modules are very similar, there is no need to differentiate their content. That's why modules also use the `struct RClass` structure, and are differentiated by the `T_MODULE` structure flag. @@ -455,6 +464,8 @@ next chapter "Names and name tables", but basically, it is a table mapping names to objects. In the case of `m_tbl`, it keeps the correspondence between the name (`ID`) of the methods possessed by this class and the methods entity itself. +As for the structure of the method entity, +it will be explained in Part 2 and Part 3. The fourth member `super` keeps, like its name suggests, the superclass. As it's a `VALUE`, it's (a pointer to) the class object of the superclass. In Ruby @@ -463,14 +474,14 @@ there is only one class that has no superclass (the root class): `Object`. However I already said that all `Object` methods are defined in the `Kernel` module, `Object` just includes it. As modules are functionally similar to multiple inheritance, it may seem having just `super` is problematic, but -in `ruby` some clever changes are made to make it look like single +in `ruby` some clever conversions are made to make it look like single inheritance. The details of this process will be explained in the fourth chapter "Classes and modules". -Because of this, `super` of the structure of `Object` points to `struct RClass` -of the `Kernel` object. Only the `super` of Kernel is NULL. So contrary to -what I said, if `super` is NULL, this `RClass` is the `Kernel` object (figure -6). +Because of this conversion, `super` of the structure of `Object` points to `struct RClass` +which is the entity of `Kernel` object and the `super` of Kernel is `NULL`. +So to put it conversely, if `super` is `NULL`, +its `RClass` is the entity of `Kernel` (figure 6). !images/ch_object_classtree.png(Class tree at the C level)! From 1cf6a9b7e7a78173506382925c52071880719fad Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 27 Aug 2013 11:42:59 +0900 Subject: [PATCH 028/121] edit intro --- intro.textile | 70 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/intro.textile b/intro.textile index dd679fd..4cd50c3 100644 --- a/intro.textile +++ b/intro.textile @@ -7,58 +7,61 @@ h1. Preface: Introduction h2. Characteristics of Ruby -Some of the readers may have already been familiar with Ruby, some may be not. -(I wish the latter for this chapter to be most useful) First let's go though a +Some of the readers may have already been familiar with Ruby, +but (I hope) there are also many readers who have not. First let's go though a rough summary of the characteristics of Ruby for such people. -Hereafter capital "Ruby" refers to Ruby as a language scheme, and lowercase -"@ruby@" refers to the implementation of @ruby@ command. +Hereafter capital "Ruby" refers to Ruby as a language specification, and lowercase +"@ruby@" refers to @ruby@ command as an implementation. -h4. Development pattern +h4. Development style -Ruby is a personally created language by Yukihiro Matsumoto. That means Ruby -doesn't have a standard scheme that C or Java have. The specification is merely -shown as an implementation as @ruby@, and its varying continuously. Whichever -you mention good or bad, it's unbind. +Ruby is a language that is being developped by the hand of Yukihiro Matsumoto as +an individual. Unlike C or Java or Scheme, it does not have any standard. +The specification is merely +shown as an implementation as @ruby@, and its varying continuously. +For good or bad, it's free. -Furthermore @ruby@ itself is a free software - source code being open and -being in public free of charge - this is what I must add in the introduction. -That's why it allows the approach of this book into publication. +Furthermore @ruby@ itself is a free software. +It's probably necessary to mention at least the two points here: +The source code is open in public and distributed free of charge. +Thanks to such condition, an attempt like this book can be approved. -Giving the @README@ and @LEGAL@ included in the distribution package the -complete reading of the license, let's list up what you can do for the time -being: +If you'd like to know the exact lisence, you can read @README@ and @LEGAL@. +For the time being, I'd like you to remember that you can do at least the +following things: -You can redistribute source code of @ruby@ -You can modify source code of @ruby@ -You can redistribute a copy of source code with your modification +* You can redistribute source code of @ruby@ +* You can modify source code of @ruby@ +* You can redistribute a copy of source code with your modification There is no need for special permission and payment in all these cases. -By the way, the original @ruby@ is the version referred to in this book unless -otherwise stated, because our main purpose is to read it. However, I modified -the code without notice at a certain extent such as to remove or add white -spaces, new lines, and comments. +By the way, the purpose of this book is to read the original @ruby@, +thus the target source is the one not modified unless it is particulary +specified. However, white spaces, new lines and comments were added or removed +without asking. + h4. It's conservative Ruby is a very conservative language. It is equipped with only carefully chosen -features that have been tested and washed out in a variety of languages​. +features that have been tested and washed out in a variety of languages. Therefore it doesn't have plenty of fresh and experimental features very much. So it has a tendency to appeal to programmers who put importance on practical functionalities. The dyed-in-the-wool hackers like Scheme and Haskell lovers -don't seem to find appeal in ruby in a short glance. +don't seem to find appeal in ruby, at least in a short glance. The library is conservative in the same way. Clear and unabbreviated names are given for new functions, while names that appears in C and Perl libraries have -been took over from them. For example, @printf@, @getpwent@, @sub@, and @tr@. +been taken from them. For example, @printf@, @getpwent@, @sub@, and @tr@. It is also conservative in implementation. Assembler is not its option for @@ -67,18 +70,18 @@ conflicts with speed. h4. It is an object-oriented language -Ruby is an object-oriented language. It is not possible to forget about it -absolutely, when you talk about the features of Ruby. +Ruby is an object-oriented language. It is absolutely impossible to exclude it +from the features of Ruby. I will not give a page to this book about what an object-oriented language is. To tell about an object-oriented feature about Ruby, the expression of the code -that just going to be explained below is the exact sample. +that just going to be explained is the exact sample. h4. It is a script language -Ruby is a script language. It is also not possible to forget about it -absolutely, when you talk about the features of Ruby. To gain agreement of +Ruby is a script language. It seems also absolutely impossible to exclude this +from the features of Ruby. To gain agreement of everyone, an introduction of Ruby must include "object-oriented" and "script language". @@ -92,13 +95,14 @@ file from the command line, etc. However, I dare to use another definition, because I don't find much interest -in "what" a script language. To call it a script language, it at least has to -avoid gaining disagreement of calling it so. That's the definition I suggest. +in "what" a script language. +I have the only one measure to decide to call it a script language, +that is, whether no one would complain about calling it a script language. To fulfill this definition, I would define the meaning of "script language" as follows. -Whether the author of the language calls it "script language" or not. +A language that its author calls it a "script language". I'm sure this definition will have no failure. And Ruby fulfills this point. From 467a8f387f9dc53219f8d56b47594c744dfeee55 Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 28 Aug 2013 11:49:54 +0900 Subject: [PATCH 029/121] edit the last half of chapter 02 mainly the parts that were different from the original book. --- object.textile | 211 +++++++++++++++++++++++++++---------------------- 1 file changed, 117 insertions(+), 94 deletions(-) diff --git a/object.textile b/object.textile index a8bc834..26711c3 100644 --- a/object.textile +++ b/object.textile @@ -542,15 +542,16 @@ condition, instance variables. h3. `rb_ivar_set()` -Instance variables are what allows each object to store characteristic data. -Having it stored in the object itself (i.e. in the object structure) may seem -all right but how is it in practice? Let's look at the function -`rb_ivar_set()` that puts an object in an instance variable. +Instance variable is the mechanism that allows each object to hold its specific data. +Since it is specific to each object, +it seems good to store it in each object itself (i.e. in its object structure), +but is it really so? Let's look at the function +`rb_ivar_set()`, which assigns an object to an instance variable. ▼ `rb_ivar_set()`
-      /* write val in the id instance of obj */
+      /* assign val to the id instance variable of obj */
  984  VALUE
  985  rb_ivar_set(obj, id, val)
  986      VALUE obj;
@@ -579,11 +580,13 @@ all right but how is it in practice? Let's look at the function
 (variable.c)
 
-`rb_raise()` and `rb_error_frozen()` are both error checks. Error checks are -necessary, but it's not the main part of the treatment, so you should ignore -them at first read. +`rb_raise()` and `rb_error_frozen()` are both error checks. +This can always be said hereafter: +Error checks are necessary in reality, +but it's not the main part of the process. +Therefore, we should wholly ignore them at first read. -If we ignore the error handling, only the `switch` remains, but this +After removing the error handling, only the `switch` remains, but
 switch (TYPE(obj)) {
@@ -593,7 +596,7 @@ switch (TYPE(obj)) {
 }
 
-form is characteristic of `ruby`. `TYPE()` is the macro returning the type +this form is an idiom of `ruby`. `TYPE()` is the macro returning the type flag of the object structure (`T_OBJECT`, `T_STRING`, etc.). In other words as the type flag is an integer constant, we can branch depending on it with a `switch`. `Fixnum` or `Symbol` do not have structures, but inside `TYPE()` a @@ -624,8 +627,8 @@ the basis that their second member is `iv_tbl`. Let's confirm it in practice. (ruby.h)
-`iv_tbl` is the Instance Variable TaBLe. It stores instance variable names and -their corresponding value. +`iv_tbl` is the Instance Variable TaBLe. +It records the correspondences between the instance variable names and their values. In `rb_ivar_set()`, let's look again the code for the structures having `iv_tbl`. @@ -638,8 +641,8 @@ break;
`ROBJECT()` is a macro that casts a `VALUE` into a `struct -RObject*`. It's possible that `obj` points to a struct RClass, but as -we're only going to access the second member no problem will occur. +RObject*`. It's possible that what `obj` points to is actually a struct RClass, +but when accessing only the second member, no problem will occur. `st_init_numtable()` is a function creating a new `st_table`. `st_insert()` is a function doing associations in a `st_table`. @@ -647,8 +650,10 @@ a function doing associations in a `st_table`. In conclusion, this code does the following: if `iv_tbl` does not exist, it creates it, then stores the [variable name → object] association. -Warning: as `struct RClass` is a class object, this instance variable table is -for the use of the class object itself. In Ruby programs, it corresponds to +There's one thing to be careful about. +As `struct RClass` is the struct of a class object, +its instance variable table is for the class object itself. +In Ruby programs, it corresponds to something like the following:
@@ -659,8 +664,8 @@ end
 
 h3. `generic_ivar_set()`
 
-For objects for which the structure used is not `T_OBJECT`, `T_MODULE`, or
-`T_CLASS`, what happens when modifying an instance variable?
+What happens when assigning to an instance variable of
+an object whose structure is not one of `T_OBJECT T_MODULE T_CLASS`?
 
 ▼ `rb_ivar_set()` in the case there is no `iv_tbl`
 
@@ -672,14 +677,16 @@ For objects for which the structure used is not `T_OBJECT`, `T_MODULE`, or
 (variable.c)
 
-The control is transferred to `generic_ivar_set()`. Before looking at this +This is delegated to `generic_ivar_set()`. Before looking at this function, let's first explain its general idea. Structures that are not `T_OBJECT`, `T_MODULE` or `T_CLASS` do not have an `iv_tbl` member (the reason why they do not have it will be explained later). -However, a method linking an instance to a `struct st_table` would allow -instances to have instance variables. In `ruby`, this was solved by using a -global `st_table`, `generic_iv_table` (figure 7) for these associations. +However, even if it does not have the member, +if there's another method linking an instance to a `struct st_table`, +it would be able to have instance variables. In `ruby`, these associations are +solved by using a global `st_table`, `generic_iv_table` (figure 7). + !images/ch_object_givtable.png(`generic_iv_table`)! @@ -698,7 +705,7 @@ Let's see this in practice. 835 { 836 st_table *tbl; 837 - /* for the time being you should ignore this */ + /* for the time being you can ignore this */ 838 if (rb_special_const_p(obj)) { 839 special_generic_ivar = 1; 840 } @@ -707,7 +714,7 @@ Let's see this in practice. 842 generic_iv_tbl = st_init_numtable(); 843 } 844 - /* the treatment itself */ + /* the process itself */ 845 if (!st_lookup(generic_iv_tbl, obj, &tbl)) { 846 FL_SET(obj, FL_EXIVAR); 847 tbl = st_init_numtable(); @@ -738,12 +745,13 @@ be found". `st_insert()` was also already explained. It stores a new association in a table. -`st_add_direct()` is similar to `st_insert()`, but the part before adding the -association that checks if the key was already stored or not is different. In -other words, in the case of `st_add_direct()`, if a key already registered is +`st_add_direct()` is similar to `st_insert()`, +but it does not check if the key was already stored before adding an association. +It means, in the case of `st_add_direct()`, if a key already registered is being used, two associations linked to this same key will be stored. -`st_add_direct()` can be used when the check for existence has already been -done, as is the case here, or when a new table has just been created. +We can use `st_add_direct()` only when the check for existence has already been +done, or when a new table has just been created. +And this code would meet these requirements. `FL_SET(obj, FL_EXIVAR)` is the macro that sets the `FL_EXIVAR` flag in the `basic.flags` of `obj`. The `basic.flags` flags are all named `FL_xxxx` and @@ -751,40 +759,44 @@ can be set using `FL_SET()`. These flags can be unset with `FL_UNSET()`. The `EXIVAR` from `FL_EXIVAR` seems to be the abbreviation of EXternal Instance VARiable. -The setting of these flags is done to speed up the reading of instance +This flag is set to speed up the reading of instance variables. If `FL_EXIVAR` is not set, even without searching in -`generic_iv_tbl`, we directly know if the object has instance variables. And +`generic_iv_tbl`, we can see the object does not have any instance variables. And of course a bit check is way faster than searching a `struct st_table`. h3. Gaps in structures -Now you should understand how the instance variables are stored, but why are +Now you understood the way to store the instance variables, but why are there structures without `iv_tbl`? Why is there no `iv_tbl` in `struct RString` or `struct RArray`? Couldn't `iv_tbl` be part of `RBasic`? -Well, this could have been done, but there are good reasons why it was not. As +To tell the conclusion first, we can do such thing, but should not. As a matter of fact, this problem is deeply linked to the way `ruby` manages objects. -For example, in `ruby`, memory used by string data (`char[]`) is directly +In `ruby`, the memory used for string data (`char[]`) and such is directly allocated using `malloc()`. However, the object structures are handled in a particular way. `ruby` allocates them by clusters, and then distribute them -from these clusters. As at allocation time the diversity of types (and sizes) -of structures is difficult to handle, a type (`union`) that combines all -structures `RVALUE` was declared and an array of this type is managed. As this -type's size is the same as the biggest one of its members, if there is only -one big structure, there is a lot of unused space. That's why doing as much as -possible to regroup structures of similar size is desirable. The details about -`RVALUE` will be explained in chapter 5 "Garbage collection". - -Generally the most used structure is `struct RString`. After that, in programs -there are `struct RArray` (array), `RHash` (hash), `RObject` (user defined +from these clusters. And in this way, if the types (or rather their sizes) +were diverse, it's hard to manage, thus `RVALUE`, which is the union of +the all structures, is defined and the array of the unions is managed. + +The size of a union is the same as the size of the biggest member, +so for instance, if one of the structures is big, +a lot of space would be wasted. +Therefore, it's preferable that each structure size is as similar as possible. + +The most used structure might be usually `struct RString`. After that, +depending on each program, +there comes `struct RArray` (array), `RHash` (hash), `RObject` (user defined object), etc. However, this `struct RObject` only uses the space of `struct RBasic` + 1 pointer. On the other hand, `struct RString`, `RArray` and -`RHash` take the space of `struct RBasic` + 3 pointers. In other words, when -putting a `struct RObject` in the shared entity, the space for 2 pointers is -useless. And beyond that, if `RString` had 4 pointers, `RObject` would use less -that half the size of the shared entity. As you would expect, it's wasteful. +`RHash` take the space of `struct RBasic` + 3 pointers. In other words, +when the number of `struct RObject` is being increased, +the memory space of the two pointers for each object are wasted. +Furthermore, if the size of `RString` was as much as 4 pointers, +`Robject` would use less than the half size of the union, +and this is too wasteful. So the received merit for `iv_tbl` is more or less saving memory and speeding up. Furthermore we do not know if it is used often or not. In fact, @@ -794,7 +806,7 @@ was not much of a problem. Making large amounts of memory useless just for such functionality looks stupid. If you take all this into consideration, you can conclude that increasing the -size of object structures does not do any good. +size of object structures for `iv_tbl` does not do any good. h3. `rb_ivar_get()` @@ -835,7 +847,7 @@ how to get them. (variable.c)
-The structure is strictly the same. +The structure is completely the same. (A) For `struct RObject` or `RClass`, we search the variable in `iv_tbl`. As `iv_tbl` can also be `NULL`, we must check it before using it. Then if @@ -850,20 +862,21 @@ That's because you can read instance variables that have not been set in Ruby. (B) On the other hand, if the structure is neither `struct RObject` nor `RClass`, the instance variable table is searched in `generic_iv_tbl`. What `generic_ivar_get()` does can be easily guessed, so I won't explain it. I'd -rather want you to focus on the `if`. +rather want you to focus on the condition of the `if` statement. -I already told you that `generic_ivar_set()` sets the `FL_EXIVAR` flag to make -the check faster. +I already told you that the `FL_EXIRVAR` flag is set to the object on which +`generic_ivar_set()` is used. Here, that flag is utilized to make the check faster. And what is `rb_special_const_p()`? This function returns true when its parameter `obj` does not point to a structure. As no structure means no -`basic.flags`, no flag can be set, and `FL_xxxx()` will always returns false. -That's why these objects have to be treated specially. +`basic.flags`, no flag can be set in the first place. +Thus `FL_xxxx()` is designed to always return false for such object. +Hence, objects that are `rb_special_const_p()` should be treated specially here. h2. Structures for objects -In this section we'll see simply, among object structures, what the important -ones contain and how they are handled. +In this section, about the important ones among object structures, +we'll briefly see their concrete appearances and how to deal with them. h3. `struct RString` @@ -891,22 +904,25 @@ straightforward. Rather than a string, Ruby's string is more a byte array, and can contain any byte including `NUL`. So when thinking at the Ruby level, ending the string -with `NUL` does not mean anything. As C functions require `NUL`, for -convenience the ending `NUL` is there, however, it is not included in `len`. +with `NUL` does not mean anything. But as C functions require `NUL`, for +convenience the ending `NUL` is there. However, its size is not included in `len`. -When dealing with a string coming from the interpreter or an extension -library, you can write `RSTRING(str)->ptr` or `RSTRING(str)->len`, and access -`ptr` and `len`. But there are some points to pay attention to. +When dealing with a string from the interpreter or an extension library, +you can access `ptr` and `len` by writing +`RSTRING(str)->ptr` or `RSTRING(str)->len`, and it is allowed. +But there are some points to pay attention to. -# you have to check before if `str` really points to a `struct RString` +# you have to check if `str` really points to a `struct RString` +by yourself beforehand # you can read the members, but you must not modify them # you can't store `RSTRING(str)->ptr` in something like a local variable and use it later Why is that? First, there is an important software engineering principle: -Don't arbitrarily tamper with someone's data. Interface functions are there -for a reason. However, there are concrete reasons in `ruby`'s design -why you should not do such things as consulting or storing a pointer, and +Don't arbitrarily tamper with someone's data. +When there are interface functions, we should use them. +However, there are also concrete reasons in `ruby`'s design +why you should not refer to or store a pointer, and that's related to the fourth member `aux`. However, to explain properly how to use `aux`, we have to explain first a little more of Ruby's strings' characteristics. @@ -917,7 +933,7 @@ following code:
 s = "str"        # create a string and assign it to s
 s.concat("ing")  # append "ing" to this string object
-p(s)             # show the string
+p(s)             # show "string"
 
the content of the object pointed by `s` will become "`string`". It's @@ -947,26 +963,30 @@ end
Whatever the number of times you repeat the loop, the fourth line's `p` has to -show `"string"`. That's why the code `"str"` should create, each time, a string -object holding a different `char[]`. However, if no change occurs for a lot of -strings, useless copies of `char[]` can be created many times. It would be better +show `"string"`. +And to do so, the expression `"str"` must every time create an +object that holds a distinct `char[]`. +But there must be also the high possibility that strings are not modified at all, +and a lot of useless copies of `char[]` would be created in such situation. +If possible, we'd like to share one common `char[]`. -The trick that allows this to happen is `aux.shared`. String objects created -with a literal use one shared `char[]`. When a change occurs, the string is -copied in unshared memory, and the change is done on this new copy. This -technique is called "copy-on-write". When using a shared `char[]`, the flag +The trick to share is `aux.shared`. Every string object created +with a literal uses one shared `char[]`. And after a change occurs, +the object-specific memory is allocated. +When using a shared `char[]`, the flag `ELTS_SHARED` is set in the object structure's `basic.flags`, and `aux.shared` contains the original object. `ELTS` seems to be the abbreviation of `ELemenTS`. -But, well, let's return to our talk about `RSTRING(str)->ptr`. Even if -consulting the pointer is OK, you must not modify it, first because the value -of `len` or `capa` will no longer agree with the content, and also because when +Then, let's return to our talk about `RSTRING(str)->ptr`. +Though referring to a pointer is OK, you must not assign to it. +This is first because the value +of `len` or `capa` will no longer agree with the actual body, and also because when modifying strings created as litterals, `aux.shared` has to be separated. -To finish this section about `RString`, let's write some examples how to use -it. `str` is a `VALUE` that points to `RString`. +Before ending this section, I'll write some examples of dealing with `RString`. +I'd like you to regard `str` as a `VALUE` that points to `RString` when reading this.
 RSTRING(str)->len;               /* length */
@@ -1008,11 +1028,13 @@ length. `aux` is exactly the same as in `struct RString`. `aux.capa` is the
 From this structure, it's clear that Ruby's `Array` is an array and not a
 list. So when the number of elements changes in a big way, a `realloc()` must
 be done, and if an element must be inserted at an other place than the end, a
-`memmove()` will occur. But even if we do it, it's moving so fast it's really
-impressive on current machines.
+`memmove()` will occur. But even if it does it, it's moving so fast that we
+don't notice about that.
+Recent machines are really impressive.
 
-That's why the way to access it is similar to `RString`. You can consult
-`RARRAY(arr)->ptr` and `RARRAY(arr)->len` members, but can't set them, etc.,
+And the way to access to its members is similar to the way of `RString`.
+With `RARRAY(arr)->ptr` and `RARRAY(arr)->len`, you can refer to the members,
+and it is allowed, but you must not assign to them,
 etc. We'll only look at simple examples:
 
 
@@ -1047,17 +1069,18 @@ It's the structure for the instances of the regular expression class `Regexp`.
 (ruby.h)
 
-`ptr` is the regular expression after compilation. `str` is the string before +`ptr` is the compiled regular expression. `str` is the string before compilation (the source code of the regular expression), and `len` is this string's length. -As the `Regexp` object handling code doesn't appear in this book, we won't see +As any code to handle `Regexp` objects doesn't appear in this book, we won't see how to use it. Even if you use it in extension libraries, as long as you do not want to use it a very particular way, the interface functions are enough. h3. `struct RHash` -`struct RHash` is the structure for Ruby's `Hash` objects. +`struct RHash` is the structure for `Hash` object, +which is Ruby's hash table. ▼ `struct RHash` @@ -1075,7 +1098,7 @@ h3. `struct RHash` It's a wrapper for `struct st_table`. `st_table` will be detailed in the next chapter "Names and name tables". -`ifnone` is the value when a key does not have an attached value, its default +`ifnone` is the value when a key does not have an associated value, its default is `nil`. `iter_lev` is to make the hashtable reentrant (multithread safe). h3. `struct RFile` @@ -1119,8 +1142,8 @@ h3. `struct RData` `struct RData` has a different tenor from what we saw before. It is the structure for implementation of extension libraries. -Of course structures for classes created in extension libraries as necessary, -but as the types of these structures depend of the created class, it's +Of course structures for classes created in extension libraries are necessary, +but as the types of these structures depend on the created class, it's impossible to know their size or structure in advance. That's why a "structure for managing a pointer to a user defined structure" has been created on `ruby`'s side to manage this. This structure is `struct RData`. @@ -1139,12 +1162,12 @@ for managing a pointer to a user defined structure" has been created on
`data` is a pointer to the user defined structure, -`dfree` is the function used to free this structure, and -`dmark` is the function for when the "mark" of the mark and sweep occurs. +`dfree` is the function used to free that user defined structure, and +`dmark` is the function to do "mark" of the mark and sweep. Because explaining `struct RData` is still too complicated, for -the time being let's just look at its representation (figure 8). You'll read -a detailed explanation of its members in chapter 5 "Garbage collection" where -there'll be presented once again. +the time being let's just look at its representation (figure 8). +The detailed explanation of its members will be introduced +after we'll finish chapter 5 "Garbage collection". !images/ch_object_rdata.png(Representation of `struct RData`)! From 7b4def792737d60e43431aba064648048d6a5518 Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 28 Aug 2013 12:08:18 +0900 Subject: [PATCH 030/121] edit chapter 02 to use the word "struct" instead of "structure" when it means C structure. --- object.textile | 138 ++++++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/object.textile b/object.textile index 26711c3..9343373 100644 --- a/object.textile +++ b/object.textile @@ -33,7 +33,7 @@ In `ruby`, the body of an object is expressed by a struct and always handled via a pointer. A different struct type is used for each class, but the pointer type will always be `VALUE` (figure 1). -!images/ch_object_value.png(`VALUE` and structure)! +!images/ch_object_value.png(`VALUE` and struct)! Here is the definition of `VALUE`: @@ -74,18 +74,18 @@ something like the following. !images/ch_object_string.png(String object)! -Let's look at the definition of a few object structures. +Let's look at the definition of a few object structs. -▼ Examples of object structure +▼ Examples of object struct
-      /* structure for ordinary objects */
+      /* struct for ordinary objects */
  295  struct RObject {
  296      struct RBasic basic;
  297      struct st_table *iv_tbl;
  298  };
 
-      /* structure for strings (instance of String) */
+      /* struct for strings (instance of String) */
  314  struct RString {
  315      struct RBasic basic;
  316      long len;
@@ -96,7 +96,7 @@ Let's look at the definition of a few object structures.
  321      } aux;
  322  };
 
-      /* structure for arrays (instance of Array) */
+      /* struct for arrays (instance of Array) */
  324  struct RArray {
  325      struct RBasic basic;
  326      long len;
@@ -116,7 +116,7 @@ general.
 First, as `VALUE` is defined as `unsigned long`, it must be cast before
 being used when it is used as a pointer.
 That's why `Rxxxx()` macros have been made for each object
-structure. For example, for `struct RString` there is `RSTRING()`, for
+struct. For example, for `struct RString` there is `RSTRING()`, for
 `struct RArray` there is `RARRAY()`, etc... These macros are used like this:
 
 
@@ -127,10 +127,10 @@ RSTRING(str)->len;   /* ((struct RString*)str)->len */
 RARRAY(arr)->len;    /* ((struct RArray*)arr)->len */
 
-Another important point to mention is that all object structures start with a +Another important point to mention is that all object structs start with a member `basic` of type `struct RBasic`. As a result, if you cast this `VALUE` to `struct RBasic*`, you will be able to access the content of `basic`, regardless -of the type of structure pointed to by `VALUE`. +of the type of struct pointed to by `VALUE`. !images/ch_object_rbasic.png(`struct RBasic`)! @@ -150,13 +150,13 @@ for `struct RBasic`: (ruby.h)
-`flags` are multipurpose flags, mostly used to register the structure type +`flags` are multipurpose flags, mostly used to register the struct type (for instance `struct RObject`). The type flags are named `T_xxxx`, and can be obtained from a `VALUE` using the macro `TYPE()`. Here is an example:
 VALUE str;
-str = rb_str_new();    /* creates a Ruby string (its structure is RString) */
+str = rb_str_new();    /* creates a Ruby string (its struct is RString) */
 TYPE(str);             /* the return value is T_STRING */
 
@@ -176,38 +176,38 @@ section of this chapter. By the way, this member is named `klass` so as not to conflict with the reserved word `class` when the file is processed by a C++ compiler. -h4. About structure types +h4. About struct types -I said that the type of structure is stored in the `flags` member of -`struct Basic`. But why do we have to store the type of structure? It's to be -able to handle all different types of structure via `VALUE`. If you cast a -pointer to a structure to `VALUE`, as the type information does not remain, +I said that the type of struct is stored in the `flags` member of +`struct Basic`. But why do we have to store the type of struct? It's to be +able to handle all different types of struct via `VALUE`. If you cast a +pointer to a struct to `VALUE`, as the type information does not remain, the compiler won't be able to help. Therefore we have to manage the type -ourselves. That's the consequence of being able to handle all the structure +ourselves. That's the consequence of being able to handle all the struct types in a unified way. -OK, but the used structure is defined by the class so why are the structure -type and class are stored separately? Being able to find the structure type +OK, but the used struct is defined by the class so why are the struct +type and class are stored separately? Being able to find the struct type from the class should be enough. There are two reasons for not doing this. The first one is (I'm sorry for contradicting what I said before), in fact -there are structures that do not have a `struct RBasic` (i.e. they have no +there are structs that do not have a `struct RBasic` (i.e. they have no `klass` member). For example `struct RNode` that will appear in the second part of the book. However, `flags` is guaranteed to be in the beginning -members even in special structures like this. So if you put the type of -structure in `flags`, all the object structures can be differentiated in one +members even in special structs like this. So if you put the type of +struct in `flags`, all the object structs can be differentiated in one unified way. The second reason is that there is no one-to-one correspondence between class -and structure. For example, all the instances of classes defined at the Ruby -level use `struct RObject`, so finding a structure from a class would require -to keep the correspondence between each class and structure. That's why it's -easier and faster to put the information about the type in the structure. +and struct. For example, all the instances of classes defined at the Ruby +level use `struct RObject`, so finding a struct from a class would require +to keep the correspondence between each class and struct. That's why it's +easier and faster to put the information about the type in the struct. h4. The use of `basic.flags` Regarding the use of `basic.flags`, -because I feel bad to say it is the structure type "and such", +because I feel bad to say it is the struct type "and such", I'll illustrate it entirely here. (Figure 5) There is no need to understand everything right away, because this is prepared for the time when you will be wondering about it later. @@ -216,7 +216,7 @@ because this is prepared for the time when you will be wondering about it later. When looking at the diagram, it looks like that 21 bits are not used on 32 bit machines. On these additional bits, the flags `FL_USER0` to `FL_USER8` are -defined, and are used for a different purpose for each structure. In the +defined, and are used for a different purpose for each struct. In the diagram I also put `FL_USER0` (`FL_SINGLETON`) as an example. h3. Objects embedded in `VALUE` @@ -239,7 +239,7 @@ h4. Small integers All data are objects in Ruby, thus integers are also objects. But since there are so many kind of integer objects, -if each of them is expressed as a structure, +if each of them is expressed as a struct, it would risk slowing down execution significantly. For example, when incrementing from 0 to 50000, we would hesitate to create 50000 objects for only that purpose. @@ -269,7 +269,7 @@ In brief, shift 1 bit to the left, and bitwise or it with 1. | `1101000010001` | after conversion | That means that `Fixnum` as `VALUE` will always be an odd number. On the other -hand, as Ruby object structures are allocated with `malloc()`, they are +hand, as Ruby object structs are allocated with `malloc()`, they are generally arranged on addresses multiple of 4. So they do not overlap with the values of `Fixnum` as `VALUE`. @@ -438,12 +438,12 @@ methods. h3. `struct RClass` In Ruby, classes exist as objects during the execution. Of course. So there -must be a structure for class objects. That structure is `struct RClass`. Its -structure type flag is `T_CLASS`. +must be a struct for class objects. That struct is `struct RClass`. Its +struct type flag is `T_CLASS`. As classes and modules are very similar, there is no need to differentiate their -content. That's why modules also use the `struct RClass` structure, and are -differentiated by the `T_MODULE` structure flag. +content. That's why modules also use the `struct RClass` struct, and are +differentiated by the `T_MODULE` struct flag. ▼ `struct RClass` @@ -478,7 +478,7 @@ in `ruby` some clever conversions are made to make it look like single inheritance. The details of this process will be explained in the fourth chapter "Classes and modules". -Because of this conversion, `super` of the structure of `Object` points to `struct RClass` +Because of this conversion, `super` of the struct of `Object` points to `struct RClass` which is the entity of `Kernel` object and the `super` of Kernel is `NULL`. So to put it conversely, if `super` is `NULL`, its `RClass` is the entity of `Kernel` (figure 6). @@ -544,7 +544,7 @@ h3. `rb_ivar_set()` Instance variable is the mechanism that allows each object to hold its specific data. Since it is specific to each object, -it seems good to store it in each object itself (i.e. in its object structure), +it seems good to store it in each object itself (i.e. in its object struct), but is it really so? Let's look at the function `rb_ivar_set()`, which assigns an object to an instance variable. @@ -597,9 +597,9 @@ switch (TYPE(obj)) {
this form is an idiom of `ruby`. `TYPE()` is the macro returning the type -flag of the object structure (`T_OBJECT`, `T_STRING`, etc.). In other words as +flag of the object struct (`T_OBJECT`, `T_STRING`, etc.). In other words as the type flag is an integer constant, we can branch depending on it with a -`switch`. `Fixnum` or `Symbol` do not have structures, but inside `TYPE()` a +`switch`. `Fixnum` or `Symbol` do not have structs, but inside `TYPE()` a special treatment is done to properly return `T_FIXNUM` and `T_SYMBOL`, so there's no need to worry. @@ -607,7 +607,7 @@ Well, let's go back to `rb_ivar_set()`. It seems only the treatments of `T_OBJECT`, `T_CLASS` and `T_MODULE` are different. These 3 have been chosen on the basis that their second member is `iv_tbl`. Let's confirm it in practice. -▼ Structures whose second member is `iv_tbl` +▼ Structs whose second member is `iv_tbl`
       /* TYPE(val) == T_OBJECT */
@@ -630,7 +630,7 @@ the basis that their second member is `iv_tbl`. Let's confirm it in practice.
 `iv_tbl` is the Instance Variable TaBLe.
 It records the correspondences between the instance variable names and their values.
 
-In `rb_ivar_set()`, let's look again the code for the structures having
+In `rb_ivar_set()`, let's look again the code for the structs having
 `iv_tbl`.
 
 
@@ -665,7 +665,7 @@ end
 h3. `generic_ivar_set()`
 
 What happens when assigning to an instance variable of
-an object whose structure is not one of `T_OBJECT T_MODULE T_CLASS`?
+an object whose struct is not one of `T_OBJECT T_MODULE T_CLASS`?
 
 ▼ `rb_ivar_set()` in the case there is no `iv_tbl`
 
@@ -680,7 +680,7 @@ an object whose structure is not one of `T_OBJECT T_MODULE T_CLASS`?
 This is delegated to `generic_ivar_set()`. Before looking at this
 function, let's first explain its general idea.
 
-Structures that are not `T_OBJECT`, `T_MODULE` or `T_CLASS` do not have an
+Structs that are not `T_OBJECT`, `T_MODULE` or `T_CLASS` do not have an
 `iv_tbl` member (the reason why they do not have it will be explained later).
 However, even if it does not have the member,
 if there's another method linking an instance to a `struct st_table`,
@@ -764,10 +764,10 @@ variables. If `FL_EXIVAR` is not set, even without searching in
 `generic_iv_tbl`, we can see the object does not have any instance variables. And
 of course a bit check is way faster than searching a `struct st_table`.
 
-h3. Gaps in structures
+h3. Gaps in structs
 
 Now you understood the way to store the instance variables, but why are
-there structures without `iv_tbl`? Why is there no `iv_tbl` in
+there structs without `iv_tbl`? Why is there no `iv_tbl` in
 `struct RString` or `struct RArray`? Couldn't `iv_tbl` be part of `RBasic`?
 
 To tell the conclusion first, we can do such thing, but should not. As
@@ -775,18 +775,18 @@ a matter of fact, this problem is deeply linked to the way `ruby` manages
 objects.
 
 In `ruby`, the memory used for string data (`char[]`) and such is directly
-allocated using `malloc()`. However, the object structures are handled in a
+allocated using `malloc()`. However, the object structs are handled in a
 particular way. `ruby` allocates them by clusters, and then distribute them
 from these clusters. And in this way, if the types (or rather their sizes)
 were diverse, it's hard to manage, thus `RVALUE`, which is the union of
-the all structures, is defined and the array of the unions is managed.
+the all structs, is defined and the array of the unions is managed.
 
 The size of a union is the same as the size of the biggest member,
-so for instance, if one of the structures is big,
+so for instance, if one of the structs is big,
 a lot of space would be wasted.
-Therefore, it's preferable that each structure size is as similar as possible.
+Therefore, it's preferable that each struct size is as similar as possible.
 
-The most used structure might be usually `struct RString`. After that,
+The most used struct might be usually `struct RString`. After that,
 depending on each program,
 there comes `struct RArray` (array), `RHash` (hash), `RObject` (user defined
 object), etc. However, this `struct RObject` only uses the space of
@@ -806,7 +806,7 @@ was not much of a problem. Making large amounts of memory useless just for
 such functionality looks stupid.
 
 If you take all this into consideration, you can conclude that increasing the
-size of object structures for `iv_tbl` does not do any good.
+size of object structs for `iv_tbl` does not do any good.
 
 h3. `rb_ivar_get()`
 
@@ -859,7 +859,7 @@ instance variable that has not been set, we first leave the `if` then the
 `switch`. `rb_warning()` will then issue a warning and `nil` will be returned.
 That's because you can read instance variables that have not been set in Ruby.
 
-(B) On the other hand, if the structure is neither `struct RObject` nor
+(B) On the other hand, if the struct is neither `struct RObject` nor
 `RClass`, the instance variable table is searched in `generic_iv_tbl`. What
 `generic_ivar_get()` does can be easily guessed, so I won't explain it. I'd
 rather want you to focus on the condition of the `if` statement.
@@ -868,19 +868,19 @@ I already told you that the `FL_EXIRVAR` flag is set to the object on which
 `generic_ivar_set()` is used. Here, that flag is utilized to make the check faster.
 
 And what is `rb_special_const_p()`? This function returns true when its
-parameter `obj` does not point to a structure. As no structure means no
+parameter `obj` does not point to a struct. As no struct means no
 `basic.flags`, no flag can be set in the first place.
 Thus `FL_xxxx()` is designed to always return false for such object.
 Hence, objects that are `rb_special_const_p()` should be treated specially here.
 
-h2. Structures for objects
+h2. Object Structs
 
-In this section, about the important ones among object structures,
+In this section, about the important ones among object structs,
 we'll briefly see their concrete appearances and how to deal with them.
 
 h3. `struct RString`
 
-`struct RString` is the structure for the instances of the `String` class and
+`struct RString` is the struct for the instances of the `String` class and
 its subclasses.
 
 ▼ `struct RString`
@@ -948,7 +948,7 @@ time the string changes is a huge burden.
 That's why the memory pointed by `ptr` has been allocated with a size a little
 bigger than `len`. Because of that, if the added part can fit into the
 remaining memory, it's taken care of without calling `realloc()`, so it's
-faster. The structure member `aux.capa` contains the length including this
+faster. The struct member `aux.capa` contains the length including this
 additional memory.
 
 So what is this other `aux.shared`? It's to speed up the creation of literal
@@ -975,7 +975,7 @@ The trick to share is `aux.shared`. Every string object created
 with a literal uses one shared `char[]`. And after a change occurs,
 the object-specific memory is allocated.
 When using a shared `char[]`, the flag
-`ELTS_SHARED` is set in the object structure's `basic.flags`, and `aux.shared`
+`ELTS_SHARED` is set in the object struct's `basic.flags`, and `aux.shared`
 contains the original object. `ELTS` seems to be the abbreviation of
 `ELemenTS`.
 
@@ -1000,7 +1000,7 @@ rb_str_cat2(str, "end");         /* Concatenate a C string to a Ruby string */
 
 h3. `struct RArray`
 
-`struct RArray` is the structure for the instances of Ruby's array class
+`struct RArray` is the struct for the instances of Ruby's array class
 `Array`.
 
 ▼ `struct RArray`
@@ -1054,7 +1054,7 @@ p(ary[0])     # do p on ary[0] (the result is 9)
 
 h3. `struct RRegexp`
 
-It's the structure for the instances of the regular expression class `Regexp`.
+It's the struct for the instances of the regular expression class `Regexp`.
 
 ▼ `struct RRegexp`
 
@@ -1079,7 +1079,7 @@ not want to use it a very particular way, the interface functions are enough.
 
 h3. `struct RHash`
 
-`struct RHash` is the structure for `Hash` object,
+`struct RHash` is the struct for `Hash` object,
 which is Ruby's hash table.
 
 ▼ `struct RHash`
@@ -1103,7 +1103,7 @@ is `nil`. `iter_lev` is to make the hashtable reentrant (multithread safe).
 
 h3. `struct RFile`
 
-`struct RFile` is a structure for instances of the built-in IO class and
+`struct RFile` is a struct for instances of the built-in IO class and
 its subclasses.
 
 ▼ `struct RFile`
@@ -1140,13 +1140,13 @@ is written in the comments. Basically, it's a wrapper around C's `stdio`.
 h3. `struct RData`
 
 `struct RData` has a different tenor from what we saw before. It is the
-structure for implementation of extension libraries.
+struct for implementation of extension libraries.
 
-Of course structures for classes created in extension libraries are necessary,
-but as the types of these structures depend on the created class, it's
-impossible to know their size or structure in advance. That's why a "structure
-for managing a pointer to a user defined structure" has been created on
-`ruby`'s side to manage this. This structure is `struct RData`.
+Of course structs for classes created in extension libraries are necessary,
+but as the types of these structs depend on the created class, it's
+impossible to know their size or struct in advance. That's why a "struct
+for managing a pointer to a user defined struct" has been created on
+`ruby`'s side to manage this. This struct is `struct RData`.
 
 ▼ `struct RData`
 
@@ -1161,8 +1161,8 @@ for managing a pointer to a user defined structure" has been created on
 (ruby.h)
 
-`data` is a pointer to the user defined structure, -`dfree` is the function used to free that user defined structure, and +`data` is a pointer to the user defined struct, +`dfree` is the function used to free that user defined struct, and `dmark` is the function to do "mark" of the mark and sweep. Because explaining `struct RData` is still too complicated, for From 6ec4d00f01ba26b0a2fd0c3ccf3515bc67c085bf Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 28 Aug 2013 12:22:44 +0900 Subject: [PATCH 031/121] escaping (C) is not necessary when it is inside

---
 class.textile     | 4 ++--
 evaluator.textile | 2 +-
 gc.textile        | 2 +-
 object.textile    | 2 +-
 parser.textile    | 4 ++--
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/class.textile b/class.textile
index 6ae1162..9ad9ddd 100644
--- a/class.textile
+++ b/class.textile
@@ -1144,7 +1144,7 @@ the class can be found from the constant.
  193          rb_autoload_load(id);
  194      }
  195      if (rb_const_defined(rb_cObject, id)) {    /* (B) rb_const_defined */
- 196          klass = rb_const_get(rb_cObject, id);  /* ==(C)== rb_const_get */
+ 196          klass = rb_const_get(rb_cObject, id);  /* (C) rb_const_get */
  197          if (TYPE(klass) != T_CLASS) {
  198              rb_raise(rb_eTypeError, "%s is not a class", name);
  199          }                                      /* (D) rb_class_real */
@@ -1523,7 +1523,7 @@ h3. `include_class_new()`
  331      }
  332      klass->iv_tbl = RCLASS(module)->iv_tbl;     /* (B) */
  333      klass->m_tbl = RCLASS(module)->m_tbl;
- 334      klass->super = super;                       /* ==(C)== */
+ 334      klass->super = super;                       /* (C) */
  335      if (TYPE(module) == T_ICLASS) {             /* (D) */
  336          RBASIC(klass)->klass = RBASIC(module)->klass;   /* (D-1) */
  337      }
diff --git a/evaluator.textile b/evaluator.textile
index fc2ba21..461ecda 100644
--- a/evaluator.textile
+++ b/evaluator.textile
@@ -623,7 +623,7 @@ 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)==
+    RETURN(rb_eval(self, node->nd_else));      (C)
 }
 
diff --git a/gc.textile b/gc.textile index eaafc59..e3e1232 100644 --- a/gc.textile +++ b/gc.textile @@ -1493,7 +1493,7 @@ This hook is called "finalizer". 890 } 891 n++; 892 } - 893 ==(C)== else if (RBASIC(p)->flags == FL_MARK) { + 893 (C) else if (RBASIC(p)->flags == FL_MARK) { 894 /* the objects that need to finalize */ 895 /* are left untouched */ 896 } diff --git a/object.textile b/object.textile index 9343373..a9b6718 100644 --- a/object.textile +++ b/object.textile @@ -838,7 +838,7 @@ how to get them. 976 return generic_ivar_get(obj, id); 977 break; 978 } - /* ==(C)== */ + /* (C) */ 979 rb_warning("instance variable %s not initialized", rb_id2name(id)); 980 981 return Qnil; diff --git a/parser.textile b/parser.textile index c8c2df0..63a926a 100644 --- a/parser.textile +++ b/parser.textile @@ -2232,7 +2232,7 @@ Therefore, here is `heredoc_identifier()`. 2982 lex_strterm = rb_node_newnode(NODE_HEREDOC, 2983 rb_str_new(tok(), toklen()), /* nd_lit */ 2984 len, /* nd_nth */ -2985 /*==(C)==*/ lex_lastline); /* nd_orig */ +2985 /*(C)*/ lex_lastline); /* nd_orig */ 2986 2987 return term == '`' ? tXSTRING_BEG : tSTRING_BEG; 2988 } @@ -2289,7 +2289,7 @@ here_document(NODE *here) line = lex_lastline; /*(A)*/ rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len); lex_p = lex_pend; /*(B)*/ - if (nextc() == -1) { /*==(C)==*/ + if (nextc() == -1) { /*(C)*/ goto error; } } while (the currently read line is not equal to the finishing symbol); From 1e66d7da6c0bbdaa7dac57c82ec831c24f6400d0 Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Thu, 29 Aug 2013 15:53:24 +0900 Subject: [PATCH 032/121] Fix broken tags in fin --- fin.textile | 173 ++++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/fin.textile b/fin.textile index 9825ebe..09867bc 100644 --- a/fin.textile +++ b/fin.textile @@ -1,18 +1,16 @@ --- layout: default --- - - -第20章 Rubyの未来 -h1. 第20章 Rubyの未来 -h2. 解決すべき課題 +h1. Final Chapter: Ruby's future -@ruby@は「完成してしまったソフトウェア」ではない。まだまだ発展途上で +h2. Issues toe be addressed + +@ruby@ は「完成してしまったソフトウェア」ではない。まだまだ発展途上で あり、多くの課題を抱えている。まずは現在のインタプリタに内在する 問題を摘出してみよう。話題の順番はだいたい本書の章の順番に沿っている。 -h3. GCの性能 +h3. Performance of GC 現在のGCの性能は「特に悪くないが、特に良くもない」と言ったところだろう か。「特に悪くない」というのは「日常生活で困ることはない」ということで、 @@ -32,24 +30,24 @@ h3. GCの性能 いためこの点があまり問題にならないのだろう。だがいずれそういうものが出 てくればインクリメンタルGCの導入を考える必要もあるかもしれない。 -h3. パーサの実装 +h3. Implementation of parser -第二部で見たように@ruby@のパーサの実装は -既に@yacc@を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな +第二部で見たように @ruby@ のパーサの実装は +既に @yacc@ を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな い。拡張の予定がないのならいいが、この後には「キーワード引数」という -大物の導入が予定されているし、@yacc@の制限のせいで欲しい文法が表現でき +大物の導入が予定されているし、 @yacc@ の制限のせいで欲しい文法が表現でき ない、なんてことになったら悲しい。 -h3. パーサの再利用 +h3. Reuse of parser -Rubyのパーサは非常に複雑だ。特に@lex_state@のあたりを真面目に扱う +Rubyのパーサは非常に複雑だ。特に @lex_state@ のあたりを真面目に扱う のがとても大変である。そのせいで、Rubyプログラムを埋め込んだり、 Rubyプログラム自体を扱うプログラムを作るのが非常に難しくなっている。 -例えば筆者が開発しているツールで@racc@というものがある。@yacc@のRuby版 -なのでRを付けて@racc@だ。その@racc@では文法ファイルの構文などはほとんど -@yacc@と同じで、 +例えば筆者が開発しているツールで @racc@ というものがある。 @yacc@ のRuby版 +なのでRを付けて @racc@ だ。その @racc@ では文法ファイルの構文などはほとんど +@yacc@ と同じで、 アクションの部分だけがRubyのコードになっている。そのためにはRubyのコー ドをちゃんとパースしないとアクションの終わりを判定できないが、「ちゃん と」パースするのがとても難しい。仕方がないので今は「だいたい」パースで @@ -57,44 +55,44 @@ Rubyプログラム自体を扱うプログラムを作るのが非常に難し 他にRubyプログラムの解析が必要になる例としては -@indent@や@lint@のようなツールが +@indent@ や @lint@ のようなツールが 挙げられるが、こういうものを作るのにも非常に苦労する。リファクタリング ツールのような複雑なものになるともはや絶望的である。 -ではどうしようか。同じものを作り直すのが無理なら、@ruby@のオリジナルの +ではどうしようか。同じものを作り直すのが無理なら、 @ruby@ のオリジナルの パーサを部品として使えるようにすればいいのではないだろうか。つまり処理 系のパーサ自体をライブラリ化するわけだ。これは是非とも欲しい機能である。 -ただここで問題なのは、@yacc@を使う限りパーサがリエントラントにできない -ということだ。つまり@yyparse()@を再帰呼び出ししたり複数のスレッドから +ただここで問題なのは、 @yacc@ を使う限りパーサがリエントラントにできない +ということだ。つまり @yyparse()@ を再帰呼び出ししたり複数のスレッドから 呼んだりできないのである。だからパース中にRubyに制御が戻らないように実 装しなければならない。 h3. コード隠蔽 -現在の@ruby@は動かすプログラムのソースコードがないと動かせない。 +現在の @ruby@ は動かすプログラムのソースコードがないと動かせない。 つまりソースコードを他人に読ませたくない人達は困るだろう。 h3. インタプリタオブジェクト -現在の@ruby@インタプリタはプロセスに一つしか持てない、ということは +現在の @ruby@ インタプリタはプロセスに一つしか持てない、ということは 第13章で話した。複数のインタプリタを持つことが現実に可能 ならそのほうがよさそうではあるが、果たしてそういうことは実装可能なのだ ろうか。 h3. 評価器の構造 -いまの@eval.c@はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー -ムを埋め込むのも何かと厄介の元だし、@setjmp() longjmp()@を使いまくるのも +いまの @eval.c@ はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー +ムを埋め込むのも何かと厄介の元だし、 @setjmp() longjmp()@ を使いまくるのも わかりやすさと速度を下げている。特にレジスタの多いRISCマシンだと -@setjmp()@を使いまくると速度が落ちやすい。@setjmp()@ではレジスタを全て +@setjmp()@ を使いまくると速度が落ちやすい。 @setjmp()@ ではレジスタを全て 退避するからである。 h3. 評価器の速度 -@ruby@は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理 +@ruby@ は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理 系は速ければ速いほどいいのは間違いない。速度を上げる、即ち最適化をする にはどうしたらいいだろう。そういうときはまずプロファイルを採らねばなら ない。というわけで採った。 @@ -115,28 +113,28 @@ p(=emlist). これはとあるアプリケーションを動かしたときのプロファイルなのだが、一般 的なRubyプログラムのプロファイルにもかなり近い。つまりトップに圧倒的割 -合で@rb_eval()@が登場し、そのあとにGCと評価器中枢部、加えて処理に特有 +合で @rb_eval()@ が登場し、そのあとにGCと評価器中枢部、加えて処理に特有 の関数が混じる。例えばこのアプリケーションの場合は正規表現マッチ -(@ruby_re_match@)にかなり時間がかかっているようだ。 +( @ruby_re_match@ )にかなり時間がかかっているようだ。 ただそれがわかったとしてどう解決するかが問題だ。単純に考えれば -@rb_eval()@を速くすればいい、ということになるだろうが、@ruby@のコアに -関しては小手先の最適化をやる余地はもうほとんどない。@NODE_IF@のところ -で使われていたような「末尾再帰→@goto@変換」もほとんどやり尽くした感が +@rb_eval()@ を速くすればいい、ということになるだろうが、 @ruby@ のコアに +関しては小手先の最適化をやる余地はもうほとんどない。 @NODE_IF@ のところ +で使われていたような「末尾再帰→ @goto@ 変換」もほとんどやり尽くした感が ある。つまり根本的に考えかたを変えない限り向上の余地がないのだ。 h3. スレッドの実装 これは第19章でも話した。現在のrubyのスレッドの実装は非常に 問題が多い。特にネイティブスレッドとの相性の悪さはどうしようもない。 -@ruby@スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確 +@ruby@ スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確 かに他に代え難い長所なのだが、さすがにあの実装はずっと使い続けるには無 理があるのではなかろうか。 h2. @ruby@ 2 -続いて今度はこれらの問題点に対するオリジナルの@ruby@の動向を示す。 +続いて今度はこれらの問題点に対するオリジナルの @ruby@ の動向を示す。 h3. Rite @@ -152,7 +150,7 @@ h3. Rite 1.9.1〜2.0.0二年後くらいか -そして次々世代の開発版が@ruby@ 2、コードネームRite、である。 +そして次々世代の開発版が @ruby@ 2、コードネームRite、である。 この名前はLとRの区別がつけられない日本人へのオマージュらしい。 @@ -178,7 +176,7 @@ I hate C++. h3. GC GCの実装では、 -まず@Boehm GC@footnote{Boehm GC @http://www.hpl.hp.com/personal/Hans_Boehm/gc@}から +まず @Boehm GC@\footnote{Boehm GC `http://www.hpl.hp.com/personal/Hans_Boehm/gc`}から 試してみるということだ。Boehm GCは conservativeかつincrementalかつgenerationalなGCで、しかも ネイティブスレッドが動いてい @@ -190,12 +188,12 @@ conservativeかつincrementalかつgenerationalなGCで、しかも h3. パーサ 仕様の点では、括弧を省略したメソッド呼び出しのネストが一律禁止になりそ -うである。見てきたように@command_call@は文法全域にかなりの影響を与えてい +うである。見てきたように @command_call@ は文法全域にかなりの影響を与えてい た。これが簡略化されればパーサもスキャナも随分すっきりするはずだ。 ただし括弧の省略自体がなくなることはありえない。 -また実装面では@yacc@を使い続けるかどうかでまだ思案中ということだ。使わ +また実装面では @yacc@ を使い続けるかどうかでまだ思案中ということだ。使わ ないとすれば手書きで、ということだが、あれだけ複雑なものを手で実装でき るか、不安は残る。どちらを選んでも茨の道には違いない。 @@ -205,16 +203,16 @@ h3. 評価器 主眼は二点だ。 -@rb_eval()@のような再帰呼び出しをなくす +@rb_eval()@ のような再帰呼び出しをなくす バイトコードインタプリタへの移行 -まず@rb_eval()@の再帰呼び出しをなくす。なくす方法については「末尾再帰 -→@goto@変換」のような感じ、と言うのが一番直感的だろうか。一つの -@rb_eval()@の中で@goto@を使い、ぐるぐる回るわけだ。するとまず関数呼び -出しが減るし、@return@や@break@のために使っていた@setjmp()@も不要にな +まず @rb_eval()@ の再帰呼び出しをなくす。なくす方法については「末尾再帰 +→ @goto@ 変換」のような感じ、と言うのが一番直感的だろうか。一つの +@rb_eval()@ の中で @goto@ を使い、ぐるぐる回るわけだ。するとまず関数呼び +出しが減るし、 @return@ や @break@ のために使っていた @setjmp()@ も不要にな る。ただしCで定義されたメソッドの呼び出しが入れば嫌でも関数を呼ばざ -るを得ないので、その区切りではやはり@setjmp()@が必要だ。 +るを得ないので、その区切りではやはり @setjmp()@ が必要だ。 バイトコード(byte code)というのはようするに機械語のプログラムみたい @@ -236,7 +234,7 @@ h3. 評価器 ので、そう大きな影響はない。 -バイトコードの評価器がどんなふうになるか知りたければ@regex.c@を見てみ +バイトコードの評価器がどんなふうになるか知りたければ @regex.c@ を見てみ るとよい。あとはPythonがバイトコードインタプリタだ。 h3. スレッド @@ -251,7 +249,7 @@ h3. スレッド その点はとりあえずグローバルロックをかけて解決するようである。 -それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。@ruby@の +それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。 @ruby@ の 継続はスレッドの実装に大きく依存しているので、スレッドがネイティブスレッ ドになれば継続も自然と消滅する。あれが付いているのは「実装できて しまった」からだし、ほとんど使われていないので問題ないだろう。 @@ -273,32 +271,32 @@ h3. M17N 具体的にRubyを多言語化するためには何が必要か。一つにはパーサの対応、も -う一つは文字列関係のライブラリ、具体的には@String@と@Regexp@の対応、の +う一つは文字列関係のライブラリ、具体的には @String@ と @Regexp@ の対応、の 二つが必要である。 パーサの対応とは、コメントや文字列リテラル、正規表現リテラルに任意言語 (正確にはエンコーディング)を許すことだ。これが易しそうで難しい。 -まず、@ruby@のパーサに +まず、 @ruby@ のパーサに エンコーディングを伝える方法が必要である。これまで見てきたよ うにRubyのプログラムは例外なくパーサを抜けたあとに評価される。つまりパー サにエンコーディングを伝えるのに通常の構文を使うことはできない。だから エンコーディングを指定するためになんらかの構文を追加する必要がある。 -ライブラリでの対応はわりと簡単だ。現在ある@mbclen()@という仕組みを +ライブラリでの対応はわりと簡単だ。現在ある @mbclen()@ という仕組みを 素直に拡張したものになっている。 -M17N対応@ruby@は既に実装されており、CVSレポジトリの -@ruby_m17n@ブランチから +M17N対応 @ruby@ は既に実装されており、CVSレポジトリの +@ruby_m17n@ ブランチから 取得可能だ。実装されたのに取り込まれていないのは仕様が成熟していな いと判断されたためである。いいインターフェイスさえ設計できれば1.9の途中 にでも入るのではないだろうか。 h3. IO -現在のRubyの@IO@クラスは単純な@stdio@のラッパーなのだが、 +現在のRubyの @IO@ クラスは単純な @stdio@ のラッパーなのだが、 このアプローチは @@ -306,15 +304,15 @@ h3. IO バッファリングを細かく制御したい -という二点で不満があった。そこでRiteでは@stdio@を自前で持つ +という二点で不満があった。そこでRiteでは @stdio@ を自前で持つ ことになりそうである。 h2. Ruby Hacking Guide -ここまで我々は常に@ruby@を外から観察する者として行動してきた。だがもち -ろん@ruby@は展示ケースに収められた製品とは違う。即ち我々の行動いかんに +ここまで我々は常に @ruby@ を外から観察する者として行動してきた。だがもち +ろん @ruby@ は展示ケースに収められた製品とは違う。即ち我々の行動いかんに よってはこちらから影響を与えることができるのである。本書最後の節はコミュ -ニティから提案された@ruby@に対する働きかけについて話し、現在と未来の +ニティから提案された @ruby@ に対する働きかけについて話し、現在と未来の Ruby Hackerたちに対する餞とする。 h3. 世代別GC @@ -324,7 +322,7 @@ h3. 世代別GC 思ったより速度が出ない -最新の@ruby@に合わせてアップデートが必要 +最新の @ruby@ に合わせてアップデートが必要 という点が問題なのだが、この場では初めての大型非公式パッチで @@ -336,7 +334,7 @@ h3. 鬼車 GNU regexはもともとEmacsのために書かれたもので、それをマルチバイト対応 にしたものをさらにまつもとさんがPerl互換に改造した。という経緯から容易 に想像できるように、非常に複雑怪奇な構造になってしまっている。またこの -GNU regexpのライセンスがLGPLであるために@ruby@のライセンスが非常にやや +GNU regexpのライセンスがLGPLであるために @ruby@ のライセンスが非常にやや こしくなっており、かねてからこのエンジンの置き換えが課題になってきた。 @@ -344,22 +342,23 @@ GNU regexpのライセンスがLGPLであるために@ruby@のライセンスが である。これがかなり出来がよいらしく、すぐにでも本体に取りこまれそうだ。 -鬼車は@ruby@のCVSレポジトリから以下のようにして入手できる。 +鬼車は @ruby@ のCVSレポジトリから以下のようにして入手できる。 -p(=screen). +
 
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma
 
+ h3. ripper -続いて拙作のripper。@parse.y@を改造して拡張ライブラリにしたものだ。 -@ruby@本体に対する変更というわけではないが、パーサのコンポーネント化の +続いて拙作のripper。 @parse.y@ を改造して拡張ライブラリにしたものだ。 +@ruby@ 本体に対する変更というわけではないが、パーサのコンポーネント化の 一つの方向性としてここで紹介しておく。 ストリーム系のインターフェイスで実装しており、トークンのスキャンだの パーサでの還元だのをイベント形式で拾うことができる。添付CD-ROMに入れて -おいたfootnote{ripper:添付CD-ROMの@archives/ripper-0.0.5.tar.gz@}ので -使ってみてほしい。なお、このバージョンは半年ほど前の@ruby@ 1.7ベース +おいた\footnote{ripper: 添付 CD-ROM の @archives/ripper-0.0.5.tar.gz@ }ので +使ってみてほしい。なお、このバージョンは半年ほど前の @ruby@ 1.7ベース なので今の文法とは少し違う。 @@ -369,14 +368,14 @@ h3. ripper h3. 代替パーサ -まだ影も形もないプロダクトではあるが、@ruby@とは全く独立に使える -RubyのパーサをC++で書いている人もいるようだ(@[ruby-talk:50497]@)。 +まだ影も形もないプロダクトではあるが、 @ruby@ とは全く独立に使える +RubyのパーサをC++で書いている人もいるようだ ( @[ruby-talk:50497]@ )。 h3. JRuby さらに過激に、インタプリタ全体を書き直してしまえー、 という動きもある。例えばJavaで書いたRuby -「JRubyfootnote{JRuby @http://jruby.sourceforge.net@}」 +「JRuby \footnote{JRuby `http://jruby.sourceforge.net`}」 というものが登場している。Jan Arne Petersenさん以下、 かなりの大所帯で実装しているようだ。 @@ -385,7 +384,7 @@ h3. JRuby パーサはかなりちゃんとできている。ヒアドキュメントや空白の微妙な挙動まで正確に再現されている。 -@instance_eval@が効かないようだ(これは仕方ないか) +@instance_eval@ が効かないようだ(これは仕方ないか) 組み込みライブラリはまだ少ない(これも仕方ない) 拡張ライブラリは使えない(あたりまえ) RubyのUNIX centricなところが全部削られているので既存のスクリプトがそのまま動く可能性は低いと思われる @@ -393,7 +392,7 @@ RubyのUNIX centricなところが全部削られているので既存のスク ということは言えそうだ。ちなみに最後の「遅い」がどのくらいかと言うと、 -オリジナルの@ruby@の20倍くらい(実行時間が)である。ここまで遅いとさす +オリジナルの @ruby@ の20倍くらい(実行時間が)である。ここまで遅いとさす がに苦しい。やはりJava VMの上でRuby VMが動いているわけだから、遅くない はずがないのだ。マシンが20倍速になってくれるのを待つしかあるまい。 @@ -403,7 +402,7 @@ RubyのUNIX centricなところが全部削られているので既存のスク h3. NETRuby Javaで動くならC#でも動くだろう。というわけでC#で書いたRuby、 -「NETRubyfootnote{NETRuby @http://sourceforge.jp/projects/netruby/@}」 +「NETRuby\footnote{NETRuby `http://sourceforge.jp/projects/netruby/`}」 というのが登場した。作者はartonさんである。 @@ -416,44 +415,44 @@ Javaで動くならC#でも動くだろう。というわけでC#で書いたRub 例外処理の互換性がいまいち -というあたりが問題らしい。しかし@instance_eval@は動くらしい(驚愕)。 +というあたりが問題らしい。しかし @instance_eval@ は動くらしい(驚愕)。 -h3. @ruby@の開発に参加するには +h3. @ruby@ の開発に参加するには -@ruby@の開発者はあくまでまつもとゆきひろさん個人であり、最終的な -@ruby@の方向については絶対的な権限がある。だが同時に@ruby@は +@ruby@ の開発者はあくまでまつもとゆきひろさん個人であり、最終的な +@ruby@ の方向については絶対的な権限がある。だが同時に @ruby@ は オープンソースソフトウェアであり、誰でも開発に参加できる。参加できる、 というのは、意見を提案したりパッチを出したりできるということだ。 以下、具体的な参加方法について話す。 -@ruby@の場合はメーリングリストを中心に開発が進んでいるので、各メーリン +@ruby@ の場合はメーリングリストを中心に開発が進んでいるので、各メーリン グリストに参加するのがよい。現在コミュニティの中心となっているメーリ ングリストは -@ruby-list@、@ruby-dev@、@ruby-talk@の三つである。@ruby-list@は +@ruby-list@, @ruby-dev@, @ruby-talk@ の三つである。 @ruby-list@ は 「Rubyに関係することならなんでもOK」のメーリングリストで、日本語である。 -@ruby-dev@は開発版@ruby@の話をするメーリングリストで、これも日本語であ -る。@ruby-talk@は英語のメーリングリストだ。参加方法はRubyの -公式サイトfootnote{Rubyの公式サイト:@http://www.ruby-lang.org/ja/@} +@ruby-dev@ は開発版 @ruby@ の話をするメーリングリストで、これも日本語であ +る。 @ruby-talk@ は英語のメーリングリストだ。参加方法はRubyの +公式サイト\footnote{Rubyの公式サイト `http://www.ruby-lang.org/ja/`} の「メーリングリスト」のページに載っている。これらのメーリングリストは どれも読むだけのメンバーも歓迎なので、とりあえずしばらく参加してみて 議論を眺め、雰囲気を捕むといいのではないだろうか。 -日本から活動が始まったRubyだが、最近は「主導権は@ruby-talk@に移った」 +日本から活動が始まったRubyだが、最近は「主導権は @ruby-talk@ に移った」 と言われてしまったりすることもある。 -だが開発の中心が相変わらず@ruby-dev@であることに変わりはない。なにしろ -@ruby@のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語 -ユーザなのでわざわざ英語で話すのも面倒だし、自然と@ruby-dev@に足が向い +だが開発の中心が相変わらず @ruby-dev@ であることに変わりはない。なにしろ +@ruby@ のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語 +ユーザなのでわざわざ英語で話すのも面倒だし、自然と @ruby-dev@ に足が向い てしまう。将来英語を使うコアメンバーが増えてくれば状況も変わるかもしれ -ないが、当分の間は@ruby@開発のコアは@ruby-dev@だろう。 +ないが、当分の間は @ruby@ 開発のコアは @ruby-dev@ だろう。 ただ日本語が使えないと開発に参加できないというのも困るので、今は -@ruby-dev@の要約を一週間に一度英訳して@ruby-talk@に流すようになってい +@ruby-dev@ の要約を一週間に一度英訳して @ruby-talk@ に流すようになってい る。筆者もその要約に参加しているのだが、現在は三人の持ち回りで やっているため非常に厳しい。要約を手伝ってくれるメンバーは常時 -募集中である。我こそはと思うかたは是非@ruby-list@で参加表明して +募集中である。我こそはと思うかたは是非 @ruby-list@ で参加表明して いただきたい。 @@ -461,13 +460,13 @@ h3. @ruby@の開発に参加するには 各種ドキュメントやウェブサイトの整備も必要である。そしてそういうことを してくれる人は常に不足ぎみだ。 ドキュメント関連の活動にもいちおう専用メーリングリストがあるが、とりあえ -ずは@ruby-list@で「何かやりたい」と言ってくれればいい。筆者もできるだ +ずは @ruby-list@ で「何かやりたい」と言ってくれればいい。筆者もできるだ け答えるようにするし、他のメンバーも反応してくれるだろう。 h3. 最後に さて、長かった本書もこれで終わりだ。ページ数との兼ね合いもあるのであら -ゆる部分を懇切丁寧にというわけにはいかなかったが、@ruby@の根幹について +ゆる部分を懇切丁寧にというわけにはいかなかったが、 @ruby@ の根幹について は全て語り尽くした。これ以上ウダウダと付け加えるのはよそう。まだわから ないことがあれば納得するまで自分でソースコードを読んで確かめてほしい。 From 0bd565381758f39138ac371d7fabb7f813f24f50 Mon Sep 17 00:00:00 2001 From: Mark Burns Date: Thu, 29 Aug 2013 08:13:02 +0100 Subject: [PATCH 033/121] First paragraph of 'Issues to be addressed' in final chapter --- fin.textile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fin.textile b/fin.textile index 09867bc..97e70cc 100644 --- a/fin.textile +++ b/fin.textile @@ -4,11 +4,15 @@ layout: default h1. Final Chapter: Ruby's future -h2. Issues toe be addressed +h2. Issues to be addressed + +@ruby@ isn't 'completely finished software'。It's still being developed, +there are still a lot of issues. Firstly, we want to try removing +inherent problems in the interpreter. + +The order of the topics is mostly in the same order as the chapters of +this book. -@ruby@ は「完成してしまったソフトウェア」ではない。まだまだ発展途上で -あり、多くの課題を抱えている。まずは現在のインタプリタに内在する -問題を摘出してみよう。話題の順番はだいたい本書の章の順番に沿っている。 h3. Performance of GC From bc4a34e46114295cce05477fbbf563e7d4a5644c Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 29 Aug 2013 17:15:22 +0900 Subject: [PATCH 034/121] edit intro --- intro.textile | 125 ++++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/intro.textile b/intro.textile index 4cd50c3..c81268e 100644 --- a/intro.textile +++ b/intro.textile @@ -111,19 +111,20 @@ Therefore I call Ruby a "script language". h4. It's an interpreter @ruby@ is an interpreter. That's the fact. But why it's an interpreter? For -example, couldn't it be made as a compiler? The answer should be "no", because -I guess Ruby has at least something better than being an interpreter than a -compiler. Well, what is good about being an interpreter? +example, couldn't it be made as a compiler? +It must be because in some points being an interpreter is better than being +a compiler ... at least for ruby, it must be better. +Well, what is good about being an interpreter? As a preparation step to investigating into it, let's start by thinking about the difference between an interpreter and a compiler. If the matter is to -attempt a comparison with the process how a program is executed theoretically, +attempt a theoretical comparison in the process how a program is executed, there's no difference between an interpreter language and a compile language. -It may be possible to say that a compiler language involves an interpreter, -because of the fact that CPU "interprets" a code into a machine language using -a compiler. What's the difference actually? I suppose it's in a practical -things - in the process of development. +Because it works by letting CPU interpret the code compiled to the machine +language, it may be possible to say it works as an interpretor. +Then where is the place that actually makes a difference? +It is a more practical place, in the process of development. I know somebody, as soon as hearing "in the process of development", would @@ -137,60 +138,63 @@ side. Well, why people perceive an interpreter and compiler so much different like -this? I think that it is because the developers have long distinguished the use -of the implementations of these languages according to the characteristics. In -short, a comparatively small, a daily routine fits well with developing an -interpreter language. On the other hand, a compiler language is a goal for a -large project where a number of people are involved in the development and -accuracy is required. That may be because of the speed, as well as the -readiness of creating a language. +this? I think that it is because the language developers so far have chosen +either implementation based on the trait of each language. In other words, +if it is a language for a comparatively small purpose such as a daily routine, +it would be an interpretor. +If it is for a large project where a number of people are involved in the +development and accuracy is required, +it would be a compiler. +That may be because of the speed, as well as the ease of creating a language. -Therefore, "it's handy because it's an interpreter" is merely an outsized myth. +Therefore, I think "it's handy because it's an interpreter" is an outsized myth. Being an interpreter doesn't necessarily contribute the readiness in usage; seeking readiness in usage naturally makes your path toward building an -interprer language. +interpreter language. Anyway, @ruby@ is an interpreter; it has an important fact about where this -book is facing, so I emphasize it here again. It doesn't matter whether it's -easy being an interpreter; anyway @ruby@ is implemented as an interpreter. +book is facing, so I emphasize it here again. +Though I don't know about "it's handy because it is an interpreter", +anyway @ruby@ is implemented as an interpreter. h4. High portability -Even with a fundamental problem that the interface is built targeting Unix, I -would insist @ruby@ possesses a high portability. It doesn't often require an -unfamiliar library. It doesn't have a part written in assembler gorigorily. -Therefore it's easy to port to a new platform, comparatively. Namely, it works +Even with a problem that fundamentally the interfaces are Unix-centered, I +would insist @ruby@ possesses a high portability. +It doesn't require any extremely unfamiliar library. +It has only a few parts written in assembler. +Therefore porting to a new platform is comparatively easy. Namely, it works on the following platforms currently. -Linux -Win32 (Windows 95, 98, Me, NT, 2000, XP) -Cygwin -djgpp -FreeBSD -NetBSD -OpenBSD -BSD/OS -Mac OS X -Solaris -Tru64 UNIX -HP-UX -AIX -VMS -UX/4800 -BeOS -OS/2 (emx) -Psion - - -The main machine of the author Matsumoto is Linux, reportedly. You can assume -that a Linux will not fail to build any version of ruby. - - -Furthermore, a typical Unix environment basically can expect a stable -functionality. Considering the release cycle of packages, the primary option +* Linux +* Win32 (Windows 95, 98, Me, NT, 2000, XP) +* Cygwin +* djgpp +* FreeBSD +* NetBSD +* OpenBSD +* BSD/OS +* Mac OS X +* Solaris +* Tru64 UNIX +* HP-UX +* AIX +* VMS +* UX/4800 +* BeOS +* OS/2 (emx) +* Psion + + +I heard that the main machine of the author Matsumoto is Linux. +Thus when using Linux, you will not fail to compile any time. + + +Furthermore, you can expect a stable functionality on a (typical) Unix environment. +Considering the release cycle of packages, the primary option for the environment to hit around @ruby@ should fall on a branch of PC UNIX, currently. @@ -221,27 +225,29 @@ the Palm platform, rather than the processes of actual implementation. Well I saw a porting to Psion has been done. ([ruby-list:36028]). -How about hot stories about VM seen in Java and .NET? I need to mention these -together with implementation in the final chapter. +How about hot stories about VM seen in Java and .NET? +Because I'd like to talk about them combining together with the implementation, +this topic will be in the final chapter. + h4. Automatic memory control Functionally it's called GC, or Garbage Collection. Saying it in C-language, this feature allows you to skip @free()@ after @malloc()@. Unused memory is detected by the system automatically, and will be released. It's so convenient -that once you get used to GC you will likely be unwilling to do it manual +that once you get used to GC you won't be willing to do such manual memory control again. The topics about GC have been common because of its popularity in recent -languages with GC as a standard set, and the GS is fun to talk about because it -has a lot to devise better algorithms. +languages with GC as a standard set, and it is fun that +its algorithms can still be improved further. h4. Typeless variables The variables in Ruby don't have types. The reason is probably typeless variables conforms more with polymorphism, which is one of the strongest -features of an object-oriented language. Of course a language with variable +advantages of an object-oriented language. Of course a language with variable type has a way to deal with polymorphism. What I mean here is a typeless variables have better conformance. @@ -253,15 +259,16 @@ practically. Yet, this is certainly an appealing point if a language seeks for h4. Most of syntactic elements are expressions -This topic is probably difficult to understand it instantly without needs +This topic is probably difficult to understand instantly without a little supplemental explanation. For example, the following C-language program -contains a syntactic error. +results in a syntactic error.
 
 result = if (cond) { process(val); } else { 0; }
 
-Because the C-language syntax defines @if@ as a statement. See following rewrite. +Because the C-language syntax defines @if@ as a statement. +But you can write it as follows.
 
 result = cond ? process(val) : 0;
@@ -271,7 +278,7 @@ This rewrite is possible because the conditional operator (@a?b:c@) is defined
 as an expression.
 
 
-On the other hand, Ruby acceps a following expression because @if@ is an expression.
+On the other hand, in Ruby, you can write as follows because @if@ is an expression.
 
 
 
 result = if cond then process(val) else nil end

From fbf120b12de8b241ce11a2c58db920ecf6fe66e8 Mon Sep 17 00:00:00 2001
From: Yohei YASUKAWA 
Date: Thu, 29 Aug 2013 20:37:46 +0900
Subject: [PATCH 035/121] Translate images in Intro

---
 images/ch_abstract_ci.jpg   | Bin 6556 -> 11276 bytes
 images/ch_abstract_repo.jpg | Bin 8826 -> 17018 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/images/ch_abstract_ci.jpg b/images/ch_abstract_ci.jpg
index 7cec9498f55021540caf4725974c7e8d6e4cf209..59b713d12f9799d5d9aad9bb332770aab8c630c2 100644
GIT binary patch
literal 11276
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
Vj)AVQ<^B!Ze?#|wDT@dP{|DN!tVsX>

literal 6556
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
NGNu0q4gO@}zW{Rj(PjVu

diff --git a/images/ch_abstract_repo.jpg b/images/ch_abstract_repo.jpg
index af55ec8507e6a53390e1dbdff895cce116acd006..e024ce5096d5f835e9a5b45f6f59bc89271ab2d6 100644
GIT binary patch
literal 17018
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
BY99aq

literal 8826
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
Date: Sun, 1 Sep 2013 02:11:40 +0900
Subject: [PATCH 036/121] edit preface

---
 preface.textile | 220 +++++++++++++++++++++++++-----------------------
 1 file changed, 114 insertions(+), 106 deletions(-)

diff --git a/preface.textile b/preface.textile
index 40a8022..0bed3a2 100644
--- a/preface.textile
+++ b/preface.textile
@@ -8,9 +8,9 @@ h2. Preface
 This book explores several themes with the following goals in mind:
 
 
-To have knowledge of the structure of @ruby@
-To gain knowledge about language processing systems in general
-To acquire skills in reading source code
+* To have knowledge of the structure of @ruby@
+* To gain knowledge about language processing systems in general
+* To acquire skills in reading source code
 
 
 Ruby is an object-oriented language developed by Yukihiro Matsumoto. The
@@ -23,17 +23,18 @@ to investigate @ruby@ as a whole.
 Secondly, by knowing about the implementation of Ruby, we will be able to know
 about other language processing systems. I tried to cover all topics necessary
 for implementing a language, such as hash table, scanner and parser, evaluation
-procedure, and many others. Although this book is not intended as a text book
-and I don't go through entire topics and schemes for a language processing
-system, I tried to include adequate explanations about these concepts. For
-those who are not familiar with the Ruby language yet, a brief summary is
-included to help understand the topics.
+procedure, and many others. Because this book is not intended as a text book,
+going through entire areas and ideas without any lack was not reasonable.
+However the parts relating to the essential structures of a language
+implementation are adequately explained.
+And a brief summary of Ruby language itself is also included
+so that readers who don't know about Ruby can read this book.
 
 
 The main themes of this book are the first and the second point above. Though,
 what I want to emphasize the most is the third one: To acquire skill in reading
-source code. I dare to say it's a "hidden" theme. I will explain why we need
-this.
+source code. I dare to say it's a "hidden" theme. I will explain why I thought
+it is necessary.
 
 
 It is often said "To be a skilled programmer, you should read source code
@@ -45,25 +46,29 @@ It's clearly one-sided.
 
 
 Can you, perhaps, naturally read code just because you know how to write a
-program? Is it so easy to read code that all programmers are already able to
-read any code by another programmer? I don't think so.  To be skilled in
-reading code is certainly as difficult as writing code.
+program? Is it true that reading codes is so easy that all people in this world
+can read code written by others with no sweat? I don't think so.
+Reading programs is certainly as difficult as writing programs.
 
 
-In light of such questions, this book doesn't simply provide a general
-explanation of the @ruby@ language, but demonstrates procedures for analyzing
-source code. When I started writing this book, I had some experience with the
-Ruby language, but I did not fully understand the inner structure of the @ruby@
-implementation. In other words, this book begins exploring @ruby@ from the same
-starting place as the reader. This book is the summary of the process and
-results of my code analysis from that point.
+Therefore, this book does not simply explain @ruby@ as something already known,
+rather demonstrate the analyzing process as graphic as possible.
+Though I think I'm a reasonably seasoned Ruby programmer,
+I did not fully understand the inner structure of @ruby@ at the time when I
+started to write this book.
+In other words, regarding the content of @ruby@,
+I started from the position as close as possible to readers.
+This book is the summary of both the analyzing process started from that point
+and its result.
 
 
 I asked Yukihiro Matsumoto, the author of @ruby@, for supervision. But I
 thought the spirit of this book would be lost if each analysis was monitored by
 the author of the language himself. Therefore I limited his review to the final
-stage of writing. In this way, I tried to assure the correctness of the
-contents, keeping the goal of reading code alive at the same time.
+stage of writing. In this way,
+without loosing the sense of actually reading the source codes,
+I think I could also assure the correctness of the contents.
+
 
 To be honest, this book is not easy. In the very least, it is limited in its
 simplicity by the inherent complexity of its aim. However, this complexity may
@@ -72,8 +77,9 @@ chattering around a piece of cake?  Do you take to your desk to solve a puzzle
 that you know the answer to in a heartbeat? How about a suspense novel whose
 criminal you can guess halfway through? If you really want to come to new
 knowledge, you need to solve a problem engaging all your capacities. This is
-the book that lets you practice such idealism exhaustively.  "I think,
-therefore it's fun!" Everybody who finds it fun gives pleasure to the author.
+the book that lets you practice such idealism exhaustively.
+"It's interesting because it's difficult." I'm glad if the number of people
+who think so will increase because of this book.
 
 h2. Target audience
 
@@ -83,24 +89,25 @@ explanations of its structure, supplementary explanations of the language are
 inserted here and there.
 
 
-Knowledge about the C language is required, to some extent. I assume you have
-experience calling @malloc()@ to assign a list or stack, and have used function
-pointer at least a few times.
+Knowledge about the C language is required, to some extent. I assume you can
+allocate some structs with @malloc()@ at runtime to create a list or a stack
+and you have experience of using function pointers at least a few times.
 
 
-This book doesn't provide a proper introduction to an object-oriented language.
-You will have a difficult time if you don't know the basics of at least one
-object-oriented language. Furthermore, some examples are given in Java and C++.
+Also, since the basics of object-oriented programming will not be explained so
+seriously, without having any experience of using at least one of
+object-oriented languages, you will probably have a difficult time.
+In this book, I tried to use many examples in Java and C++.
 
 h2. Structure of this book
 
 This book has four main parts:
 
 
-Part 1: Objects
-Part 2: Syntactic analysis
-Part 3: Evaluation
-Part 4: Peripheral around the evaluator
+| Part 1: Objects |
+| Part 2: Syntactic analysis |
+| Part 3: Evaluation |
+| Part 4: Peripheral around the evaluator |
 
 
 Supplementary chapters are included at the beginning of each part when
@@ -114,80 +121,80 @@ parentheses after the explanation indicates the difficulty gauge. They are ==(C)
 
 h4. Part 1: Object
 
-Chapter 1: Focuses the basics of Ruby to get ready to accomplish Part 1. ==(C)==
-Chapter 2: Gives concrete inner structure of Ruby objects. ==(C)==
-Chapter 3: States about hash table. ==(C)==
-Chapter 4: Writes about Ruby class system. You may read through this chapter quickly at first, because it tells plenty of abstract stories. (A)
-Chapter 5: Shows the garbage collector which is responsible for generating and releasing objects. The first story in low-level series. (B)
-Chapter 6: Describes the implementation of global variables, class variables, and constants. ==(C)==
-Chapter 7: Outline of the security features of Ruby. ==(C)==
+| Chapter1 | Focuses the basics of Ruby to get ready to accomplish Part 1. ==(C)== |
+| Chapter2 | Gives concrete inner structure of Ruby objects. ==(C)== |
+| Chapter3 | States about hash table. ==(C)== |
+| Chapter4 | Writes about Ruby class system. You may read through this chapter quickly at first, because it tells plenty of abstract stories. (A) |
+| Chapter5 | Shows the garbage collector which is responsible for generating and releasing objects. The first story in low-level series. (B) |
+| Chapter6 | Describes the implementation of global variables, class variables, and constants. ==(C)== |
+| Chapter7 | Outline of the security features of Ruby. ==(C)== |
 
 h4. Part 2: Syntactic analysis
 
-Chapter 8: Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. ==(C)==
-Chapter 9: Introduction to @yacc@ required to read the syntax file at least. (B)
-Chapter 10: Look through the rules and physical structure of the parser. (A)
-Chapter 11: Explore around the peripherals of @lex_state@, which is the most difficult part of the parser. The most difficult part of this book. (S)
-Chapter 12: Finalization of Part 2 and connection to Part 3. ==(C)==
+| Chapter8 | Talks about almost complete specification of the Ruby language, in order to prepare for Part 2 and Part 3. ==(C)== |
+| Chapter9 | Introduction to @yacc@ required to read the syntax file at least. (B) |
+| Chapter10 | Look through the rules and physical structure of the parser. (A) |
+| Chapter11 | Explore around the peripherals of @lex_state@, which is the most difficult part of the parser. The most difficult part of this book. (S) |
+| Chapter12 | Finalization of Part 2 and connection to Part 3. ==(C)== |
 
 h4. Part 3: Evaluator
 
-Chapter 13: Describe the basic mechanism of the evaluator. ==(C)==
-Chapter 14: Reads the evaluation stack that creates the main context of Ruby. (A)
-Chapter 15: Talks about search and initialization of methods. (B)
-Chapter 16: Defies the implementation of the iterator, the most characteristic feature of Ruby. (A)
-Chapter 17: Describe the implementation of the eval methods. (B)
+| Chapter13 | Describe the basic mechanism of the evaluator. ==(C)== |
+| Chapter14 | Reads the evaluation stack that creates the main context of Ruby. (A) |
+| Chapter15 | Talks about search and initialization of methods. (B) |
+| Chapter16 | Defies the implementation of the iterator, the most characteristic feature of Ruby. (A) |
+| Chapter17 | Describe the implementation of the eval methods. (B) |
 
 h4. Part 4: Peripheral around the evaluator
 
-Chapter 18: Run-time loading of libraries in C and Ruby. (B)
-Chapter 19: Describes the implementation of thread at the end of the core part. (A)
+| Chapter18 | Run-time loading of libraries in C and Ruby. (B) |
+| Chapter19 | Describes the implementation of thread at the end of the core part. (A) |
 
 h2. Environment
 
 This book describes on @ruby@ 1.7.3 2002-09-12 version. It's attached on the
 CD-ROM. Choose any one of @ruby-rhg.tar.gz@, @ruby-rhg.lzh@, or @ruby-rhg.zip@
 according to your convenience. Content is the same for all.  Alternatively you
-can obtain from the support site (footnote{@http://i.loveruby.net/ja/rhg/@}) of
+can obtain from the support site (footnote{`http://i.loveruby.net/ja/rhg/`}) of
 this book.
 
 
 For the publication of this book, the following build environment was prepared
 for confirmation of compiling and testing the basic operation. The details of
-this build test are given in @ doc/buildtest.html@ in the attached CD-ROM.
+this build test are given in @doc/buildtest.html@ in the attached CD-ROM.
 However, it doesn't necessarily assume the probability of the execution even
 under the same environment listed in the table. The author doesn't guarantee
 in any form  the execution of @ruby@.
 
 
-BeOS 5 Personal Edition/i386
-Debian GNU/Linux potato/i386
-Debian GNU/Linux woody/i386
-Debian GNU/Linux sid/i386
-FreeBSD 4.4-RELEASE/Alpha (Requires the local patch for this book)
-FreeBSD 4.5-RELEASE/i386
-FreeBSD 4.5-RELEASE/PC98
-FreeBSD 5-CURRENT/i386
-HP-UX 10.20
-HP-UX 11.00 (32bit mode)
-HP-UX 11.11 (32bit mode)
-Mac OS X 10.2
-NetBSD 1.6F/i386
-OpenBSD 3.1
-Plamo Linux 2.0/i386
-Linux for PlayStation2 Release 1.0
-Redhat Linux 7.3/i386
-Solaris 2.6/Sparc
-Solaris 8/Sparc
-UX/4800
-Vine Linux 2.1.5
-Vine Linux 2.5
-VineSeed
-Windows 98SE (Cygwin, MinGW+Cygwin, MinGW+MSYS)
-Windows Me (Borland C++ Compiler 5.5, Cygwin, MinGW+Cygwin, MinGW+MSYS, Visual C++ 6)
-Windows NT 4.0 (Cygwin, MinGW+Cygwin)
-Windows 2000 (Borland C++ Compiler 5.5, Visual C++ 6, Visual C++.NET)
-Windows XP (Visual C++.NET, MinGW+Cygwin)
+* BeOS 5 Personal Edition/i386
+* Debian GNU/Linux potato/i386
+* Debian GNU/Linux woody/i386
+* Debian GNU/Linux sid/i386
+* FreeBSD 4.4-RELEASE/Alpha (Requires the local patch for this book)
+* FreeBSD 4.5-RELEASE/i386
+* FreeBSD 4.5-RELEASE/PC98
+* FreeBSD 5-CURRENT/i386
+* HP-UX 10.20
+* HP-UX 11.00 (32bit mode)
+* HP-UX 11.11 (32bit mode)
+* Mac OS X 10.2
+* NetBSD 1.6F/i386
+* OpenBSD 3.1
+* Plamo Linux 2.0/i386
+* Linux for PlayStation2 Release 1.0
+* Redhat Linux 7.3/i386
+* Solaris 2.6/Sparc
+* Solaris 8/Sparc
+* UX/4800
+* Vine Linux 2.1.5
+* Vine Linux 2.5
+* VineSeed
+* Windows 98SE (Cygwin, MinGW+Cygwin, MinGW+MSYS)
+* Windows Me (Borland C++ Compiler 5.5, Cygwin, MinGW+Cygwin, MinGW+MSYS, Visual C++ 6)
+* Windows NT 4.0 (Cygwin, MinGW+Cygwin)
+* Windows 2000 (Borland C++ Compiler 5.5, Visual C++ 6, Visual C++.NET)
+* Windows XP (Visual C++.NET, MinGW+Cygwin)
 
 
 These numerous tests aren't of a lone effort by the author.  Those test build
@@ -197,37 +204,37 @@ below.
 I'd like to extend warmest thanks from my heart.
 
 
-Tietew
-kjana
-nyasu
-sakazuki
-Masahiro Sato
-Kenichi Tamura
-Morikyu
-Yuya Kato
-Yasuhiro Kubo
-Kentaro Goto
-Tomoyuki Shimomura
-Masaki Sukeda
-Koji Arai
-Kazuhiro Nishiyama
-Shinya Kawaji
-Tetsuya Watanabe
-Naokuni Fujimoto
+| Tietew |
+| kjana |
+| nyasu |
+| sakazuki |
+| Masahiro Sato |
+| Kenichi Tamura |
+| Morikyu |
+| Yuya Kato |
+| Yasuhiro Kubo |
+| Kentaro Goto |
+| Tomoyuki Shimomura |
+| Masaki Sukeda |
+| Koji Arai |
+| Kazuhiro Nishiyama |
+| Shinya Kawaji |
+| Tetsuya Watanabe |
+| Naokuni Fujimoto |
 
 
 However, the author owes the responsibility for this test. Please refrain from
 attempting to contact these people directly.  If there's any flaw in execution,
-please be advised to contact the author by e-mail: @aamine@loveruby.net@.
+please be advised to contact the author by e-mail: `aamine@loveruby.net`.
 
 h2. Web site
 
-The web site for this book is @http://i.loveruby.net/ja/rhg/@.
+The web site for this book is `http://i.loveruby.net/ja/rhg/`.
 I will add information about related programs and additional documentation, as
 well as errata. In addition, I'm going to publisize the first few chapters of
 this book at the same time of the release. I will look for a certain
 circumstance to publicize more chapters, and the whole contents of the book
-will beat this website. at the end.
+will be at this website at the end.
 
 h2. Acknowledgment
 
@@ -281,13 +288,14 @@ contributed to this book, but I say that I couldn't successfully publish this
 book without such assistance. Let me take this place to express my
 appreciation. Thank you very much.
 
-p(=right).
+p(right). Minero Aoki
 
 
 If you want to send remarks, suggestions and reports of typographcal errors,
-please address to " ":mailto:aamine@loveruby.net.
+please address to "Minero Aoki <aamine@loveruby.net>":mailto:aamine@loveruby.net .
 
 
-""Rubyソースコード完全解説" can be reserved/ordered at ImpressDirect. ":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721"(Jump to the introduction page)":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721
+"Rubyソースコード完全解説" can be reserved/ordered at ImpressDirect.
+"(Jump to the introduction page)":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721
 
 Copyright (c) 2002-2004 Minero Aoki, All rights reserved.

From 5ba4042f09ad0a95267b8b9f12f4f3cc31f77ec4 Mon Sep 17 00:00:00 2001
From: ocha- 
Date: Sun, 1 Sep 2013 03:36:00 +0900
Subject: [PATCH 037/121] edit chapter 04

---
 class.textile | 217 ++++++++++++++++++++++++++++----------------------
 1 file changed, 122 insertions(+), 95 deletions(-)

diff --git a/class.textile b/class.textile
index 9ad9ddd..f1e793e 100644
--- a/class.textile
+++ b/class.textile
@@ -8,7 +8,7 @@ Translated by Vincent ISAMBART
 h1. Chapter 4: Classes and modules
 
 In this chapter, we'll see the details of the data structures created
-for classes and modules.
+by classes and modules.
 
 h2. Classes and methods definition
 
@@ -185,7 +185,7 @@ instead.
 
It's used like `rb_define_method()`. The only difference is that here -the first parameter is just the _object_ where the method is +the first parameter is just the "object" where the method is defined. In this case, it's defined in `rb_cFile`. h3. Entry point @@ -341,15 +341,24 @@ which function calls which one. For instance, `rb_define_singleton_method()` calls `rb_define_method()` and `rb_singleton_class()`. And this `rb_singleton_class()` itself calls `SPECIAL_SINGLETON()` and `rb_make_metaclass()`. +In order to obtain call graphs, you can use `cflow` and such. +{`cflow`: see also `doc/callgraph.html` in the attached CD-ROM} + +In this book, because I wanted to obtain call graphs that contain only functions, +I created a `ruby`-specific tool by myself. +Perhaps it can be generalized by modifying its code analyzing part, +thus I'd like to somehow make it until around the publication of this book. +These situations are also explained in `doc/callgraph.html` of the attached CD-ROM. Let's go back to the code. When looking at the call graph, you can see that the calls made by `rb_singleton_class()` go very deep. Until now all call levels were shallow, so we could simply look at the functions without getting too lost. But at this depth, I easily forget -what is going on in the code. That's why in those situations I check -the call graph to have a better understanding. This time, we'll decode -in parallel what the procedures below `rb_singleton_class()` do. The -two points to look out for are the following ones: +what I was doing. In such situation you must bring +a call graph to keep aware of where it is when reading. +This time, as an example, we'll decode +the procedures below `rb_singleton_class()` in parallel. +We should look out for the following two points: * What exactly are singleton classes? * What is the purpose of singleton classes? @@ -429,8 +438,8 @@ ignore it. `rb_raise()` is error handling so we can ignore it. Only
`NEWOBJ()` and `OBJSETUP()` are fixed expressions used when creating -Ruby objects that possess one of the internal structure types (`struct -Rxxxx`). They are both macros. In `NEWOBJ()`, `struct RClass` is +Ruby objects that possess one of the built-in structure types (`struct Rxxxx`). +They are both macros. In `NEWOBJ()`, `struct RClass` is created and the pointer is put in its first parameter `klass`. In `OBJSETUP()`, the struct `RBasic` member of the `RClass` (and thus `basic.klass` and `basic.flags`) is initialized. @@ -443,7 +452,7 @@ parameter. It looks like `rb_class_boot()` is a function that creates a class inheriting from `super`. So, as `rb_class_boot()` is a function that creates a class, -what does `rb_class_new()` is very similar. +and `rb_class_new()` is almost identical. Then, let's once more look at `rb_singleton_class()`'s call graph: @@ -516,18 +525,18 @@ non-essential parts.
The first and the second half are separated by a blank line. The first -half handles a special case and the second half handles the general +half handles special cases and the second half handles the general case. In other words, the second half is the trunk of the function. That's why we'll keep it for later and talk about the first half. Everything that is handled in the first half are non-pointer `VALUE`s, -in other words objects without an existing C structure. First, +it means their object structs do not exist. First, `Fixnum` and `Symbol` are explicitly picked. Then, `rb_special_const_p()` is a function that returns true for non-pointer `VALUE`s, so there only `Qtrue`, `Qfalse` and `Qnil` should get -caught. Other than that, there are no valid non-pointer value so a bug -is reported with `rb_bug()`. +caught. Other than that, there are no valid non-pointer `VALUE` so +it would be reported as a bug with `rb_bug()`. `DEFER_INTS()` and `ALLOW_INTS()` both end with the same `INTS` so you should see a pair in them. That's the case, and they are macros @@ -564,14 +573,14 @@ h3. Compressed `rb_make_metaclass()` We already saw `rb_class_boot()`. It creates a (normal) class using the `super` parameter as its superclass. After that, the `FL_SINGLETON` of this class is set. This is clearly suspicious. The -name of the function makes us think that it is not the indication of +name of the function makes us think that it is the indication of a singleton class. h3. What are singleton classes? -Continuing the simplification process, furthermore as parameters, -return values, local variables are all `VALUE`, we can throw away the -declarations. That makes us able to compress to the following: +Finishing the above process, furthermore, we'll through away the declarations +because parameters, return values and local variables are all `VALUE`. +That makes us able to compress to the following: ▼ `rb_singleton_class() rb_make_metaclass()` (after compression)
@@ -607,8 +616,8 @@ rb_make_metaclass(obj, super)
 
The condition of the `if` statement of `rb_singleton_class()` seems -quite complicated. However, this condition is not connected to the -mainstream of `rb_make_metaclass()` so we'll see it later. Let's first +quite complicated. However, this condition is not connected to +`rb_make_metaclass()`, which is the mainstream, so we'll see it later. Let's first think about what happens on the false branch of the `if`. The `BUILTIN_TYPE()` of `rb_make_metaclass()` is similar to `TYPE()` @@ -617,7 +626,7 @@ this check in `rb_make_metaclass` means "if `obj` is a class". For the moment it's better not to limit ourselves to `obj` being a class, so we'll remove it. -With these simplifications, we get the the following: +With these simplifications, we get the following: ▼ `rb_singleton_class() rb_make_metaclass()` (after recompression)
@@ -655,15 +664,15 @@ vertical direction is inheritance (the superclasses are above).
 When comparing the first and last part of this diagram, you can
 understand that `sclass` is inserted without changing the
 structure. That's all there is to singleton classes. In other words
-the inheritance is increased one step. If a method is defined in a
-singleton class, this construction allows the other instances of
-`klass` to define completely different methods.
+the inheritance is increased one step. By defining methods there,
+we can define methods which have completely nothing to do with other
+instances of `klass`.
 
 h3. Singleton classes and instances
 
-By the way, you must have seen that during the compression process,
-the call to `rb_singleton_class_attached()` was stealthily
-removed. Here:
+By the way, did you notice about, during the compression process,
+the call to `rb_singleton_class_attached()` was stealthily removed?
+Here:
 
 
 rb_make_metaclass(obj, super)
@@ -694,7 +703,7 @@ Let's have a look at what it does.
 (class.c)
 
-If the FL_SINGLETON flag of `klass` is set... in other words if it's a +If the `FL_SINGLETON` flag of `klass` is set... in other words if it's a singleton class, put the `__attached__` → `obj` relation in the instance variable table of `klass` (`iv_tbl`). That's how it looks like (in our case `klass` is always a singleton class... in other @@ -726,9 +735,11 @@ creation of an instance of a singleton class. Singleton classes are in the first place for singleton methods. Singleton methods are methods existing only on a particular -object. If singleton classes could have multiple instances, there -would the same as normal classes. That's why they are forced to only -have one instance. +object. If singleton classes could have multiple instances, they +would be the same as normal classes. +Hence, each singleton class has only one instance ... +or rather, it must be limited to one. + h3. Summary @@ -756,8 +767,8 @@ Up to here it's something we've already gone through. What's going after that is the theme of this chapter. Why do classes have to make a loop? -First, in Ruby all data are objects. And classes are data so in Ruby -they have to be objects. +First, in Ruby all data are objects. And classes are data in Ruby +so they have to be objects. As they are objects, they must answer to methods. And setting the rule "to answer to methods you must belong to a class" made processing @@ -791,13 +802,15 @@ understand. That's why here we'll restrict the meaning of "data" to "what can be put in variables in programs". Being able to manipulate classes from programs gives programs the -ability to manipulate themselves. This is called reflection. It fits -object oriented languages, and even more Ruby with the classes it has, +ability to manipulate themselves. This is called reflection. +In Ruby, which is a object oriented language and furthermore has classes, +it is equivalent to be able to directly manipulate classes. -Nevertheless, classes could be made available in a form that is not an -object. For example, classes could be manipulated with function-style -methods (functions defined at the top-level). However, as inside the +Nevertheless, there's also a way in which classes are not objects. +For example, there's no problem in providing a feature to manipulate classes +as a function-style methods (functions defined at the top-level). +However, as inside the interpreter there are data structures to represent the classes, it's more natural in object oriented languages to make them available directly. And Ruby did this choice. @@ -805,9 +818,9 @@ directly. And Ruby did this choice. Furthermore, an objective in Ruby is for all data to be objects. That's why it's appropriate to make them objects. -By the way, there is a reason not linked to reflection why in Ruby -classes had to be made objects. That is to be able to define methods -independently from instances (what is called static methods in Java in +By the way, there is also a reason not linked to reflection why in Ruby +classes had to be made objects. That is to prepare the place to define methods +which are independent from instances (what are called static methods in Java and C++). And to implement static methods, another thing was necessary: @@ -819,8 +832,8 @@ classes necessary. Figure 3 shows these dependency relationships. h4. Class methods inheritance In Ruby, singleton methods defined in a class are called class -methods. However, their specification is a little strange. Why are -class methods inherited? +methods. However, their specification is a little strange. +For some reasons, class methods are inheritable.
 class A
@@ -843,8 +856,9 @@ inherited.
 h3. Singleton class of a class
 
 Assuming that class methods are inherited, where is this operation
-done? At class definition (creation)? At singleton method definition?
-Then let's look at the code defining classes.
+done? It must be done either at class definition (creation) or at singleton
+method definition.
+Then let's first look at the code defining classes.
 
 Class definition means of course `rb_define_class()`. Now
 let's take the call graph of this function.
@@ -862,7 +876,7 @@ rb_define_class
 
 If you're wondering where you've seen it before, we looked at it in
 the previous section. At that time you did not see it but if you look
-closely, why does `rb_make_metaclass()` appear? As we saw before, this
+closely, somehow `rb_make_metaclass()` appeared. As we saw before, this
 function introduces a singleton class. This is very suspicious. Why is
 this called even if we are not defining a singleton function?
 Furthermore, why is the lower level `rb_make_metaclass()` used instead
@@ -936,7 +950,7 @@ rb_make_metaclass(obj, super)
 }
 
-Last time, the `if` statement was skillfully skipped, but looking once +Last time, the `if` statement was wholly skipped, but looking once again, something is done only for `T_CLASS`, in other words classes. This clearly looks important. In `rb_define_class_id()`, as it's called like this: @@ -945,8 +959,7 @@ it's called like this: rb_make_metaclass(klass, RBASIC(super)->klass);
-Let's expand `rb_make_metaclass()`'s parameter variables with this -values. +Let's expand `rb_make_metaclass()`'s parameter variables with the actual values. ▼ `rb_make_metaclass` (recompression)
@@ -968,9 +981,10 @@ caught between a class and this class's superclass's class.
 
 !images/ch_class_metaclass.png(Introduction of a class's singleton class)!
 
-From this result, and moreover when thinking more deeply, we can think
-that the superclass's class must again be the superclass's singleton
-class. You'll understand with one more inheritance level (figure 5).
+By expanding our imagination further from this result,
+we can think that the superclass's class (the `c` in figure 4)
+must again be a singleton class.
+You'll understand with one more inheritance level (figure 5).
 
 !images/ch_class_multi.png(Hierarchy of multi-level inheritance)!
 
@@ -999,8 +1013,9 @@ h3. Class of a class of a class
 
 You've understood the working of class methods inheritance, but by
 doing that, in the opposite some questions have appeared. What is the
-class of a class's singleton class? To do this we can try
-debugging. I've made figure 7 from the results of this
+class of a class's singleton class?
+For this, we can check it by using debuggers.
+I've made figure 7 from the results of this
 investigation.
 
 !images/ch_class_mmm.png(Class of a class's singleton class)!
@@ -1009,7 +1024,8 @@ A class's singleton class puts itself as its own class. Quite
 complicated.
 
 The second question: the class of `Object` must be `Class`. Didn't I
-properly confirm this in chapter 1: Ruby language minimum?
+properly confirm this in chapter 1: Ruby language minimum
+by using `class()` method?
 
 
 p(Object.class())   # Class
@@ -1060,18 +1076,18 @@ Well, the singleton classes that were introduced in classes is also
 one type of class, it's a class's class. So it can be called
 metaclass.
 
-However, you should be wary of the fact that singleton class are
-not metaclasses. It's the singleton classes introduced in classes that
+However, you should be wary of the fact that being a singleton class does not
+mean being a metaclass. The singleton classes introduced in classes
 are metaclasses. The important fact is not that they are singleton
 classes, but that they are the classes of classes. I was stuck on this
 point when I started learning Ruby. As I may not be the only one, I
 would like to make this clear.
 
 Thinking about this, the `rb_make_metaclass()` function name is not
-very good. When used in classes, it does indeed create a metaclass,
-but not in the other cases, when using objects.
+very good. When used for a class, it does indeed create a metaclass,
+but when used for other objects, the created class is not a metaclass.
 
-Then finally, even if you understood that some class are metaclasses,
+Then finally, even if you understood that some classes are metaclasses,
 it's not as if there was any concrete gain. I'd like you not to care
 too much about it.
 
@@ -1112,7 +1128,7 @@ metaobjects' bootstrap is finished.
 
 !images/ch_class_boot1.png(Metaobjects creation)!
 
-After taking everything into account, it gives us a the final shape
+After taking everything into account, it gives us the final shape
 like figure 10.
 
 !images/ch_class_metaobj.png(Ruby metaobjects)!
@@ -1166,13 +1182,16 @@ the class can be found from the constant.
 (class.c)
 
-Many things can be understood with what's before and after -`rb_define_class_id()`... Before we acquire or create the class. After -we set the constant. We will look at it in more detail below. +This can be clearly divided into the two parts: +before and after `rb_define_class_id()`. +The former is to acquire or create the class. +The latter is to assign it to the constant. +We will look at it in more detail below. -(A) In Ruby, there is an autoload function that automatically loads -libraries when some constants are accessed. This is done in the -`rb_autoload_xxxx()` function. You can ignore it without any problem. +(A) In Ruby, there is a feature named autoload that automatically loads +libraries when certain constants are accessed. +These functions named `rb_autoload_xxxx()` are for its checks. +You can ignore it without any problem. (B) We determine whether the `name` constant has been defined or not in `Object`. @@ -1187,11 +1206,13 @@ virtual classes that should not appear at the Ruby level. That's what we can read nearby. -As around constants are involved, it is very troublesome. However, we -will talk about class definition in the constants chapter so for the -moment we will content ourselves with a partial description. +As constants are involved around this, it is very troublesome. +But I feel like the chapter about constants is probably not so right place to +talk about class definition, +that's the reason of such halfway description around here. -After `rb_define_class_id`, we can find the following: + +Moreover, about this coming after `rb_define_class_id()`,
 st_add_direct(rb_class_tbl, id, klass);
@@ -1210,8 +1231,8 @@ how to do the opposite? By doing things like calling `p` or
 `Class#name`, we can get the name of the class, but how is it
 implemented?
 
-In fact this was already done a long time ago by
-`rb_name_class()`. The call is around the following:
+In fact this is done by `rb_name_class()` which already appeared a long time
+ago. The call is around the following:
 
 
 rb_define_class
@@ -1289,13 +1310,13 @@ The structure is like the one of `rb_define_class()`: before the call
 to `rb_define_class_id()` is the redefinition check, after is the
 creation of the reciprocal link between constant and class. The first
 half is pretty boringly similar to `rb_define_class()` so we'll skip
-it. In the second half, `rb_set_class()` is new. We're going to look
+it. In the second half, `rb_set_class_path()` is new. We're going to look
 at it.
 
 h4. `rb_set_class_path()`
 
 This function gives the name `name` to the class `klass` nested in the
-class `under`. "class path" means a name including all the nesting
+class `under`. "class path" means a constant name including all the nesting
 information starting from top-level, for example
 "`Net::NetPrivate::Socket`".
 
@@ -1351,19 +1372,20 @@ Ruby you can use a method like the following to create a class.
 c = Class.new()
 
-If you create a class like this, we won't go through +If a class is created like this, it won't go through `rb_define_class_id()` and the classpath won't be set. In this case, `c` does not have any name, which is to say we get an unnamed class. -However, if later it's assigned to a constant, the name of this -constant will be attached to the class. +However, if later it's assigned to a constant, +a name will be attached to the class at that moment.
 SomeClass = c   # the class name is SomeClass
 
-Strictly speaking, the name is attached after the assignment, the -first time it is requested. For instance, when calling `p` on this +Strictly speaking, at the first time requesting the name after assigning it to +a constant, the name will be attached to the class. +For instance, when calling `p` on this `SomeClass` class or when calling the `Class#name` method. When doing this, a value equal to the class is searched in `rb_class_tbl`, and a name has to be chosen. The following case can also happen: @@ -1378,7 +1400,7 @@ end
so in the worst case we have to search for the whole constant -space. However, generally, there aren't many constants so searching +space. However, generally, there aren't many constants so even searching all constants does not take too much time. h2. Include @@ -1401,7 +1423,8 @@ Module#include (rb_mod_include) rb_include_module
-All usual includes are done by `rb_include_module()`. This function is +Anyway, the manipulations that are usually regarded as inclusions are done +by `rb_include_module()`. This function is a little long so we'll look at it a half at a time. ▼ `rb_include_module` (first half) @@ -1549,8 +1572,9 @@ this class. ==(C)== Make the including class's superclass (`super`) the super class of this new class. -In other words, this function creates an include class for the -module. The important point is that at (B) only the pointer is moved +In other words, it looks like this function creates an include class which +we can regard it as something like an "avatar" of the `module`. +The important point is that at (B) only the pointer is moved on, without duplicating the table. Later, if a method is added, the module's body and the include class will still have exactly the same methods (figure 11). @@ -1570,11 +1594,11 @@ module between a class and its superclass (figure 12). !images/ch_class_include.png(Include)! At (D-2) the module is stored in the include class's `klass`. At -(D-1), the module's body is taken out... at least that's what I'd like -to say, but in fact this check does not have any use. The `T_ICLASS` +(D-1), the module's body is taken out... I'd like to say so if possible, +but in fact this check does not have any use. The `T_ICLASS` check is already done at the beginning of this function, so when arriving here there can't still be a `T_ICLASS`. Modification to -`ruby` piled up at a fast pace during quite a long period of time so +`ruby` piled up at piece by piece during quite a long period of time so there are quite a few small overlooks. There is one more thing to consider. Somehow the include class's @@ -1618,14 +1642,17 @@ Well, now we can explain the part of `rb_include_module()` we skipped. (class.c)
-If one of the `T_ICLASS`es (include classes) that are in `klass`'s -superclasses (`p`) has the same table as one of the modules we want to -include (`module`), it's an include class for `module`. That's why we -skip the inclusion to not include the module twice. If this module -includes an other module (`module->super`), we check this once more. +Among the superclasses of the +klass+ (`p`), +if a `p` is `T_ICLASS` (an include class) and has the same method table as the +one of the module we want to include (`module`), +it means that the `p` is an include class of the `module`. +Therefore, it would be skipped to not include the module twice. +However, if this module includes another module (`module->super`), +It would be checked once more. + -However, when we skip an inclusion, `p` is a module that has been -included once, so its included modules must already be +But, because `p` is a module that has been included once, +the modules included by it must also already be included... that's what I thought for a moment, but we can have the following context: @@ -1646,8 +1673,8 @@ class C end
-So on the contrary, there are cases for which `include` does not have -real-time repercussions. +To say this conversely, there are cases that a result of `include` is not +propagated soon. For class inheritance, the class's singleton methods were inherited but in the case of module there is no such thing. Therefore the From f39297571adc88d034a14834c6dc8b4c9cf7f7b5 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 1 Sep 2013 04:00:24 +0900 Subject: [PATCH 038/121] edit chapter 04 to fix a mistake --- class.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class.textile b/class.textile index f1e793e..ce2bc8d 100644 --- a/class.textile +++ b/class.textile @@ -809,7 +809,7 @@ to be able to directly manipulate classes. Nevertheless, there's also a way in which classes are not objects. For example, there's no problem in providing a feature to manipulate classes -as a function-style methods (functions defined at the top-level). +as function-style methods (functions defined at the top-level). However, as inside the interpreter there are data structures to represent the classes, it's more natural in object oriented languages to make them available From f14685308da6f60882a1f595e028cf2a409c5ad7 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 8 Sep 2013 01:00:49 +0900 Subject: [PATCH 039/121] edit chapter 04 for some of the errata that were not applied --- class.textile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/class.textile b/class.textile index ce2bc8d..848f7b3 100644 --- a/class.textile +++ b/class.textile @@ -623,7 +623,7 @@ think about what happens on the false branch of the `if`. The `BUILTIN_TYPE()` of `rb_make_metaclass()` is similar to `TYPE()` as it is a macro to get the structure type flag (`T_xxxx`). That means this check in `rb_make_metaclass` means "if `obj` is a class". For the -moment it's better not to limit ourselves to `obj` being a class, so +moment we assume that `obj` is a class, so we'll remove it. With these simplifications, we get the following: @@ -783,6 +783,11 @@ object oriented languages where classes are objects that `Class`'s class is to `Class` itself, creating an endless virtual instance-class relationship. +((errata:
+This structure is implemented efficiently in recent Ruby 1.8, +thus it can be implemented efficiently. +)) + I'm repeating myself, but the fact that `Class`'s class is `Class` is only to make the implementation easier, there's nothing important in this logic. @@ -1219,7 +1224,8 @@ st_add_direct(rb_class_tbl, id, klass); This part assigns the class to the constant. However, whichever -way you look at it you do not see that. In fact, top-level classes are +way you look at it you do not see that. In fact, top-level classes and modules +that are defined in C are separated from the other constants and regrouped in `rb_class_tbl()`. The split is slightly related to the GC. It's not essential. From 7e732d3581240bc618290b51c50c27d8b2e4bb03 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 8 Sep 2013 03:10:35 +0900 Subject: [PATCH 040/121] edit chapter 06 to fix the parts that were different from the original book --- variable.textile | 75 ++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/variable.textile b/variable.textile index 98758ab..3a3a019 100644 --- a/variable.textile +++ b/variable.textile @@ -31,8 +31,8 @@ We will talk about local variables in the third part of the book. h3. API for variables -The object of this chapter's analysis is `variable.c`. Let's first -look at the available API. +The object of this chapter's analysis is `variable.c`. Let me first +introduce the APIs which would be the entry points.
 VALUE rb_iv_get(VALUE obj, char *name)
@@ -41,9 +41,9 @@ VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
 VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
 
-We've already spoken about those functions, but must mention them again -as they are in `variable.c`. They are of course used for accessing instance -variables. +These are the APIs to access instance variables which have already been +described. They are shown here again because their definitions are in +`variable.c`.
-I'd like you to look at @local_tbl()@ . -This is the function to obtain the current local variable table ( @lvtbl->tbl@ ). +I'd like you to look at @local_tbl()@. +This is the function to obtain the current local variable table (@lvtbl->tbl@). By calling this, the @nofree@ of the current table becomes true. -The meaning of @nofree@ seems naturally "Don't @free()@ ". +The meaning of @nofree@ seems naturally "Don't @free()@". In other words, this is like reference counting, "this table will be used, so -please don't @free()@ ". Conversely speaking, +please don't @free()@". Conversely speaking, when @local_tbl()@ was not called with a table even once, that table will be freed at the moment when being popped and be discarded. For example, this situation probably happens when a method without any local variables. -However, the "necessary table" here means @lvtbl->tbl@ . +However, the "necessary table" here means @lvtbl->tbl@. As you can see, @lvtbl@ itself will be freed at the same moment when being popped. It means only the generated @lvtbl->tbl@ is used in the evaluator. Then, the structure of @lvtbl->tbl@ is becoming important. @@ -1752,7 +1752,7 @@ which is probably helpful to understand how the structure is. And before that, I'd like you to remember that @lvtbl->cnt@ is stored -at the index 0 of the @lvtbl->tbl@ . +at the index 0 of the @lvtbl->tbl@. @@ -1760,7 +1760,7 @@ at the index 0 of the @lvtbl->tbl@ . h3. Adding variables -The function (which seems) to add a local variable is @local_cnt()@ . +The function (which seems) to add a local variable is @local_cnt()@.

▼ @local_cnt()@

@@ -1784,17 +1784,17 @@ The function (which seems) to add a local variable is @local_cnt()@ . -This scans @lvtbl->tbl@ and searches what is equals to @id@ . -If the searched one is found, it straightforwardly returns @cnt-1@ . -If nothing is found, it does @local_append()@ . -@local_append()@ must be, as it is called @append@ , the procedure to append. +This scans @lvtbl->tbl@ and searches what is equals to @id@. +If the searched one is found, it straightforwardly returns @cnt-1@. +If nothing is found, it does @local_append()@. +@local_append()@ must be, as it is called @append@, the procedure to append. In other words, @local_cnt()@ checks if the variable was already registered, if it was not, adds it by using @local_append()@ and returns it. What is the meaning of the return value of this function? @lvtbl->tbl@ seems an array of the variables, so there're one-to-one correspondences between the -variable names and "their index - 1 ( @cnt-1@ )". (Fig.10) +variable names and "their index - 1 (@cnt-1@)". (Fig.10)

@@ -1812,13 +1812,13 @@ If it is not, like the instance variables or constants, You might want to know why it is avoiding index 0 (the loop start -from @cnt=1@ ) for some reasons, it is probably to store a value at @local_pop()@ . +from @cnt=1@) for some reasons, it is probably to store a value at @local_pop()@. Based on the knowledge we've learned, we can understand the role of @local_append()@ without actually looking at the content. It registers a local variable and returns -"(the index of the variable in @lvtbl->tbl@ ) - 1". +"(the index of the variable in @lvtbl->tbl@) - 1". It is shown below, let's make sure. @@ -1854,7 +1854,7 @@ It seems definitely true. @lvtbl->tbl@ is an array of the local variable names, and its index - 1 is the return value (local variable ID). -Note that it increases @lvtbl->cnt@ . +Note that it increases @lvtbl->cnt@. Since the code to increase @lvtbl->cnt@ only exists here, from only this code its meaning can be decided. Then, what is the meaning? It is, @@ -1863,9 +1863,9 @@ since "@lvtbl->cnt@ increases by 1 when a new variable is added", -Finally, I'll explain about @tbl[1]@ and @tbl[2]@ . These @'_'@ and @'~'@ are, +Finally, I'll explain about @tbl[1]@ and @tbl[2]@. These @'_'@ and @'~'@ are, as you can guess if you are familiar with Ruby, -the special variables named @$_@ and @$~@ . +the special variables named @$_@ and @$~@. Though their appearances are identical to global variables, they are actually local variables. Even If you didn't explicitly use it, when the methods such as @Kernel#gets@ are called, @@ -1883,13 +1883,13 @@ let's summarize it. First, It seems the local variables are different from the other variables -because they are not managed with @st_table@ . +because they are not managed with @st_table@. Then, where are they stored in? It seems the answer is an array. Moreover, it is stored in a different array for each scope. -The array is @lvtbl->tbl@ , and the index 0 holds the @lvtbl->cnt@ which is set -at @local_pop()@ . In other words, it holds the number of the local variables. +The array is @lvtbl->tbl@, and the index 0 holds the @lvtbl->cnt@ which is set +at @local_pop()@. In other words, it holds the number of the local variables. The index 1 or more hold the local variable names defined in the scope. Fig.11 shows the final appearance we expect. @@ -1978,22 +1978,22 @@ Meanwhile, @rb_dvar_push()@ is ... It creates a @struct RVarmap@ that has the variable name @id@ and the value -@val@ as its members, adds it to the top of the global variable @ruby_dyna_vars@ . +@val@ as its members, adds it to the top of the global variable @ruby_dyna_vars@. This is again and again the form of cons. -In @dyna_push()@ , @ruby_dyan_vars@ is not set aside, +In @dyna_push()@, @ruby_dyan_vars@ is not set aside, it seems it adds directly to the @ruby_dyna_vars@ of the previous scope. Moreover, the value of the @id@ member of the @RVarmap@ to be added here is 0. Although it was not seriously discussed in this book, -the @ID@ of @ruby@ will never be 0 while it is normally created by @rb_intern()@ . -Thus, we can infer that this @RVarmap@ , as it is like @NUL@ or @NULL@ , +the @ID@ of @ruby@ will never be 0 while it is normally created by @rb_intern()@. +Thus, we can infer that this @RVarmap@, as it is like @NUL@ or @NULL@, probably has a role as sentinel. If we think based on this assumption, we can describe the reason why the holder -of a variable ( @RVarmap@ ) is added even though not any variables are added. +of a variable (@RVarmap@) is added even though not any variables are added. -Next, @dyna_pop()@ . +Next, @dyna_pop()@.

▼ @dyna_pop()@

@@ -2011,7 +2011,7 @@ Next, @dyna_pop()@ . -By reducing @lvtbl->dlev@ , it writes down the fact that the block local +By reducing @lvtbl->dlev@, it writes down the fact that the block local variable scope ended. It seems that something is done by using the argument, let's see this later at once. @@ -2019,7 +2019,7 @@ let's see this later at once. The place to add a block local variable has not appeared yet. Something like @local_cnt()@ of local variables is missing. -So, I did plenty of @grep@ with @dvar@ and @dyna@ , and this code was found. +So, I did plenty of @grep@ with @dvar@ and @dyna@, and this code was found.

▼ @assignable()@ (partial)

@@ -2041,7 +2041,7 @@ So, I did plenty of @grep@ with @dvar@ and @dyna@ , and this code was found. @assignable()@ is the function to create a node relates to assignments, this citation is the fragment of that function only contains the part to deal with block local variables. -It seems that it adds a new variable (to @ruby_dyna_vars@ ) +It seems that it adds a new variable (to @ruby_dyna_vars@) by using @rb_dvar_push()@ that we've just seen. @@ -2058,7 +2058,7 @@ parsed. First, as I said previously, the @RVarmap@ of @id=0@ which is added at the beginning of a block scope is a sentinel which represents a break between two block scopes. -We'll call this "the header of @ruby_dyna_vars@ ". +We'll call this "the header of @ruby_dyna_vars@". Next, among the previously shown actions of the rule of the iterator block, @@ -2075,7 +2075,7 @@ dyna_pop($2); /* …… appears at $2 */ @dyna_push()@ returns the @ruby_dyna_vars@ at the moment. -@dyna_pop()@ put the argument into @ruby_dyna_vars@ . +@dyna_pop()@ put the argument into @ruby_dyna_vars@. This means @ruby_dyna_vars@ would be saved and restored for each the block local variable scope. Therefore, when parsing the following program, @@ -2128,8 +2128,8 @@ is expressed in a natural form. And finally, at each cut of local variable scopes (this is not of block local -variable scopes), this link is entirely saved or restored to @lvtbl->dyna_vars@ . -I'd like you to go back a little and check @local_push()@ and @local_pop()@ . +variable scopes), this link is entirely saved or restored to @lvtbl->dyna_vars@. +I'd like you to go back a little and check @local_push()@ and @local_pop()@. By the way, although creating the @ruby_dyna_vars@ list was a huge task, From 5efa09679ad478e15c4a80efc5c44a118b866a13 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 17:03:07 +0900 Subject: [PATCH 058/121] rephrase a line of chapter 12 --- syntree.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntree.textile b/syntree.textile index 8ef108d..dfdfbc7 100644 --- a/syntree.textile +++ b/syntree.textile @@ -157,7 +157,7 @@ Fig.1 shows how it seems like.

(flagUsage)
-Fig.1: How RNode.flags is used +Fig.1: The usage of RNode.flags

From e15f6f4669fa1e51baf5a04f9c43c07ba43dedf5 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 17:06:35 +0900 Subject: [PATCH 059/121] English images for chapter 12 --- images/ch_syntree_append.jpg | Bin 23511 -> 26484 bytes images/ch_syntree_dynavars.jpg | Bin 13119 -> 16000 bytes images/ch_syntree_flagUsage.jpg | Bin 9799 -> 11047 bytes images/ch_syntree_flags.jpg | Bin 10977 -> 12521 bytes images/ch_syntree_localtbl.jpg | Bin 5938 -> 7125 bytes images/ch_syntree_lvtbltbl.jpg | Bin 6969 -> 7754 bytes images/ch_syntree_tbl.jpg | Bin 6300 -> 6511 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/ch_syntree_append.jpg b/images/ch_syntree_append.jpg index 24c71872893a7a3ffb728678dfa9e62d5d21ca75..8ea56d5f5f7a9f9a50108bd03abcd33933d1383a 100644 GIT binary patch literal 26484 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 literal 23511 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⋙p9@|y1I((;NpQs8oTnz_n@nsilmH}+28{HL4>4{*AJwm|;> FO#m!B@{0ff diff --git a/images/ch_syntree_dynavars.jpg b/images/ch_syntree_dynavars.jpg index f56244d01855ff62b1398a4fae0fd3f25dee6ce2..024a534a42d7f5a9a1421ca18b7c198fc647a28f 100644 GIT binary patch literal 16000 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
kkPKz!dtUKLTmAOc7 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 CCzrDT literal 9799 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 diff --git a/images/ch_syntree_flags.jpg b/images/ch_syntree_flags.jpg index 8b9dfefae116c00eddca0fb147b567ac33241960..7c23b69a8b573f71d3ac40d198395df09d6f3f8f 100644 GIT binary patch literal 12521 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 JL+B3+{|hCgPL2Qo literal 10977 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 diff --git a/images/ch_syntree_localtbl.jpg b/images/ch_syntree_localtbl.jpg index fc07cbc65c1231309bdb0a02764eaec579d146a9..23115703bf275bbef213083adaa01791d9c0cb83 100644 GIT binary patch literal 7125 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 eGm9E_Nts|1-@&5pZl)=9M literal 6969 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 Date: Tue, 17 Sep 2013 17:09:40 +0900 Subject: [PATCH 060/121] remove unncessary "first" from README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d98b890..4397463 100644 --- a/README.md +++ b/README.md @@ -65,4 +65,4 @@ This translation work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike2.5 License](http://creativecommons.org/licenses/by-nc-sa/2.5/) If you'd like to translate this work to another language, -please contact the author Minero Aoki first. +please contact the author Minero Aoki. From d17f342e9ffcf7ed950f80e98b25ff1c6aaa72ce Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 18:05:49 +0900 Subject: [PATCH 061/121] write more information about the ruby explained --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4397463..0b376c8 100644 --- a/README.md +++ b/README.md @@ -39,21 +39,23 @@ $ jekyll serve # this compiles files and starts a server on localhost:4000. [Jekyll usage](https://github.com/mojombo/jekyll/wiki/usage) -Version of ruby used is very old 1.7.3 -It seems there is -[no tag on github for this version](https://github.com/ruby/ruby/tags?after=v1_8_3_preview2) +About the version of ruby explained +========== -Get Ruby 1.7.3 -============== - -It's available from this Organization's repo at -https://github.com/ruby-hacking-guide/ruby-1.7.3 +The version of ruby used is ruby (1.7.3 2002-09-12). +It's almost a year before the release of Ruby 1.8.0, +so things explained in this book are basically the same in Ruby 1.8. -`git clone git://github.com/ruby-hacking-guide/ruby-1.7.3.git` +The details about this version are written in the +[Introduction](http://ruby-hacking-guide.github.io/intro.html) -or from the original site zipped up +You can download it from the official support site of the book. http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz +http://i.loveruby.net/ja/rhg/ar/ruby-rhg.zip + +It's also available from this Organization's repo at +https://github.com/ruby-hacking-guide/ruby-1.7.3 License From d1cd22dc28af7f6b31fd319d53aa97dd8ec39bf8 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 18:11:48 +0900 Subject: [PATCH 062/121] edit README for readability --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0b376c8..fcc4ea5 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ About the version of ruby explained ========== The version of ruby used is ruby (1.7.3 2002-09-12). + It's almost a year before the release of Ruby 1.8.0, so things explained in this book are basically the same in Ruby 1.8. @@ -51,11 +52,11 @@ The details about this version are written in the [Introduction](http://ruby-hacking-guide.github.io/intro.html) You can download it from the official support site of the book. -http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz -http://i.loveruby.net/ja/rhg/ar/ruby-rhg.zip +* http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz +* http://i.loveruby.net/ja/rhg/ar/ruby-rhg.zip It's also available from this Organization's repo at -https://github.com/ruby-hacking-guide/ruby-1.7.3 +* https://github.com/ruby-hacking-guide/ruby-1.7.3 License From 0f8c343a0ec6678640246c8b4d70b9df985699a8 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 18:15:23 +0900 Subject: [PATCH 063/121] fix a mistake --- index.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.textile b/index.textile index 32c8037..886739d 100644 --- a/index.textile +++ b/index.textile @@ -57,7 +57,7 @@ You can download the version of the source code explained and the tool used in the book from the official support site of the original book. * "ruby (1.7.3 2002-09-12) in tar.gz format":http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz -* "ruby (1.7.3 2002-09-12) in zip format":http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz +* "ruby (1.7.3 2002-09-12) in zip format":http://i.loveruby.net/ja/rhg/ar/ruby-rhg.zip * "Pragmatic Programmers' nodeDump 0.1.7":http://i.loveruby.net/ja/rhg/ar/nodeDump-0.1.7.tgz * "RHG-version nodedump":http://i.loveruby.net/ja/rhg/ar/nodedump-rhg.tar.gz From e5ac5bebfa94b6f483561680900acf7532b4985f Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 18 Sep 2013 14:10:19 +0900 Subject: [PATCH 064/121] erase unnecessary white-spaces from chapter 13 --- evaluator.textile | 198 +++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/evaluator.textile b/evaluator.textile index 461ecda..ec1265e 100644 --- a/evaluator.textile +++ b/evaluator.textile @@ -60,12 +60,12 @@ I'd like you to remember. h3. The characteristics of @ruby's@ evaluator. -The biggest characteristic of @ruby@ 's evaluator is that, as this is also of -the whole @ruby@ 's interpretor, the difference in expressions between +The biggest characteristic of `ruby`'s evaluator is that, as this is also of +the whole `ruby`'s interpretor, the difference in expressions between the C-level code (extension libraries) and the Ruby-level code is small. In ordinary programming languages, the amount of the features of its interpretor we can use from extension -libraries is usually very limited, but there are awfully few limits in @ruby@ . +libraries is usually very limited, but there are awfully few limits in @ruby@. Defining classes, defining methods and calling a method without limitation, these can be taken for granted. We can also use exception handling, iterators. Furthermore, threads. @@ -90,7 +90,7 @@ answer = eval("lvar + lvar") # the answer is 2 -There are also @Module#module_eval@ and @Object#instance_eval@ , each method +There are also @Module#module_eval@ and @Object#instance_eval@, each method behaves slightly differently. I'll describe about them in detail in Chapter 17: Dynamic evaluation. @@ -98,7 +98,7 @@ behaves slightly differently. I'll describe about them in detail in Chapter 17: h3. @eval.c@ -The evaluator is implemented in @eval.c@ . However, this @eval.c@ is a +The evaluator is implemented in @eval.c@. However, this @eval.c@ is a really huge file: it has 9000 lines, its size is 200K bytes, and the number of the functions in it is 309. It is hard to fight against. When the size becomes this amount, @@ -113,13 +113,13 @@ I'll list up some ways. The first way is to print the list of the defined functions and look at the -prefixes of them. @rb_dvar_@ , @rb_mod_@ , @rb_thread@ -- there are plenty of +prefixes of them. @rb_dvar_@, @rb_mod_@, @rb_thread@ -- there are plenty of functions with these prefixes. Each prefix clearly indicate a group of the same type of functions. Alternatively, as we can tell when looking at the code of the class libraries, -@Init_xxxx()@ is always put at the end of a block in @ruby@ . +@Init_xxxx()@ is always put at the end of a block in @ruby@. Therefore, @Init_xxxx()@ also indicates a break between modules. @@ -128,7 +128,7 @@ Since @eval()@ and @rb_eval()@ and @eval_node()@ appear close to each other, we naturally think there should be a deep relationship among them. -Finally, in the source code of @ruby@ , the definitions of types or variables +Finally, in the source code of @ruby@, the definitions of types or variables and the declarations of prototypes often indicate a break between modules. @@ -147,9 +147,9 @@ it seems that @eval.c@ can be mainly divided into these modules listed below: | Thread | the implementation of Ruby threads | -Among them, "Load" and "Thread" are the parts that essentially should not be in @eval.c@ . +Among them, "Load" and "Thread" are the parts that essentially should not be in @eval.c@. They are in @eval.c@ merely because of the restrictions of C language. -To put it more precisely, they need the macros such as @PUSH_TAG@ defined in @eval.c@ . +To put it more precisely, they need the macros such as @PUSH_TAG@ defined in @eval.c@. So, I decided to exclude the two topics from Part 3 and deal with them at Part 4. And, it's probably all right if I don't explain the safe level here because I've already done in Part 1. @@ -175,8 +175,8 @@ h3. From @main@ by way of @ruby_run@ to @rb_eval@ h3. Call Graph -The true core of the evaluator is a function called @rb_eval()@ . -In this chapter, we will follow the path from @main()@ to that @rb_eval()@ . +The true core of the evaluator is a function called @rb_eval()@. +In this chapter, we will follow the path from @main()@ to that @rb_eval()@. First of all, here is a rough call graph around @rb_eval@ : @@ -210,8 +210,8 @@ Then, why is this in this way? It's mainly because of the restrictions of C lang Because the functions such as @ruby_prog_init()@ and @ruby_process_options()@ start to use the API of the ruby world, it's possible an exception occurs. However, in order to stop an exception of Ruby, it's necessary to use the macro -named @PUSH_TAG()@ which can only be used in @eval.c@ . In other words, essentially, -@ruby_init()@ and @ruby_run()@ should have been defined in @ruby.c@ . +named @PUSH_TAG()@ which can only be used in @eval.c@. In other words, essentially, +@ruby_init()@ and @ruby_run()@ should have been defined in @ruby.c@. Then, why isn't @PUSH_TAG@ an @extern@ function or something which is available @@ -244,15 +244,15 @@ programs with built-in Ruby in theory, to use these interfaces is natural. What is the @ruby_@ prefix ? So far, the all of @ruby@ 's functions are prefixed -with @rb_@ . Why are there the two types: @rb_@ and @ruby_@ ? I investigated but +with @rb_@. Why are there the two types: @rb_@ and @ruby_@? I investigated but could not understand the difference, so I asked directly. The answer was, "@ruby_@ is for the auxiliary functions of @ruby@ command and @rb_@ is for the official interfaces" -"Then, why are the variables like @ruby_scope@ are @ruby_@ ?", I asked further. +"Then, why are the variables like @ruby_scope@ are @ruby_@?", I asked further. It seems this is just a coincidence. The variables like @ruby_scope@ -are originally named as @the_xxxx@ , but in the middle of the version 1.3 there's +are originally named as @the_xxxx@, but in the middle of the version 1.3 there's a change to add prefixes to all interfaces. At that time @ruby_@ was added to the "may-be-internals-for-some-reasons" variables. @@ -268,7 +268,7 @@ official interfaces of @ruby@ interpretor. h3. @main()@ -First, straightforwardly, I'll start with @main()@ . +First, straightforwardly, I'll start with @main()@. It is nice that this is very short. @@ -338,7 +338,7 @@ This point is generally considered as "lack of features". When there's only a single interpretor, what have difficulty most is probably around the development environment of Ruby. -Concretely, they are the applications such as @irb@ , RubyWin, and RDE. +Concretely, they are the applications such as @irb@, RubyWin, and RDE. Although loading a rewritten program, the classes which are supposed to be deleted would remain. To counter this with the reflection API is not impossible but requires a lot of effort. @@ -358,7 +358,7 @@ The code of @ruby_init()@ is omitted because it's unnecessary to read. h3. @ruby_options()@ -What to parse command-line options for the Ruby interpreter is @ruby_options()@ . +What to parse command-line options for the Ruby interpreter is @ruby_options()@. Of course, depending on the command, we do not have to use this. @@ -368,10 +368,10 @@ This is also where the file passed as a command-line argument is parsed as a Ruby program. -@ruby@ command reads the main program from a file if it was given, otherwise from @stdin@ . +@ruby@ command reads the main program from a file if it was given, otherwise from @stdin@. After that, using @rb_compile_string()@ or @rb_compile_file()@ introduced at Part 2, it compiles the text into a syntax tree. -The result will be set into the global variable @ruby_eval_tree@ . +The result will be set into the global variable @ruby_eval_tree@. I also omit the code of @ruby_options()@ because it's just doing necessary @@ -383,9 +383,9 @@ things one by one and not interesting. h3. @ruby_run()@ -Finally, @ruby_run()@ starts to evaluate the syntax tree which was set to @ruby_eval_tree@ . -We also don't always need to call this function. Other than @ruby_run()@ , -for instance, we can evaluate a string by using a function named @rb_eval_string()@ . +Finally, @ruby_run()@ starts to evaluate the syntax tree which was set to @ruby_eval_tree@. +We also don't always need to call this function. Other than @ruby_run()@, +for instance, we can evaluate a string by using a function named @rb_eval_string()@.

▼ @ruby_run()@

@@ -417,9 +417,9 @@ for instance, we can evaluate a string by using a function named @rb_eval_string -We can see the macros @PUSH_xxxx()@ , but we can ignore them for now. I'll +We can see the macros @PUSH_xxxx()@, but we can ignore them for now. I'll explain about around them later when the time comes. The important thing here -is only @eval_node()@ . Its content is: +is only @eval_node()@. Its content is:

▼ @eval_node()@

@@ -444,12 +444,12 @@ is only @eval_node()@ . Its content is: (eval.c) -This calls @rb_eval()@ on @ruby_eval_tree@ . The @ruby_eval_tree_begin@ is -storing the statements registered by @BEGIN@ . But, this is also not important. +This calls @rb_eval()@ on @ruby_eval_tree@. The @ruby_eval_tree_begin@ is +storing the statements registered by @BEGIN@. But, this is also not important. And, @ruby_stop()@ inside of @ruby_run()@ terminates all threads and -finalizes all objects and checks exceptions and, in the end, calls @exit()@ . +finalizes all objects and checks exceptions and, in the end, calls @exit()@. This is also not important, so we won't see this. @@ -461,8 +461,8 @@ h2. @rb_eval()@ h3. Outline -Now, @rb_eval()@ . This function is exactly the real core of @ruby@ . -One @rb_eval()@ call processes a single @NODE@ , and the whole syntax tree will +Now, @rb_eval()@. This function is exactly the real core of @ruby@. +One @rb_eval()@ call processes a single @NODE@, and the whole syntax tree will be processed by calling recursively. (Fig.1) @@ -472,7 +472,7 @@ Fig.1: @rb_eval@

-@rb_eval@ is, as the same as @yylex()@ , made of a huge switch statement and +@rb_eval@ is, as the same as @yylex()@, made of a huge switch statement and branching by each type of the nodes. First, let's look at the outline. @@ -522,12 +522,12 @@ branching by each type of the nodes. First, let's look at the outline. In the omitted part, plenty of the codes to process all nodes are listed. By branching like this, it processes each node. When the code is only a few, -it will be processed in @rb_eval()@ . But when it becoming many, it will be a +it will be processed in @rb_eval()@. But when it becoming many, it will be a separated function. Most of functions in @eval.c@ are created in this way. -When returning a value from @rb_eval()@ , it uses the macro @RETURN()@ instead -of @return@ , in order to always pass through @CHECK_INTS@ . Since this macro is +When returning a value from @rb_eval()@, it uses the macro @RETURN()@ instead +of @return@, in order to always pass through @CHECK_INTS@. Since this macro is related to threads, you can ignore this until the chapter about it. @@ -541,7 +541,7 @@ h3. @NODE_IF@ Now, taking the @if@ statement as an example, let's look at the process of the @rb_eval()@ evaluation concretely. -From here, in the description of @rb_eval()@ , +From here, in the description of @rb_eval()@, * The source code (a Ruby program) * Its corresponding syntax tree @@ -629,7 +629,7 @@ else { First, at (A), evaluating (the node of) the Ruby's condition statement and -testing its value with @RTEST()@ . +testing its value with @RTEST()@. I've mentioned that @RTEST()@ is a macro to test whether or not a @VALUE@ is true of Ruby. If that was true, evaluating the @then@ side clause at (B). @@ -639,11 +639,11 @@ If false, evaluating the @else@ side clause at ==(C)==. In addition, I've mentioned that @if@ statement of Ruby also has its own value, so it's necessary to return a value. Since the value of an @if@ is the value of either the @then@ side or the @else@ -side which is the one executed, returning it by using the macro @RETURN()@ . +side which is the one executed, returning it by using the macro @RETURN()@. -In the original list, it does not call @rb_eval()@ recursively but just does @goto@ . +In the original list, it does not call @rb_eval()@ recursively but just does @goto@. This is the "conversion from tail recursion to @goto@ " which has also appeared in the previous chapter "Syntax tree construction". @@ -677,7 +677,7 @@ let's look at the code for it. There's nothing particularly difficult. -@call_trace_func()@ has already appeared at @NODE_IF@ . Here is a simple +@call_trace_func()@ has already appeared at @NODE_IF@. Here is a simple explanation of what kind of thing it is. This is a feature to trace a Ruby program from Ruby level. The debugger ( @debug.rb@ ) and the tracer ( @tracer.rb@ ) and the profiler ( @profile.rb@ ) and @irb@ (interactive @ruby@ command) and more @@ -685,8 +685,8 @@ are using this feature. By using the function-like method @set_trace_func@ you can register a @Proc@ -object to trace, and that @Proc@ object is stored into @trace_func@ . If -@trace_func@ is not 0, it means not @QFalse@ , it will be considered as a @Proc@ +object to trace, and that @Proc@ object is stored into @trace_func@. If +@trace_func@ is not 0, it means not @QFalse@, it will be considered as a @Proc@ object and executed (at @call_trace_func()@ ). @@ -724,7 +724,7 @@ Let's look at the leaves, too. -We've seen @self@ as the argument of @rb_eval()@ . I'd like you to make sure it +We've seen @self@ as the argument of @rb_eval()@. I'd like you to make sure it by going back a little. The others are probably not needed to be explained. @@ -734,19 +734,19 @@ The others are probably not needed to be explained. h3. Jump Tag -Next, I'd like to explain @NODE_WHILE@ which is corresponding to @while@ , +Next, I'd like to explain @NODE_WHILE@ which is corresponding to @while@, but to implement @break@ or @next@ only with recursive calls of a function is difficult. Since @ruby@ enables these syntaxes by using what named "jump tag", I'll start with describing it first. Simply put, "jump tag" is a wrapper of @setjmp()@ and @longjump()@ which are -library functions of C language. Do you know about @setjmp()@ ? -This function has already appeared at @gc.c@ , +library functions of C language. Do you know about @setjmp()@? +This function has already appeared at @gc.c@, but it is used in very abnormal way there. @setjmp()@ is usually used to jump over functions. I'll explain by taking the below code as an example. -The entry point is @parent()@ . +The entry point is @parent()@.

▼ @setjmp()@ and @longjmp()@

@@ -778,28 +778,28 @@ void parent(void) { -First, when @setjmp()@ is called at @parent()@ , -the executing state at the time is saved to the argument @buf@ . +First, when @setjmp()@ is called at @parent()@, +the executing state at the time is saved to the argument @buf@. To put it a little more directly, the address of the top of the machine stack and the CPU registers are saved. -If the return value of @setjmp()@ was 0, it means it normally returned from @setjmp()@ , +If the return value of @setjmp()@ was 0, it means it normally returned from @setjmp()@, thus you can write the subsequent code as usual. -This is the @if@ side. Here, it calls @child1()@ . +This is the @if@ side. Here, it calls @child1()@. -Next, the control moves to @child2()@ and calls @longjump@ , +Next, the control moves to @child2()@ and calls @longjump@, then it can go back straight to the place where the argument @buf@ was @setjmp@ ed. -So in this case, it goes back to the @setjmp@ at @parent()@ . -When coming back via @longjmp@ , the return value of @setjmp@ becomes -the value of the second argument of @longjmp@ , so the @else@ side is executed. -And, even if we pass 0 to @longjmp@ , +So in this case, it goes back to the @setjmp@ at @parent()@. +When coming back via @longjmp@, the return value of @setjmp@ becomes +the value of the second argument of @longjmp@, so the @else@ side is executed. +And, even if we pass 0 to @longjmp@, it will be forced to be another value. Thus it's fruitless. Fig.2 shows the state of the machine stack. The ordinary functions return only once for each call. However, it's possible @setjmp()@ returns twice. -Is it helpful to grasp the concept if I say that it is something like @fork()@ ? +Is it helpful to grasp the concept if I say that it is something like @fork()@? @@ -810,7 +810,7 @@ Fig.2: @setjmp()@ @longjmp()@ Image Now, we've learned about @setjmp()@ as a preparation. -In @eval.c@ , @EXEC_TAG@ corresponds to @setjmp()@ and @JUMP_TAG()@ corresponds +In @eval.c@, @EXEC_TAG@ corresponds to @setjmp()@ and @JUMP_TAG()@ corresponds to @longjmp()@ respectively. (Fig.3) @@ -822,7 +822,7 @@ Fig.3: "tag jump" image Take a look at this image, it seems that @EXEC_TAG()@ does not have any arguments. Where has @jmp_buf@ gone? -Actually, in @ruby@ , @jmp_buf@ is wrapped by the struct @struct tag@. +Actually, in @ruby@, @jmp_buf@ is wrapped by the struct @struct tag@. Let's look at it. @@ -844,9 +844,9 @@ Let's look at it. -Because there's the member @prev@ , we can infer that @struct tag@ is probably +Because there's the member @prev@, we can infer that @struct tag@ is probably a stack structure using a linked list. Moreover, by looking around it, we can -find the macros @PUSH_TAG()@ and @POP_TAG@ , thus it definitely seems a stack. +find the macros @PUSH_TAG()@ and @POP_TAG@, thus it definitely seems a stack.

▼ @PUSH_TAG() POP_TAG()@

@@ -897,7 +897,7 @@ do { This method does not have any overhead of function calls, and its cost of the memory allocation is next to nothing. This technique is only possible because the @ruby@ evaluator is made of -recursive calls of @rb_eval()@ . +recursive calls of @rb_eval()@. @@ -913,7 +913,7 @@ carelessly used at the outside of the evaluator, we can't make them available to other files. -Additionally, let's also take a look at @EXEC_TAG()@ and @JUMP_TAG()@ . +Additionally, let's also take a look at @EXEC_TAG()@ and @JUMP_TAG()@.

▼ @EXEC_TAG() JUMP_TAG()@

@@ -933,13 +933,13 @@ Additionally, let's also take a look at @EXEC_TAG()@ and @JUMP_TAG()@ . In this way, @setjmp@ and @longjmp@ are wrapped by @EXEC_TAG()@ and @JUMP_TAG()@ respectively. The name @EXEC_TAG()@ can look like a wrapper of @longjmp()@ at first sight, -but this one is to execute @setjmp()@ . +but this one is to execute @setjmp()@. -Based on all of the above, I'll explain the mechanism of @while@ . +Based on all of the above, I'll explain the mechanism of @while@. First, when starting @while@ it does @EXEC_TAG()@ ( @setjmp@ ). After that, it executes the main body by calling @rb_eval()@ -recursively. If there's @break@ or @next@ , it does @JUMP_TAG()@ ( @longjmp@ ). +recursively. If there's @break@ or @next@, it does @JUMP_TAG()@ ( @longjmp@ ). Then, it can go back to the start point of the @while@ loop. (Fig.5) @@ -950,10 +950,10 @@ Fig.5: the implementation of @while@ by using "tag jump" Though @break@ was taken as an example here, what cannot be implemented without -jumping is not only @break@ . Even if we limit the case to @while@ , -there are @next@ and @redo@ . +jumping is not only @break@. Even if we limit the case to @while@, +there are @next@ and @redo@. Additionally, @return@ from a method and exceptions also should have to -climb over the wall of @rb_eval()@ . +climb over the wall of @rb_eval()@. And since it's cumbersome to use a different tag stack for each case, we want for only one stack to handle all cases in one way or another. @@ -961,7 +961,7 @@ we want for only one stack to handle all cases in one way or another. What we need to make it possible is just attaching information about "what the purpose of this jump is". Conveniently, the return value of @setjmp()@ could be specified as the argument -of @longjmp()@ , thus we can use this. The types are expressed by the following flags: +of @longjmp()@, thus we can use this. The types are expressed by the following flags: @@ -983,7 +983,7 @@ of @longjmp()@ , thus we can use this. The types are expressed by the following The meanings are written as each comment. The last @TAG_MASK@ is the bitmask to -take out these flags from a return value of @setjmp()@ . This is because the +take out these flags from a return value of @setjmp()@. This is because the return value of @setjmp()@ can also include information which is not about a "type of jump". @@ -993,7 +993,7 @@ return value of @setjmp()@ can also include information which is not about a h3. @NODE_WHILE@ -Now, by examining the code of @NODE_WHILE@ , let's check the actual usage of tags. +Now, by examining the code of @NODE_WHILE@, let's check the actual usage of tags.

▼ The Source Program

@@ -1085,18 +1085,18 @@ if (state) JUMP_TAG(state); /* .. jump again here */ First, as @PUSH_TAG()@ and @POP_TAG()@ are the previously described mechanism, it's necessary to be used always as a pair. Also, they need to be written -outside of @EXEC_TAG()@ . And, apply @EXEC_TAG()@ to the just pushed @jmp_buf@ . -This means doing @setjmp()@ . -If the return value is 0, since it means immediately returning from @setjmp()@ , +outside of @EXEC_TAG()@. And, apply @EXEC_TAG()@ to the just pushed @jmp_buf@. +This means doing @setjmp()@. +If the return value is 0, since it means immediately returning from @setjmp()@, it does the normal processing (this usually contains @rb_eval()@ ). -If the return value of @EXEC_TAG()@ is not 0, since it means returning via @longjmp()@ , +If the return value of @EXEC_TAG()@ is not 0, since it means returning via @longjmp()@, it filters only the own necessary jumps by using @case@ and lets the rest ( @default@ ) pass. It might be helpful to see also the code of the jumping side. -The below code is the handler of the node of @redo@ . +The below code is the handler of the node of @redo@.

▼ @rb_eval()@ - @NODE_REDO@

@@ -1111,8 +1111,8 @@ The below code is the handler of the node of @redo@ . -As a result of jumping via @JUMP_TAG()@ , it goes back to the last @EXEC_TAG()@ . -The return value at the time is the argument @TAG_REDO@ . Being aware of this, +As a result of jumping via @JUMP_TAG()@, it goes back to the last @EXEC_TAG()@. +The return value at the time is the argument @TAG_REDO@. Being aware of this, I'd like you to look at the code of @NODE_WHILE@ and check what route is taken. @@ -1136,8 +1136,8 @@ while_out: There are the two places calling @rb_eval()@ on @node->nd_state@ which corresponds to the conditional statement. It seems that only the first test of the condition is separated. This is to deal with both @do@ ~ @while@ and @while@ -at once. When @node->nd_state@ is 0 it is a @do@ ~ @while@ , when 1 it is an -ordinary @while@ . The rest might be understood by following step-by-step, +at once. When @node->nd_state@ is 0 it is a @do@ ~ @while@, when 1 it is an +ordinary @while@. The rest might be understood by following step-by-step, I won't particularly explain. @@ -1156,7 +1156,7 @@ So, I've actually tried it. It's simply rejected at the time of parsing. It's safe but not an interesting result. -What produces this error is @value_expr()@ of @parse.y@ . +What produces this error is @value_expr()@ of @parse.y@. @@ -1168,7 +1168,7 @@ h3. The value of an evaluation of @while@ a value by using @break@ since @ruby@ 1.7. This time, let's focus on the flow of the value of an evaluation. Keeping in mind that the value of the local variable @result@ becomes the -return value of @rb_eval()@ , I'd like you to look at the following code: +return value of @rb_eval()@, I'd like you to look at the following code: @@ -1215,12 +1215,12 @@ Here is the passing side: -In this way, by using the macro @return_value()@ , it assigns the value to the +In this way, by using the macro @return_value()@, it assigns the value to the struct of the top of the tag stack. The basic flow is this, but in practice there could be another @EXEC_TAG@ -between @EXEC_TAG()@ of @NODE_WHILE@ and @JUMP_TAG()@ of @NODE_BREAK@ . +between @EXEC_TAG()@ of @NODE_WHILE@ and @JUMP_TAG()@ of @NODE_BREAK@. For example, @rescue@ of an exception handling can exist between them. @@ -1236,7 +1236,7 @@ end Therefore, it's hard to determine whether or not the @strict tag@ of when doing -@JUMP_TAG()@ at @NODE_BREAK@ is the one which was pushed at @NODE_WHILE@ . +@JUMP_TAG()@ at @NODE_BREAK@ is the one which was pushed at @NODE_WHILE@. In this case, because @retval@ is propagated in @POP_TAG()@ as shown below, the return value can be passed to the next tag without particular thought. @@ -1278,9 +1278,9 @@ are dealt with. h3. @raise@ -When I explained @while@ , we looked at the @setjmp()@ side first. This time, +When I explained @while@, we looked at the @setjmp()@ side first. This time, we'll look at the @longjmp()@ side first for a change. It's @rb_exc_raise()@ -which is the substance of @raise@ . +which is the substance of @raise@.

▼ @rb_exc_raise()@

@@ -1299,7 +1299,7 @@ which is the substance of @raise@ . @mesg@ is an exception object (an instance of @Exception@ or one of its subclass). Notice that It seems to jump with @TAG_RAISE@ this time. -And the below code is very simplified @rb_longjmp()@ . +And the below code is very simplified @rb_longjmp()@.

▼ @rb_longjmp()@ (simplified)

@@ -1320,10 +1320,10 @@ rb_longjmp(tag, mesg) Well, though this can be considered as a matter of course, this is just to jump -as usual by using @JUMP_TAG()@ . +as usual by using @JUMP_TAG()@. -What is @ruby_errinfo@ ? By doing @grep@ a few times, I figured out that this +What is @ruby_errinfo@? By doing @grep@ a few times, I figured out that this variable is the substance of the global variable @$!@ of Ruby. Since this variable indicates the exception which is currently occurring, naturally its substance @ruby_errinfo@ should have the same meaning as well. @@ -1387,7 +1387,7 @@ virtually on the top. This means, since @NODE_ENSURE@ and @NODE_RESCUE@ are above the main body which -we want to protect, we can stop @raise@ by merely doing @EXEC_TAG()@ . Or rather, +we want to protect, we can stop @raise@ by merely doing @EXEC_TAG()@. Or rather, the two nodes are put above in syntax tree for this purpose, is probably more accurate to say. @@ -1398,7 +1398,7 @@ accurate to say. h3. @ensure@ -We are going to look at the handler of @NODE_ENSURE@ which is the node of @ensure@ . +We are going to look at the handler of @NODE_ENSURE@ which is the node of @ensure@.

▼ @rb_eval()@ - @NODE_ENSURE@

@@ -1451,7 +1451,7 @@ so the value of the evaluation of an @ensure@ clause is completely discarded. At (B-1,3), it deals with the evaluated value of when a jump occurred at the main body. -I mentioned that the value of this case is stored in @prot_tag->retval@ , +I mentioned that the value of this case is stored in @prot_tag->retval@, so it saves the value to a local variable to prevent from being carelessly overwritten during the execution of the @ensure@ clause (B-1). After the evaluation of the @ensure@ clause, it restores the value by using @@ -1509,7 +1509,7 @@ nd_body: I'd like you to make sure that (the syntax tree of) the statement to be -@rescue@ ed is "under" @NODE_RESCUE@ . +@rescue@ ed is "under" @NODE_RESCUE@.

▼ @rb_eval()@ - @NODE_RESCUE@

@@ -1577,7 +1577,7 @@ static int handle_rescue(VALUE self, NODE *resq) -and it determines whether the currently occurring exception ( @ruby_errinfo@ ) is -a subclass of the class that is expressed by @resq@ ( @TypeError@ , for instance). +and it determines whether the currently occurring exception (@ruby_errinfo@) is +a subclass of the class that is expressed by @resq@ (@TypeError@, for instance). The reason why passing @self@ is that it's necessary to call @rb_eval()@ inside -this function in order to evaluate @resq@ . +this function in order to evaluate @resq@. From 0d678a07914f00150e256544a9fcaa9e40840df5 Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 18 Sep 2013 14:40:49 +0900 Subject: [PATCH 065/121] edit chapter 13 --- evaluator.textile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/evaluator.textile b/evaluator.textile index ec1265e..22e68c1 100644 --- a/evaluator.textile +++ b/evaluator.textile @@ -257,10 +257,9 @@ a change to add prefixes to all interfaces. At that time @ruby_@ was added to the "may-be-internals-for-some-reasons" variables. -The bottom line is that what @ruby_@ is attached to are either what to support -@ruby@ command or the internal variables and what @rb_@ is attached to are the -official interfaces of @ruby@ interpretor. - +The bottom line is that @ruby_@ is attached to things that support +@ruby@ command or the internal variables and @rb_@ is attached to +the official interfaces of @ruby@ interpretor. @@ -337,16 +336,17 @@ This point is generally considered as "lack of features". When there's only a single interpretor, -what have difficulty most is probably around the development environment of Ruby. -Concretely, they are the applications such as @irb@, RubyWin, and RDE. +more than anything, +things around the development environment should be especially troublesome. +Namely, the applications such as @irb@, RubyWin, and RDE. Although loading a rewritten program, the classes which are supposed to be deleted would remain. To counter this with the reflection API is not impossible -but requires a lot of effort. +but requires a lot of efforts. However, it seems that Mr. Matsumoto (Matz) purposefully limits the number of -interpretors to one. "it's impossible to initialize completely" appears to be -its reason. For example, "the loaded extension libraries could not be removed" +interpretors to one. "it's impossible to initialize completely" seems +its reason. For instance, "the loaded extension libraries could not be removed" is taken as an example. @@ -613,7 +613,7 @@ bundled to a single @NODE_IF@ type, so we don't have to treat them specially. -What is important is only the last @if@ statement. +Only the last @if@ statement is important. If rewriting it without any change in its meaning, it becomes this: From 787e2175452a682dc03ccc86cc2625f27fc710ab Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 18 Sep 2013 14:46:04 +0900 Subject: [PATCH 066/121] English images for chapter 13 --- images/ch_evaluator_usetag.jpg | Bin 41164 -> 47306 bytes images/ch_evaluator_whilejmp.jpg | Bin 14809 -> 16605 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/ch_evaluator_usetag.jpg b/images/ch_evaluator_usetag.jpg index 6d7981fc1efeae4e109ba8ae2652b82063119212..8e829a8c1b8251618c36e1dd3721ea622b955763 100644 GIT binary patch literal 47306 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 literal 41164 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 J3+sO2{{khDLqY%m literal 14809 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 POZo3u^0)mdUC#eE)81&f From 19e196ba5d49c4a20a64f58a2582c6013d07deca Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 18 Sep 2013 14:46:47 +0900 Subject: [PATCH 067/121] rephrase a line of chapter 13 --- evaluator.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evaluator.textile b/evaluator.textile index 22e68c1..b9670b7 100644 --- a/evaluator.textile +++ b/evaluator.textile @@ -1260,7 +1260,7 @@ This can probably be depicted as Fig.6.

(usetag)
-Fig.6: the return value propagation +Fig.6: Transferring the return value

From d9b1bc1d3790d9785bb2a0c1a6083de3536af0ef Mon Sep 17 00:00:00 2001 From: ocha- Date: Fri, 20 Sep 2013 15:32:25 +0900 Subject: [PATCH 068/121] erase unncessary white-spaces from chapter 14 --- module.textile | 212 ++++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/module.textile b/module.textile index bea210d..615ca12 100644 --- a/module.textile +++ b/module.textile @@ -34,7 +34,7 @@ is a perfect example. What to be careful about here is, what is changing during the execution is only the stack, on the contrary, the program remains unchanged wherever it is. -For example, if it is "a reference to the local variable @i@ ", there's just an +For example, if it is "a reference to the local variable @i@", there's just an order of "give me @i@ of the current frame", it is not written as "give me @i@ of that frame". In other words, "only" the state of the stack influences the consequence. This is why, @@ -56,7 +56,7 @@ And these kind of scopes are expressed by stacks. However in Ruby, for instance, you can temporarily go back to the scope -previously used by using iterators or @Proc@ . +previously used by using iterators or @Proc@. This cannot be implemented with just simply pushing/popping a stack. Therefore the frames of the Ruby stack will be intricately rearranged during execution. Although I call it "stack", it could be better to consider it @@ -86,13 +86,13 @@ it's at least twenty times more complicated. First, I'll briefly describe about these stacks and their stack frame structs. -The defined file is either @eval.c@ or @evn.h@ . Basically these stack frames +The defined file is either @eval.c@ or @evn.h@. Basically these stack frames are touched only by @eval.c@ ... is what it should be if it were possible, but @gc.c@ needs to know the struct types when marking, -so some of them are exposed in @env.h@ . +so some of them are exposed in @env.h@. -Of course, marking could be done in the other file but @gc.c@ , but it requires +Of course, marking could be done in the other file but @gc.c@, but it requires separated functions which cause slowing down. The ordinary programs had better not care about such things, but both the garbage collector and the core of the evaluator is the ruby's biggest bottleneck, so it's quite worth to optimize @@ -149,11 +149,11 @@ The fact that @ruby_xxxx@ points to the top stack frame is common to all stacks and won't be mentioned every time. -The first member of the struct is @self@ . -There is also @self@ in the arguments of @rb_eval()@ , +The first member of the struct is @self@. +There is also @self@ in the arguments of @rb_eval()@, but why this struct remembers another @self@ ? This is for the C-level functions. More precisely, it's for @rb_call_super()@ that is -corresponding to @super@ . In order to execute @super@ , it requires the receiver +corresponding to @super@. In order to execute @super@, it requires the receiver of the current method, but the caller side of @rb_call_super()@ could not have such information. However, the chain of @rb_eval()@ is interrupted before the time when the execution of the user-defined C code starts. Therefore, the @@ -161,7 +161,7 @@ conclusion is that there need a way to obtain the information of @self@ out of nothing. And, @FRAME@ is the right place to store it. -Thinking a little further, It's mysterious that there are @argc@ and @argv@ . +Thinking a little further, It's mysterious that there are @argc@ and @argv@. Because parameter variables are local variables after all, it is unnecessary to preserve the given arguments after assigning them into the local variable with the same names at the beginning of the method, isn't it? @@ -187,8 +187,8 @@ C.new.ali -in this case, @last_func=ali@ and @orig_func=orig@ . -Not surprisingly, these members also have to do with @super@ . +in this case, @last_func=ali@ and @orig_func=orig@. +Not surprisingly, these members also have to do with @super@. @@ -200,7 +200,7 @@ h3. @ruby_scope@ class definition statements, the module definition statements and the singleton class definition statements, all of them are different scopes. The stack frame struct is @struct SCOPE@. -I'll call this frame @SCOPE@ . +I'll call this frame @SCOPE@.

▼ @ruby_scope@

@@ -243,7 +243,7 @@ cnt = nil # cut the reference. The created Proc finally becomes unnecessary her The @Proc@ object created by this method will persist longer than the method that -creates it. And, because the @Proc@ can refer to the local variable @lvar@ , +creates it. And, because the @Proc@ can refer to the local variable @lvar@, the local variables must be preserved until the @Proc@ will disappear. Thus, if it were not handled by the garbage collector, no one can determine the time to free. @@ -264,7 +264,7 @@ h3. @ruby_block@ @struct BLOCK@ is the real body of a Ruby's iterator block or a @Proc@ object, it is also kind of a snapshot of the evaluator at some point. This frame will also be briefly written as @BLOCK@ as in the same manner as -@FRAME@ and @SCOPE@ . +@FRAME@ and @SCOPE@.

▼ @ruby_block@

@@ -313,7 +313,7 @@ preparation for that case. Additionally, @struct BLOCKTAG@ is separated in order to detect the same block when multiple @Proc@ objects are created from the block. The @Proc@ objects -which were created from the one same block have the same @BLOCKTAG@ . +which were created from the one same block have the same @BLOCKTAG@. @@ -323,7 +323,7 @@ h3. @ruby_iter@ The stack @ruby_iter@ indicates whether currently calling method is an iterator (whether it is called with a block). The frame is @struct iter@. -But for consistency I'll call it @ITER@ . +But for consistency I'll call it @ITER@.

▼ @ruby_iter@

@@ -352,7 +352,7 @@ but you also need to inform the fact when "it is not an iterator". However, pushing a whole @BLOCK@ just for this is very heavy. It will also cause that in the caller side the procedures such as variable references would needlessly increase. -Thus, it's better to push the smaller and lighter @ITER@ instead of @BLOCK@ . +Thus, it's better to push the smaller and lighter @ITER@ instead of @BLOCK@. This will be discussed in detail in Chapter 16: Blocks. @@ -362,7 +362,7 @@ h3. @ruby_dyna_vars@ The block local variable space. The frame struct is @struct RVarmap@ that has -already seen in Part 2. Form now on, I'll call it just @VARS@ . +already seen in Part 2. Form now on, I'll call it just @VARS@.

▼ @struct RVarmap@

@@ -384,7 +384,7 @@ And each frame is corresponding to a local variable scope. Since it corresponds to "local variable scope" and not "block local variable scope", for instance, even if blocks are nested, only a single list is used to express. The break between blocks are similar to the one of the parser, -it is expressed by a @RVarmap@ (header) whose @id@ is @0@ . +it is expressed by a @RVarmap@ (header) whose @id@ is @0@. Details are deferred again. It will be explained in Chapter 16: Blocks. @@ -402,7 +402,7 @@ h3. @ruby_class@ @ruby_class@ represents the current class to which a method is defined. Since @self@ will be that class when it's a normal class definition statement, @ruby_class == self@. But, when it is the top level or in the middle of -particular methods like @eval@ and @instance_eval@ , @self != ruby_class@ is +particular methods like @eval@ and @instance_eval@, @self != ruby_class@ is possible. @@ -412,7 +412,7 @@ without the @prev@ pointer, how could these form a stack? The answer is deferred to the next section. -From now on, I'll call this frame @CLASS@ . +From now on, I'll call this frame @CLASS@. @@ -434,8 +434,8 @@ Its struct is ... -... surprisingly @NODE@ . This is used just as a "defined struct which can be -pointed by a @VALUE@ ". The node type is @NODE_CREF@ and the assignments of its +... surprisingly @NODE@. This is used just as a "defined struct which can be +pointed by a @VALUE@". The node type is @NODE_CREF@ and the assignments of its members are shown below: @@ -445,8 +445,8 @@ members are shown below: | u3.node | nd_next | preserve the previous @CREF@ | -Even though the member name is @nd_next@ , the value it actually has is the -"previous (prev)" @CREF@ . Taking the following program as an example, I'll +Even though the member name is @nd_next@, the value it actually has is the +"previous (prev)" @CREF@. Taking the following program as an example, I'll explain the actual appearance. @@ -483,7 +483,7 @@ A ← B ← C h3. @PUSH@ / @POP@ Macros For each stack frame struct, the macros to push and pop are available. -For instance, @PUSH_FRAME@ and @POP_FRAME@ for @FRAME@ . +For instance, @PUSH_FRAME@ and @POP_FRAME@ for @FRAME@. Because these will appear in a moment, I'll then explain the usage and content. @@ -569,7 +569,7 @@ nd_body: @nd_cname@ seems the module name. @cname@ is probably either Const NAME or Class NAME. I dumped several things and found that there's always @NODE_SCOPE@ in -@nd_body@ . Since its member @nd_tbl@ holds a local variable table and its name +@nd_body@. Since its member @nd_tbl@ holds a local variable table and its name is similar to @struct SCOPE@, it appears certain that this @NODE_SCOPE@ plays an important role to create a local variable scope. @@ -579,7 +579,7 @@ plays an important role to create a local variable scope. h3. @NODE_MODULE@ -Let's examine the handler of @NODE_MODULE@ of @rb_eval()@ . The parts that are +Let's examine the handler of @NODE_MODULE@ of @rb_eval()@. The parts that are not close to the main line, such as @ruby_raise()@ and error handling were cut drastically. So far, there have been a lot of cutting works for 200 pages, it has already became unnecessary to show the original code. @@ -609,9 +609,9 @@ case NODE_MODULE: -First, we'd like to make sure the module is nested and defined above (the module holded by) @ruby_class@ . -We can understand it from the fact that it calls @ruby_const_xxxx()@ on @ruby_class@ . -Just once @ruby_cbase@ appears, but it is usually identical to @ruby_class@ , +First, we'd like to make sure the module is nested and defined above (the module holded by) @ruby_class@. +We can understand it from the fact that it calls @ruby_const_xxxx()@ on @ruby_class@. +Just once @ruby_cbase@ appears, but it is usually identical to @ruby_class@, so we can ignore it. Even if they are different, it rarely causes a problem. @@ -634,7 +634,7 @@ end -In this program, the two methods, @a@ and @b@ , will be defined on the module @M@ . +In this program, the two methods, @a@ and @b@, will be defined on the module @M@. In this case, on the second definition of @M@ the module @M@ was already set to @@ -645,7 +645,7 @@ the constant, just obtaining and using it would be sufficient. If the constant Lastly, @module_setup()@ is the function executing the body of a module statement. Not only the module statements but the class statements and the -singleton class statements are executed by @module_setup()@ . +singleton class statements are executed by @module_setup()@. This is the reason why I said "all of these three type of statements are similar things". For now, I'd like you to note that @node->nd_body@ ( @NODE_SCOPE@ ) is passed as @@ -741,7 +741,7 @@ the Ruby's ensure. Immediately after the start of the function, the argument n is purposefully -assigned to the local variable @node@ , but @volatile@ is attached to @node@ and +assigned to the local variable @node@, but @volatile@ is attached to @node@ and it would never be assigned after that, thus this is to prevent from being garbage collected. If we assume that the argument was @node@ from the beginning, it would not change the meaning. @@ -750,11 +750,11 @@ it would not change the meaning. In the first half of the function, there's the part manipulating @ruby_frame@ complicatedly. It is obviously paired up with the part @ruby_frame = frame.tmp@ in the last half. We'll focus on this part later, but for the time being this -can be considered as @push pop@ of @ruby_frame@ . +can be considered as @push pop@ of @ruby_frame@. Plus, it seems that the code (A) can be, as commented, summarized as the -initialization of @ruby_scope->local_vars@ . This will be discussed later. +initialization of @ruby_scope->local_vars@. This will be discussed later. Consequently, it could be summarized as follows: @@ -794,7 +794,7 @@ module_setup(module, node) -It does @rb_eval()@ with @node->nd_next@ , +It does @rb_eval()@ with @node->nd_next@, so it's certain that this is the code of the module body. The problems are about the others. There are 5 points to see. @@ -911,7 +911,7 @@ put it shortly, it is "@alloca@ that is assured to allocate on the stack @node->nd_tbl@ holds in fact the local variable name table that has appeared in Chapter 12: Syntax tree construction. It means that @nd_tbl[0]@ contains the table size and the rest is -an array of @ID@ . This table is directly preserved to @local_tbl@ of @SCOPE@ +an array of @ID@. This table is directly preserved to @local_tbl@ of @SCOPE@ and @local_vars@ is allocated to store the local variable values. Because they are confusing, it's a good thing writing some comments such as "This is the variable name", "this is the value". @@ -926,8 +926,8 @@ Fig.6. @ruby_scope->local_vars@ Where is this @node@ used? I examined the all @local_vars@ members but could not find the access to index -@-1@ in @eval.c@ . Expanding the range of files to investigate, I found the -access in @gc.c@ . +@-1@ in @eval.c@. Expanding the range of files to investigate, I found the +access in @gc.c@.

▼ @rb_gc_mark_children()@ — @T_SCOPE@

@@ -953,7 +953,7 @@ access in @gc.c@ . Apparently, this is a mechanism to protect @node@ from GC. But why is it necessary to to mark it here? @node@ is purposefully store into the @volatile@ local variable, so -it would not be garbage-collected during the execution of @module_setup()@ . +it would not be garbage-collected during the execution of @module_setup()@. Honestly speaking, I was thinking it might merely be a mistake for a while but @@ -978,27 +978,27 @@ assigned on this line will disappear completely. Then, when is that? @SCOPE@ sometimes persists longer than the statement that causes the creation of it. As it will be discussed at Chapter 16: Blocks, -if a @Proc@ object is created, it refers @SCOPE@ . +if a @Proc@ object is created, it refers @SCOPE@. Thus, If @module_setup()@ has finished, the @SCOPE@ created there is not necessarily be what is no longer used. That's why it's not sufficient that -@node@ is only referred from (the stack frame of) @module_setup()@ . -It must be referred "directly" from @SCOPE@ . +@node@ is only referred from (the stack frame of) @module_setup()@. +It must be referred "directly" from @SCOPE@. On the other hand, the @volatile node@ of the local variable cannot be removed. -Without it, @node@ is floating on air until it will be assigned to @local_vars@ . +Without it, @node@ is floating on air until it will be assigned to @local_vars@. However then, @local_vars@ of @SCOPE@ is not safe, isn't it? @TMP_ALLOC()@ is, as I mentioned, the allocation on the stack, it becomes invalid at the time @module_setup()@ ends. This is in fact, at the moment when -@Proc@ is created, the allocation method is abruptly switched to @malloc()@ . +@Proc@ is created, the allocation method is abruptly switched to @malloc()@. Details will be described in Chapter 16: Blocks. Lastly, @rb_mem_clear()@ seems zero-filling but actually it is @Qnil@ -filling to an array of @VALUE@ ( @array.c@ ). By this, all defined local variables are -initialized as @nil@ . +initialized as @nil@. @@ -1008,7 +1008,7 @@ h3. @TMP_ALLOC@ Next, let's read @TMP_ALLOC@ that allocates the local variable space. This macro is actually paired with @TMP_PROTECT@ existing silently at the -beginning of @module_setup()@ . Its typical usage is this: +beginning of @module_setup()@. Its typical usage is this: @@ -1046,10 +1046,10 @@ is that ... Let's see its definition. As described in Chapter 5: Garbage collection, in the environment of @#ifdef C_ALLOCA@ (that is, -the native @alloca()@ does not exist) @malloca()@ is used to emulate @alloca()@ . +the native @alloca()@ does not exist) @malloca()@ is used to emulate @alloca()@. However, the arguments of a method are obviously @VALUE@ s and the GC could not find a @VALUE@ if it is stored in the heap. -Therefore, it is enforced that GC can find it through @NODE@ . +Therefore, it is enforced that GC can find it through @NODE@.

@@ -1058,15 +1058,15 @@ Fig.7. anchor the space to the stack through @NODE@

-On the contrary, in the environment with the true @alloca()@ , we can naturally -use @alloca()@ and there's no need to use @TMP_PROTECT@ . Thus, a harmless +On the contrary, in the environment with the true @alloca()@, we can naturally +use @alloca()@ and there's no need to use @TMP_PROTECT@. Thus, a harmless statement is arbitrarily written. By the way, why do they want to use @alloca()@ very much by all means. -It's merely because " @alloca()@ is faster than @malloc()@ ", they said. +It's merely because " @alloca()@ is faster than @malloc()@", they said. One can think that it's not so worth to care about such tiny difference, -but because the core of the evaluator is the biggest bottleneck of @ruby@ , +but because the core of the evaluator is the biggest bottleneck of @ruby@, ... the same as above. @@ -1076,9 +1076,9 @@ h3. Changing the place to define methods on. The value of the stack @ruby_class@ is the place to define a method on at the -time. Conversely, if one push a value to @ruby_class@ , it changes the class to +time. Conversely, if one push a value to @ruby_class@, it changes the class to define a method on. This is exactly what is necessary for a class statement. -Therefore, It's also necessary to do @PUSH_CLASS()@ in @module_setup()@ . +Therefore, It's also necessary to do @PUSH_CLASS()@ in @module_setup()@. Here is the code for it: @@ -1092,7 +1092,7 @@ POP_CLASS(); -Why is there the assignment to @ruby_class@ after doing @PUSH_CLASS()@ . +Why is there the assignment to @ruby_class@ after doing @PUSH_CLASS()@. We can understand it unexpectedly easily by looking at the definition. @@ -1126,7 +1126,7 @@ h3. Nesting Classes @ruby_cref@ represents the class nesting information at runtime. Therefore, it's naturally predicted that @ruby_cref@ will be pushed on the module statements or on the class statements. -In @module_setup()@ , it is pushed as follows: +In @module_setup()@, it is pushed as follows: @@ -1140,7 +1140,7 @@ POP_CREF(); Here, @module@ is the module being defined. -Let's also see the definitions of @PUSH_CREF()@ and @POP_CREF()@ . +Let's also see the definitions of @PUSH_CREF()@ and @POP_CREF()@.

▼ @PUSH_CREF() POP_CREF()@

@@ -1159,8 +1159,8 @@ it's very easy to deal with. It's also not good if there's completely not any such thing. -The problem remains unsolved is what is the meaning of @ruby_frame->cbase@ . -It is the information to refer a class variable or a constant from the current @FRAME@ . +The problem remains unsolved is what is the meaning of @ruby_frame->cbase@. +It is the information to refer a class variable or a constant from the current @FRAME@. Details will be discussed in the last section of this chapter. @@ -1169,7 +1169,7 @@ Details will be discussed in the last section of this chapter. h3. Replacing frames -Lastly, let's focus on the manipulation of @ruby_frame@ . The first thing is its +Lastly, let's focus on the manipulation of @ruby_frame@. The first thing is its definition: @@ -1186,7 +1186,7 @@ on the stack. The extreme consumption of the machine stack by @ruby@ is the fruit of these "small techniques" piling up. -Then next, let's look at where doing several things with @frame@ . +Then next, let's look at where doing several things with @frame@. @@ -1211,7 +1211,7 @@ You can infer it from, for instance, @ruby_frame->cbase@ which appeared previous Then, why is @FRAME@ not straightforwardly pushed? -It is because this is the place where it is not allowed to push @FRAME@ . +It is because this is the place where it is not allowed to push @FRAME@. @FRAME@ is wanted to be pushed, but if @FRAME@ is pushed, it will appear in the backtraces of the program when an exception occurs. The backtraces are things displayed like followings: @@ -1273,7 +1273,7 @@ nd_defn: -I dumped several things and found that there's always @NODE_SCOPE@ in @nd_defn@ . +I dumped several things and found that there's always @NODE_SCOPE@ in @nd_defn@. @NODE_SCOPE@ is, as we've seen at the module statements, the node to store the information to push a local variable scope. @@ -1283,7 +1283,7 @@ the node to store the information to push a local variable scope. h3. @NODE_DEFN@ -Subsequently, we will examine the corresponding code of @rb_eval()@ . This part +Subsequently, we will examine the corresponding code of @rb_eval()@. This part contains a lot of error handlings and tedious, they are all omitted again. The way of omitting is as usual, deleting the every parts to directly or indirectly call @rb_raise() rb_warn() rb_warning()@. @@ -1314,16 +1314,16 @@ result = Qnil; -In the first half, there are the words like @private@ or @protected@ , so it is -probably related to visibility. @noex@ , which is used as the names of flags, +In the first half, there are the words like @private@ or @protected@, so it is +probably related to visibility. @noex@, which is used as the names of flags, seems @NOde EXposure@. Let's examine the @if@ statements in order. (A) @SCOPE_TEST()@ is a macro to check if there's an argument flag in -@scope_vmode@ . Therefore, the first half of this conditional statement means +@scope_vmode@. Therefore, the first half of this conditional statement means "is it a @private@ scope?". -The last half means "it's @private@ if this is defining @initialize@ ". -The method @initialize@ to initialize an object will unquestionably become @private@ . +The last half means "it's @private@ if this is defining @initialize@". +The method @initialize@ to initialize an object will unquestionably become @private@. (B) It is @protected@ if the scope is @protected@ (not surprisingly). @@ -1333,10 +1333,10 @@ My feeling is that there're few cases @protected@ is required in Ruby. ==(C)== This is a bug. I found this just before the submission of this book, so I couldn't fix this beforehand. In the latest code this part is probably already removed. -The original intention is to enforce the methods defined at top level to be @private@ . +The original intention is to enforce the methods defined at top level to be @private@. -(D) If it is not any of the above conditions, it is @public@ . +(D) If it is not any of the above conditions, it is @public@. Actually, there's not a thing to worth to care about until here. The important @@ -1355,8 +1355,8 @@ top of the method body. It is important that @ruby_cref@ is passed ... but details will be described soon. -After copying, the definition is finished by adding it by @rb_add_method()@ . -The place to define on is of course @ruby_class@ . +After copying, the definition is finished by adding it by @rb_add_method()@. +The place to define on is of course @ruby_class@. @@ -1365,7 +1365,7 @@ h3. @copy_node_scope()@ @copy_node_scope()@ is called only from the two places: the method definition -( @NODE_DEFN@ ) and the singleton method definition ( @NODE_DEFS@ ) in @rb_eval()@ . +( @NODE_DEFN@ ) and the singleton method definition ( @NODE_DEFS@ ) in @rb_eval()@. Therefore, looking at these two is sufficient to detect how it is used. Plus, the usages at these two places are almost the same. @@ -1396,12 +1396,12 @@ the usages at these two places are almost the same. I mentioned that the argument @rval@ is the information of the class nesting ( @ruby_cref@ ) of when the method is defined. Apparently, it is @rval@ because it -will be set to @nd_rval@ . +will be set to @nd_rval@. -In the main @if@ statement copies @nd_tbl@ of @NODE_SCOPE@ . +In the main @if@ statement copies @nd_tbl@ of @NODE_SCOPE@. It is a local variable name table in other words. The +1 at @ALLOC_N@ is to -additionally allocate the space for @nd_tbl[0]@ . As we've seen in Part 2, +additionally allocate the space for @nd_tbl[0]@. As we've seen in Part 2, @nd_tbl[0]@ holds the local variables count, that was "the actual length of @nd_tbl@ - 1". @@ -1447,14 +1447,14 @@ The next thing is @rb_add_method()@ that is the function to register a method en -@NEW_METHOD()@ is a macro to create @NODE@ . +@NEW_METHOD()@ is a macro to create @NODE@. @rb_clear_cache_by_id()@ is a function to manipulate the method cache. This will be explained in the next chapter "Method". Let's look at the syntax tree which is eventually stored in @m_tbl@ of a class. I prepared @nodedump-method@ for this kind of purposes. -(@nodedump-method@ : comes with @nodedump@ . @nodedump@ is @tools/nodedump.tar.gz@ of the attached CD-ROM) +(@nodedump-method@ : comes with @nodedump@. @nodedump@ is @tools/nodedump.tar.gz@ of the attached CD-ROM) @@ -1505,8 +1505,8 @@ I'll omit the explanation about @NODE_ARGS@ here because it will be described at the next chapter "Method". -Lastly, the @nd_cnt@ of the @NODE_METHOD@ , it's not so necessary to care about -this time. It is used when having to do with @alias@ . +Lastly, the @nd_cnt@ of the @NODE_METHOD@, it's not so necessary to care about +this time. It is used when having to do with @alias@. @@ -1591,9 +1591,9 @@ end -@A.new@ is a singleton method of @A@ , so its class is the singleton class @(A)@ . +@A.new@ is a singleton method of @A@, so its class is the singleton class @(A)@. If it is interpreted by following the rule, -it cannot obtain the constant @C@ which is belongs to @A@ . +it cannot obtain the constant @C@ which is belongs to @A@. But because it is written so close, to become to want refer the constant @C@ @@ -1653,8 +1653,8 @@ point another node, but @node->nd_rval@ naturally continues to point to the same thing. (Fig.83) -Then, when invoking the method @C#m@ , get @node->nd_rval@ -and insert into the just pushed @ruby_frame->cbase@ . (Fig.84) +Then, when invoking the method @C#m@, get @node->nd_rval@ +and insert into the just pushed @ruby_frame->cbase@ (Fig.84) ... This is the mechanism. Complicated. @@ -1671,7 +1671,7 @@ Fig 8. CREF Trasfer h4. @ev_const_get()@ -Now, let's go back to the code of @NODE_CONST@ . +Now, let's go back to the code of @NODE_CONST@. Since only @ev_const_get()@ is left, we'll look at it. @@ -1714,7 +1714,7 @@ Since only @ev_const_get()@ is left, we'll look at it. h3. Class variable -What class variables refer to is also @ruby_cref@ . Needless to say, +What class variables refer to is also @ruby_cref@. Needless to say, unlike the constants which search over the outer classes one after another, it uses only the first element. Let's look at the code of @NODE_CVAR@ which is the node to refer to a class @@ -1722,7 +1722,7 @@ variable. What is the @cvar_cbase()@ ? As @cbase@ is attached, -it is probably related to @ruby_frame->cbase@ , but how do they differ? +it is probably related to @ruby_frame->cbase@, but how do they differ? Let's look at it. @@ -1775,9 +1775,9 @@ multiple singleton methods, many people choose to write in the left side way of using the singleton class definition statement to bundle. -However, these two differs in the value of @ruby_cref@ . The one using the +However, these two differs in the value of @ruby_cref@. The one using the singleton class definition is @ruby_cref=(C)@ and the other one defining -singleton methods separately is @ruby_cref=C@ . This may cause to differ in the +singleton methods separately is @ruby_cref=C@. This may cause to differ in the places where class variables refer to, so this is not convenient. @@ -1862,7 +1862,7 @@ nd_value: -Both the left-hand and right-hand sides are the lists of @NODE_ARRAY@ , +Both the left-hand and right-hand sides are the lists of @NODE_ARRAY@, there's additionally @NODE_REXPAND@ in the right side. @REXPAND@ may be "Right value EXPAND". We are curious about what this node is doing. Let's see. @@ -1878,8 +1878,8 @@ value EXPAND". We are curious about what this node is doing. Let's see. -You can ignore @avalue_to_svalue()@ . -@NODE_ARRAY@ is evaluated by @rb_eval()@ , (because it is the node of the array +You can ignore @avalue_to_svalue()@. +@NODE_ARRAY@ is evaluated by @rb_eval()@, (because it is the node of the array literal), it is turned into a Ruby array and returned back. So, before the left-hand side is handled, all in the right-hand side are evaluated. This enables even the following code: @@ -1906,7 +1906,7 @@ Let's look at @NODE_MASGN@ in the left-hand side. Here is only the evaluation of the right-hand side, the rests are delegated to -@massign()@ . +@massign()@. @@ -1937,13 +1937,13 @@ assignments, so a flag is received to check. Obviously, the value is decided to be either 0 or 1. -Then, I'd like you to look at the previous code calling @massign()@ , it was -@pcall=0@ . Therefore, we probably don't mind if assuming it is @pcall=0@ for the +Then, I'd like you to look at the previous code calling @massign()@, it was +@pcall=0@. Therefore, we probably don't mind if assuming it is @pcall=0@ for the time being and extracting the variables. That is, when there's an argument like @pcall@ which is slightly changing the behavior, we always need to consider the two patterns of scenarios, so it is really cumbersome. If there's only one -actual function @massign()@ , to think as if there were two functions, @pcall=0@ -and @pcall=1@ , is way simpler to read. +actual function @massign()@, to think as if there were two functions, @pcall=0@ +and @pcall=1@, is way simpler to read. When writing a program we must avoid duplications as much as possible, @@ -2004,14 +2004,14 @@ massign(self, node, val /* , pcall=0 */) @val@ is the right-hand side value. And there's the suspicious conversion called -@svalue_to_mvalue()@ , since @mvalue_to_svalue()@ appeared previously and +@svalue_to_mvalue()@, since @mvalue_to_svalue()@ appeared previously and @svalue_to_mvalue()@ in this time, so you can infer "it must be getting back". ((errata: it was @avalue_to_svalue()@ in the previous case. Therefore, it's hard to infer "getting back", but you can ignore them anyway.)) -Thus, the both are deleted. In the next line, since it uses @RARRAY()@ , +Thus, the both are deleted. In the next line, since it uses @RARRAY()@, you can infer that the right-hand side value is an @Array@ of Ruby. -Meanwhile, the left-hand side is @node->nd_head@ , so it is the value assigned to -the local variable @list@ . This @list@ is also a node ( @NODE_ARRAY@ ). +Meanwhile, the left-hand side is @node->nd_head@, so it is the value assigned to +the local variable @list@. This @list@ is also a node ( @NODE_ARRAY@ ). We'll look at the code by clause. @@ -2020,7 +2020,7 @@ We'll look at the code by clause. (A) @assign@ is, as the name suggests, a function to perform an one-to-one assignment. Since the left-hand side is expressed by a node, if it is, for instance, @NODE_IASGN@ (an assignment to an instance variable), -it assigns with @rb_ivar_set()@ . +it assigns with @rb_ivar_set()@. So, what it is doing here is adjusting to either @list@ and @val@ which is shorter and doing one-to-one assignments. (Fig.9) @@ -2032,7 +2032,7 @@ Fig.9. assign when corresponded (B) if there are remainders on the right-hand side, turn them into a Ruby -array and assign it into (the left-hand side expressed by) the @node->nd_args@ . +array and assign it into (the left-hand side expressed by) the @node->nd_args@. ==(C)== if there are remainders on the left-hand side, assign @nil@ to all of them. From f68a573bd65a206304424f8ddee06cfb970e0e5f Mon Sep 17 00:00:00 2001 From: ocha- Date: Fri, 20 Sep 2013 15:36:31 +0900 Subject: [PATCH 069/121] English images for chapter 14 --- images/ch_module_cbase.jpg | Bin 18714 -> 23686 bytes images/ch_module_framestack.jpg | Bin 9332 -> 10474 bytes images/ch_module_massign.jpg | Bin 5557 -> 6971 bytes images/ch_module_stack.jpg | Bin 8399 -> 9261 bytes images/ch_module_tmpprotecttmp.jpg | Bin 7822 -> 8724 bytes images/ch_module_vars.jpg | Bin 12754 -> 15799 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/ch_module_cbase.jpg b/images/ch_module_cbase.jpg index d699a9c04eec8b698e5d9fd6e52b03f898249c40..0ce610f6f272312a9677d7826e9ed4a049335019 100644 GIT binary patch literal 23686 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

}i`Z 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 O-RHaej}YIf1t}k=0`TZFB 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

(anchor)
-Figure 1: All right if it is in the heap +Figure 1: Being in the heap is all right. * パターン case * 側 side * 同じ内容 the same contents @@ -628,7 +628,7 @@ The maximum argument count is 15. Note that neither `SCOPE` or `VARS` is pushed when it is `NODE_CFUNC`. It makes -sense because if a method is defined in C it would not use the Ruby's local +sense because a method defined in C does not use Ruby's local variables. But it simultaneously means that if the "current" local variables are accessed by `C`, they are actually the local variables of the previous `FRAME`. And in some places, say, `rb_svar` (`eval.c`), it is actually done. @@ -915,7 +915,7 @@ super This `super` has a behavior to directly pass the parameters of the currently executing method. -In order to enable to pass at the moment, the arguments are saved in `ruby_frame->argv`. +To enable to pass at the moment, the arguments are saved in `ruby_frame->argv`. Going back to the previous story here, From e9ab6df31f293505bd839bd54a25e0a026f2e0dc Mon Sep 17 00:00:00 2001 From: ocha- Date: Fri, 20 Sep 2013 15:42:34 +0900 Subject: [PATCH 071/121] English images for chapter 15 --- images/ch_method_anchor.jpg | Bin 27410 -> 32990 bytes images/ch_method_mhash.jpg | Bin 8248 -> 9056 bytes images/ch_method_msearch.jpg | Bin 8128 -> 8753 bytes method.textile | 23 +++-------------------- 4 files changed, 3 insertions(+), 20 deletions(-) diff --git a/images/ch_method_anchor.jpg b/images/ch_method_anchor.jpg index 00e7af894e0064851512b14e940d127cbfe147f5..af5c5373a291330bd1921fbde000d238668ad054 100644 GIT binary patch literal 32990 zcmdSBcUV)))(4z`ilTs2rFSqOD7}fG6d|D|)PSN=69~QcbClj8fOL@r2oR9oi_$xW zB39v!Q|`UzJ>Pwwd*6HR_s6%N2lnilHEY)T&8)R&X0OTl==lubwvs!-0sv4| zHG z`SO)(S1$gpU%hhW>h&9>q}NGFZ`{1`>vi)6ImJy1@*C9DG&I!IOpJ_-Oss#ufFvX& zWH-oe-@JL7ftHe%;qL|iZsNQNKzWr&gNTP1NC_aK1QJsM&szW)7h)3wf4Tmy(&Z~8 zmxzHxSO1Xpd)Z9@;0h2(OiWI4{VK_2lFJvm5fNXye1(dVnuMK$Mo5@2sDq|;iKo-M zC2{qU_G4%X=g^CnjKaVh@J zgbR2m-BXWP>yNbmP8#@aNYP8&|G12#SE=$jMe<;&9$|3X|MX9F+fG+~QWUp)C@^ms z+5S}aPadx_p3JdiX0SAPE(khj8^`uoX<78!kD03|M1t;*c@xmMp_t?f7kOU+_kh4* z)4TJ#8;r=nN11o~xT^BQ#UvDU{w9z4RoxIcswD!W@&$_{~m zM-T&^5m-m6iXBJ)Xdp%S!r`JOgHAFCm)rvqR6t{}Rs+XIWGccAcOJeA?&yy0Mu#`4 z0lvn0K6nOrY}syNPF(y!==`{2(G4ZJpS@oNF**F z9vgHtwPn_t(MhvY#t`f;%0@qk{GwvYwS{leaCdhzsjqt7NS- z+9s5WoAxZgFAM;0R`^MVSi zx3sSO)EZ@;lo-6;C}MwEB6O=QD)QUHie3Y8WLO8!LPhTK^1|0K?^9^>+U0F0f*CNn z57}14uy_GSR{Et`ntXZ7SyuTY>&Z&_+i?s?89tq%)BLxMZc+)`CY zCCIE%_v>crEZS(m%ax+V!@yi<>YIQLESRHicGC5M7CIN# zQlfU8)1i?zRSqWCcggVO<;hHe6`SxO zRps<@X*6<_DC&AZoUS>1zqQ--e%>O_2XyvzhwRSizQXW@*O+^2-=+7R;L2DVsJ|66 zorH>%5yttI#)c+Bqx8ws9Q|G(nH=y#PPePsiDRL0dq0d|62SbKrYN->&wwWG9*!bA zrODp$el`MJZ4W#Pg?T)@XARglZT3?F)n(i&_xCKGX?%yC)(jhOlKqEjECud%%UFrH z*@O4Ao2)v+!w%PFUKw5szBwU{t^ z59j~!?5>b;#R=?5lYkXYr0YsGM>ufJLBuB?C98Eq>Egg)Uxi1X%QgW3%8jveF`I^2 zz9WqKP*`1*UNspHEO<0)D3Hvk^_Gw^#sqjG&*cvQct8^AnDn#NJgPo%isxWdJQM>b zP?wPKk#c%&5Ez0;+6VYnuG>m0Z_7l;^lrZUlw~mmuSpSi+yHi}`zU$bSR{wyb9d4kYd2 zXI+6rJAVX)C@Ahy_~nwr_g`m|9X%I@9+XFxs}rQ@Yq#xCpLf|D$dO} zsu*w!6xc@0R^9EMW*)sjW_q)LdDj#CLa!|}Ir8V@1$rDQXf5?v78{r`sF?m2#Rc_tNK?}$L_-{1jlEKq zqnBo+LUNBX+o*3wL%~d4t=;@_Q5s0gtkUq#G=%c0Y){~jo_0cWBM2m{oybF27-uqu zM+jP8vSmSf4Y=tPJ=k@KVTwNT1Z|jqbjfk9z&9SkX}9nAKNa#^(cLQ^jWg%@WP!#B zb7u?Fp_3t|X4;0~)9Cg2#f`%r5+2V3tv(^{9`o{QD~M%GthpxIXVnv&mHjA=)aUM+ zcxN9X-(sp>p7QW%+-IGN=s~xa^UJZf$X2LdDuzO4|RSc=Eh$f+i zh;r29reOA-<6XiNp2J}t-)<*3ys;^-b*xfF?+R%%V?hkx3+cI~!^8XYh=f-M*_wrW zMn35YnvChsmT!LaHPs#{fo4O%&{b0oelVCxyC^!YcV6U&yr86F184k?_Szt`8vU1` zc1t67`bvg3@o!@%opm3qqzH0D$8l)0D7gOO>tI(q5yJ+G*mPZhQS`yA~)X3@=N3mBS53MzY(fAgSiPSZ1 zByfh}ep`+yf9E@cl6`8F414z_mXVOE@yfi3@5vOW0B+Mx3pH2F{St@7fkX!Tn!tEE zOfCt{jh_=-9^+>rsMQv`a`2;5LuVHp`5DIq)bGtD=6>2k4|SGHVKU3bx65A$uT9zy zW0%*~j5Q_jOE<4E>5H{GRuzHU3&u*Kn0p8N-Xlj7MOO#=jt8h7(iMJ7eC7FA+I7pX zYNBsy^;7%_#w9#3iSTXsDTm3L&xGFb8lEx<;5>Z{@3efcZ=0< z^p7U=!`^ox*F0<>=w?l7glLu@bB}tZW2*H!mWX=|5ZcL8w;Qv{b5EkVocP zSZDh@Q5D5Mf+SrcGCrpiQT> z_@qq=4B@HJ_h4K!C+3bJr3(bzb7>BhSwR@T{_>_GIh+MoZLt90g9xxLSr1b$8uTM#J`=w*=Skyb?l7zKvG-lFxY6~p3 zf&vZKO}r1TSOCvbb>-bEnH6ovpnV%+VUD z#n3Uc33^XgpzLIWi-_ugJ6+}j>7+ejH%a;BjzRIA+-X$_JPj@Z3HF6Xx9!XI$a6Bh zk1`71wxqSFP*?Zb8?>{^RI{|7HSKtv&CLxOYCv*{gU_PL8mZ*Y0Z76*z#;4uEN_`A z4%coLZ)U|9UndQV7&(qYyxD1u2C;@js1vqmEtNVDbo5O`DhX)akap_Y5z` zI|nSA4SJKu*x({$!h(?6=hmC+D?uSNjdLatp5;hj^XeS^?oz+(heJEJn$N}c(-91w zQ?hLESwt(7ozZ^h_S`Xnr(7Ca(D<^E_8y6rBQ${_zlI-J`JBxRrC;a}c;8!ir0D zGI0P!%pb-2h;1gv7dOPBv4dQzgE$q9H1KibZE~X?UWPjFjIs~{>$2lo`I-ac%YHD7 z9cu*@ln* zWM-TL;?Atz-fH>{rQ2WXHA}71rGDB&6Px`r;QrS?#2oe$4>@{*QYJ zzt{TZMoNB-M@Gu>=C#jSuVmU>sfN(!fP>uUg3~u&O_BLZ%RgWzsbM&A_IH0w;VgEz z0{HftW!ZY00GzohJMei9L;UfkS7uSW3aK)qIKAcAQSZTC9?CZ!sd?{2DEgM))km9w zjm&H;{~oi;yyOm*k}2u9a;m{|z||$n)pNiK4bjPO;u14{#~q-k+wVV&^|$f=E$`p_ z&v%e2GPBV(#vu*Gj8Nu7C-8qZ0EJVY)-md70$=c z2T^_MB#67Ck#38{gMs${5$iulL4Es-Gi(muFh!;VZ<`14`v@^W6w7(>&@!7LqTh$# zzrR%Z-@w!U)^GJd{_NP~SWxnM)Bm9QwX_&@Z)$EG^u6RFiXt=7gp~6JYNYg2B-EHV02{e6UAX$gaP4T=Ne~xP+NyHMIa20c;feJl12CknZ@-`zy&eUPF(BwEhyhDIeto zM&sOT(4mZ2bgG6uxz!{njC{l>W*4$(vtHJbn0W~D*yy7AXbkt{!CEP!SAm2riutl# zb*c1u6_+{Dl2>t;(B<6H@mN{vv|hkNRu$0Y+q*r%7!c2j7~%QaKs;hN=bcO4SEh%+ z?1|EmfQISpjH`M+Z!Q((Lnt(aH4Xy~dMU#eThCOyPLAwIkhLYlikA;O9Ej{W>r2Pg=dbW)&_ zdRN~x>xhe}ytOB?p;@@L#Mba#KhT0VC7kLR^l7m|XOc_-_*37DtCnfoZ^%e57s&XE zXpMg~lp^;2 z?S7ZrQ=MK53A%-|4g1avBE76bj~49W337~S9mGdE{(A0d>l1gk#exAPSm8e|V(rkp^ z0$qpe48lFSCb{Bzr}0Lu`!07#Yz0C_=7x7(JaOq{7S>4`WQ|6^qGW|yrDqc}1+o?p zYn}u)+AD{wn)I|!bfc$qsx@hk4vU(7rHz+Mxc1UM4plG>q4~ku-!V_Ms0zQeaU}<` zjhYzsq>)0i^`>Rm-@Ol?otR>PyJSa4NYh}Fb>dOu&!rt~Sw;p7RVp33KCUh*fP!mf z3@;sbMCI!(;IE>{a!h2B({%y-4~5~DoEr8nUCcqQNzz6QHrm-me298_GX!d8`^@RF z9wtW*ZT&3WZBPE5qP;$rOV3&lka+>N;1Wxl=dab1n3A_r@gfOuwO@f_Qhr5W^m}T*jiz3LJ@@3YlE0ZfqLsm6vp7*q8IZNfW>f_W`%Pxxa$% z#mE=fQlZjXd0(?nh+oBm* zb03l)@e*&-jsg7ptGGWVpWNcipr8-z=_q%47P&)(S8<@6gwmwD^#QX@jo&Pod>5C? zSGjiocR>Gp4uP(_CfJQ;H;;$cScZ-{f?bZ$j%}a_L(I@@gEc#-vfzFB&efLO5i^gw z7ij)6{;5em?gt7SoiWcwS&cEO`?w`hg2Se~+<+V4+U{oY(X)rd+wpi~`7sYC>V7B& z?z59F=4eg=k!_AD9=x;;Da+Z4y$Oswk72ts)!Qz-N2KE!i@DfLig4t}{ zr^Yutq8s|MM<>?Oy|CKKrwqAz63zIQw4b^@#XOzo{mF0>)tmm!{ojFP`>z0bJBqZb zv03^7RYl=v_8{^$p-vEGDl`^zXFiYg6EG$b~ahiVRKWB759}=4ty9Tzr)lZQZLO;GRIio=(7M)3{Yq= zb)09=7RKP6hq&=*dQUmQ7GZ~x%$XWIw9Oqp`6~T#p<$hJyWOE8n{Y_BRHIP7$}JG* zm7KODE9)j&-6Xvo$$nfl`)SIOwLG@~wL5+ec*4!C;XMT&#L4pqK3lTz^7{&JjQ@IT z-eKvLl`1>E4v{KdOAfU5=1s%zjP9@(KhN8<&ksx|@fBJNjXjRX*$T>pJcjlDXcFzQ zPGrhITWsG)0C|3g^)F0NFTRTs1$`jmoC)9|Y-aRL1LczDL2cV!jB~;BBWnygL0KZ0 zRPmUu)wujcPGsX75^?pU&oDhb4Mf&^-Il6oPSzb43k?OalcZ^fH<|Z86*_$<+5@0v4S8J6d19`-qIAQ9R zv*cr2ve+Leb+6E|^hes{(>XzdW+R$lv;srEjf|S}lUgVBC*fQC*a0U)+b|YoM94yt z=*Vh}1Wh6xbRG!?d%;E_>-+T%(#;vmK-qYUH}&xiv?(K_9M1$GmQrEX%GcT%B5|~R zqG^lhRj^CV>(w<_nZNT~HJOG<>&J$6mTv*vzH&U5@_7bkP0=`NLzf%aVQz-_Oe_fQ zIY1wEU6_US4x5r ze)<2_HC&f`^{|w<;OA+^Xv567*w~b7!FiEO2RR)Ai7biw&rtF-@;W$InUd{H!yZ+S3ERBg9*H2*;}ZF=)$5&Ke-dHK%L-%j{T&X+n&C-rV@bE#|3QWBYxm{l)joLy}k@eS)K#=8_#CrLUlfZ=2Cbn#V8> zaYcH*n0^nZ;^fp1^KNDLOn9BF{e1$UU}m`56?Z!>G7f6K5Ia+9)CflZ9J%AEuqANE z2ziv73$NL%eSS5PeH+|Q-Ax<;|A58l#phW2-nU4 zsjWGMKPJCY4%5*Os~_-3Pt6`w2#>aN5yr)yO$b&cStXAo($+g*5FV73X>MI?)Sq{D zu2)Mom{Z&?v+M1qw-gKon~KPen0<7J*uC~81w2p*NvY@Nf8oE<&d?#u!pUMJ82Xf1 zN7@pZRcc|A4cn6At{kc#6qLi3aYsB@aH{a{u{Tzr$!%NB`eGlt=&D3kw%57d7Ky3a zq0M)X=QBd;f7p@tgJi;EpS&L|t5|u60~9*Qj8z!UT2u5I13~}&d2HfK=LaTjcTAy* zQIB};inuu*6BaXDv33H}j@pcmb^C!L1j*sa+h2V9kMEPH%<0>k`W(xxH!*WYJpB;y zef=Cz3i#15r@4G$*JyeAhU8+}%h32_?r$`HS=$Y#X$Q|)B_p%! z;32#Q?kX_b{|}A-|38UyV3m9IN=wX1Sfpga6-G(beI-^8M>-ns)OhJ~*?&R5zrIWN zCm~FI_b)!Bxi69sw8*0WRQ69Eueh})^|qHcn|8%m3>$ZY1V%+PYA7p1PJ8~RTwOeCrRloI!DLiwT=ixGyL0KHSLP%BYDA)Vsc$Exi^+NAvM(9|L&4%bY zT({1uKk;$*9581}vSMYaYCM9RLniMr!RtnNw1u*=$<-U0fpp*T-7{+h^406N;#YN3 zCsHmOD3$qTQsc8Zk?~^MlhFMK@Yuc~Zq>2M=vVIlr1vhe{;vj3=~}hU&yO^c7+E#b zR&mu)d`nP)PKU4SQolxMCt3L@8{MdO^<$&x4HP5wRnYZd|EzvwrlO`YkC?PZqcd%B zJaO9iJE~Y7u)u4q_wxt*-;PFwg>Mug=tWblI!Cf$!o67J3f;v3HxN#Xc z5d~Gsd|QweSjiNkOBt*^vK>>EJy($sZ7muLMT+JmzPPmm@b?Q8jkMnsyc*&}Ul14^ z93@0*wvhPPr<#l(Iu29z9MhP>uaA8L9Qa-KbkV8lPL1pv7scK$S-Dn-Q0Eir^x+w6 z4Pq^XUX3r(=Y?HtbR_6E^W8}JLGu(P}!=-15cLJ_2;Gsej{ZU6;GFMyajO5_*f|az{VYif z^@i~j!<;L_6XxlUYH{UH3c}#jXf0 zTb!44{WGmwTK~Ks{|}BIsNB7~{&SpgCgxQnxFp2F(XB{0S24#;=sV_3+g`_!I>`_9 zRh96XschoNiC_sa0neG+L>H1Ny~_91BtqomO{K; zM7EZc)>rdk+E-8~DF#XiIsr$+;Q_R&XhV6YtB5MNJccX66YcX@Hjv0RbhBY6TNdxx z>%fKSWr($c>%=qA1z>(a%LI7hxsC#j0FGu!I&iVaQJ=U*#|$O2-|BsYAUy_AS1M`C z7fJ{>UndNM+NqvCUQGhv&Bu&u1?kOh?NKjkjSoCYK3-?kra6XYDjTKIfmv;h;A*|3 zA~ru--xKP2yXdZsLBwwNFskC~g%#h0b_->3U)kL;M?7YHB%m%D2OS=U#>O71`Fnu- zION|tPLI_1AV0BJA@Cj;DNrW`=#F^>SSCtzb6bNeM8$q^c-$OoM4ZLk&1u|~1nht! z@%f$Q-34jYU)U@6ZPU1)xGL~H{*L4jt@6g0dEFp!*%IMnTNIPOe1JYC@6=txuE3t*Be zlDdd0i)U8LUrR=UqcI!Yw}#WFbJ!@vURG>bh`Vj($)F6hl=66}%JC|(-8*Ua2PsyZ zc4p{U-C^0FUN%~)uM<7(ZRRRD?>cSx91fl7ZlXG$G7aAdChX}CGiYbM9GYPn5zh^; zhP}TM7d|WjdqPFT_7Tqm#lN?{sosKuXyX+LsscLX@pE7Y^X|!k%!KCR$M#xQkqG+7!a->Y27Ww^Xo(fzx7Q z2uYK6;&Iw;kyc~nMr9kL@^bgI=3U=B#@)l=EFX-+&A!UAf1l|>U~V zIaIC-UJrYR&aQFqWf5P0^;oq=(0BVPr)-hTr{_sYpeI;q3d{B`q7NwgG2PfK(LiRS zUV#!MoUCJQ$VgQBXW{Vxmm8Pmh?;F3#^`oJMWsheMk6P0IMQ@dy%1h^v`4Q<@7_)E znuSv#P-!7tsHNLikHYT>$JX_cE07k4ruJ&&L81$|RD5370&```GCQ@WE0$ ztpmVr&`*m863&J5K?YMObm^2^L)-E^1xBo z)KSRWyj-`q=5E4u_+1k?;}o{HvsGikmNNa@5%^%|#QP`gF9YwL`9%bu@_uvpTwKoZ z+&VfeOca-J6K(rFf4P-ieJ_B$(6MaSR|9W6z-qoN%^{pywculh>+kxBVG2q>l{3E) zeg=bh4A)=~Q``(?`(3MCm#n=l&Bn3mi*m9xcO$)#NBo@P&UKEHQx$U&$dN9ZbWbst z&cpZ);*!Qtim`6g>WQaws>j6T;dcvhsHrH?mG_lQ;Q@9=QFY+Bx{LiskhHwjpG@RG z--;sgUvx|AZmccHY@Hiz$HWF}f_*#Q{j!_rD1~>nl&Ue&>;`Tv-J|un{%Qep8cjmz zl+3eGbT{J=s9SJHJjj><=s0Om%~xMq&%jg~A;T~NGzWUZ=4%Bg2g1lot_s58N7&FT z6PSR1f`eB8(lAYhjJ3M)Z3|UfFF)Ne7h?X*;&AVY%R&u?-!(#YULDtp`KhYs!)mfSu#(`n6FX|?&gQ^il_~HCDao%L2IsO1c{_hPpU*zT0 zvR=)Gm*g#(DZN>LdbT&=dtF_Ext;FIFkV9%lV3QPd%0`mICy)V6 zVZVFaSHZ?k-{L>tA+e%Jftpv^v0a?^*iO7R1>8f&t=^`1d%^O*9IzolaSrg3d^OkR zXRZLeI5qSp^{~p4rtq_vSEyQYvA$8OOKy@Dx?DtarWI!Er`V)tW~kOyMa?%0>39{h zL`BQ#yAx7Y&bQqw0D|ZnetL(Kd-e8`IaxdxIlTkyN=`AdtK{bz?@)x=gCK&vs_`^y&KnS2R@mVy!v zdkekLWmLslu#=8mA@r%sYs6#Mi%k`Iaa%gQxq-ZFcWRo%ko)sd_#mE?pMsN#GFl>;bS-rUW;A?8>#3A~+$;W^Vhv9A3GiE} zBlPkEryPRX${N}?n0-{DqVV6d^s%5Rf$xTs;2FCv&3lEtR=+IQl zPE!!Oi{;U1O&h_%8({q7m~#Ngf2r-8%}BZ;Ra`3MeZgzhC$CapJsY$Ye~kdstf|{U zzAhmT0S+oNOa$apT@77JSXi&aeg`&kQiKB(3M@?UYgFSWbyU zIYKWU0lzJ}-+7i1L!<4MKI|=J z1f8`4_G?4sR31(D8Nsq158LpI{DPb{#}Ru8EJ{7@)+mk4t3%`8k6XB(S_d!g zLR7Aw3Oj;Qb*gi8Pg)43_Ny$mw}z834~`wF@W*+oc-3cHP(qq?d?~IJE&BC0o1%H} zWIWL4O!LP(f0N&G0DpcRU3!vsdn@p>(#)OCYSbMEmo5j8ANXjP`{FcA+#wr(Jj6`+^NZjLWm#z*MmqH3HrJbT06b_PVVAr{3Q4nT{ti&AZuy=v z<83q66_EWjltH>n_WQ`g`O5EF6Voe;xOqJ3npCYXvpf7V(5sWhjdn-%?ON8+ev+O^;Rl5T}x(vLaoh&lJ#TO`^nTp`em zl4X;P5U0n`U*btuDSp{eak9gXu&<4etlE$vdD+W(v$^8(U+UHme0h4v#vPUW{0`Hd zb3oEI$rm1aknOoUHCfv(0M>=iE@VU0(EcaO$j%;;lWu(ydE$ywttZPjCb`Oz! zX^>Bh9?4T)Oj33r0S=yeSvM8EExn9o|D9P)>fzUVBMl4C^_*Vl$O#YgU{x4p+TIGo zp3@*RtLMe}h)b;%Rzv*jdc_G~h?GoGMTprVx+38vA5=d_b@g+WX6LH^UcX~$t3!_M zksM@7CHO;ekxM1E%T^o@*B`NS@w-ov^vuASYWqN1NR@v=Z#6`@o-xblo=n}Ee*O-F z^Nx$W9(BtzHbdiQ&F%JwBU(7#!eS@Z3N>AU7V(L^qr&jTbZhKRlL?ZwG{%sAO)})w z^EorecjB9;WJQbEDS_1!0XCT?%gIXz>Plzdf2=j#H7tC@&(vzOW%@{l*V;fQzL{6T zqGEhW3JW)0Vy_3UdAI^*J9mTkU1&yVd*b5~ciA83A^4}TeM$Y()`SM+?U5y;Z-B5q z$$Un-E(C%W2%SjH{%kEJXr*>_hl_`iLNbkiD86AaJc!jwFRDlOJOqksr&fL#O~K2(nXO1&1zP%e=gaKx@!vNHEqD)p8d)hw z2$JwDTZKyVPWuo0>l~J^R|;(lL@h=F5?ke5`Q)mV&#-KqPD};c*ue+$>ia(Nuf$3g z>_nZP#p47XU{+*RrQGlJ=Nre+ogY zdb6<`%ogZZrEk*M)4j>%rAID#lvmzmFt65VhIo3;-(R_>*BBu!uc5tQX&pO1ly*D$ zfv=*)wNuZ^DIQKo7X$(BY$tjmD^DU^Pk&;gmPNT2`iq|TaMjV>jP=tQ@r}dz`b|VU z6Co_*@hL)IPiI~XtBs?kS5_Do&17oVe2X-d2lLa0f&EbnC)#C>SScIf~6PIc9?IP$bdL|0`A-0F}%S0(Y(OTQi_2p4d(| z=)SVOr#$K~J#yCSy&)s-l^^g%dadBO%;ok^)-@|zjeM{YW63T^xF5o0xI<$F!Koa- zD-RxiS+?(l(F~smeV@d_W#~BV@!8m=3Ix49l0#DuK59kk8{_LX-tsg(c{U_rXRt@Y z8b^B%F@7SE8h+%Q8{gxC57UGb6|cS{!5H!;WFN@058V3ruOba=`b;6KT{ zQ98{}6sG-?5_-74rIi`OQwb};sM@7toyw%~3=M}@a{h(1|Imw=zx#C9+^l+bBfaCx z%OrvOfs;Nx+IL)E$L?k78FFX$HZH?HIl?N^B_y7@7yGy z2TmS!LpjOO3~z5hLUnI#mvrh56-e73#?#3vz0MBPR`wOaDeN%)s98&MkbC_zP%L?P zd}495LP)8m=v72XetUWxedqnow#JesQ!ukBG!EA;eP$c0MJlL%)3 zq|i|)^?u216tiRZ0sucxul68^xZuM|ra^VAKv&>Gt7n6m#hkP1jR!{=9wP$;=XtcJHUrhvF_o8~uC z%^QIl?~DBhBQu3JJhi)^`$#>k8pMwEY41D``7qP}t$o&+Wee+3w&tQ%lhqYs@-PLY z@e}1M_S3sa+U}$<=-%m*Cvdk2MR3iON~wb_;s=IEPnSg@(cuTt=O#=A%Z`|)ekU34Fhx`iQ8DOo8pj>s{`^z4_7O4rl zT-k3<*9u!LQa4f}=Y1nTYR&BNq$0p0@x1y^JLDzQl$Fd1Z0pB6sVwwy=7R{kxm6slz=H{e)oel<41}lE zNeb;Ya}PqN86<>dy>nvmlUNNWb*~WpuF0mMjCyVVlOOTurQRhvToPTw6_wSzx24k5 zeGOWx`(n(Ci3HQl{f?3EQdn=&;{m2}CV8Z|QK-2GjGCQsw65mIs+yE$GHlE zjMa1skFN#ed9(FeWy;!6Es|JU!r)zjG&#?7D~eSv0scoISp@+M5xzCUJSi&VuAiv= zr9$50BF)n-iG2{TGsE;+=eIRaPFZsGNQ{!3-TXXndUM8r%N_k)z+3zA)jnsNun-Tf zTeDqAYOxIkBjgwMdy3P z3Xn!uWHmD{xUr-rdvEihD({xR#*oAH+iiytsdD!774#J``h3I@O{qu5R{8YGc_6A74c{GJ*#P)m=}F<=M?s^N$(? z&EB(jsVmiA*Fx%Z2N}3RV%WjcxNK%H%OGwKOA7Vq8Yhk-E}bd!pix!UOprlFh7;I2 zbjLGOBd#fLSixk{rW@>JQciC&ej}B*?dOu|z8QCbvA-4lr$zPeliXi!|K^F`KGbM$ zo_mO?hk8`@CRv2d?G&)Jkj_L5OLV!@)3ruHdFi^X*`T*__?ZJX7B>fl0oIZ2i?bLq zRhi2aYwq>IBx#dcdnEfU8ZE?q)4WH-N3*;yflGGOr@&JO>SDldWhjgPSykAmzsFQ7 zg}k4!;<`M=z1hJ2N!F2X$2VywRr^4nARXz?s1mz&#wHZ0P%kkPknoa`4dZFIc`-l9 z>$lQQercfY;Y9+*``2gcCGR@>Z^ z4tK_{e^M~~X z#DD#F5GeE>NbEsVI=8(HNd7~{sxVW7eNI~mbwjFR3VP7I!i%aEc-&5W4Ok3-{tb +!images/ch_method_anchor.jpg(Being in the heap is all right.)! If at least one `VALUE` is on the stack, others can be successively marked through @@ -336,12 +328,7 @@ tree step-by-step and caches the result at the same time. Figure 2 shows the entire flow of searching. -
-(msearch)
-Figure 2: Method Search -* キャッシュ cache -* クラスツリー the class tree -
+!images/ch_method_msearch.jpg(Method Search)! @@ -388,11 +375,7 @@ It is `EXPR1()`. Among its arguments, `c` is the class object and `m` is the method name (`ID`). (Figure 3) -
-(mhash)
-Figure 3: Method Cache -* クラス、メソッドID class, method ID -
+!images/ch_method_mhash.jpg(Method Cache)! However, `EXPR1()` is not a perfect hash function or anything, so a different From d9f8cdfbb7ce6029d8e2145a5e530a0da88bbc58 Mon Sep 17 00:00:00 2001 From: ocha- Date: Fri, 20 Sep 2013 15:47:05 +0900 Subject: [PATCH 072/121] English images for chapter 16 --- images/ch_iterator_dst.jpg | Bin 7101 -> 7986 bytes images/ch_iterator_dynavarseval.jpg | Bin 19879 -> 23357 bytes images/ch_iterator_framepush.jpg | Bin 7896 -> 8908 bytes images/ch_iterator_insert.jpg | Bin 8076 -> 9203 bytes images/ch_iterator_itertrans.jpg | Bin 21770 -> 24878 bytes images/ch_iterator_stacks.jpg | Bin 16976 -> 19828 bytes iterator.textile | 50 ++++------------------------ 7 files changed, 7 insertions(+), 43 deletions(-) diff --git a/images/ch_iterator_dst.jpg b/images/ch_iterator_dst.jpg index 6c00527bfe5643f1135caf03a2f68943bc8abe62..9bb53cae003176b1fc95d68bccb0a4fdf93fd628 100644 GIT binary patch literal 7986 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 aXO6xfHr^>rd~4zP6|ph;`-u*GJ@sFlI?AvB literal 7101 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 diff --git a/images/ch_iterator_dynavarseval.jpg b/images/ch_iterator_dynavarseval.jpg index 8d72964a4c9ec1ff4757b53e7b4a8f7fde746304..3f45316323bb638757b8826e4eb108185025ae79 100644 GIT binary patch literal 23357 zcmbq)1z23mwr1lljXS~JEqHKucPF?z1kwra7Th6Ng1dKc2?UpJ+&#fHFr4$=yXVZz zy-#NL_x0D+d)KbDs%q80w4WEBHvmL3e)hHifPw-u02%Pt^?VEfN_$&5`U7A9@GrMT z0D$LH0H%bstECOV8vJqx<{1hI1t7x1!y~{WA|N25AijLikP#7)(a=#*(NIy*vC;p$ zu+cHGu(2@FadGkRaB;~)zQz`-K`fH;V_RMgx^ToRIa8k&~VG^zLmy2utFj}OT_gj%$-?nS*)R-PY!CDo_! zHhTLM))jm8)A8{Od~1-_wg&!<^uJMgh5*pvUf2S{0RiHGE3%;+OVXeGabM#2ZIREu zs5nqp=E`BKnLpAsd8uixJK9nBehU^IPT{+FI~R)|&zmM?gDJ5zte*tAsg5CM5IQJ~ z5?H~PJXxp})AMvuLtRJ?y+8BWfI8emMiYX0!r8?U$`m9OxT7(grMx~7tt@uUv7*bb z+A9~-WcY%}W0WwZxVw4yb)_iaEi6D@EvjxCZviha z@B480dX#36K`&5eYw{zt3wWna5#z=v1Lt=92aUX2a0KL3vr@_tzO)xz?^o=j6(5$5 zMaL8sRL9)c^0}rw&LpdBiKsR|F-0xUvRvKdUDt1mZM(Zx)=SJsly1;u_jT`X%d8Y# zn=8$pFI{$uCmI+lB>A1N#g@B|e~X>@dF*8vKYeKw-wPxzI9<#j58Kr)=Q>&Js6<|9 zdJ9uq6UDM>n5a8(N#(WXUOt+=Dham?ah}p^;^gx0;b<-{u58|p!yp=Li^tW3Pp9WS z_O=_dOKc)v5Fq$Cqno0sIv$8Gxixq~Z=^X`{|VbX_1h5-nJF=9Y`*_z9{4w_Z^}#F zmoRokTIcQ{2frJ3K0r(wc8coFc7{dY8+=p$V9##E3Ja$ylZpwtLLvLvEH4H-=Z)RB zO<`d;w*ry2Or_JEZbFnv-Atc$C&{u!o3bGG^yiydE|(Q5EA&2AA5QSuHrxE|84!TGXo$>NofV&#Htc=1Zn1EeO>fgks~AclXk*Wuj9)&yd_NX3 zFUdfCnJDq`bv1Infu0E;-U6&vf=718XThpj-f_6-+iy9ZKr_z*Yvir3G)6}D0~j(g zGinm!yPeiSuv}HC)nn1+9i6!=mc|LO6!8 zz*Bd3@Rp%r|A&*5sjy*L?r}tgND4Y**h8LCtLy0c8ogW|j|-pQ*hM1i)hVQ43%32b(Eb4R ztE;%*SksvKl}w}ji%4FNUl%i|lU5r^0G3`|30T4q1$0z~7PXt(_Ft666OWUUJTSX| zBr$GLbyTjz2I~f_uXS|2itM-HR#+-@nIiPSdG%I!*W21o%ed}qZB1=tlD7Reym#6& zpr^BLlZKoj$NJM=m;}&R<;xZngfH`>W-Vdj?MPKth@~1L)hxE8f(AtKcA_=x_ePqD zgnOUo(_}|PuW2Z_A)hV>55GBysdOcEm(&jmI*rYsi7PyPmClqTZ4yMiQ5l@Cis14v zE?D*M$ETqRIwRe415%VJ`SHAg7^>5cR`kl6D6q=Z>FPetk}AIY8MuVOR=TswN%)Y1 zY29`j&(oE7^lb05m9@rg=5}VKV%bVony@0r(kyejbC%XsORX82I*Q^pkdTo)Yb&>r z2kM|oz;8>ZZ$APSR1*)%KD!AI<;^lTLmFP$2)bxX0X3>?IzQk>JLIZ#iThG?x1Szd zpRBBa>zVhX+a2#YS+M;_j_GD&s=_P(h4` zm3;|~l7VxXaLI{PPUP&Nk)j;;OE-uXy{F>OU^fYG(*hSjA#i=MZeQS)0VbNFra1;jDykf=)&!=>N z3?+|80xSLu0wI#!N<7@+!x2tkObJDg22_+sqNYVb3rgYXhSHh{($1YQofg0A3ll#C z4DU`3W^J=|!G?Isp4-K}PgejhQ%4$>B6_%0mM|gAg&6Qxt>pU&)AF)Ke()7fzhtTm zcqiJ5JIH7*+5JIA=C>c-Dd~>48iCN2?L_ZLyI&Y$Vbm$71b&$|{%XEV8eY^y#$h#+ zUGB#wVNPzd^Xqyk-z3v)&dQ&u%PIQdlZ~?x+S(y610}E9ovfzZg~s?@ElZ z65NFD&>`q;_1j(U1gwJRD*A*dR6ik`G|q6Aw$;peA6wS(z$YoaOeLPLJ6q>w>tiTa zK&e#w1lg11oY2blMX_}hDnAvimWDUqVs<{UIySRPTK7ibIK{|ompHT1zg3h2E&(E^ z#oGc-nNfraq7};-TglH}qZ4iMGaIORq}h#7)?v*5o~sF3nLkM8=jJsnbjI-t^*$}K z%R-_M*trxEmSugK&9|cG#j4+;?TwFX!AD1bV-)}0O@<)xI z&LDny70C671V;!li#^L8M5VLyTg838liNn&lL@;HNHGYUlSJ=n3!M;egnx(0KIIIM zla^M&RYr+c^lQATS{R_=Hxf`*n3G{M^~z<_R@drxEPGoFC;U$}!atNn+303a)04Sx zlsDj2swL=@#qhj6Nu}RiYgP0P=}V>Gy-~0#f~8uLXs{qb_Q`nn2?~|>?*$WxdY4>} zt5L(&8 zTj>1OJY()6bN#?TytFaH_pEKYU=vqaGh_szSgo(*K(nVKnWca2*SM-So9vo|b!bbR zEED8$_4g)!P!Sw4kf7HIE%JsdDNn;$NiK+LeI$R^et)?jeQB;sah|l)Nnadmr25fP z#C>>2`sfO}c+ekTmyI%&lej)ISIjm_yXF$j$ee-W*4geN3QtnYe5-^rEn4we#|<1U zLq6qcK1gT`DTynnNJ@SN9D>`{Ihijzr^;H7mcy51=^PuD;{c!*^mdA?Q}<=xw_0~Y zYb!;_QS>LgI^fh#BMw%-ON3YaAxTbUJQN~Pm{|J0u*lrd@D0Z6@((ygK9%O?(tG&T z?uymY7p`3-Q>D4~%$q;z)ki0N2U>4RdNG#6dgp8VO@HKU79sbf&7`PTiHf>{Equ4#%QPT zJY++0-7A5y<5Efnu6p03kp##x_76KD@hiPm4-MI=NkIN}x5}NldE9EN=r0)4<>rSmu@D6lw7nLRuwvsTUewTNqF@KSXN-g#em+#ugDb2K`Kg^_mN;lttm99Y(U6%MjYE^u zNS{eD0PVCnu^R~HFYn4?GgEQN{Npnn>g9>TaVI7 z?^Jg)1X@~J9aopUPE2510x)emZF5zxdz(K^y4FF9UWHqX!B~QB5v9zY!xqura4u%N zR*Q%**L;U}x)oW5ya`Vr)O*ed-_4st(jgxco-RVHkb;N)DcRU)u`b8HNMF;)y=y`U zgPEnuTLUj3>i|S$GkUw?BzV5F)Nhm3OHhWJtZz^3)vwT;%YY8kz{>>*SE#P|wH}l{ zdb^FfKTpuC!9t^CPhq{QU{R<634IZ9r{+TXO4^EhH$k~5oc@b-Ct4BwUqFp54(r*z(ed9 zW>z3#o#^pwV~ag#(#&@{-1a+xskaSjVrQNOvvKOhqI91rvbUf;aQt7A&&I+jle8Q$ z2O>+VMgwTW^ATgUbO=%EY4N2`rrfA^Jt5)^8$U`v5ghV%_sY;M(<_UMm(a)r9nGOSlx4BvKpFEG5rI2DV%QV3^y|TV ziEPx1u^y1p1H3`sY8O_JSB9CwUyxa4?v5jb+aoI2xy;eEN+zwT-zD(CG)XT0DI4iR zF%JSheLVe*XA9QS?a+Q_xUP3}E1ofROGvggs1ET6HH@PdA@%?DArM3E00nRHj3k9z zX5ty344>FIr35>-lYm#Z*(p=$NN5zS7LU{02ivX(>#B08<5k8MMF&&OU}nJW!FujRf)Lar;RWlGa9 zLcx%hR~{wJHqzu=rZwaJ|KTQ#PBxL4Ey55`^>U8wM$vCN<`?Vlf79YU{RkNWf7|S&@S?xX7^`-!af`C27zY}f zbU&_B%q=SQR2Eh^FSN{nkO;@(EqJ0l0y+?<+CT<3uJPV$grvdfnr_gbVSz-}LN}Q4 zk&d?gt8!n1GYY*B%1>&j5#^Yh_|nMUm6tM!5wKG6!Ze=jqGUcFhuIDdE0OHVEX|b` zW<6Ae``BBd+CQLZa#WR>8YYnmO12K9x%Mn{`)kV3c*aia_SUY;<&tvHM10z*)g!%3 z7|o;@IF6ooa3@CqnM}Wm8x!fp!`4<&592j~1ZePqD-5R$-K&LAm_KEnFyN)@9#ba) z8^hU%iHVCR=<6cMVB8H?D;l*N4l_v2B0w$u6{NfxoFF`Tz3J%KXl8TAyb!6~cROQe zMz%&x8Yd2)=isfrxWEp?Q49Yd-F|AOI7eh>k4r?HRl(QOcm-`GNeFd2)uAvWisR38 zFxr|YxY$|rE^fui&a0Oxl^}LoUN&)aAK#43#+A|e74Dsnvwfa^Be;ay{uE16p< z{u)@D@~Lj)(uAU{GwO>~h*2L#e_99Z$L`p$fuysfDe@NW=v9WpHm+4?dn!cIt>R_rcBMyiPZ>7MjSV6 zHh%?ansnEJ+y9coe;tSUXMH%?T7P4Va;9C?Icc&)URtO1xfZLI6+jPBoH?d*TZwP~ zx1bJ)c-VQVtn`!hI!g?3*LY(d1DWZObHXSOE#(3zp}%6KveZ6PI$mE)hJIxGdPl@) zh4xOkqxf8dleY9*j1Wy7T_eX}5FUk1|E#jo5-aLggPGScRo_~@w$C=%KHadheSgwrutE<4%up0Doa%tYsK#xp8?Zvj4WE7 z0Y+c)+dvLrb8nF`wMJ(l*e%&?Wefq-==)SX*mB;MPG?{D{+s)EfwO9P)Ar)e0NkAo z%4-+jU?xoX&kSs3EndZ(8$9Meeit>%Us|_3s89yFj*`n=uB-mR7cvw&TFE?g!uDAJ zvzzm0u+*1E4Kd%5t93i!o{4mkAMMMFOWufR|qd1`}3h?5LS>$fQ8~*8&Sp%-Dr6~hD-+67xG7*=M19@EoazXvHF1i(YX5fn-+9Tu4 zwR=P(B2EtSt)TjLXF`i}?IvvHpXF967dCc4=blc7!$;s*&Bxw0q*QBkGl=FWZ93dd z)v*Nb{$oQhBesWP`;uv2vkuwGuXqnYsA(XI(xxErf|zOO*{fOmn(xC! zyf2>ttO@?GNvCoBFsA? zd>8D`ubupXWzOG|_1B8XTnnsjuW|FcK=yycl!1C=9$EV^td?*Syd9Y#jpR<QptHo!4ILyt($0zEq z_s1dmAf?*JfjcXcF|(~Se$(TsV(Gb}S3MZ3wT1KxnGF2LztT2lcFgU5jxS_7EiY=j zw+kcgOw+p8CSK|x44QgxQn_}*7a0LUCcqayNRF!6s%TYNAK$k}MempQAg>4BjA9Ac z)jYO+uI*|MBiSoaoGeRRoH@r-Tz|G4|y%V$^4^w=3esT-x*U2|Y zxcEi+7t44ZJ>S*Rc!LV;oSb}OV)-9*W1W*we3LMH-9NbXN4O3^LDz%x5&0L2it<|e z4O`fjpMJj|dSO(l_g5W4x(|ono10E^)5-8-jN(#w?-f3qapTI4*Bi|6gCiBJucM1B z&CW0HYnjB%JOhS#>lxeVw$+=rW~{Zd8)*4wel!sEbcjjXv_>wzS~i_>1ld2_y(E!< zy6=3%e}LaTu0I1Jzle2E?yYOJVeQh4v5Svn7T4Cxpa6TNe3F_KqqB!!vT>ZMMCqQs z5euLNPfw{`O6G#Cxn|(;?J(!n4tU7T#6hm(HB^18qs|Mu;BHJmHdDvRpNw2&7X^y4 z*D-N4p>H01t@x3x-a*+HSA+jYKOIQ&{2_f#TW`@lPr{ct^U=k#$*Ds~$^79AAhQ^s zuAbuVMGixKl~|2X^Dm@QeY+<^oXv0TRh*WMd3b+wz&J!2%FIcq{;_mJjsab%qoeN# zJQtEx!~f;28zjqx%jx@~Z}?U-4pn!#={n8Ne&+OMzV)>`*&Ix}>AJW zfch6!R*iYvM%B-;bi^7Eh!KCs6b;uC0(fw{GbP?1WHop@z?My*oi-t#8&F41D9~3! zFt%c{v!Pf3XVp zx7CFGJl4ZWVRYuGxbH)N{6Ijx`MVIoC~b^(3d{R6iZ~%=2?yN2L)H?1F|+k(8om^D zrFTy5b2995%F(diGUp?B^0Vb9qDpgM<7tJt)9qPC{FoCbER+rTqcf~C5c?PiR6{kV zm9>;&=e$LWZKuWLwQrSIs|^hcQUJ-GPpaniCAoF=Z?lV1rIc%#XtV6`%~|C3cXWqM zdDq@CW|01owX3;^s_Ea-!eKrTvRzbv2COO3n(N*8p8nRyX_};2SQrc==WoC-U9u6A z$D9I>{d>9(ZZooczpDZidcyW%&U_?agWA_W1LWX_LvkqKPxKgSwkNI7bO?ZhG%K%w zh&wzT?M6Yu5Gv@C4EUlN$rD}Z0zCFgRp{Uq0M&(>=8uV(BJERtGS!?^zYA0_@K%CV z>2SZ9@V@=t{_bsLE)_M`vXQ{aZ+(Kb)*#AXCvRtqAHO3li(%dRG#qL?*&KmeL?4 zShBy4jKvE@00b0-?5_Kd!PPY{yZ1XGD35yqrRQ|qL?5>IQd6}}ji$j}pTnrPO4KHp zxR$*8JtS~*xvBAgp}czfidOR%D{!ZjNRPq>SB%d99@r%JJCF0xqfc$aP6aHHDveNY zr;|8rox&M+G~^{9;fuX@;!&CK-t&HBifX8GOD{1zX*+(haSS)pFE?D(X;NzyVS#kn zbQ<~o7k_vwFzCZ|b$F3ZQ}GrBJpJ4fX1eXirzFBqIS4DNYkDVU#i>a1a&kD;%Bo_D zGh3T`ruY22t8?#C-jWbDfP~w22cn zw9j*PIUM#+~C2CBIV~j$<*MX_j;dOdtNI%|t zdjM(zdV~8K8fw1QBw1LzqW%`WBup9* z%)fQqPeoAJY@%_RF7ckNdjx0QNNnR*NMBRFX2J#M-_{jxLhCNzd@aR;C~clIz)9Mw zh);czTGp*S^qpJ)HKNQabW=?hvGQ^DPDanDpPAjSN(tM1=Jggoo3ypm{w{b)_zgqkq>o@EXzDXT`mBn;Jb~I{IXpX7=|nM$-+} z$0zcy_o*S7?;j#w^bh9zJ4NyD;4+W3v4yn9qEr01P>PS(hVGwr7G+ciUCOA2@_uS}EzYV4ndm?x@aB@tzA*lGzgn5^={@A?EK^5-!#>U!W=W zuPO-mm-9qXwvF$>Tum*&-z{G*O1?d-cX{uPb6X<14L;A$5l;^SK_x5Q__*uo)rQeZ8)n~B-JMqOe(mfPND<13fKC~aun&7+Lv>pM!#CYsABK=6l#=xwU3 zYN<{#vLS9uw1I7*<|%G#pp2FRsl0uEfm$N}=$a`Xr%N6u(HOmwFCWaJmc&J4_Y7#_ z0spKyUtFt?vmbMz+@7Hlp8wD{-a-QJi)0etf>C|&nqn+IDe*zb-1NnNLPR8wvqpQ3 z^`8nU@Iw)jOz>?V)V zpwcU85=zT*pp42BY`CJup%m`nkN2sg1w*71b`;l)p0i!0bNDgI*L467eBW)L*5ap> z?SXWM#~*8q>a*m6;m$~~aa6mYzU`aRdsHIM0DBMnijgt$gXo7S(AbL@9C?>6J7v46 zgJ&cWR5aw)!9@Z)xm8T%zq*yEqhYGQC_i8~*$Ii17Pi5MHRhzBqGm1M?|nn2zj?7 z5f0$rN$m zKx~rT8uiKs%+ktlG*DaXC-2X1Nvf)wl6jn{WL-p}RHCDWR4^w>r*ENd^lpER_m6@9 zdkrL`c>Wpdt(Zm_yr^J!GSr{xRrxD+4dgSctRqmum<=Wu+~OyTf*13E|8M0{Ah`>( zr*A_c7jy!@FWor)pQ*ouYRvYM;{~vr=zDUG5Xkdyl7rui|8VD|r;>JI<)?0WEI)}+ zc^bxCMvwgqnBZU&c6)w*jDH5~D!M-Gum5@W{>I(^B-{qu@ck}R|FcbJ;b%P@SxV6*$EYEHj~}c7`{WR1+yo=u@|g9 zJ2^m2`xygbU}s3H4;s8s@Xv`H_e$#;#L?>FvF~ZfUVcXCr!++*Z6OFF7|M_6645N3}==@`*lN_;_FdOuqo+9GcZC3Vk) zqZZwqbYtt5{ch(fIADb-fn3Kh=p#ast}u+@T_iAf;|vw<(lGhmPYzi(6&c$~79>P& z{t{Wq5C6lot^W*txSwN?<9;^+PF>$4QY0(-XWnA{?fkeyL!3_iY=YaAiF?bQcS%OR zL`v#@{ZT%C6F8m;{Y~bsiWg;l!JrtyWnsb zmR;05&hm*3GC~~Kzu{}HzK2+w5vqNJz4)Jgc!kawzJ*D4d|2vw* zyBBAV5A%OBwMRDemce_kHqh8*)Le?Bx1(k!8t-1Ld-7Sp}9EorLHTF z{rVV_=k`V@*zvS~C+~=8nc7xhX=+(^Xo-B+DCWAB)^R_dxj$-nn=jx{s5+)*z@|>^ z#cx|Bi5LVY>@0IV$zNIfI^po48>oD5_(C9^W-;hy5>I>jv)GB;8F|RUO0E5(Aax0%~K(5nd_5>W+x_Oc7 zp6++KYnKn$@4j%e>Q?0zA9ZyB2Q*!N4*GUjcO$0;qb7Z5z{ z!cXfi#7agcW!-45w2OT^NIPFPS;O+H6+%jw;(tYDf)7)=Y*QyoI!Wq#SC!z~8$9`- zPd)*iS-(UYf?hsCa3^#jJ z+($|ss~_;li-RDe#j?a%koUaK#MYR$^~IWoG~eHmdilB0BJbu zVDd%3@?ip%oO8W@cXafX?+35TpY|Xa((%#eR($7^V(`l6T*qcME(($KObI)0J>vtK z$}!jyM%CAnOf@mE_IWOoGMjy@{1e;eqeaD<$wIiXEdA6MPTiAv70b>GaN2XeK0XoF z`CPX_jyH^^S?fz&bdj0}G>Y_wNvtr#Cmpngx-h1M5w=?@qa9kE(HWE^7c}7=0V|}Q zv0o`tw-LSKSPHgF0n7er+m~I-BPCAl*=p@w(~}*X^wqY)s6}3bi3*ETEBC*Cj)GZFA0K62DoNK+vJK zM}r)}RVBX}?UTV2cCzMg)5(i%I97?>vG>Z^xl*pJxx939xGHYk`WHx1qDstLYYOFV z`SSJOu4%cb+Te@cf0Oa9O^nZ1=SNa=cTp*CFGWPC$w24hh{eOlu5PJK!WkI(-h)3+ zY6+j|Pzl}tRxhtHWLn^-H??n!CTf!^{2Kj7xU{=9=Cv}^{WH}S4%!EVqI(Um6V=&c za9{T5?IYpWrA$tJk1V1k1FEPZKJ5D}(drfCkdC&Eg(*;+c&_{CU0u<*hjvJyu14ld zIX35wf;NHlE{oVPytO?O1Jr$yzhYIW0~$$Lp=0^k3b7N{au^r@M4_T znU@`CM{6BbW7|qTw_Hv3q-HNYS>C1Hhb0y-z*MGVCLpIlsP9}xa!;`pClr|OVVC9m z0V~lz-|z?iwh!L^{<4?P+oedqQ$vpFAT`~=}>gJ{B{dULqU-v!@^%kCIr;-d>7ZeV`3M$5D zM^Exj3=Ry%{-}jFT2|U8!(0&gwi!3e=TL8|OOaTc6%V8%8%T{TQ4UOOtZy%(mX?^F zL%>UKXn}R;?xhRmFO}wd{gb|+gm%e?JvtQegQa{$Q4}>ZM;RQ=UxyQ9v>w%6YTU(p zGe-O~_-9uu&69a4Ldstq{x#IYO@!p;KMfQ<0|vxzeL49flFXi7ZJOOW>f;2PYj_w% zs*{wY%n;DgG-Ln1R(adS8JAJ4AVefgm0OKX=@tm}sj*zwZe2(V>WRlN2^DxX)(oOQ zz=-1h%tA-7tF9n*6G8Is!vC{1-)c-xXLP_#E%syE9v?3@wQidpHMkr#{Ci33gA>1< zwDYh9Oo|>5e`a~ZkQq?TL`h18{CS#%w}U18PC!_zjZ=uqfn&I|P` zV>9R750cGTc@RIJ9Cc$et;K@ww^Dj8!ISB&>^H2qhGpgi>zWTHWa48?F= z-56sOE|5(LaKdmIw7(?*rPzP}O`^U7C+Bv23T9R-RIzeTsa-J(<<)h>TdsA2oJ~43 zvbgeCE=+QetDltm)w@=VqNi3g4d4NB2ZDmqOvplp= z6*&MnF|OE&;X~*^MN(ndG*6JJ&BoqeY}fv-&|!hnp}24rS!qC`|Up=OZs1?_q_1v z7)R`3d914lt}`%@8eaSi)7uEr?Wxn1)@_RInW_cZiYSV%AyXU|!R+vd@FQi$iloxG zf@H)z?uA+^%JZXS#f`ew$9!+xq8wbNZMj@-?lEiuJ;zhd88s=k_=C1$&z6>{74>7+ zv9_wS20Lad{4eun_99~ox<4p2Xi7BvJ0f6g8}E4;v%{+RZ$txY*>go z&vSNXaS_`Cl22@kTMA!OhrGm zKlNGblLr}!cbsLViPuMv5#AV)q5SvsKVGowYr@5xlRO1r6Ol+%lR%^Dq4HZh;YW+w z9!F!0vOCdrCavC=x*3U*u|3|nO5bo=4=TznU-#e=@Fo3!=_0-oJX&GL_p>kk=^hjq zY-BBdV6HsqOcFa2vh+UTS3Hu>e>uX7(};jO;mSsIffXhyGmA+7aa{f*Mrji>f6hx4B~;;3pi+g~^MMMN~O3p^_5;D00HR3BLi%m~o>Qd#6n9FN%^oNuiMi!IW>$)LVd zspw79K=-PHtVoIYBWt5ZeC?-_Pjj@iRG4X%%%Qottw66}d#&M8kLi&)g1n||BmHIh z`aJ)Q=!1f1fUgrphzCC;CAVK<%3A`g;s06whN!%`IWdZQg;p3p61Y7|V-XRFzhMtb zJmjaUQyDld?W)XLci($*)No(r5%WT!VIODCZTt$blrHZl=hi=c`TwE1eVMUJk?gw5 zCF;6KQM>A(&GZxs7)M)8wj^s^R$z>g%#Iv|xoG>M5?(h~(jYFAU&Tp%Ww9#xbjD@% zx+Bm{Xx&qYxP?x6NzrluIN)57SSm%R@kzp6-$RLw{~oiVMmeUT<;BX;*k!tU zre0MRN_p^TYE0a`H{zK50zwJd%~f{roA-`)v2&rCgYdAkmRi?xEBjK(xEUm}v)IzE z7Ou|Wza$n$w!1B3#V{tPJS2 zy-3%X;v+iFbu&o|t=k;5xJ$+WsOP9#vbYLKBDW{K+Ry7m_s@9-MD<&uhh=!^*ITV_ z3ZjZc71ee0tYTR4->Br>J8WgYlpX2AhlU~RAS>|6sLpB|W3~Rj$sB&LPjrcXD$Yhwz$#d?%u>-#p>=J5A!mm4#oSYNC5y;drwaJ>YO6>eo zEeKP{?sx)4jJz>RC-;$T#w-a2XRCtrXq9~zs@^&C>gWSS3Jv+G!%5{X_>236m9YEm z2h|8R)m*#&Q|GUluDz8z>|?A5j9G|PvzT6wcHqTX$nl2_W^o>cmk2k#nd77}Ja5V5 z?H_`85UB(lR<4Tp>k<%9V=TP7BJr@U6S0hYMn`wQ^QQ0z%uWVwlmRhtv7hiTJlk zW!Vuz`H2&wMKR|`KH)EH;IU$*Kbe?zNa?|bwa#4>_A`zf2-w(=->QcLFPVR~9B zbre!bD`<6^bb;z6Pyp&N?$p#k`_eDJ4nQ~m5<~wl4f}TihOHWZFxe_DV#c3!UTcR& zJjEk?7X1VEwZRSAtfe+WUTvUl~{j zpCh*76|N%9HaIC~l(2@#QjV~DddSl#`hhs*I2oB}~n%k*b-Ibp=jR}=*q~49|E~1x})RD{5UJ3cN+iX&-VIO7?I-xeq^2_WRD{TWG1S{=1$vk}nzaF=q zMjrnTPye%g%u;_zZ$UEPU1<1bZ!G-LxfvBA6nGsQ(+5&^91kx|FieSEGtsMY^x@j% z@596zbX+rwbio=0LP1P}kNsNuC}- zOPLBQ1!5Qq8rr(iMN@Ykt?ZOw5F2VV-yG2$YAByS-Re8f;s!UZ>$sGEweg(ba~qD5 zsEV_mEyHV0#_RDtaHe#;llh}w)k-0qgw~gK)Qc#7IH~g@^ur?ZZDeE@9H{gTX?JbZ zup$CKg2Bkiq~sA%I_vke|GYp*svBFLng7nt52271`(yksd@5_U-zj1a^BJZwgAWK0 zzx|O&BVw%{3_-9cfxlqa_wi1i5qLXI8prj3VH;^S>W5&BxBD zCGdYZl&v6WUls2leF!o^QqPIMIc`26Kp6T%9Nl@a@p-g?c(b40>Er2KxD;7UAd!_f zZ67yEW2#lg(&4)Kh0+dt2(yRuQG-V-F2s^eit!0F-nt*zD>aj`_y|$_GQ*Dm=frOW zCHeY}fZP5+0jy}rkCoT-hy^?OS!T?yw=X^==2q@G z*%$vfiXhpP-6}4XU<^Do3N>n`6wT2rA)!81q^SDjvpUL<5kl>hmsp&kMOHuQB7umd zbTL5@{&z3?2xD2)h*cm)MWu46{-v^hgJU$lG7fgXz?UN#LDX zH~C&=shP(HZahSkudA*Ht$>u&1Ufr0H3XtZ+idY?2@%R@luX0VIdLemBMJy(wp_sR zx%kyKyHay0pD4C+R5GSjac;6x?0Gz^aEnjSZDEj+wnzvYKy_YZs6PZYfo-Bf_3VLF zoqRXZO6pHe3ZTa__-^*ogM>z*=ye}A3dKFTjX41|-q?|}-ashahRYiu?=9A`5bbLM zQ8$ux&D9IfvD=*bx48Lk-_eF0Ac7QTlPKOsgmR?^`%}Iu!W}KVS|6`r57^LE)2?gumNlYL!7qvU)e;H>Ok?`W4(5< zF^07xHWDEHz9-Tf|JWE)%;a1!C?-M|GT~%U%jKSV5)nox>y;7WI&#>o{}Q)t#cS(! z@eeT@-FA0W@^P%zCx|KL(0wzofs0W?ImMCC*8wLL>>f0bm7wd^io-9FM9%tEq3PI5 zIg-fLw^6j0V?G}dDUFl6U_2Ai3fH3Dednc8(BgW*9`xZ92S?2j?ow-H)ozdHd^0=o ze|2)5(Qvlino*;7VU!px>VzPA34&-ZAtJgEgwf4JjS;UJWz-QRf+!(c#9)+(-b1tm z!|2^8iB7)BS?jF#{CLkweaAuf6xZpMBl?y0#i>Zdu0AP{XhgPm?9H5q3(4 zpMpcDh%3pY$A+rFn+h8H!NJh-4}aI^GNhMFFtjX8pN6vUBJ8yfinCW{`%y9Sp|-M| zOtv<4f{l$4UjF$#Dy>4gGd>->*B}Hrr-$4Oq`s?~g@|-Sn^{W>6TK2*T9rDcV&O} z8zQ*ufn@VEj>Y<|{1EnIKz-DRE<|A0Ed_#YS2JqUQss3`1>8o8DWlWJy_W;H@_qTR z^ZxNB>0DfF1)Z}zLUS-5-fo7OElgVtcgAD#EMiD;r#g_7z@1)TC?S}WRd3rQIw%7Kvuw2O;SC&?e zgl2q>-l@{dR1#2sr9NhYN;+!--?Hs$3SfiHixpFul7@Ui{NQrdX2^;02 zq0{RTY2?<5i;vj=(L_!=mQ4$8H+&D4B!)#s*XaY82Y~K+W~rh(^Og^1ef@qi3%!Zc z(Q&Ij4JmmPP^*?+N%rM;oL%Xyz9Cyuj*y_>`{-HgF&Vll)q9tX5|#{Y!7+zSuS`r!reHA%9? zrh3{CA$#@2SzQzL$4MM-86eg4l;KIyB=0x#-fz|#Iu|`$RZpX$?+&;_97pJ+(Di zu!e5DOV~DbmyJz;xqr~~`cCId7RGvh86_)XUMC%5Hwywm7gXP^BO7I;f0io#F4`LJN@Zt+$e=o{6u``QaEm}3;+02raMP*($% zzp%U`q2)f0^@lO_^3CEuZF4{fWF`9b%yhdbhZn>l+Y~?a`>Q%`wS~7r$!LEO^?MQJ z4hUnvHSJrd;?fl5=dnn)YGUrl$Jy@|Om}w(IP(Oe4JJF}>`Bl}WO&v{^JvU9n;R<| zL>+qVRV)uWhhanET(pgxd=wM2JR9*bant}^>sLb6QV_Uk%ybs1xx|)Ox}iT z)!RE*O#k8=rowuDYM6%B^w-VdV6qnOtHlR%8@81LUYrT8SS%pzFm_7BmrMucdxKyc zI2W#&eR}`ktOse-jPyi3JVWi){WX?95Da9L7={g^kYzCFnYTFC{kWv?z$8!{jYCz* z@~8d8d=rb}k77*`=Ss0K=BSSFwf>P-8rm{AM<~oj+eCV9=!YXIdF&}&RjKALBFmu2 zP}ka9jsM4H*B$rN{~Ljsf(DV4UY((#bGHVLijA&oQNPauzQj5v z+XFqk_}ED`TmPYl`Qq&eW|D~ zZ>iQ@IYSk^R8Xa&%Um+)dUU@QffzB1>B^K8xLMVohO1#ya@vm0u_>Sp-vxn=v~)b`?ac?f~z7GGhyjwEd1w2(oq_2#)yOgWfl%a+)d{z0V zSC?FwFh*EB(4DyId>Qt2&yEzhvcQW zE4#g2r-?R#wAJz10g!!VQbBc26+?Rjy2FX9J1!NAs5aXgp*lJ|-e~`6)8pHe2_8Yu;p%Lw)7<_ab+{#7s z5*MP@Kd0R#c@y_86l`i}I9_{OmbHfMa$;?8pkvD33cJ940!$@|MaGng7ElG5d&`2^ z7pyh&tPUjIe9XEc#q>IO5~g~fCx2O9Z?QiGD@rninsR#WA$KI_lKs=tp!XM_^=PuhLC{ncCE za(fE};xlJma!iyALzyc+OCH&fO>arQa2*X6{6+LOw1Qs558r>N?6{bB(>Ft9KG~S_ zRHfUsOjEEP-#2CGX&!<&?gFKT?k80{ypIqB$Tm%DKb6nZhMd1DYyKfgCO z<1ZqRK-6y-q<#=4V$$cH!ksK1M@Ky>q$B;zz@-Co0n==rf$v=vjC+fHwp^3&E^>vL z9W(Zv`fe}kI@-=3<*l!2w_k#Y(ImALfcolB30^}G(@g_*#?5Ku;Q0q9mzK;XQX}AS zboEj(I+S39790T|QQ8`JZJY{PT3FU=eZAh?F^G^kr>8iWbNGy}#{~<>vm)Lf#(g}m z0KPA8=({MB8?|+Ol+@+Dn5j)D5N=@M{a`?2U2VdXVaPqKgCh9zyQrR~N$I^48==7* zs3v?nwWKao6AifheHYKC;KiK3;&18(c6`-zDl$*DEg-PhK(?J66i+f_{qn%@_Pp-8 z0?>9*zf@KwWeX4je7&2wmq^w#K;Q2LT#_@eJ`gDnR+XZzDJTrR8IFU-G9Wk<@3sM5 zFLDS!yx*SyDX?>wF3U=bNjxcv@!DuG(bc7-_HOu27b!_BgyX~W*_&IwJ@iF}PQSlu z-K2ubz-s0=@>P4&kWoa(JIr?<@lwEjsZS-;zCd1AM}3Y@*q=V4lJ$|NZlE$Y%Y_z!RWYg&t8$ zUuB)~U~R$HjYhsBf^h4YwB@Zh^&zDG8^8Tc+6Y$=LHA}4B|z!x4}Z!|{;U-fFN`c@ znh{#o36Nzbh%1$c2Gj&!waC9&%q(N$k1y@W8&w#)1RRF(UFKh|U=X+$sX;+AZ<%!k<5;Wl$bkpcH1h ztq&=Pi`pM_tg1>k6*uKm^VkJ|JvAt~#BYn)ZTBehH^auxg*d1ApE!?r%_Guhr&T^F zX6rY8Z?mSk_&;xBf9D%Q68MufR61ENE;U~g2&ebdb|2i5+*mjGlh^)e4H^Gn+tpiw z*5Qz!_gDnU?*9jk%0JsRIf*q@$(^Fwy38(YCOB{rznCBTN1-CYiX1`y{EnQCgNR`Do&AmMnb7Q_Tvw!$G6O zgaE~RR92Lzun)>gsemlzWZoY=(Igqv_ydJ%blFN|GN|gm+S{kMNfZR z+T_KZ?^pPF9i`~MpTnmi*{OzkP7cGsosuQ`>5PdIAno#Ng3F#}ZJ|jM!q5~?p7J8Q zL;7d{8*N;R6?LrYO8Vz${?=IYzizi+8yU8^_{fWm{F^#wKhNl%-^qCI_xxfY9NuJmuM~MyW44T9-&<;X31|Ktg3Gy%P z9F>t4??VZu^mxCPL?^(wByfcdA+|Zxf7F)$_tt&;<8RbXY}y>}s>$P&e2?fKSxPet zo#jas-4#Uru($u%(U8q%^!>ITaXEWZ@Yvnkpwo<<^Vm-AWvjobiN&J#Mf}>kZ3HN` zIVH<|XI~8@@xQrl&4)#Q1W0-@)qY(2bbQ2QDf<4N&EptaIo;z{J+GpzFHPEY$-vng zAd$tLANGDhZG)czI-VZnbMOngeSDvy#gA?huyeiB&}KA>>9>`jn`ALrsV=V)2bD4V zQZdBazqi|*2`OTL`5&E6+uu8oWCYDkM#(p_fmus4=3IbDTSseep&mfQp_MQ^qpxzyX8pkNIfV)Sn*GxU z8mkHYg6O)+>}ysg4;?W9ljU!8RHqzKzwqwyeIJRFC*2ROD67?)nmGyckoQVuICf;IyIC6G|GMT)znv`A@zUBRscZE%O6Nejh-758GLxO*wZi@Upf zafg@QbI;rRo_qiAzVqJr@@0;-vc5Uz8gq;}hx~Foemf7Kc&4DN0KmZ#6bA|b+};30 zpvu;7%}t@^rZ%PyZ=Fm{pvLY{Mb$S@MGIR;Cr7x0rJWO$)5O%p5^gGOXJhT~*7d<3 zw^IOl01*KJApt%SAt50#G0`8ScgaXeNJ#0asDXDG86ZrI3}7&nm6rp0pPK~?<`jLv z&Bre!Bn06QmlhL{;uRDU_}vK(F)=YI2`L>J8Jz$#m|5W8rrYlTN+KN2J9M}>lz=;w zIJlHJw=DoL00(df7yFig|C{g$aPbK5;1FSdRigml;N8KwgNuuuIvx=L?teUuhfhgB z#Z1i)BmDF2U7Gs>_I?BRSl(zvM1CTo6@2{C7!@_-kY3WnDkLKBo6c;-+N?b~SEMV^v#u(T0=EsQ1$@`oZH;jlvZ;sO8 z^1w#fG7gJ*@$O@?4sL-~w`_BDt9+mZQbqr>=uA$vEbcV)!s_wF6iy63mmkktyG>am zSOg9MNz6jJD$)h4OG@e#DJE3+0@q~SRl1?$UZG|U9yN^15WF8~481m^AcDGYRbPK$ zag@rS_Dd<(CV3t>%A_L`egP2fi``Kr(h|C9$DRq{QDxd^dtCXm0mQ( z)m2X}B#lBn{{Yg6D^O+2FVhITS*ltR0OI!!)lSc5hk7b{okK4}m*cv#a#2ZS_O z3+b831SF)LW5{-TK#V`g+DvjAIoO3O=?}&it$G7|l=vcXD>g-lCV}d+xn`Eks9}LF z$QYcJ+|j!qXaXXVYG+|H^0Y-vdL|7Ot9u4nzG`Af` ziKYE$yY-25zkAC;h=S=r`^#koONP^Sk`z1)oN>?q)Nr)darqHeCZa>+_{RQe6o`g7 z(k!OT8lj~F{PSpcp~!95 z&#|V;h;p5jT|HpfjT+Ria^3!|>UCjVO9ww3!)ov&3|^6Da|Ad^xtDK^ z)e^R9|6l*vps?Qm=*J8B(e&KQ{!lYVcLhTb^8Zaq3h zbzsc49y-)x-)-je{VD_8`-_;HUn`PjuA8cz4AWe43jMNBEM|E=EyCw?KL|q~S*dF^ zRgX|(l%aEHt>$mg*FOT!OEvW?A)n+b%y{Ct6Mgn_jPonnN0LX5?V0!Ar3`Jc*O596 z5hd27zZZ6)*Xv~yd5S|}6Uf*%HaCr0N(_F$`E}aKuSDh*V=Uw8CKx}nN=#uyOdYW z91qs2r>$rT=s%~>!>tsUih4`Ur1Lk;DsgpO))<|yKM?-Z7K=~GV}c8t805qSJv^Hd zd~)t1{w9B_R-w^Q$=6^RJ|MoQXZ9qSh!!5y9+Ep?2ez(z0^o5rYeJjp-!d2@hefG_%%q zLyiwY@2mZtiMCJ&2j2L-xP~(_%QT)=bUKq)@%M=8HMTwD^KG>bZ;Ikz^nC{|{8B7z zW*OZsdZU_wOFfwAoe(jvWaMSIf;JU<1WIPA*b`&!iYvd*;c^SaEZ@T=T~-F?yGU&{TX<%A7{#)m|l+TOaK z+LSx?(LcOjM2(tpSoI^VHbTaaH;^V1r^0yNy7Agg%Qd7tm`^SQ&thb_YzjS>{fe9- z{ZDV&sZA0rKM^ zBHH?O5#}?my0v1{@J2jH#l+o5qq%Bi5HR+(VTVxuyU)b5?G4SNoA0Px5s6gJld#x~ z_`JCAsY?|Cg~n0ZsWSx>)oV3kfWreE8RE?6twx{{|- z%itE!-E{YD#FM6Rr>cw0P%GS_l461m7~}VBo{ZSmTfmHQY1vS~0<9(8Tumv#wJ)^D z;R*vgaTK!d3ZWPch6pl!UsaOWMQlh#W&8G|%$nQ<#U-lxlt1&nTV5cc=ecOf(m_81 zqGurjI0@a+y9F4^dCmNQ#2M$Rd|DQ42h~1QFETV>!K|fte& zbU$ofysF|`;_#QKWV0jmMvnG7bOr5{kp2OOF6p8?HCqW zq4hum)1U?SCu&z=2~97sI0Z4Pb0 zy*G61wj+@bw-Et3#svM=I_Q-*Cg|1}-pZrnmfcuj@dYG^RIFQ{Tbg|+UB6gvP=9bH zQctxjP`Z<&hNA{{$`XVU{8misZo7=I2S3-O4(Oo-tl>9pqH`Lm=KlP+n_ zRo^lU;8ta^#U1-O&tSKJdT2zWy>z&iF6j$o%J?|=)LG0wG^)Vr%1H<%3Toe65^xou z?0KiXBOD?lwF(0<=*eq0GFORRuZt2$q;)EXQ;4oO{1}Hk%FD216}oWYb=`sGsf8Mq zjCt#-kYEZBPu%)P;E;^9X|lBTpLUI6)ot>3nOGv-DyaLSSnMdYWx?!Eo`d5;5m$(X*ie=d{cQc{|BR2-)eohL{kl1#Tc5O(N&t&4Z3mPjqswtAALLLD|-`Cx`6IJ?0orJB)5# zI{XwW6|I!tG|U8oUKBE^5_VJWG4>;~o_*tD`dOjPfu>+9aKc2i*KllzMS35gSo|0B zm+Yx~Tx7|26{g3w6&ucMBBn@h0VMLeCn!I}d!vFtMmEjBxwoU&4hCitPI^O5PmonWUI~S|lq( z#VO>^9=q}?3cL6c9w2TE@2{y%I^rRm;+SmnqMkn;?REVfk1B3j zSWhkV0B&@amGwgx7)~CMJ_uH_7)u)@vJfMu4;Lti;F^$9R)9B}WKn6nVls zTP~bQ+rs-5)SWLsm0!>T{m55T71(Iow19w^7RPO&L!3>JY5m5p~$=upjL&(fxh4Hyx zVVT}+U-;Yh5+)!7@$xre5^*%b9jMdkP+cE&?Y?%%yIg&r4LLh4-Ykn|4idX4WC65O)$N^LGjt;8)<6e+eM}y-TP7 z`XKgx`;wv?!e=PoQ%NGQv7ySx5AWg*P(Yy*?&QE<1ouzE#>mnw(4w0c9Y#P6I?u2E zmrE<&A@EzkzWV`W#?{uINOZquQ(Uo@F4M^+<0dkHXFWOMq& zAi`InU$$Og6|=8?8c|7Zn*F0vk2`gLmac&O;!fe6LkM+OcxkQ${eIA|uTmGXRCJ&9jyzsdGxHa;-PnPo0_h28ctBhh{ z>soFb_LcPn=Oyt)Y=?N%MO8}NNrF?4Kr5&8VOP7d%*?}f+M}5=tMx7%^G<5n{Z6m3 zZXv^|%}D#pgq6;vA|0C8PHxNwLhhIi|7}tof22h!Vau*|ws%%yS!rB2a&pZ2Lgt_! zEiGe0?@j9MLyI7J*IWyA+O-OQzNb*C5jk75TbG$Cr>;YRrMFc!4Gg7|RYG=}fmsJC zENGp!FahNQqKDn9^v@GLtq5sq9O5rx3c4plK6%gxPq{;=2FmFXjQg=)yzN2%PW z=}F7POUI(uIzMYL5<=v5BfUgW!@j=0XvScQ;UczRs!~p4OXPAyQvpITp7k8>o`NG7 zqwY5C8Zy=R{8~50%vvdn>4eaF7s3<{{7f2tsQ9|#o`GUO#RsQe(x8?wtC5tY<+*zS zFF5+8M7=-qSYQ=NN`>3*@p*PcNlRO-^qvG6Zg-?7iu`HHje5N!z5Q{?rvg(6@{k_8 zAiIo%i*jl!(Q47RefTcMuh4793eF1iPRV^;v>!fh5TkU zZ*96&9Fv%>F_yn5$rR97cX?5f>8UQ`G2SNKC|)d5a&K1t=>V6NhNX0X?!-*;wO+pr zCr^Q+LH}y_YD6(?oSASK4-a=4MHp(cWU~sEoJ)$kp(tAyJXx>1QsM~5uCK+i-H|}P zMU8f(cz{*ZW<$X282QpJC(A8>eRbXE%KJ^_XC`$M(6ILgXzm1s-dpMZVC~t6YoBrH z44xvpMq_=7L3IC0wYsx#nf7c!8TBH|sV}Sy!u+G_n#llNXIl~D%_%GG!^x|4g>i}b zBP-_H2a6{MZnpSE(Nm+xYuT8&ox5Ot!s@I@dTnkstl2j8AXS5v4xpF)-mUXjr}PO6 zZh7b26-2hmz~|eM&2+n!k%LMcmB)<@_yKEbkZZ}18v)r?+`m|Sv$=|0mayfhw}mEB zw0wM}<9C!;H$mGcQ3dXdp`PjvVYbr)@w#!-yu3$_OYiRwhZR8`*^q%`yW|+(Tfi_n zFzu+lR?x9{LQdhhF<_U#2dV>49h+xni=&<(v6?C-V6*yp}wh&{Tcg)3may zjip;aj(uvI;#r#K-}wC5lZF=iq|k9>?3FZsn04hlCB|W?+BnsZXQ9wz>00nme18`H z*HgRkiwqX1zuehsd>_w8N&SzuDl^~SBLZ%q7nG~O zbRsS(wNJyr#0R9SW{D13=PMbKImM$A^3+{A2gGxOw#t{vFv-K5u$$yIA9~25-(M`M zBJ!lJr3C!m*k*2nJg`(?S|*5Ps#NRqGxF1_uMF-rTg&kIwdRagb`$L4p5CE8}UPZp1MazhE9 zEDa-50)(hHb=0+Foc3=4L)CptELZA(=QRZlM%}Urg$*Gtr>`Ab7e!{gUQnz3$;ivi zik|W|_#%D_s8aRPn4@in+i8ngjdj%Ym9SaLSGFOZOGsC$cF0b^&R1{T9>Fd%ZQhrdbjM$E{CcNY;7Abwop$UoeL=|cRR%@#Co9I!(w ze#fI(#>1loCk#gyi##FJFduRAnF{v@PBdJ1us#^UL~}m;Aq?iP6ao4&5DBLJ!y!78 zV^OSz6|hT$G!DKhyak+mw!8&I0()hD0)rYEJ06%n97AyGyqCKLkogKnR(WCSD+h&7 z?t z^!OB7;yH@lF49U;o7&Hyf9Lb2Po!H)rDCjlCKU{dzyGwpFGfEoe5^%qy6WQm3)Xr4 z&F;&uQ~R2bH$-_$`b2pwTx|>;%a*KGIO)T{n@?bE!cqP{H@J@88Y6(9lT+3RDK#&4 zC5qoV+-3YgCHz-+S^QSXF1b7J25Xp{+-10q48r~v(67}uzjQ_McmB-*Q~OzrW~3~? zON1LY9Q0E9DbWU#iQto{lMTYE!S-J%mXAl?MXxU$2rG!+kiHEGa;dMqzvIIAw$G;T zi^VYvIY}m!t(pR&hqHK_HEYz7EF&8TuR0HKhtu-yc^|1-F?X2#8exp+7>_yXDbWw} z^ycbH_@OjAIUBB6f0w#ZxcU~b&Tan7{)PzhH=c`L%>=9_*x|3UBcL;$2(oPclD@4x zK?;a;-GiO9NrIZrZ5}bdO!g2%I`@h+`SZ2OKhpAioSMu2DkTl z9BrfWNgu^1CKHrHbN87wx4qUb;+>&h_ML*1|& zRGSYWWZv&D7F8C1BHwaYkK!(v)G<-7WPbTAJ#f-qT9p(KHD}=cQEH~m`0NpD^U9Zj zB1KA8wYF)#HoEcP>9MCQ6&u5YgG<-Ns4Mb*qdJF5nNOp;svTU9f1I1R_rn$AIUj;m zaMidJc3mHR%)g{Zgw=qoH4&K@DqLgBO~x>J2IqA>?2h$+SU`=kluofCXwPVeUe3T> zN;l&yBj&)hFDW@rzRG(={LAQ6q~nQ?Y5-l^amtI`@SoLH#ocPp*nE+f#P2E&9e;C*8?4kA3HnQLl&xod(&w{G@ zJbbJqk;4P;6YZ*Wk&&Ywcu<5$5)XPPG@yx6&W?y^1*y!QCJPrZc5?JXv+S*2kSp?P zMw#$OubI8 zBY|YtDkAZ~ro~EnAK9Hzpr(C&Q6wC&vGLb9jVG;x@_QBm{sfL|zP12T<3%24*=J!k$80?I1iO|zcNbxNlC6PBV zXEgduqOoN;FXid6%dJYTR%P7-u zIqJNNe%pKtm@|9=c71S__-oXozl-uD|IVNQmCtA1@G8VGUB)DP&rt(10(-cUw>_ zxSM{o6fNVL%b)V5I~888xPZ*^!eWZZoW|xGI~+y@HMklJiB{moMI-@HiPT71prTlH z*b8X+?`^xuA=&DK_&Yt6_*VB|=lzI=7f7`@Xj)!-OPN?PbCW}!@CGnf{vx+H{w~aL8Hp}!|_%-Hf?O$%gr1~rII7ynMt70RQrW`wGy8KbpiX}qZ zUpy^3D^ig~KH(&l4|YiOu*9CUkd?^o7Qj)W`tjn^uBLV66KP!VA`{{FYQJ^#w4Q+O zsBuZBqllmkN%P`YW2<{Q3)5mPbA^gI+Aa+pJRh-w=I_JPFp4BzGAU6SY%kftFC;9% zgYcol)*7Q4Asy3RAsUZ+d5R?Yj)*gCFD0R2lj=76wnj;gxbCqI)IG5Yg2QdkzjyeZ z#*iI*tr_Am>XDIQr;NwM8XEQFEDLT3YCtRc+A!=unjy)b0% zo{^pcE#=V5tcvE&U8MLJ6JtmICxOvZY9x(6xfil+RK*^Yy5*Kq)7$T}hYQswpW_To z&8s_YlS#&1kukV#3-o;bCGvnBu0%x>>TGd&gnIfLxAJciVQfQ5NuT?Wj)+<{9>w$v z%z1-Bck1BuqsqfQ0kLYIYQIxx;$KM~*qb%OV=2)aSH)X^8?@pde#O7}{c(l5wvoOA zThz$(RABch$2tkJv-7BDFrJ{d^>zD9}~CyQ|NejWE*%8_Expnf-qB81v1ZQgxZ$N zxAzW&Vn9rQ3Fxk1MJc^!p$Pl4iIURxyS;8Wg^xm%B#@`uiYawzQRA>93WXoQ_kOD= zQIe#B`0F^~om5&3`Rm&(9xb9peL0i?jFA)p8lWi^sX|F;%4%_Pg;+Cup5I49{kvjTm?3lqa88~&3}=x+PyGMWDB6q!SP zHgPUPr()-rN`0boFk#%BmnX&RN6Q;eo7|a%PZq4#4s!f89x*ZB0bdFS3K(EE!Ds-a+O@?sekkBJIL1iyGPoHx4fip%c5=XMB~E)ZWjJI zC8nZSp)mZuQ?XLTsGA?;75;6o4?hOmG;aJeNk6HdC-vXe$B*0s zSgWWu9xB>571#Pu1Of-Q4Mv@|hVLlBo;R5w_Ctigl^L0-jG8==IV^s>PQ}l5zXZyd zABKe0+)ThEX~7g`XS|QNhXhx0BPzT(AQ?h?zfykfU%wq*8b8^lP?UHk^uVx58Q>+G z{Icm~{^*U`p9NN=QJ*y_oSC{l8Zq{wNNCIG#|6QKAurXfD5eAV$J&4D8_0Y~99h`Y zul1WV5-q1GG!2LnZz&ZrV%6byi%yc75+w38KTV);M7q~rp@GpWRmQ~+wM?Hs)lih} zJkneJW>Z5XO)4P9-+QW{ZYg20F|l@c(_1-@y1H)lUI}&V57s-dk!6{bic-K%CKc^3 zw@qA(h`9YL8J$NZyt1NPQ};Sa;N*#|1D2lv1W7>nI2p7aDOsg6M_zEC#0?`AP$AJ4 z4g-_NMjWx;)XA25O`iV0H$rq??s<%Y+AW~yC6V{3_^#~1-?awaoE~^ks;SV-fBhhEJgtxz<%h{Hq0x7@{^-r;YMqxvhNU?rC#THn|0LyUS&AF2D1Yc*f(cD~JokCb%M3HC zIP8(uY5YObt`a0{l)%1~6{!FoD6(TFFyk*N<_{%9DEQ*a;W35(!@liPSLlU`?WI&c zN9;%WJgI2$nW>vboo@H^`ji<+tyR~wMTsa+aQ;WG4|}9y3G~-S{1+#q#LQ=y+_`48 z=cV~Xex4pgc;$k!{@*r9LYkYGvL}j^w}3EgqPPbCa01(MpY7cce`Gt<=1!6QewF+_ z@xdY$WI+vVCTlNkV#Rc0u*Z5Y@7()oc$aZ;)XOW3ZLMY}t0>-}2#u%>D*+~D*MgjU zdr?x%3L4k5>L5n#pY<}zp^~=);rzl#ZgI8EaM)we-M(<&U`YtYWkZ(lXgoMM%G#7jlz&2FZRf6Z_ zOOm{6!72PpDwro?*_EHRM1Ab;*S7Oj(<17_B95$DGTb_tYcqTnB^vFJpTfTLv-&(O zL2D5n*ZzjBAV!g(o!Bm%>Xbakg)w0!Wv1Uky>HbhvO;tfKY`L@sondfe_H%tT{?#8 z!IlK@5znT@w%oyNzrsQO>3wv3S7_T@+~Wn7mI$WGH_~L5K%C6F9OD-jN5^E_E-;=} zabBB~$Lt+#s@?gA;~%?>{0!=OO>A%)K%3IAW^={70fJjVx#y}T5K}-S;1RCkU?zXJ zRCQHG^!Sc`VE`eY5Y^5W46l$n5@xexFH$PRy%M5Yd;)Jyy=%X>j@rFGQcS5@B?y1A zT6V(k;^44U_NmbI>*|0Vm9k!~OUvPr65D$S%e3T}qLRS8t(noX`eNb4{@2?4viN*C zc#O8E;n%rr?_eEI-)$kZVz@(6_M=a3snDdc3{0dum&g!9XYC4tZfX47a;|EGV1!&V zp(3G0BeH;CwC>%unxnx@aR+!6MNm;HcRZFrQv1)N{dY^G$}6!y%8f9Po}%)a<-(>X z?TFa>|F<*H-gX6>z%{XloZSL$0ibY0>9||KK_BK8Fdv6%_ij1rs_Z&WXw4}n-d5+R#9koqPTJ;v5uFduTOS+Hy*>RQ^2XjlMAqSRc0wc zCLbj!+I%P5G7&xG>+UqJ32RfdWv5#=iZS=c9uri0p3O+IBa~{zKI}BisEz!6NTlPt zop^oYl^jt8OZ`>nbpTG92jI>hsX`f!!e(tU{vt*m;AZ1`hDg;)-_^57f_9LqucIF_ z7zV(jJ1dZCyw{;cZzY_&(kRFar^WL2I(x0-F27}dE0JK z6-Z{KfrTt^h)~_+#(h`Xe;%N_zBAa{5|v3+Jvs5r^Ve$c{mwR%rUGglCN|X`cFp2z zjm~}%sdg0?kww6ZgXyPvja9V6bBxmvFjHu-)WE8RS<=hNEolsG*5 z_DG@GVC-1T=@@t7+X2Ap?K|nKA&A$Nw@yz`{jZ9hR)K1Gik3(4d(06$pmD?V8BjdP zU8iuWTv1{ z-7BTV=An&ZZ_Y>Szc=CkBpEUP^6GP(a*FAv4N{s+&V|)is<(hywz)%?&_6w~|5J-T zbgjJc`mj9ybKHYq$Y$W%l9c0P?V-Ujp|C28N8dW!cWF6L&HF*wT?fLJK+qvada{gp z-VU}xDe?L5mUHJ0K|sxa-RTKZbPREUF4kMkMJ%T$LZ6uU?A_={oeakdKx)(dXs`eJ z^nbr1T$!`I(mYV)3l=tz*7#YLd%^g=r{8slkz;3)1Z!ZPi;YoY`R5x;BO!^$H0|~z z#JDGQ=DS3a4F7dv|8hlydBqXXDp1HU*U8Fw!^3i8!8&gqU?AdSn&$l-eg9vc{%@Cm zq?Q}dL&O&&jcX_F`Ty)Rif`T&W4Z-YWHs->;O*)~!R;F9FZmfg21Ga$q!|X%Zvl89 z&VMe||JXunFgNdJEI?bN=6li^Hx?X^|J$hl?hPVd!yNllzR=@|{2t_~AcgAtzXFW^ zj~sf|sp{UH~=cr6s^@Lruplz8wfZsq|yN*lN?~F9_^R&TwktmhjcRfCszo(6nYu^ zfLpzi)>ma|THkaE*P8H2N_y!Xl1C4_R06*1l#wA{$~LA@B=`7i%>~Sj_*176s!)F5M6>>Og9+N~Vj6F85@B8#(bWw-Yi{*(>xqGD20gU;l zVA;aXFow%sft}nb)Y-d{fc?%|_u=Rae}??5GQd>=_9E|R4Y%0k%P!|Iszgw$QgxoxaXab&aEk2e8H+6498prIJYaqb}B%`&PE54lI!dIf932lt)5HTW<$~ ztxh~|$!G`8QUR?p=JKCb7<#T+c_OD#^9>`%=g6zk$)Qcr)n!JFnz+%A6O@(Sev3q% zJmh0u)Sngl|82Ad47c-iAQ0eJpX?)xuKKM!9YkEyz0vtajH$G$i5xL!!q1DwUYIpx z(kn^#2BhsOGs)Nf;o5N!ZYtntxVR&r?P;3ABqJGu6Con|`4&L=9+*)~0t3MsX#_e? zywFSGi`M+fl%@0hBGQV)DGS0L@u3)=^VQwGXJe-# z|4QNXS$C2R8IK+Fwdum{0BBc4{kdZjjf(6?>vu2Z*5O+*?;M4WrkEQai&7{gj!d7Q z17DyRPVBTf&%zk|-&0DQFpp&ZVvkCb{4CHe`USVJS0?47s9<${j3VaG=K5gv?g;tF zVj{E8kY}1W*Sjg9z?~~>>4@E-Vq=Dou3ek`vF_U{5GB&}NX73h)UV+D+yxdKE74tm zs?c){HeD#%pVA(xy$>ANU?62>j2NBA85n@Q{B9(e^oor}lR2QyCSScK;%Qj%1UrcL z!bQ87E$Rs{O^MJ0BncDl<6IWNR$-EZvZP{8CX)4USmlkVA$sU_A^x>|bg7CQ?zevV zuAoi^Eri=N)02<~=TFag8ebViwE&U2r5@8vr0G)|9CGf-gs)NZ!fq@4-vmwqoRoxC zx81S$#gG5v-uM4-6YBoRoi9TU{VCYTQO^fkI&+6YU0{b*O}N+(eBQ5QPj3A5Jz1C= zwn?)>{vc>?z=h9Jh{zCun2yNj@F2*4GaH0`9JP#gG-?Z!{j_xX4c)IA2K7ZHCt*%r zB@H&W#x;iJor@q;&#B|aq!+a&MfAp8hJwh#;wydh#5vA?VUtLHha!Dj0j#$G8OTw% zjM>Ds-E!($^GzgS_mpfQIO^)mXHf1u(fqhM(kB&op#%}Mx~X; z-+0PyKs|fPE*3gv`vR_6f&bro7fR3b!R_TcYJ6n+XtY6RC=0W-WJe$i%*4cq8fvB0 z{kzf`tMe!nNvh%<4{ET`9bql47A{~qct$SY(NJS|I@exWRy1j*AXUDMWU(-;V zM0_#3OuNgmLx^z{5w8wz8l{s+)zLV5Hn6uL178%O(4mm)3@+crBGMS&X7DM&ch=}3{@5vWO)U&J92Ede)zV(RUCO~2AZ z2X6rphVPpnSlpDkPAn}Bs;i~>bsFzzuZl^9SX&mnBzYd)ItlGuI9m6(e);<~#B+km zfeG&PcmFJ}*+cpwo9KhOH{old8pNRzwujiue9T+C;5WywUAL=<&LM$l|-@ z$iKZ(EqlUy3otzp_qzokTqvyJ;xVGk5jG+%qWtl+D0ptTZ_7F0kXw2Z8-+xoTClDm zx@&eETT*TMT~U<)Ap74aO6OYlUIhnst)^SDtOy~hnpoYBI$09Nt_#LtWti2tt$4cq z%K5sW4wc3~DiwglgIj&+Q`|n|V^pZN-yJR`F$}Iz06?r4(63C$XTwD{w6xJZ3O{tV z?sB2Y+vBLDdk~F3o{~_;kR52(`K|;lSxL0PArJt8@2u5yWSA)IIWg`F9)0xRa&) z8M=4ZKh$tai9Fleu2hKSt6LapM3G4RcEJ9qzuNSx;n8~o#=O(g)8=pc4guRRSqq3& zB%TpcQ9##T<9B>r!9sjWyXQMpp8-0S?GG#>vbyKKS5u+-(TB1JsFlh>2Q&M)EXN0b z!dVmekjh*E>Kxma442Qy`OuE{KGl5qsnM~t<|L9=FC$uhj?IZYdMy1II5mwB>XmOR zsc{kF(<|&$Av{)QY@c?ac$RivelL9oH$*gi@_Szls#2k>neiTa;g|}Ckykn_wb4Q- z|9kJ7-pmZdOJlo;r-EtHQ_{I2tFb`!Hh|n|J>&^34<1E*V%XCT{uGemyrJ(|xpmdn zSe%z8?(Uqiv_cbXD`-_eb@A*fDdOX53iFbJR6LZe2zT3#8Lzir1Xb}!c1gH~Ek)Lr zi%c&BKYd{QYTWgee1J;Wfb_?mhO~hWc?j2PPpj5OEHJR>Ugv`Jgt0qGJ#^vPtRkOx zEP}1>0OrsSqwEyB_LdJ8&b0UMHgCzbOdZs~PNDpQ!pCA;TLfY9%!@-#SA5^ zZwr5WtRYr%apo+PmMAy*$4H7-+m{37V%pN;;f^PC9^768)na#q4v*AQWBMH)t&nwX z6Jz16jz^<0ls27jcc85PqTU%LvTmo)c_o3-GHJ;_wF|fwQ#bB$IjwTBt)Df3rP-Y6&>GPq1Z8?)(p>&I0L7Nx?Jn3QdQOb7LQr(<}@ zO@ykU&7C{4BX-hFOiCI7GxGoayZKr@67m)9II#@E~UA!3%8@*Tf?nL|A*KuQxPpT^FkyC$@?EH=@yb zm~In#Roy@1?|Y{CQ;=h3mSwJ?VJox*E_$MnbSs9M0HsS2uFi&$k9STgnlGPrn>8KS z!`|hpHZVlI&c(CS{E&{VzGI;|VNk#UY>5Sv6Vu-J_}XIoO>%?4Q|OeQ?Dg>x4Clx8 zggm`oXmWAJ4L>#3pW8mo#drIhy{PDxNf3`%E{7-%xfxfLrg3OyXUM$rxD2{ z%a-fXthiO=&3z+yKAas@!b}k2;QBcdVZlV6uY2dcgr1OV^veeSt%-oeifWvHIy z8_Y5g<9giRu^3v5kUPS;^B=&kmvsi>ThD)2gzFG~N6h$+{x77(9qMhm`;x~4Cx0F) zxvY&wH2modc{!Kab8%!%xHf0&CcZyAVAfF+uzb!L&ux3OiI4}+l{=wtpy-&iV-SQp z6eAMb&_Ym=VG^}`2RN3bJ7LS1(^}$u5ce#~gkC$96FF6C!eVoL#9`<_?6W!*;9d0c zy7?^4M`T*^*dulq(u%LDW;Fe7jjbxGj=MLPrOE$2BmpDhOAxrbw5(?Bo|d>YegT$D z(*H5)7j3b^)oP4ZxKLTNeUguNUQHh0_5L#4px?sGVT4Z$sV!ORq**{8u{M0^dm8Bk zIA(?B*oT>o3${N{PHGy7eIQ7B5)#VxL$SKP{PbvZY#OC|Ub!%rH{570**?3N zvtvZf^gZ(xUV5JKeI1pA4TH6#)L?nv%kbxa$p-hY={>Bve!pLz${x#RtZe*Qr>!;Y ztCWbSyrRvnYHy#l*B5c0Dj7=M;1zzC5}{Vl*A-WQ(MWj{OV;g3)eh+C;Q*`?i(1J) zao%nw2I96RtZ8x;4cR=Ht!r8V2kcnGaly)%9ViPwE) zaL2_kwd3GXQkzK8ErA@}~j^a2o@Cc9&kvw2UNB*NBzK?^3IOZy%a?V_ogKdHiTvHi+;q zVZAx@{&6;o2yaE^9$B>G!i6@@r3;*N%tj)5E-P7RHgxFdv5VT;;ue~vD$DX^8LW6Dxmzf`BpGWayq{yF4f7)z%> z^+)ccf(eeV8{;0|RB^TGZvhnMnrGoJu>W!Tr!D46Y#Zqc2WlIm-J7g_G?6Xwc^2m*h+F(+w(=QJ5@J(^Ads z?_Xgh7&?hbvH2<9*k23rH?6Jel>WFs zee*aZJSrqdzi{6uhmJfhQpf{yoF=^N+3%J5alRpGnNK|AjcnAPDA&WEs1PJ%b%37Kwnf?X*V$=W3A%!Dw zRm^os;P^@@a1%c1be4RbohpB`w240Kdw9ayD;d=$H>*teA*%Y}81)aGlWLU94kP8V z=u};R38SnZlDY*86k2(tB`)>JYtb=&0L*(@Q77rzl3I+%sEp0F;+Z+(tAwlHv#Esj z@3RU%KIk+GcbCR6PA=?SVtx=Q46Zp5`Wf>0ceKdlkA3X~Pu`sR@5Vwtl1-9EyA@1L z5D7@7vQLLp%q?o<;K`6_LDp|j%E*9>B-I80Cyx@=ac3!WdnSJ6m}?N)n*3O44iwB9 zxU|{udxZ7J*s{u+*uwmqZes`auw359WlM2D#}MmFojmA|9c&^{yk`dCVtM_k&K54$DHPoNiKkjK*NVrH7> zB5DU!l9Z{z%PrS5y6=z6k(IOUCwMdl)Z4W8+KXBvyQi*l-*FJO5`}%H5p$;^W^3_u zk|C1(?dOw$zuk{<1o4o*zprzEfSb^SyMPBJ18}D)r|;fdH9jwV@C~1IR+3H21zuV) z%VBXupwt1pRDsEXH8~Pe#NEwaf}EG^koKPz_%(PLo1(tNDrbDgVXiykBBjc%3H<&lQhp9y9;`UYoId4D&YvQBg&f*DfKZX+9xM>!c+SV<$0t zv(JD5!KP)U{L@7b$P%pVe3pMw#O2k8J-S;Rt0e7#6rKHp#0@76AVm22_kVr}Ke$f@f&Y{#5D-Egh%ZRNrR3;;3!g$FhwE%5%Jmqolj zgGHt%e~5ev9k-MDC}xH{7cJEdi^WZ#_`XzvU)@zJgR^r8vAFz6*2{C1yxw2O_)R{N zo}kU;;rAaM(?0c!E{fkR32iVUPeE`jScwi-XEYQ*7>@HBtVGBAsvtZ^SkkW4V~DR* zDHDW9@N6Q&!X(`lh`$jK3hRsz{9pUlwJlEl#E-z%lb#+mSfy;pt zkCRKTZQ*5LU*I^EUGUr4BbEBfPbD;0MlR=dRL;8mdg{SL zhd0^&85;&`tNvImK0RPdmhY9jSq|5ByuN4h@GeUe6aVZ>ygYho%c>>Lv?_gOzORz7 zcdvR*^^AA-v%NTZ7XTM1FlR_R+yZ5Nk^z@m+We>SSvPJ8-`sM`_sHqg53bgWbNX{W ze)(E5aj)?H-Eq+z+M=J<{mb8RIlki0s<@yV9Y%l68B3pRKVS9odVbl2np~ccv)?)= zY@al1=`Ksj)FzL&R>qO{xVcjp1UQS^b~o>vt8lVjclLsVQNcQqdXZf#6xfpw?s86= zy`(ciT`kCJ*PFgy9yN;BeR zN~ag*-Fg0Fa;=bA^regYT}0-Y&YIluQAb^&D>651E1T2AS1O(9VycsNZ~eP`-nRF^ zC2rHE%U4(CG50-rcY7Ykk3XAk_e50We6G0oRXpRnte^Tfeigye+?g4nk3a2Kolsm{ zDWP>qyhiOT51)craihN!4Wv3R|o7H`{D6{<^f{!^>x?O&qgRZsh2^==oy$ z?wx~P`S0V4IP)sw?#%H!yNmVFJKHn+8In6*m-zAPynQBf;o0j)O_Qq)#nPmIUQGKl z<;?-``3u`{Yq<}#WA})@9~Ct7gsvO_NRJnIhr*W0!= zy*#8Je&WNM+*zCN%@dYPnDl$r%g*F(|LEB_k0Pxs{HsyM80R0jw@UA#Jm1;x6Y7zy!XxSX!QgU&L7{z&K`@I zFX$BQQy!gGn`Zg&-iJr#`%akXJkU+CoT{_+w1AYwi+h>ZQ_|NTtFDUqzGJSec>)9b zwf9e&uS~T}occ`Xob1Nwa&5cC6&3O~s2`WMmt~P=XJzwRTX-VtaZ%Yqm2JU3Y}@yL zjr#P+I{W&*2^mj+oSEsq%`RUc1Oyp6Rt;+P=yyzMazF#rb~XHS_3_ z>m9dp(iH6-Uh}93-CJ)f#CZK6+uT0umhCYI(*>O}VvUy@o{a3voOnF1uH)B{pYx5H z{c?D_!esSj{!Hxo7{%JRrm%9#_RZCs+$wqd9xS+dJnX#D;l5zyzRfWk`uX;XA9?%x zTWZ1e`MC;b-pHx`SoUac&$2hgZnHxUTo!o0@65G57ZUQt9>2-HbwQKSCj)4zY`d>Q~GB)AwPAvHh= za8{xG3!t<^!cnUVEd!beo=JGrJ^H0ud)%{-=yz3|o0%_+*hA^x*PH{Mja$E74lZE{ z+0Gx8A+OutZs}We<=Xywe>!4yMoXl1PAI}R+wg~;b2CX+^}BGcVX@L8MKOc{Z*(!2 zLo@4U+?x-z8mKGGSGDO8!wUGTH-ppr6h2<}$}xM4=~18HbjHp?TZ6cDlJCE|Y1!zbY;F!A9SU_Kcikaddj>oEJ`h%I?N(QPiG0bAHvRpL?b<4;F>Ci>RUJ~rc z4^QzVTU}GfF5VOS{Tr_NY3hT>>P}Ddjy-mJMAYtHZuXtBH-$XSW)*}!%rKJ(d=LUDIOg|Qg%O#_^@AV{s zqvuYskh~5#m42BqIP{mL{F4Y(s`RyIm6I9T>Dse*D3eM?FiA1Tm`A7D zaL;ybt0BACLh_*6WHtjB7v8X?2Y(a$$=*kir`ODoJ+4o-V)xPxIXFr;}Pe* z9$yEa9Dh;k#r-q^dA_bb?V!4};ZyMDS$vTFf*XCBxwvdPGueoj7lP@pR*jFVut3LL~TWbMqoa;nW~$E=_| zD9>xZ%4fi9-|MI)Hl2RrZ-#$I^)y3dJHPr3kxBkj3GS2;;fK?hT%gXN9|GpG;5HS4OOxQ{o`ZM4G#)S zE>Ux5kbtw1UfA)H%3V{(bz@|b08@$aX;lWD(jA{I$T?t;D?Dtz71~>PAPReiepu9t zKJKC!&$9WHZcdHtU)Y5)H+LNHGa**30(0DTd(j*ba**2zJP@TsRqyzZxY_)edIVd5 zq@RnLqTz9L?vn(s37ea2=I*Ia2A)s`nB$U-iDmBnB%o4HPIIx){M<=xw{f+k+42>$ zAKeFoEmrcjc?S}RV#e~zd#4#pOJ-^8*OTI6@=Z%2_FkVG@!B3n9mlS(=XP85+!kvK zTG8!gvvD^ciAc~L1x$Z3_uYfv?hue~UnV^=5<(?)@YX8!F`A>xy2JqZ64;?cp;R%USN zF9Gtm#RTNPtRl>`KT4t|&8!aSYA$cCMC@w&DW;M0a7)cW;?$kBIF#l1Ro2dhqUalz z2-ZpHVGFw7e&j^2d>Y{iU?v9`L=x&mN|xQ`M-ZKc028Hch7-qoYLaTyLhF1R*snx= zkKFK^#cbxs712MRGJGC! zj6gO*6wM7eoChrKB$}+)*HOyfB@3nnJR>K+AQTq>7kt_nJqO(1?Kq0uF4Q3XH=u)3 z^ zPxkwFBOspUaDRSL#C)OWlYX-N$r%Nlx*;Jp`PI`pdL!|sDR-b1>-+k)MJeX6KGN$8 z+>B3Mv(>Zubu$GL6HXPhohe)JZXZ%S13ASTJ^apwt5n%GnqrxqB7QG^TL(_rs)^#W z27Ku5Qv0dKBOV|J z32)if(+Mh1Mg|*?YOpGISL-+v-;2g~ zbgIWGxwJ3*z*+8TQ`YOqbrK=f&L}2~A^20iYDN0SIiL-S9#}&~XALZfV0h{@JOe!VU=wqTjf`eZFzE-!q&1=+uK181^QndR1Vl4jrPRoSG5oW`FFSOQ0#v%WnzwCD{P_+~pDTo+P? z57YAgF(*i=hU!*LL5h8MB0VCpcX88#t)bUangXICYBh3Bt@|xaPRnpGrtJ&+uWa$?*Nfzz zb7^8^qN)}=I*!|?clZ%+v%Lm%mEb|O7Bzkt?B&Fs&FZh-{fW^skGFUTi4YIjHl}nJ zX&K6U;_FJV(y^E%*S6VRLe^r=?|X&eKfs={f$@%Nxr^BX+%9l|DUml5TC}&qcMs12 zhquu)Cv%5Yi^#LY*Q{m+sKp^>*MH{A3c~=L$EovGWPGD@MlM` z^|MfW>L_0W!R^6H{4^?5;Lo(;-&gr%7Go`ADf?rwn;72}T$s*yaxWb}%t*lNo>cW% zV~}edvC(fQ&)-Tm-{JS3Z){TO3%wAs0kwE>6B&jje9}8BG7pZ=Xc3<0vhAV*Z`na{ zAmI;o3EPv`tY!KF_h@{oJ*(l1TMU|{Ix<5Aa0VX6@u(3z1w%H2d4>_`HhbDa)6bI< zUMn(KnnA2Q_39@H)~xXyKEajr(bmk|oQL@pa`S^VYVL_$Vp^rE3mDJHSzL^N1xYD9 zOE{)h+*h)WGq-X@K8I6rMBOiP9C9`$q;n3?(SyH@)xIkpE@}<8SF?Y^zS;YGOoBM}03wSLl`4o93{YYQ$&|MIjO=YReEK>faH#%LQ;GR3zid#r<^t>TIY6LZ zRKlRg5$<-YUki0qZ-W{ryDNn8-InksSnBtGM(k`GuzDXT?1yhInVNvxY9j}D2aW-WMU zXc&MA4c$VOrsmVoe!Hw`&74z|biHmb%O`O*F4tj&VcM8vcXV!uhFVtpGK_1tLT8!- z*X?A<7ay+E&g7kW^E$nehQGp;SKA>~GXA7(h*8S73--+g@t7oIL~NkI!m(}GZh^KM zH6ydnk)V?ib7w-NLoD056T0fT)RjV4O77Id`$)OS_gzJyTGpJ&k!qxF&RDU0`p6>g zox?#|{4^2IIpBFtkr#v}c64E9DP!_?FStBGpqw|(=B z3f&`ph_$Lfmj_F6bQ0v|R(bkFS++3R(IWc;SV^{6{2SJ$y()XQBDWU&AlZ(if=8xn zZFBS9z^J+A0 zjx);y_za{74lk+Pzj}RH5T_tmXOMiiTe^IZG_l#@r9XqoG;#!?9s4D(|8y&r@8wG# zyLf@VfafNxW_}rVZALBfMA6Ya?&CGa?yJ!L(fgxmuYCG%m-F2jr%4bxCb-$EExW7bC;iy+%zo1i)r%nE16k|t8SBpF8I*u@o`#;pkhAbFFmZ#>$?U-nNczsA@!P}-rPo
&jvZ!}Y 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 diff --git a/images/ch_iterator_insert.jpg b/images/ch_iterator_insert.jpg index 456025015b02d36140f992711448d4f7a18cfa91..b83037cc563fd7f87ca1c2ddd19f3971cdfd18c7 100644 GIT binary patch literal 9203 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 diff --git a/images/ch_iterator_itertrans.jpg b/images/ch_iterator_itertrans.jpg index 180c5197c36ca388e7473d1d98b6d1f1a2d51841..a0cd02e74c099a6dbc13b74b081f40278c35e9dd 100644 GIT binary patch literal 24878 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 KZ{RL{r~VBevB2yA literal 21770 zcmce;cU)6T*EXDhQ~?Q1sZv4-olpb;MWiLvB=j!5_aZ3BQ9ybL1PBPyA#{)~AR-{W z_p0=c2!dkaLp{fH&i$PGzMuE|-rqO>?AdG9%vy6@Yi4K9%+A@=*&6^QTnVNG0G=mS zAS(cH_6;Dx3Uj_=Yt3qF?PBe5$IIG^)xwWeSwn|a+0NC|%hS@s-pz}Z$I9Br-qKpu z&BfW{jxU7tY!+}EKukzTL`XnPL_|bFLQG0VLr!+_A{jju^(7i+hN~>h3`|U{U_owH zc76^fCZ1~$eqj+YF|n)MQnHdz89`Ao==Vl|BqStc7s;-WlV5?dF|k4akJDKz07MKp z!b9T&K>$1u5FZ3QYX>j^fB-!F^IigeB?3Yq{slZD;`35VN&tWW4DY@4gGACL*g3B(#qY-J3gmPUKwc- z9FkYvF6!~{Q9@R3B{8>{O&&N`>7K$WP7HQF(;%?dgO;1gP*MMW#=4ux6h191F#YfQIG z`O7d_3fa&@dcf4L`TziaTZTPFR-WWTcPpDJjH{;NT8=Dh2NVb0ZEVQH#=*WLlZ*N9s5AfU?9Uv#yQ1Q$5><)zvh{3x@Zs({Uy@bk zn4TcI0Z@wEuK!JZM})3`oqbe4k_#1G(TTJ}hpH2E(qq%3;i9ra0W*MdT}N8OQ8DX0 z_a37w!&6QWyM3x)>TVbogxN{=#qS zk9i}NX_<Q}1Me{+$U~|v-bCoAc!%Fa}MO+{*k9EpLxiZv7 zw>411nQ1-$n^XuzwB z+4ihB1|=Z#voO8R6O=Qif=7o zAu?HGddvgrB{douhw9d6*s{kT%*W==S-XX!0){-pi0 zE(g)gzUq=Q0B6wccUhfMRPh}W_idBj?9_%Vtj}P|T_S@@EsOFDnWR2?ltQqx3a`=` zP)<&X3Md2lq3U?7D^e}0QOJ#&`rKoGLXLLIt6^iLOpj;OE??>MK)(KjLM1n<^Xk8b{klG?B{5nTsAzS5QzYHe8=HKc7H;Br>Aj zw-!5UA4s1X#w>5W|!x=9Q0HTw-FK;OxnL_Xy^#vQ%MT zX>1jKJ-*(t-*fXM7r&)kw_^+jddq7p<>62XW|CJhZZcI>cZRWiJj_zSaINE*WBc$7 z!y`=FQyxN4{RC?25FGlFzV2{3N3yJcq>#Zl)ilxXQWk|zmf4a47P?)~7Y11)|xp@YV)1?lB zRFlCXn4cU_m%(F_ENcxG0*p=QRP6+`AACy>yYPWcyk-OpORuuY;e>k^_Q>pZ@EMR} zlUr)S#;lwAbw^qyweGGADOJB+DVvFhd;ncttu(%{LY^}!%Mn}ZyZ z#3iL3+UFsr5@VHcry4|0ZyZ&kU=$Tqg1=s^zp_lz08i)qM0=VRa$U51UNxq0Ta2?E zQ&lREmuDQ#rMFdaagWxeq=Te>JO{b@+PxFD$`iHV%m;OTRR_y~JXPPr<1Gk@`>a01 z#^!{~hk1A_+T`(%FXq{ds0}s`JZqSBrz*wG5j6eI+^-7}t!Zk%P2}}tHdR$>jt1rq z2`f0blq&(++;c1p(jntuaKK#>z2ODX&L11I2aQEd(7Kz^2ptF<5ft9w#p>cNf#a{9*LAUN#m~gTV|03|u(?gM6^w>6V$b4AV3iUEk&x7T+gQ+sxis@jnn^p< zCgGRtScyz;A{w}ch1&vmiJ_68RlG}cqraSU`XhS`3C13J89a$n@M?(fd(J8BATco= zZ^Fx=v+p@4cimo_LOo^Y^_Dkja9*uCHF{1x?xFNFL>`H5*q1gwZB_dTe^mLF}-R0R8AzwL^_a{u7tmu8=jA<1pz0NNo+4o~1F4m_d-VD2vl-5vmD^XMV=@+9i%fCupO{p|CB@YkBNW zB}u1xz_xQ0oU5O~IMJZoQ*RiEv(wu+jv@nb7U{>UT0We%exJ{z5|i1pD-@;ARn zJ@5K&_DvHG53$sgy;L!lP^#*L(&shTUal6mnzVs4d4Iq< zD&1c3{S+DvclP81fdEqj3^q}pbXnqcO1ghzwhJ5Wl~0^et5LO5K#LcKMM9(cPR#BS z&(SK!hX_}P%S5xGxX&M5Z>nnhJGE*I$kzk z+nf=XBAe>?Zp_=Er0|_7_el~B zEJN9Hgux#BCStY^@Ar5F0En2C(ijR~IrYF&83PJN6pDR!OOl?RX+HDfbZXPl5*&3cLOpm2M4|J}E4I$|hA!4#={>98-$VW(;pNGF&a^lK zY?vvS3uOLXLHJ&fj%7LLa2|Pe zIN}K8V15H(-0rFKuwvK7*+Yj*)}}0(B>=<88%yh4Z+DA6x9j;>=D>m%3sT46^LKkN|XTljk3gUGJ7-nUtT!R$eD!yZg zVX^omj#w;&+cV}WE42@PU~|yx!uOGB*Wvk?K=CqH4W-8Aq{j_;#wR&DNNuNh8Z&V9 zl$F)Aon}%*klm)ajT{-V;((rxrIX%(!_e|%F`YB9euZ^MfZFRvs3P+kaXo)E3+MGw z@yX|#5HU^?PW>2l-{Nsp$l#~ zubWzsVMA9r)nRcxW@B^wo1(+M{aNYBmQX%Byq6JqW1DUnIOU>_#{@}b2hwB<2Fyod z8N*<`hRXq2t_==&xR+l@tMj+YMa{fJXG&XKp(#=H*L~qJYkDADE{UBCHT#cx=Zph{sJKCsRXq9~{_Utwo0WQM5wxU|4+7hHXF7Oyo zff|N`^#tFaR4$sR5mfw3{GHztz<)cD>o@}pwS=`A$^E_jk{f9T;bQnrjh?SVbgh3c z!v~_?jP5;9I|CRU6$73AECgmdS@i{f(ZQlwoYf0^GozwjdqBwMq4@}QBf=S)O)NNOwW%xW^m>qg z`1&V@__T92kRE*_W`csIGo4>-q}{#`qN8$VyZ@Vmg`ED@Wq}^(wG3 z943&t>+GatyN=igzJj%iE=$Wt%TAS#ZaQhR&0ddoQNBB(4vJ5D4`a|YeOS}#dF#zy zML(Cc$680Ar;ffRV?&~XJ3E%zet!RbJod;2v4vkNewAUE_rq%l|D8{iTjB(2w|dd< znbe1Zr@95O5Ae%#FU-6<{NR@oSZpwLO)C#KNz-R3UX>>x-&uflwQy(VIq*hct?Xu$B zwPhWOvBC*ZC8AAJlZI`IFT+vy_JFjSt%q|K1UKpgIgV!Tk+@v9Wb2$0&uSN-V2C!P zcRIb^M=)ZkbaX9M)mhTP#-!9D~dV`-Z*@laGYwZtBgy?&1>63GE%mTQCBKhwwRly()p zpsiyFuU1m1!eANdusCH4aC~83SH!#x-q@e<^hfSLO|nGw1e*A+?N1A=12-<3|54-T z6&Qqj_m6Wd;1O;Tp;q=Xua3mEyHJGfh=C??ZW=B<`U1Ab&aqKJy5+tbpc6835pQsL z_q7^Eya!b63>QO}r_PR8J1)vGYc3mB6=O)PMM=~Oc{7~ZPCz1|-MmKjZV|l*)AnNH z>LJ3d4B^62OGI3WIHV^J@tRTLLXTbIBYAaY??tu~T+12YBxqi#W3RvX1*{lhJ;Ggg zWi_kriStQ6PZy%lC?0pKu2*Ju%F3q|z~BzutsYk9 z_9a*%T(^PKuyPBM8m{HRHmc3x@%tmjY0T}}9R>a&^y!1@0C~|iPF;1Wtr91CL}1d$ zJSWV>=(1RC9;c0pI9056MiS7sV88;W9;p>kaGOF31nB( zbU;aFtJ)d2iYkKgp8w?WPuUcg!YU<9rG`awIl!#EHDFM zg&H}x-*V7l^cb{-PshGk-gY;UCmC7V*pG$M-eXAzfVcWP%6nSXMh=)hkqK&7XBYK` z&lZlf?fFI1yJqEno^R!Z&{V%2pi*zpF~D529-+xME96f)w3^Ms689)5DW@b_DFz;0 za7uF2VF1?%hO;3>RJ-N%Tt8m~XLF5gX)eTz!A;HpNjZG9T?F5l>11yd>)?dzNW7_? zT_tQ6sN$Y9gf)`&Or8P6g6?;|J_EcWC@tp<{CH9CA{YA2h+pZr*h7CdT>Jhl_t3rU zFKOT8KvTMvp>yqsnUFS4jY`hGZWo&5pnh#M&KFv9LnxTBhLctXj>cTULTcO&!lyfW{pO z)S(BZSE)5`N91yGyt9%CX6WHf%7qB>M64&iXHYv811_p|x>a)erBq+Y&LSX_Z15a` zgQ2A)#4xM@TsPl3fH+9&?GoIWf++pv`>TfTm${np6JVIM&iCOk@GASJsDQ7L7S)r5 zgqy*-S?Pv(sy-47VVENPFj!&tBym?i3_%Y{mZR8WEC?~|bRX_?q$Ngc9Y6-YsWs>D zOrv*)lo#g0!ouokqlg*<1PeQEUm99LWr#jz(}8)*LnSf{(@Z^D-WxQ&O)^`-><`^? z&qi1dnU^ss);lrowIr5wy?3T_6f5|Y>mUtSO?pM`?sY*W95TR7-_75cU(PHDQHWf7 z@kw68k+zPfk4T6(blA;3?6~D5A%p!4AkDUV1_%h!K>4hyh9O-$C3t2QKN-N!0Q0swv`E1$7CKo@{a zztoYoF^DXzrxTbMnHj{dpvy{Gwc)t}cb{+V#qXvpns>|f$$|iYn3Cb?(slOz+3-H4V^AF+UME-^ec{b$L*_yAUUo#vq@dsQp{D%W?D#u zTZilQ1o~zo0pt0uf=_Ws-c3XRw}$5~W!ZppXgM5LFk=fk9s0YW|8Pe-0mW(C zzuPPwSrKPZn28jT7%1oTdq0@ zp)OAZdE5|rUwauBxh*Gk^~xtBqOpz-nH+cCl-$O9hA4X7K7@egJX;p@kn)|T#@zha zXosizqrGM|Gedl)*r@xZAzQ9rhv-+Fel;j@-ryx%@3x$W&YfjmXLhHh4lQHJ;kkR< zV318ug0z|A8qg+N)g$XxftvrU0m#tX58mMoj@mtK^$q%?pDb@^WyoJp1*T&@XA1n1 z0(fb|F`IYC8##Fk81Nwl?lq-T_dJoc4FdZK78T@8(dYg=+VVIZqEPOOR#~f#(YoO3v!eFl_kPX}08L{_aod6O}l=5+a5jX}gM>@PyO({4d)SbGba#FJNn&soOP z3zv)~=C4~MP%v#!v7l6;+#0vrlSTrp_}@$NUP*)BL$D;khrREM$7bg#?YZaYidZmh3E8dp%C4NQvvbr#kIoyJC5e+F7ny zsOD56jDtf|`l^8!;FOz4NHsnPBBX)FT@t9_d192N$Y@hz#mSea5S1I~Aq;xLBO++! zbd7@MB=ZG(^$g`_Nr8B(bIHO*$d>sY zYx*1%AHweiAGM!uN5_E-#yRR=VpYKvSVc$C_-!m?M zUP9=2q{k<`Br%p)v11AkfmJF5ta(Eh!k9e^^Adx zJt7YR?XTwBKyLt@^PfRwWs{1ih6N2#wpVXUvl}e>ajm;f;Fny`fP6-ld^=w$8!p7Z z7=S~(5V71C!PEZ(D8lncRsKILIM50$JDx^}k_lR___0=aY2Q&KZE<*YIZONqXp~uvlq-Qc=)2J`Dg)8Fqv0^JXqTv z{*-@cyIf+$0ksWddreaXOQp)iCRqx6HKe@cF?{(-cU}Yi`N0wOTMa!Bu@mgf^hFKi zHIkb>=ldbGyK*)@7i0ODMh_=?oNT{p=7ftd&G7&8V+r#*^3) z<`39u)jZVu^D9*xE~2+QCR0f=`vDtG(a&H!904a~i$79>YQ(CW*Qo65L>d|e~= zt>teUCfXx5sgJCDI5_5}vscoSmKO9lM1kIa@c2KkKw8sGg?6p9NC6KB?Z3J= zL}9LU@Qv$3?|i0=^vk)+(?&viA{^0@3GzcluR7rzeDw5Y$O;nukEUY!{mM4p>f~Z* zc`B5i)%k*SUC?y@TFtuehTll;WmrUAv`n{F7kKyEGN}8 zkwIBx|8eVkcD#l158-*v@ps|3U&22$mDF0bKh<0q(1F*E<n0qQ0H{Tu$C%MTDc$F`2 zy@-V%7t*AuL^|lypCnFZK>chzE5Tt^s~V;W&8-0!e^~l@PWpebB=sBPzXlO-TK(ma zy_V5qDrW>)tpik0=Gi!0oIay*u5WM^INrbZk5v6%CiR?YGh!X_-bdqLXo{$Ym(_khuC%xno@ zBzJ#TTn1r~Jzns#q~oF2Oz^RGNGo@3p}ma?-x`0uLIQ`Z>jPmjRFOU|hGKQ8;X^$- zx`&}agr4TTqt)A*YQAErHTHQ&+E(YxuJS&Qbha`N_3^Bh`24+6O2+DRWS)v&061>i6?(msc4R6hGrbzXqlH$`(#6obumxFlx4 zGOCART-rTUY-n<;#bp12f)ms^=prEz` z_W_*wBqS2nT2lY%x~k@Vg;2Vt7ySr`#LX@%{0IW&%N8GdN)Qe-GbRvK19|6<5dq!A z@Mx(CztOlvYY%n~X~03RWYY7;;QkP;aOI~k9k2 zzcBM}Z~woriQ>_|9wl=voc-oijzjJ-mOD}-enVS{cGB@vWlBaTUP0YjTe6)Ik2-cy zD-_(715e-2l3_hf7e1>lw6a!w73rcFRr$yjOLtpZtjPcJMNu0C1s4aMP{Fo9~U2b&M+0(XU)^YH7~#`U7ifXBEja} z`Q|-LB+)x7odp%WT@5Tcc~u;INsnYKON?$I{SUniXI|KN65#;_`wtf{5hKHf+ zd(@PT?6)yVOXT(f-a}F6iy9pDwX6qGmu~CT0y`=RGeEy>I2^ZHMp|5@M|~wXogzDM zx>X)*?$_K|?nH#C45P&GY*DI(m0JYo-27^O!#db~%;7aLt=-Y-D?vCe?Ls%R$VmS) zyF=q>lhu-YCqbvabnSE>;Y3-*v%n02F!6VPm?DZY_h)FXpb!X?vBV!5-wkqix>XST zLw03p>T##`8Q|O}d>JE3$G2BlT-}Rj0ZUVlI)!D=og$)ZXSl0G^mOi@T>T%dE?;2@ zEqB6?v>=z^_+jZaUHc7a!Rfhm{OBzIyj? zzNd7%Hy7{*e?qhVUGE>f``P@ZE3HT3_sp4$DDQTD@9%eiHHm-7L^>)jMd7}k>k;0q zWu0sjmRVT-0r;ONh@B&Iv;G{1M`@u4@B;=%t!=N)r%U${FprFy_<|evHr_hmyK-AD z^4J9yd2RZFI^YSEL^HxwGLTeOD0YOhZMV#?J!rX1ov=;Fe8 zcH68*tKA#<${1X%6nwZ{o4N>8$>0fX9;PXpcl=N}d5|~{x2-veu6_gRYE=4hu&u?s z8{Mf7b^DR0+h&4WHMLLs+s-Up)A9WMvTer{if@0~@$iv-ANqK!;6^=uLgjv<*i9X& z53Nk;vG=pGPH}@}fR&wl4{Aw&c*iLG?P|GJVae#IZqS}${Zf)!qMmqt-qUxdW9H!c zTDAks&F_IQc+T!eC8D(N>`MMiaQ^?oz@PC!e@>y73k?t2!R_V3rhmB50m6*sr^BW2C)a3VVT#Lb9 z^~p|tH39rnO7y2SneyQK!m|$U9&4N=9LU5XCp0_zg6**|o!tmSGA)i@NLq+ZkWIn# z6PF&xS0#MAKl%pT1EN}I54bm{%^LCkJn4-`RT)`W4JmCagn3gLyE-JzL~R$Kk6+wP zs5DcTbNg@J{H2#~N-e%{8)vKM^~8%!C-qF5JpymQ`OLm#ykC3|z`fJd%6#*LNo!qN zK>YH8(TK-rF7NC6IKG5?Rq~$ctqSvLu)^V9_Vi( zkp-H!8$hL;&O&94fDaMw#dj^5X5A_*g6#x>$Oq*!~|tQ)+xT{4+zp4^JuA`RW1f^$&jS|Kxd z8w6D3OZ=*Kde#)~mEk|B4CG8l6)Wf5(LdxE&F5v$@F-NnIe_y_k7lLqvNwSiuXH9V z1+PZxSSMfMe#WUT>5Fodk0ym-U8~U6fpKKFO>Hl=-rhQ20=w!hveaQSz36R()*Gtk z5EUH?i)vM9?VwE@U%FL(rv`-(hb#Dz^+9+BVB*#$XalvbnAbRa#~}2pnmyBK**$@Z zrGypv+EEE-biY&`ZMoxYCV_PeZVl^tf`KF`qH(QEmms% z2h{zA6E+A(nm|>Y@*OG|aiV7JvZ^SICs9FHI=8Ehmq$bk%R~H!iCD zB!Qsy4>JCCy?+|scAM6P*71r~Vsx-ixJZ)G#FkKv(2X;|w^!T1Bg*gEe_L-R;0X42 z*lL=Lz`&hJOKZ}nijhpt(%ko!klva~EpDKXugN@a66#}8p7D+offf0D8Ydc+;P-6ksNFH`5Jj=` z+iBE#DJ2L}%_CE91;pDy-RYi3$U6CUDd90w+FB&NYZlBMElix3z^NrI#RV)Ea>Zd5 z2khZptqum`mH5JrhFqpzdRRIkA|Q3b z+iRpgsv{s!+MH$u|4gOM<;%ghKNJ+;5cCB`b4BA;pjue|Fttn1V2uG?vaScGnfiJm z2`fmlU>E-EQ{)*yDU(d#I8W(IM{JG?iTNJ@9?>o2E)2vk4Le9Jxq zP~y$t{T9016vY{-Rr>^Bs9!^ymPIHD6btXp@ zq{o-jLO7aLz)Spw4Y+A=jtnlpyTO7#Un#1=HNWwG5ZJC>O1x-*KY=U9_)%)rl2(}K zlbDbKtI2@GYSFQtZ;oDoDmPynH#Hucht6(eJ30lnaeI$x(y-oG5YJ%lcwiiZNH28x zg?u}RT~^t8h^2S!I%1+?-mqo9 zrH>G#*c2zwW|LyUin`Qm;_|9;Pol z1yf3T>w2j=*gzAKku16i^b@9a`5!MfygGze+fyn}jS{Ss^H9sR%R8^#W{eAr#q|@b zPuhd?q{DjFO1)Sao`#li8088+<${fJcQ3iN`K?}0gusw-%QiWp8n{Z#j+Jjs7eQCu zAFTfMTDDvQkK%k(BpyQVY~aX8a`Wx=QcAOu{ZGWLfs$F1dBY+y*SA%XtIBbjSnO8w zy``HyN>&dNiFQw&X z5zKmqq)t5+r@yR1F0a2lo@^3GdvEu z>;DXK2h+FT*V( zG>Qv?!2Y*Qhln8K&hIY7!W?G+tJlj~0P&mT_vDxgbPg`Ws{D|Zhy9`Fb*}eQR{C8} z;D_FS>J=?6#zN)ew0Pl1q*{_jS_e5KrA-Y}GZ^^ke13cJ-?;me2!{uBOIJ!6tAy2R zjT-1|dEKcDKlPjQsW0)C2}27M&pC%RzY z8s8GNQ#=DWl_+`&l<(hLs(nXwf91~*O8Fi_mH&$nvTq|WIsXvrUEbT1k%Q}>BiPa1 zs{>mTiudQ?tkh2mbn4Ct=KMi$<1d1B&j7y|{-4a9GhF_Y24aS4_~&t(ZLtW?iY*>n z^S3g~8lr5^*TALVY$#MzloPzCC%fVUECQ=(a#hk5n-=WOg~25&@03S06xisqKufRYq5aBEy z9V|iIU3-W#Q0W_(L}2$tfpfpi{F@^fGLqZQAjU|z>vNHKz(MD7z}NB&IVP8Di!+~A zfPcTmPs*OZfm6rep`yxUk`jBv#glLd{WHKC{t6S3`JT&ICE4l2R0tVNM+!q9Z^9#8 zs=oR9Ps zit0NWmzXU0HgevsiV9fG`BIH4B_~?hz;5j!refu{gqdw$ej|sgD~CcZoPQ!K8MXst zCc5;_Ry(o20`k$uIQZUiimD*wW@4lkBd@;Mqf}9Q4;<`Og^|HDFM3uT9oy$n)9SB5 z{pN#{Vt|;_jr_clw3xSI!+ERp^zp1`fM6evp~fh}*TSZFHkKgf%%OO$TRhX&h*{2h z*timU!Dn*|I6QYk+Z9{ED(7Sg74{-9Ptab2|H!g@Vt!61fEk&a@4FLbnhp7u3W2nd9=QMECO zYLwI8{3s0^e4Kbvtj~DIcoykTL4{#TJME5Cu_^^QOEG

|@BD#K?R8`MfkPWyd{3;=vUl-#K=4O;fr4?9u?cH`BSIzh#S!P=yY&BefDS z;b0^aJNqZVU$z{+bMY@J(D~)llP9=9Kk09(z|-Gf2EOb3o3rTJ#b*F7GPbYRHo^$1 z0Ytr=v)?N6SDW==GB6WwG)C;42Lb~GVv{;)MC$F|wUGl0x|P8~MrNS`;Yg>X*v z^pK8_H-rui*;g*As~xdkcA=utKo-6;b5|cN7|-d*$ks(lXo{q&osz)8xnDZ*9|b!I zu*W`3FG86sJVNA`7MM%ZC)QRsq=QxXbM-jQ&JXp>5h>!)Ff535coYq%B-~(XSGaR2 zGr1zV3Z9S{yMRv2!#>sQ!n;T-s*&BB|N0d_O}M&+kBJYS-ZSUAWcpX&++8aWCei1G zrV2?P-lOZK);goyB90nPtM&dl=C(ey%xc*C4Pl24c&B&;ZDw=d3ceL@YT-@EeTRwn z&toAnuWs6Ze07wkcLp$QwLJqQKmB&T;Z2HPOjZ{iLCdqM{%T!gswSOW>2AjKiU4uH zjX~+CBOo;ETBM#~$CpKnlEXEDdN`!-dd;qcx`R>($Z%p~8))-pJW(VF5}li*Do{2n z68|;Xp*gQK@7Y>iYO7?u7KB?NmquI+Yg|WUQGm30XgXGv8Wt7RbKD$7I1|X!4i!;w z*kdn5Ju&7P6k(3IZ(W-(W8Ig>FlG~YR3gViQ~2@a!Uan8?i>%u$Yix$id$|P^RWkK zYBc@(waV3+-A{4`4(j8o!4B-gqeF)7l74OQB7xHOo!U}+E1uYE%@beEg~Y&<)S$NV zn;QNaf$!dkRkOxhET|&V_uZ&M{|{EBiPrl#Zx@T40aSWIZfzM)oPT56!3AF~NrOUl zq7tp0T{ABYnSX~|Of99IxF?>oFB;qxtt-0VBhbp>H?H(?eJ6PeI8Y>!vAg(@^BCY+ z6nU^XEmVP@uI(H!`~02i4q#n}artSLnK^04B@i<0wLWeY{>AqAY`MXh8YtBwk*r)WiS<^PwG-* zd&ZqUqO6SBdF*qu^x~o08sdGrQ%`+%s|Iiz-A0Jgg6R~r>dps$8*vJUtUdy84 zGv0iWKmEWA*|Izq1oPE=`AzZ+5PEM4X!iQbA^C(`@K(T$Y}cNck%8h?cUc{>>P-b=R4@Ha;)RA8)K`u5^-d9jizDZZbmGB z-y8y4(#z{?DeJXaPZ3ss`Wu2j1)ZhpN7gud&?9DGvK=Okj)nThPjy|`_u654@ae@5 zzv)Ekh=vP0lx-|k3KEnCFY}aJby->2*P6_v5cgn=9;UuRFcu!zLqdn4FQw@Zr!!wX zG}+q)cn?)76V}@oq~+Xb2g_umg2(hCMUq19<^Co7n640kkjv&DyZm8U4uSBl#F4I@ zf;j}s9vUi4XX=dzl>Qy)^5?#R=Rlv2l>45?KL?kl&;A#x?;}O=GBQHX8!f< zeN7RwLZZdLR216=#$5#Hl4*&?$sBvf&iO3a*Q-poVpHDqdL9Zl@B(g4;Oei>r^UnCz zvNC^sk3-~ZaWWa+^U(JTsd8~oaJKUf*tSYUtBu*@foP**&HyC@78R%Q>NaWNSifVQ z0@~EzBU74uht!fULGH_x5XJVp~Zsp^#NH?+|0HA0YOU?LLC6>Y~Oc`3#Zp#v5 zr3&T~KmRPOH?t9Nk+7$3HWYjYa2Xs2jB=A5aCLXzsBJ3DVVR6-u}fFzi>#CK5PsecfBo9DY;@(t zdx}(`3{?WGa(%?EL!dd+AR_yX3UXR=dde@t{n;n5kchyMY@lGMh}xj@O4xiX{iGJ$FM7~3i*CLb{>)wVxCz?Y@&2#|;i zIVP=Rc{hNQebYDeEi{jJzG_h@7dk1kU#tA;TqO?S%y9A;zfSM4@O~2*Y8SuaEFr_H z`(!$IqA9^LLp$kE`dXG>tDj3eXdO9f%r-%{G|&yVRT355VxJD`t+p$X$xnYvST$QH z4Y`G#5}1lz9=|h>}5Ky=S0Xp#E|;7?lQ~dRYUk%Qob@G-g_zy zINmpH`g`ZerznhZ_40hrtfe9E{ck(?&Dt2St!9>6us5Sk0Q~2H`0o-&K5rRPwsVYD z)M9*{4*o)81q&!gZQdRw42&TO4ZGn250kl6<~_N2I9QNwt(z^)H)jA|PondcMBR5Y@j;evEqRNHdem`` zZX`?_q&jzyUuHPyM z3$=zhs4O~)A5DFX>Zy9`UPmFqaHDf^>RXRr^OJg6EKug-3NV_C^a zq@anvc`w5m;1l#;&RzeNw7(qpX-rVe`+r(F)2ODhB#r|ys5EN~3d&+91Z4@z5(E+1 zF$o~DV^~}WU_wA42of5lTQDF3hCQGel1Ly*q+uY2APPs3W!RJ$SwchxQNVQ!iwoEf zr)P#f$1i=Rzui}_&cE*a)u}JH>b`(qIYvorPpWy>Jg&ZhtBklu>g&*b6m=lBqopSO zI6{dAN-v#NpE7yvQdY7yNTD;lK&^Yw7gypN(L8=G8{2bDuj8Kxjd>bPze~Yf*m(Vd zNqf989#iXA-II$#G-G$>SPA|%&9nA7>t~j(tF=Sr(EISsC)IuUoRSvQmIPtVB5fA1U|{zA+g+ToOqB%XL- zIu_Ysun_f(h(^UB^!V_n5&X)HJeLHa(9XlJaBDQ_{f~wOf?*N{8Ip|^b={(CFeV^t z^Y;7NNYEE&@58ZbHgi0`@h8@o20{#myAGd`+`5&EZ7#_+`&GRRN2%;cGp^~5mHJac z9u8L_W72LN33t<{M4@pcmW9Oa&VA6WjExx*4#ZpNJ5gY)9_(QhI4&7ez-+DKZsWcj zvhc11V@MbRH_kTTr`c$4D*=Cq99vjarFU5AO!kgcHftmiID+7{kcMJt!8~$vx=c=P z?d|)b^wA4R zMR9>YZ*3``ihL*np~~$v%W8Mey|o~ri5_tlgkFzWSC-V>9T(g)mY%{MoP1bpPZG@K z9V}@+iF~X<=LMQ*X0<$m!Cg8yBdAk!r_iPYkwgp={G)3XM|{WEYNie& zov?DAc$1@0^w^dfS?DFI;3BZ`hPAJ2ayPWLK7(KkLSBWmok^C17tL-ucAT>8kdL+>-V5kUA0?~4{Iw3Z_WcNUw%iTy&8$PSo| z&+gQ7=}tfu#34PbHb+*za*w_(OfFN&xpe00l9@jt!1&mZAuM8Bw3fwbd@*Ny@(B}? z_gRRNf)ZaDd0xH9Ez8AE8bf8g4ZcvgiQD+n?6vpv@s0s0tDo1xKCTm|-CwM#}OO2dn%wC`gHJM6_zxCrJ`Lqt!ghC_wj%O@`Bxv`d5kI01g+zpMk_=RjtQM1w59Fds99QP&5G#z7` zOsH9h%m^sL(t~9Xx<)v(CH&}R9?~vPO)7-t$$)YSx0kfO1~_vQn&Y1P~qjX z#}?9){|`6i-_;Nr883H|E|-TUV9{Awg~B$=KBC?omHeA4GQ||0>)rPHPpvPN$vA5D z`G}d8R=MdWRq+(iLAL^xi!AS+kC^*1s6E}ZsiS`7#ClW>1DXH9F``^#aSQPNGN>AJ z=yjYYV6x@8JZZ0=e=1EMK-H8kSvv%^%IC!#lD#9P?MbfG5i>_6bp7dcGVVe$U^-V0 z+9zh6;XCvJ;l4=&8@Lb%ym2U(?<4B+x@q5{QI@Rtw|riW5BVym*g3mcX%1|jp_0#e zBU=ycS9@3GBx*LxRC!!wi@`ccE-v!l=`8;x^!{Wn4B$s4cB*@|^3fN^ygrK%dx3`K z?f-o=wGQBTw^g1I>1-VZ1Q3~-82%LZc9mRHv&AKU(||w2uWbOUR^UC45C9F})Jd`$0Pt%Uz;fHk$I%(!)OnIZ^J@+e1zJD+~L{}L{oV>y4}Jj*$Db`B19c0OKSUOvG; z0u3W0Bl9`tOBXI&;^AcF8GrTNtjz@4y7OGk4O z{`e$%2D(#>w5Ms#{8idtGA{rC3;;ShM*1`7&d}1G`TgT)=}ytJvN2p?XS^=N!I^Gx zaolWT5_j9g0jwds%;owU+_5W=;1Z;$ds-YtmK7m2#FSXd0qdfaQVVPS9u*ZUTw?vR z>Ay7divl=DcfuDd9V*s)L;2Y?@z|Z;`)jS%F-|+J35l^2Ze# zkv8arGHb(-vy2sY2`vZp^jq-lR;K~(?`zEX>5;x{t9`&M&Fy>fB-6va4Ha}c7!uV$ z#<#i6c~?y*k`=D>c{LqtR(VGRijthWBduMwyto-2S{igz$J=`o9>p9q@`i?y2oRqj z0;ZlQBQl_L@3)K&I`E-kmiB;2^&*=$RtrCw8}q~@bw^l~8S(l@r@X-QF>}^=olv-W zlPLHz{F3d=2Ev;?W=b1B{lvUoSch@H(Jyj7k4RbwPjDYNdPB9={{_HDeUHfr-)Rn; z^DqHD^o@l4tDN_@s^rKEfk>|svOB7W8z=#VvCGQNXlc>1-RyW%X9;9&;74r5yd2KN zt@T;gbBm-Y&Wlv;D`=5EP1Ykr-|@6ryc(xOP=}lR*32#SNRkWt2-H-jMtZW)1eORH zDv-ckzG3EJa209yy?^SBt-dIF4(x3z!(r$W$i9{ywg?yQyU7nU@StttK?s|m!}Dbi$D13kcY6sy zNoy|kOP$aP(+&I`PM)el(H+QWc74hiR4(ft`g%@C3~vZP`cNUKJd2ByKvH5C&A(6# zNg0=E4^FiwbK!}h`tjMfgp0S_`2C3vR^Anb$c`sIvwGp;NC@`jjVzZs4TQ+Om`MS3 zz*#n~=t3zCw4MnY2A?nD6sp(X&$#|C3OENJmoTx@SLAiE$uZFlT;Z)M>=N!LG^UdX z_;eB(W_a_fUu4k+$RqsFX3J!=<-%gTwM>A{Y*oxb;4i@3Y8xl?#sN{JK6nm7P@C`A zOvXN1(DpsVo45aPYAsD^FOOIB_2}%!rV~(kDT8FEhrq7S$#gX5yS=PEO5}b4tfnU0 zT)y@v4Wb!(b;t)X6j^Jv@AuTY+sg)BN4pdi*=d-|8m0Zg*xpZe5DG297G2NIg{>7M&^k^eH(dDHYcBDAG&K?8j?Ln>DgM>KRsu zoF=RMTwIgMM;#SQD5OajDTAUavr;DbH)LfbB;4higacrP_bla(xc4I|6URBGLPuT} zdFy(9`3-Hz_sXSr#4z8IuVn5>lv>Ycw+d(Fnp|b^xz-ucJJFhB425jeM{}KJbr=pA z*l9g3P>xeX$BblHi~2QWyw}gA)S&C#bY4+!5UOkH$((5P)ZwQoBb9y2HphmN8S7>| z8@V(e<&({J(oZA6E!T_#ZgIBm_%r!q@(jY(kjp;(H3D9wZeMCPdOONc^0r7K(@PJe zxCP(18tg(>X>jb_fW5lF@hyH^q52r~x-(PS>EW~vx9q@iLk2uG)(@l{&w;xvSN^4f zHUgVbKCSD;gps$|wN3*z_mG7fXIt?kgMQzEVM49U%E(}v+zt)4Ig3+%WH?RRgLT&X z*@)J~oCKrSw)iS9Y*-z~tbh)dK$v{`2Giq&p-Ej7u@veM?yt(-$!)2q(&pxHg6TJ= zl=30n1COXUi?IU!BPMBZcI{G$Y^E3OJ{GT)Wixj1&`-&LbjWofw<1$cOADi!x=v2UG z*(c_#S63%x8XwHmhlUY|H z=uBW^N8tJ9W5tp7`HcE2cli2K8WC{c?!95FQwEloNZXVi3heRCB1SVQW8Db9OJBb* zV+^KwwC)$!fpX%6p_nwao(wj%ThNWXfS%R%!TXY)lG64)iSp}5XOeVVai#DnbKM6T z`ad14aH`76D53LWYR*5= zp*wqgh>~<)(J!hsXlPsDVdhccSydr5mRi)ooyx(yqHhS)rXh#WFBi@vDwcU1GHY6- zK#sfeY^jm9^=2D(o*X4TwjtQ!B&TasaI zX;NBH(c#O6S%pFqpOZAHSWxv<~R(P7H*C6^B^J;fqEu#)LF9~s&Tz^xttGs zX55jZ)qZ4Gk;GzrwftfHN9@bjwdgTIRk6;Gn5}zaYx7{~by(Jr!#il-0?lZkpL}}J z;*$f9n6=(X*1PWc%r;EV3S}KBIl2C=lDUEIZfFmM6{_xD3IrOdv&qk2#vkwJ1&5)g zDbzDh$2lh@JaT~fu`y>TK80c}-}b*WM`mW>odXt3&%&V-`dSmEg1(d5{<7JrmkO^9 zC@gP2mhT@WZF1RuMnHo=swiWY_uN&(LD|C%yKk_rzI)cI($`JCl|-zci~L<>!iT(u zZKYK_NG8;@&`sPNga=EIXkcY!^^%pP(aR!~Du2JJT(b3)*Ft8aI$<*C4*3|m^eIQK zLdKlfrRE=2ZOr-H_7GRYJToHMEshL?e) zkq0{s-USiza;<}{iE2OY4EYPSF*6}HlUw5+1&WKItHz(mD`wFr^?1?Lyvp8EJk-w& z5|@qb>a`tjFya|;+Ar|UTP#=-q7{0&_u1?je*hyRS-w#QzVYOg@r-6$%_LhD!623X z=#uvpLkx9sL*@!dd@-rcSschSoXiK_p?R3;J+bE;wC_0N*Fnh#dWNt%_G6YErYYU>Y48X!VQ7iSIfBgxHn25Y-TwJ zQ11R*iWncK5^K@GVxDfUMj^hnyf3LxX*_&mE?KuTZZVbPwJM|sGMamBm#tVWbKu^wblR@}PJJoRQNbp<{L zrNGHh3KCc<7}j#jOs+a^BH%!wK~|=4NMawTpY%z7&?zSW%cuI!`G!D(r3(wwzW&!T!OB+YvAQ|yxw=xh=|MBa;L zlUZGo2v!lU;WfN2GWJ|VrHdFskZA88#UPxsl;hcE(SDI+LtNcM<2P?-XTS%W!D-Z+ zabvhHquj$j6VMsN2V&K%wovCp<;*hL4^Sc;*)ZHggxXd-%U~!6s%2EW^VWKKy#lU0 zko5?uPog%(=H!zK6glz%SI0;c;Z3>u!W9gw?URXam{U}$!bUSpShzFZn;W7YKz~O~ zsM5o-<-rigsH_mmT8)^_45@>y71=a#F>ER#N44;4NT}gF=RoA$1)pH@+%Vo1QmS&E zo(mWw67hw_RI@W+a!@O+F3Lx!IuM4rXCbPVr7aIih35YJ(bFF;I+l$MW=lkzQAM2% z&GzPWp*Qe7pI4d*QO_%HIbI&~u^*ciIsWcvX5Q_h<)RTEWv?6V zS<16o*nYKc+;SmRXJi>=gKP+spb@S-XvkZ}V#>Ftu?NSv{0%1cE=U>=034sRs;ryB=2<$5g#AVp3y||BEO~2FS z*%(jBy`kKk^;EA?jmrFu52-pzersTav6Eo60oc-*X-DGNyh zdjt=eEGAITbbrVREHRLLFNRG{7qOR#lr+y4>J?EANTw7SriZg3T-u7#{EX-8t%-yI zG3K*g&zCUQoF!L=30~dTkRvp%wCq zQ=}2WIxa3D<3*o}(skJhX8VG#oKeg{D34_T)Tsd$oV5}-O(STat z#Y{8-EabhMzx=|)$UE@BLjJm26;)XfueM_4hA=2s{WjGkLo79mCc611yPVRwB~t1; z2{!x%0LE-w3~Epy8opOpDSsev?iaw#`tx(TWzV6Ul#i54h$X^f#q0cz8=x`GmWUta z9r5vfLMCcH3Pjay=I7h#RlwHnmh0dyz-vJr_wFqOzs8SwMxj}4@8>h(RUs^*a)JG* z+?w1~+{Yx7_a;q`p3Pt*6CXygnwPvYgXOPe9#U*9GJP|h#RI7+CNJ6*vwDC`Mw)9+ z_oU4m5DKyRyjm0F!1SHNuB3kC=JDo{bDQm<;oeL&6oHScJ^gFwa{m86;nGgT+N3%Lb-hz4Q6hX;I69QD@8Mw<4*6U}8NuO$L{0^PAafIm$F=TF5M{Xgl)jA3|joLckIDCa<+Q=Ywd$pT> z;;%Vl%s{}ZKn*--DF{I)U4p4|i1`TwgL!yH;IdG~K~nB-&_iKk;~l4Bl&SEL{Lltd z@LnMNqR0ZG_XXCQn@Xplcuon)1%uy1O1g+VBeizzSoUbVAqhBDF~OXWaQ#~0%a;xq zT94-rlfNZv9KQ%ri2rtH_gkUU*I$6RMg4ED(M{*WI&C8V0A`arX^><2 zwNjDBg(xmbI5zlXE8ys2FGrLY&Fe^7c_O73R7SHgtcHe{X!wP6n7Xl#w2bB+uhdW8PSVj_z7?h4 zHRBn)+0@+r+`Fszb;WPoO*72?Y!w#<$ckSQ_2u38#6NXwu(1l{fgJ!^_F}BVg<4A#3wilNkf?T(dA(%5M20_TiS{-%I;X3IAQB38{APcf2Vj(ZckzSZ;o8>TWtFnO%logqvY2PE5)dv?7rG}O-`cEC z2d{QF@pM$9+M?em8k2_X2W{paHBM#r!oE%dT_7gHeCO?1=Kro4x^&;OpOcS21%65S zcQX1r(tq-LDtxi74R!1d27WPieWxqmuRVGSl zR2F7&bK5&Pc>}(-J*HU3WZz4iJ{p%dkT525R~WRfM%gCizLLFNsIzuqVro z88(!;Xx+#B-lh@3&4xoK9SBi7myD(FdKJNSUm>~P;p?^YXTDg^Q*MsLu5@a;-;nD3 zq538biFb$0T{P?F5*jP<7;TQ3*u>z9bV5erG_YZd8Z~{oV=LFj zN3!q(+IjS70pK$RraQ`=u#U#f=ZczQWh=^T;~>*B3u>dvL0{LwvM33m&-x4_=|(gaJ1Y~)#SVJU zVsO)-Ocm#i?pd`o(~xO4-gW72-QQej?)gO9O4_iI)+rj$IILEAGg0ll_XM#BtRC6< z;A25_-bnHGOoTqY2f7`+M7qiAK9F*dCx=84D+Q9TWPd3`HL-H`Tye8O0D%w_M;+Tp z>2|RnIJdX`fiK?8(YXJiRhq$O`fq(dLR!D;v6TOj`d^9ArK3K7Mjd~GeR+2>q!^W{ zSY>v3pY!*0bANb@+6)aSNLrbWELn=YmVkI`BJ}F=U0yqU`*!OARX)7kK(Vw)-o2$! zyG-i7LXdvl(tER9xOYACwF~%CzH5e>;Lj)ut)vVg9e;-kOu`4U$xDlG&lH->Dcl=; z6vN!?${j5+dHM4Os)1lw`Dte)9U^r42GEiiaHl6Q{6H_&q)hJH8@p7ldv%7|xwN)j zffLFC5(>)$=~r|h^80?<6wbi~re>at8k<1a;>(nu>E?kU89(IE;42){Y!ROpxQnj_ zfBNz9Z0F|&8lAjhMBX*e@L6f zyz}a!`qs!a^;Y1YsQ?~JSKn;3J3*Aw6NfF+!$K9zHn=39`w~n-mZBn|%C}41Qd_IZxr?jVwp&^A|AwX!+XBwV^zO%DMHc zeF;0VtGoo>G!DH42wc$Cwwh?gHbRBiha@UpI?JgY-*_SI$_&^ezni?G>@=$qE%IX= z=_6P485>>Jae>u_O6jF{(vjj5^#qA^*ErtBn76`qabI5n2}t=XQI%wZT-V; z1P_Z4LL-gMEAbSMQjn42nX;|*7CclREyEk{JXsnbq zp7*TyhA0`=6y;PoAT&t3P1|H$zNTM0aow;EZbw+ywdZjpydQA0Nh!&b@RlnI6_X8V zmHS>3DHnXN%Ddr?RK1r(ekH=s1spqpYGUCCsnLaAz~Ki1a1?8yfC;TMJJH8-@8}#X z6;xolEv^;LdASpM;G1!C$R1OmcagRSThim9=U!FIS$aRg3GsZiLHPq)r$awKg;WM( z-Te4o`8-IIKEDiJ9uaTcFLb}!N~;ccpCXD{zBKThgG`0~MDs9N%M0q>R%#y%pW@Y( zJK{-?QC0S(IU^R2)r;n`Rr$s%^1>#EXrPU(+SX%|H9XP~2rTXcb0Hc(RgOr$6pK91 z6{gvA?+$rvdJIxq*6^DU($LxD^t|XKN6Hpr!!t{c;*@`YTlAMT)G%?O38g{Yw<(e- ziZ^gJx%r&yd<$3I*m7Jm#?GsuT~CLq`TFwI91MQHN|^83YG5h$Anl-m86r$ZAY7a^hCr3+2$P-0e^b9YR4b4mUYNNl4 z(&h->u~shz)npPe-#0(6U7vJ`t5TyBHRHLJ6Z$S$D`w>5Z;W1jk{blLMU{%iSDajp zmuNk!H)VY{iKl`#FoI5bGEWQ!0!dH%an2nm1}uKWit7#c%AP>ALV-csGclhBq2@;B zz{d3J#AFp5oJ=;{P0l6dJ2fNaPFB{G^YFu-C>zpD3x4;$o>;nk(dN#!)3ab6Tv{fA z42Oa5GpqqWZqpQcb*n1K-#EpTEnzXKcwGR8uAO97?IuVQnOq;rC}WH>Q2r_kRO{;$ zI`45bsbT6vrypNm(W?xej?o3YoG%rc(>5=+N1SMPsrnY2<3*GhwoZt2Nv+}0DM`D{ zgB$gKmchxs*6Z~+;iW-WPy^4RW;_(t6H1bR2z3uJKLr7#S}iC&-)?A|+Si9rvcBHa zQ;YJ}#ts5ypCF*8n{+m_K$%&W6NZO}JFO!Bm_mM!_|;HZbL`5;rZ^8xs~_Z;Pt6X; zTJ!ti1A@!Ky(K`!yCR7?+GyOH^MVnh@~<6#Tw_dr;mY&AHX@U*?`?ge|I7=0n&l6( zy)D~!O8|SHx0h{?u8spHlfOeIAqC(Lh3F}x*EI_VU%V!-_+0NW3~Cx7d@>E~#yPDC zb+-V#g1;T1szWbsM5={yvXV+~t{N4>wNJbw5{KyPyAh@xcW~^n?4uA8r)1A6!1qcJLudim6^_p9ETrss+ z!AHs4d%17DdN*6g^FqRA=kqrL4KdYaO%=}9gy$Qa8ElasEq3TP6ufl;r4*)|>0Ka! z?IUFaqE66m`iEw1JaZgAs&8MHc!42a?-Bv$1r z=IQ&)2Gf9?_1;^XrJShYxGJgOPrc7_&7LW-7bwQ09C!7AgvQ9M`zBMui2Rbs z)i%&zO!rwmqm9t_iM>V5pQZ9%ui`mt z;yHltkLgXCFqs!hioTMYEdCY}77+o;_wg5J&f_kt2$%!EuMmktDg=;R1iTT%J>h0i#=j| zsIv~LxPgomKfXbNtKkAs?ewXI=&I{B$Sq0jd5wq|smTFvi;NEJ+_M#L+0s+jx%GTo zCBZe`@;hpOz7o0+7l>`##C5IVL?y!9-nQgbq`9?-+7dSJc)fi;nZoDP`hYm1pQ=~=egWcRIxmr?s>*7z zLhh;DAg|58HcQhCu&nTEtX>i%|-0sy+eU}wz;$y^k^gF;cXw#f+; zA!YktLB52T+^f|lB`^+zF^_%MmQlCsYHqJbn8~m=?VC&Le*WZ^*m}^f_N6ubiuIdx zs`cr9#_3zXuX}$Llq~@-PWn}i;$8H=zoz&rx_=n;W0vae&#?8L;Ng}58Vl7KSg2X~ z6S{}}*}vT7{RQYfv8r_ZUXU*R;e}+ILyM%Enua`sX_e~6I;X*bv+=^kgPQ9o36vm8 z3o0zF*9ZuvKT56+^;o~9M*B^7`bNXSWdWM-;;nqj@rCn%joN$<82vOA+{4<4LDh9r)ztotPb^X1_ zP?~|=0s6f7)N+!Hl)KGT12+*0PiB{0rE&g4R{tAkM%s*?=e|?uH(b+SG9V7c?#~(b z2{(p4egRsnlRxTpK2(>RDyx4wX?~26jcGg0mUb1K{7u_s7+>)VP~dL<Xs?DqK|g9aS#MsE6FICJ5IH@=GG7j4PY*?0Q@n@<7C54kH^dw&6LYiu?vBIc~` z9t~+b#qHY6N`9U6c3#RjH}I90^ctz)OqW8fzN1> z($2!qpPN~eXQhWlHO4Xo=5iYhJK9y3-Z$3w_Eb(iT?OeW_v5iGp}_D4Lk=QdF4C++ z194`=gP%n{S|1Oy63a*n<}vxCGK{rRhVbq_gj=%dlcVQ5#xuVF&e@9l{61e4{`xlkpI!Bk+eiimT5a;Z5jIyyr5OT} z@FpylOR_&*;#9HFT#Rb?$W!5WTQ(Boi;1k`L2_==GyNoK0yDFou&IP;xrzS-#bEgK zGm#w=oJ6;R@a70eG;6MZ`r2KBtHSX}i*&Ul*wez5To%!WZl8eKi8&$Q~j!l6uow&=cTS zLg$0}$!v@Aum@YP%xluX)%BEBh;v5XXeD}~u>lC{u_br5+gkD^vuHDw4WSf=Q&S1PG)vS5!PL)1x99XhaK^vlva|LI- z(oXK6?Wg4utsVDEn$@4tHnY)uHHd^JG+M(UI@CLIDg>~XliIh5(%l`JilXLNd_%6H zlksa8jTzL`+b0=Wh@CW}s;Fj?Tobr(VXTTE*n2xQa;9`5>3L~x+lwc8YC|63F#SG= z$h=D)91*^%glj_dk_~yx_fVZjk(kPciiW89&6WhCs9jZ}iLK^{6kX?j6$8HD=Np~} z#b)GNO7$R*8vVePl7*a;lM4^cZiT6Fsz)Y=d5*`r);M77MFvdHOQ&1TTJ z+K-GD$5j#s4JAZ_D;&Zu3pe1N7mZ(-S7xJDPX`(H5dC1DC${6d+c|D(LtyC;h*&?Z z$%1w%rO7*MPAPF-EpJ)AJe)LObMvcoc2f*OSuc{c?BH956kZ#zy`Ye|xyAO)RRXmA zK1ZZ#Nz6wEAQW#0SFgCTF}QKPQbY~yDsQsVNTs&02Y&JeB7i^-fvjP`%L;_k-jb6l(ESma44^saK+NR`eS;^OA7$ zHaLo63rFQydV=;YAhUcTJ7{4;+T2F-*#owbmPGCFQtV*=aH0&MLHtc{hESwq$s`57 z^I4d@aH~EX3!Juz1!kSq^yqxk0BjH+knD3P5NEE)!W5bfXR#^jpR7);6Z+q(HdE3} zE@z~N7+BfsMxHlU@ZE7=qTKcmWeQ~;NLUIh$-fO^{0x7}d+TJZ1Xdp42YcJE^9`NS{K0|a&+q>sc$Fra0@9@@b^4mW7 ztTF|@@2y0hv3UmTPIsJpV#p*6>iBZrBJ9??$s%E)pvvNq>mu@COgE`w~YzTew9T-#;O+;+p` zrIfO<^YEmZM=Ij^I?R9+w9gTfm|^=!?UI|@3p#UfmewxP+5{DV<7+d`f|Mkr?(Q7+Kjz&8Wuy4fU2F2$I@p+{Q}gD@P1`!`p#<)`d#V& z8vf}P&Cl#(@A9j;9aR<;4^Nl*fm|}LsnT=K3h)Efkl{R^_gBDk5V6x_?7MU^TDiy> zG+z2Gp(Xuh$C3V5jQs#i)(Kv#8bYsCvY24Lp(VZkQpsof^`KVe=}6lE>Chu_SdFpU zv%t^uH#YByLP(|O1N>UKIqrqcbtyNDbTbHC*2-S>3S0M-F>O%reXq=oCwhah%54vY z*r0H1jI9kBBdtFK;1sw9-xEE|$##z++<>VR_BzPZo4a`p#EU_?jm&?OSa~`WWDwve z-2EDyR;$HpN-`M69kRzqW{AA@OGMeiDe{$DBk9c{iB`A`H+Z~aTR)wJ9d2SFY*_A1 zK<4_Sc*l)fKH4H2&Z*0fI66{0kdpIDY0R^pCf|+u&FF>opOpRsd zfA+vq9te9t6WtsUqd0#Pr~<(id{@Eu?R zztqvPzrJoYy=|&=AMIQ695{W!&y*EBG4{?NxB8Jb$Ks$BcT@d2fG+A0=W4 zu%$yW(;*0m<{JyFuJdbDIe3uSJrB*RCSXBtBUizWV#Vy-EKq{{l(;E0ImUun3)w|y z=nVKio_lk`H;~tJmcKG?tlDM1H=De1+?)hoRG4rnIi3z}4GkhKXDnLSveC&zlOGhd zZs}dWnX+78BIP=5&}KS@gXe|l^YD9tnw#p{y@)+NY)~LK^{#kV(Pq*M&<%&fhxeyL zqYooKpUat7Ze9Z$9k|RU%XISnws59q=d7vnO}-7#+*Jd<07RQ9nNM;{^MT7A=Uj8Q zp8W|_?jGD%x;LylR-cS*0d4j2cEhEaiG(i zzpg1wFrLK{u@ymQV5WDN^ko&M;N~2!<)Uin!djZYSG%3Q;Zr2fk1J`)jsfLWOqi#7 zymhP^G^?uf2+t#mImL2Bg&jHCI+yMB<)B4|LFbTS8QtikdWRwdQ_2HQQ$N846%SMk zd_IMo61L6E(&*l!Z2lQw;WDoD;EE}mA8_3Q#`9ovggmf{fE%kzyZ{tm^GYeKvyU`dWgzPa`j);4h8uDqm9 zR=yi#3I^1X_aIyme!ZlO51&#Lq>9empHD!d9yxeR`Q71$2?wOKTkeJ2GWht~K!4m; zp)gvsw(&!S)R_!n5z6ZhIK;c5L&qs>xlFoO$H|p+s_o+a6Z8cN30>ih(m}m1n?cFu z!HB|xgIoj70h7Ol!9U-U<0=R>T+ikan{H3FraiG2A@t^vc!JAa21hl(zuNJ?e2Tey z+|~TO(Ek@8`kkOd{W@T!&b(NvfCqEGmkcWp#3>ez$Dk#_eM{Fa zbg+M{Zy|-}oF9k`HhML>Hg@ExE=secepWR{clO!$Ovb41(z{-QE?xWf0)LXOWwXb& zG8l1xDZVRaV6IO4qOA3l;^kh1w9nHj?_C6(8T5g}IvpF&zDh&>F1Ffc!jW8kbL5{MovtD%?>8(hJh7k*rErD_Te@(dm z1wH)#r2pL#pp!P__NDNZxM-3C#t6NrtGX#8VP;BmabP%CG@%Y|md+*O+)q3B`+%cc z9_4@i`KF&dn7(V~J|b8mhcJf~ z5RZpcn#ihd_ky3Wd(}Yv~V$@4GbL$A3PKxDWV=Jh_B;p&I${ z#0To>+q_Qo?1yiBM&AjQ$-UU)zCFcn&a2V41xcD28Jhb3_3Bdl-G#whz=!`zBsikJ zuK3>f{93^Q@26(QPe#YgU+3u`+HKvX!nBael>Esmp6^UQroNUDNr=9VkaJ>^wg||V zQJhj)BVhOGzkSsI{CU%A>1XWJwO@cIFxaeFniW1Muzao#70dRLu+q{BzcZ9pkXaXb zocm`@jFL-lcjn>?Hs0d6@C^1P(?s(ws;1@(4`AmOD}g z%Ns{;6xW~NAGpA{=I0mvAG@->bi%y7$_|Uz9bcj08+|@0<4dR@XXn>S^&jpGEyx*G z3sob~Kb8_WVhU^n?Wtgbp2>H!EKiolm4}RzBf^0Z25E!k(L#>aH=-KAWE?gt<1M#6 z?F)me=H~8D=r=^*f_6tN@V(im>$6Jx#c5JdtM#3RPm-GP(tM*uoh@_vbb14mJX!R_ zq}Bcl<_enE-R2x+Q`6a`ONG}$JUmxEWm2S^O;i(SzHVR zHnu3ohmSCqxqr9QB_FX9U+k-|vHo>u`!`wsr=I@|nzw4J^`p%<`G@vTyT}t<2ECC5 z@@$&{OuGzOC2VPcckw?p-|uaJoOnI&qQ;xX43P^6&t2}jz=~amW=6Qyd1+;@5gJ7ye*#)~tMVcqz z?cq`vgOMlZ^|Xe9rKfh4J(gUW^on^WX}c(Guy-RYHSmNNU$ zqo7DLx2`WoC)@TS_LZF{5)=Z=BaI@8a3~K$j`%jYdUa*wHZenHO_~0TbIF@;-n$E)*oW$S`bSwAN(vS7&I_ZB zHD2eM7#hA@Wcn?NaMQb7q%3t{_Buow!x7C>hq1Nm0uQID0X!x>@-*4?;RPDW$ooDI zk&s5MxKuRC$x7gx?1Iz&1?1x&`I199r#`_UG~cN6)7DAfp%&Odp<7w*Mx&y(u9bLY zPQ31I@Y*kcR6@n|vbot9+rb_Yem;gOf|G|5%S%ktobz_eG?(U{fOI*K%W@f1YSN(U zS5^y(eKt)0u**R8eMbHpy9aKJG1>QDU%m0P{ou`cX1NdfcA>XJHl7ObAm6IBA3gds ze#;@J>xs)!$BJ(C3RKg>ly$P~11~IzO`rVuF3b*YvOR+R_&G9c7`~s>zLagoNzSzb}al{zui)z90slE%6bXno$fb+k8Li zb1c%|#I_i611O=HWt&TU;=@rYv74wI_jP8wQ~p0=MEJuBK=bY*3h9b@8Xi>KZC?-9d) zlXU+-QLQt&i*l(h3p-JfuF{1LJo8|GX>CLgY{EtfvYE39@;Y%LxTz@(u)YNV=)NA$ zj_3_QoMmcG6MHGE1Yfx}S98rJIEzFjyX%S#T;sMXBPKQGI&uW%-V1F;cwG@qJg$G9 z(%;h7!{xlRmyC>jV}TxfQk`a1&a+&V`5BsVntIJs?d#H~QN=W&`LztCA^u2(j%p+o zQd~}Tg5N8I%*+2)!W*+~mgT(S&?VpW`3WWW9D`svj}hJ=Z6Za*Ae+y<=jW5r5Kz08 zVd0^3Pj@p!$V7_ImqOQL_hhU=~ADMWn1w}Rj2q?=q(*tdD zt?Xm(=LP;A0@-{ln9Shk5-bw+i&ZS8%W{zS_6Ss;J=2M=L2l5=-!H(t`7gi(V2?fN z?VjMbCohg81%yy@KTmc!D9c{}W4dlb)rZ{=cO_4pb^yWXKA$hiKYH%|xWy4JVcO%R zSaT>-ANxvwT%OA)bL)5o`!HQts4m~@8y;rysdxw#wA(Qex zOfgFtgg37*_%O)rCgy~+ZAcU5vp(v0wtVc9xc32&{-4@n`~xDI^T-Mb_wD6rLuKhU z@e_cU3SWa3Q0@7gn{BsTSrrkshOt-@5WO2_6$QG;E>6(Ro5Dc(;#g*VaE&6ed^0t; zEhbZ+=DhI=jSFcgP?e5OSad(FVbdLCJm<9-k>+u-lO(S`EKyW=?%qoSZ)auGT51r z@ap>s|9=ZorN3*vIR}Lta5k7%TD^XO-PVDc5xSh854(yGp{Pb+*&a+(ODoCvQjNS_ z8KEdv^o|j ziA!D(k`*32r+Q0Gk`3L&{r%ALq#4nbm zfdWPG;r7c5GD5{5EU-CVq+EFAo4eO^X5bOZ#J&#M%@&WXrO+L!T_eI>Y9)JL*>Z;~ zQKGi0fX$nAAx8ZONo2{wNLH|LaD%gqQ2--RP5v=BDbRB(RKl;cV?M*%Y?*mPg91h9 ztj{`^T+pKUd3qqZmq~jx?Yjv{7L_xWGb80t8)x*jLSkZfOfmN^d`WG*LPx`-lneJ5 zJX5T8nm+2}8yF>*KkP0au4U|Xp14IY>0TfqH$8R);2xJqgqmk5Kib$ZLkVfnN8h}N z1~-0`z6M=l75R9hW9_oKJnk`C%*b@i*iwku(<2yO5N}gdEm~aoV|iDugyU68RY@fR zY@wEOOPecm^4Nu|>2b+Yb?5esM0P|NTHNpUaA1B?^Zs4T+7GhR94rnsDR^z)Wi1sj zRk@USl-@*8$@(Ny!EPY*$lve5S#5sY94rN!IAp>_g>P~tMeNyrM}6s~RZ%<*)EaBG zUY{(;2E6F}RF0+$;V2tWU57Pjb%#_ziFJ^H=gHoE7r5-=`)PuxGj(DW*BRqr3cH z>?^eB-osh3nDH@$gHX9A+B`MqSqzmDUXGid%+KOyb!XNRV zv_>(u`Irgv2tyGZqLuF1{X6uLl%Gz`6HPB69KY1buYAlSU{{v;lb;{k6!W>V_`}Vs zy$i(xw!{@0smXTJ56ps&`iIXLE%uDs<-*ajQ=R;Xo|_-XjznG~0D(Rn-@0^X(r$Rt z{2xy$=S|AEAhR{vF}jK6xtcKkRWBSlKzE90%W0HTrsuUXwC3nwiX$7*Sx#}swB5?!wfOFzx=QqJ%u zNJ+xApCk-3y#2pk1OK}ni%wdP529aU4nE3SN2A29lpt5-sB^;7|6?zmyEd0<1TIh1 VxUk0d@e`y4N2qz0Y#!tPn*gJ5&vF0& literal 16976 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 diff --git a/iterator.textile b/iterator.textile index bd8bc26..51f8b48 100644 --- a/iterator.textile +++ b/iterator.textile @@ -143,15 +143,7 @@ the existence of a block does not mean the block is pushed for that method. It's possible that the block is pushed for the previous method. (Figure 1) -
-(stacks)
-Figure 1: no one-to-one correspondence between `FRAME` and `BLOCK` -* 上が先端 the end is above -* FRAMEに対応するBLOCKがあるか? Is there any BLOCK that corresponds to FRAME ? -* ある(けどイテレータではない) Yes. (But, this is not an iterator.) -* ある(本当にイテレータ) Yes. (this is actually an iterator.) -* ない No. -
+!images/ch_iterator_stacks.jpg(no one-to-one correspondence between `FRAME` and `BLOCK`)! So, in order to determine for which method the block is pushed, `ITER` is used. @@ -289,13 +281,7 @@ At this moment, a method finally "becomes" an iterator. Figure 2 shows the state of the stacks. -
-(itertrans)
-Figure 2: the state of the Ruby stacks on an iterator call. -* 上が先端 the end is above -* イテレータか?(FRAMEに対応するITERがITER_CURか?) - Is this an iterator? (Is the ITER corresponds to FRAME ITER_CUR ?) -
+!images/ch_iterator_itertrans.jpg(the state of the Ruby stacks on an iterator call.)! The possible value of `ruby_iter` is not the one of two boolean values @@ -508,11 +494,7 @@ but a new `FRAME` is created by duplicating. This would look like Figure 3. -
-(framepush)
-Figure 3: push a copied frame -* コピーして作る creating by copying -
+!images/ch_iterator_framepush.jpg(push a copied frame)! As we've seen the code until here, @@ -671,14 +653,7 @@ If we focus on there, we can see a link is always pushed in at the "next" to `ruby_dyna_vars`. This means, it would look like Figure 4. -
-(dynavarseval)
-Figure 4: the structure of `ruby_dyna_vars` -* ブロック起動時に(rb_yield_0で)追加 added (by using `rb_yield_0`) when invoking a block -* ブロック起動直後 immediately after invoking a block -* ブロック変数を追加 add block variables -* 追加された変数 added variables -
+!images/ch_iterator_dynavarseval.jpg(the structure of `ruby_dyna_vars`)! This differs from the case of the parser in one point: @@ -690,11 +665,7 @@ a single straight link. But according to the errata, it was wrong. That part and relevant descriptions are removed.)) -
-(insert)
-Figure 5: cannot properly insert an entry -* ここに挿入しないといけない must be inserted here -
+!images/ch_iterator_insert.jpg(The entry cannot be inserted properly.)! @@ -804,11 +775,7 @@ Therefore, if `0x10` did not exist, `state` would be the same value as `TAG_xxxx (See also Figure 6). -
-(dst)
-Fig.6: block->tag->dst -* 常に1 always 1 -
+!images/ch_iterator_dst.jpg(`block->tag->dst`)! Now, `tag->dst` became the value which differs from `TAG_xxxx` and is unique for each call. @@ -1108,10 +1075,7 @@ In this way, one by one, the flag is propagated at the time when it pops. (Figure 7) -

-(flaginfect)
-Figure 7: flag propagation -

+!images/ch_iterator_dst.jpg(flag propagation)! Since `VARS` also does not have any `prev` pointer, From 18cb99d77850c6e884ea56b83ddafd566b1b480e Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 25 Sep 2013 06:13:54 +0900 Subject: [PATCH 073/121] edit chapter 08 --- spec.textile | 725 ++++++++++++++++++++++++++++----------------------- 1 file changed, 397 insertions(+), 328 deletions(-) diff --git a/spec.textile b/spec.textile index fe425f6..22ce53f 100644 --- a/spec.textile +++ b/spec.textile @@ -16,37 +16,43 @@ Readers who know Ruby can skip over this chapter. h2. Literals The expressiveness of Ruby's literals is extremely high. -What distinguishes Ruby as a scripting language +In my opinion, what makes Ruby a script language is firstly the existence of -the toplevel, secondly it's the expressiveness of its literals in my -opinion. Thirdly it might be the richness of its standard library. +the toplevel, secondly it's the expressiveness of its literals. +Thirdly it might be the richness of its standard library. -The literals have already as elements enormous power, but even more -when combined. Especially that one can create complex literals from -hash and array literals is a great advantage of Ruby. One can simply -write down a hash of arrays of regular expressions for instance. +A single literal already has enormous power, but even more +when multiple literals are combined. +Especially the ability of creating complex literals that hash and array literals +are combined is the biggest advantage of Ruby's literal. +One can write, for instance, a hash of arrays of regular expressions +by constructing straightforwardly. -Let's look at the valid expressions one by one. +What kind of expressions are valid? +Let's look at them one by one. h3. Strings Strings and regular expressions can't be missing in a scripting language. -There is a great variety of string literals. +The expressiveness of Ruby's string is very various even more than the +other Ruby's literals. h4. Single Quoted Strings
 'string'              # 「string」
 '\\begin{document}'   # 「\begin{document}」
-'\n'                  # 「\n」backslash and an n, no newline
+'\n'                  # 「\n」backslash and an n, not a newline
 '\1'                  # 「\1」backslash and 1
 '\''                  # 「'」
 
-This is the simplest form. In C everything enclosed in single quotes becomes a -string, it's the same in Ruby. Let's call this a `'`-string. The backslash escape +This is the simplest form. +In C, what enclosed in single quotes becomes a character, +but in Ruby, it becomes a string. +Let's call this a `'`-string. The backslash escape is in effect only for `\` itself and `'`. If one puts a backslash -in front of another character the backslash remains as for example +in front of another character the backslash remains as in the fourth example. And Ruby's strings aren't divided by newline characters. @@ -59,10 +65,9 @@ in the string. string' -And if the `-K` option is given to the `ruby` command multibyte strings +And if the `-K` option is given to the `ruby` command, multibyte strings will be accepted. At present the three encodings EUC-JP (`-Ke`), -Shift JIS (`-Ks`), and UTF8 (`-Ku`) can be specified. (Translator's note: -`-K` option was removed in Ruby 1.9) +Shift JIS (`-Ks`), and UTF8 (`-Ku`) can be specified.
 '「漢字が通る」と「マルチバイト文字が通る」はちょっと違う'
@@ -79,17 +84,20 @@ h4. Double Quoted Strings
 
With double quotes we can use command expansion and backslash notation. -The backslash notation is classical, it was already supported in C, -`\n` is a newline, `\b` is a backspace, this kind of notation. -In Ruby also `Ctrl-C` and ESC can be expressed, that's convenient. -It's probably of no use to list the whole notation here. +The backslash notation is something classical that is also supported in C, +for instance, `\n` is a newline, `\b` is a backspace. +In Ruby, `Ctrl-C` and ESC can also be expressed, that's convenient. +However, merely listing the whole notation is not fun, +regarding its implementation, it just means a large number of cases to be +handled and there's nothing especially interesting. +Therefore, they are entirely left out here. On the other hand, expression expansion is even more fantastic. We can write an arbitrary Ruby expression inside `#{ }` and it will be evaluated at runtime and embedded into the string. There are no limitations like only one variable or only one method. -This is not a mere literal anymore but a whole expression representing -a string. +Getting this far, it is not a mere literal anymore but +the entire thing can be considered as an expression to express a string.
 "embedded #{lvar} expression"
@@ -109,15 +117,19 @@ h4. Strings with `%`
 
 If a lot of separator characters appear in a string, escaping all of them
 becomes a burden. In that case the separator characters can be
-changed. The string which contains the one character `"` can be
-written with a `%` string as follows:
+changed by using `%`.
+In the following example, the same string is written as a `"`-string and
+`%`-string.
 
 
 ""
-%Q(")
+%Q()
 
-The expression isn't shorter, but nicer to look at. -When we have to escape more often, it even becomes more concise. + +The both expressions has the same length, +but the `%`-one is a lot nicer to look at. +When we have more characters to escape in it, +`%`-string would also have advantage in length. Here we have used parentheses as delimiters, but something else is fine, too. Like brackets or braces or `#`. Almost every symbol is fine, even @@ -131,12 +143,16 @@ too. Like brackets or braces or `#`. Almost every symbol is fine, even h4. Here Documents -Here documents are a syntactical device where one or more lines can -form a string. A normal string starts right after the delimiter `"` -and takes everything until the ending `"`. Here documents start -at the line after a `< +"the characters between the starting symbol and the ending symbol +will become a string." < + Here we used `EOS` as identifier but any word is fine. -Precisely speaking all the character matching `[a-zA-Z_0-9]` can be used. +Precisely speaking, all the character matching `[a-zA-Z_0-9]` and multi-byte +characters can be used. -The characteristic of a here document is that every line between -the start symbol and the ending symbol will form a string. The line -which contains the start symbol delimits the string. -That's why the position of the start symbol is not important. -It can even be in the middle of an expression: +The characteristic of here document is that the delimiters are +"the lines containing the starting identifier or the ending identifier". +The line which contains the start symbol is the starting delimiter. +Therefore, the position of the start identifier in the line is not important. +Taking advantage of this, it doesn't matter that, +for instance, it is written in the middle of an expression:
 printf(<
 
-The start symbol can be somewhere in the line, but there are strict
+The position of the starting identifier is really not restricted,
+but on the contrary, there are strict
 rules for the ending symbol: It must be at the beginning of the line
 and there must not be another letter in that line. However
 if we write the start symbol with a minus like this `<<-EOS` we
@@ -176,16 +196,15 @@ can indent the line with the end symbol.
      <<-EOS
 It would be convenient if one could indent the content
 of a here document. But that's not possible.
-If you want that, the best way is to write
-a method which delete the indent. But beware
-of tabs.
+If you want that, writing a method to delete indents is
+usually a way to go. But beware of tabs.
      EOS
 
Furthermore, the start symbol can be enclosed in single or double quotes. Then the properties of the whole here document change. -When we change `< <<"EOS" @@ -199,29 +218,22 @@ the complete literal mode. Everything even backslashes go into the string as they are typed. This is useful for a string which contains many backslashes. -In the second part we also explain how a here document is passed. -But I'd like you to guess it before. -(Translators Note: In Ruby 1.8 and 1.9 expression expansion and -backslash notation can be used in a normal here document. -There does not seem to be a difference anymore to a double quote enclosed -here document.) +In Part 2, I'll explain how to parse a here document. +But I'd like you to try to guess it before. h3. Characters -Ruby strings are byte strings, there are no character objects. +Ruby strings are byte sequences, there are no character objects. Instead there are the following expressions which return the integers which correspond a certain character in ASCII code.
-?a                    # the integer which corresponds to 「a」
-?.                    # the integer which corresponds to 「.」
+?a                    # the integer which corresponds to "a"
+?.                    # the integer which corresponds to "."
 ?\n                   # LF
 ?\C-a                 # Ctrl-a
 
-(Translator's note: Strings in Ruby 1.9 are not byte strings anymore, -they have an attached encoding. `?a` returns the string `"a"` in Ruby1.9) - h3. Regular Expressions
@@ -251,45 +263,49 @@ One can designate more special patterns.
 
This matches a string where there's a `From` followed by a `:` at -the beginning. There are several more expressions of this kind, +the beginning of a line. There are several more expressions of this kind, such that one can create quite complex patterns. The uses are infinite: Changing the matched part to another string, deleting the matched part, -determining if there's one match and and and... - -A more concrete use case would be extracting the `From:` header -from a mail. Then changing the `\n` to an `\r` and -checking if the rest looks like a mail address. - -The regular expressions form an independent language, it has -it's own parser and evaluator within ruby. It can be found in `regex.c` -in the Ruby source. In effect from a grammar view point they are -treated the same as strings. Escapes, backslash notation and command -embedding can be used almost the same as in strings. - -Of course regular expressions and strings are treated the same -in the Ruby syntax only. Regular expressions themselves are a language -of their own with own rules which have to be obeyed. This is a subject -of a whole other book. We won't go deeper into that here. -Refer for instance to Jeffrey Friedl, Regular expressions. +determining if there's one match and so on... + +A more concrete use case would be, for instance, extracting the `From:` header +from a mail, or changing the `\n` to an `\r`, +or checking if a string looks like a mail address. + +Since the regular expression itself is an independent language, it has +its own parser and evaluator which are different from `ruby`. +They can be found in `regex.c`. +Hence, it's enough for `ruby` to be able to cut out the regular expression part +from a Ruby program and feed it. As a consequence, they are treated almost the +same as strings from the grammatical point of view. +Almost all of the features which strings have like escapes, backslash notations +and embedded expressions can be used in the same way in regular expressions. + +However, we can say they are treated as the same as strings only when we are in +the viewpoint of "Ruby's syntax". As mentioned before, since regular expression +itself is a language, naturally we have to follow its language constraints. +To describe regular expression in detail, it's so large that one more can be +written, so I'd like you to read another book for this subject. +I recommend "Mastering Regular Expression" by Jeffrey E.F. Friedl. h4. Regular Expressions with `%` Also as with strings, regular expressions also have a syntax for changing -delimiters. In this case it is `%r`. Here just some examples. +delimiters. In this case it is `%r`. To understand this, looking at some +examples are enough to understand.
 %r(regexp)
 %r[/\*.*?\*/]            # matches a C comment
 %r("(?:[^"\\]+|\\.)*")   # matches a string in C
-%r{reg#{1 + 1}exp}       # imbedding a Ruby expression
+%r{reg#{1 + 1}exp}       # embedding a Ruby expression
 
h3. Arrays -An array literal is contained in brackets `[]`, elements are separated -by commas. +A comma-separated list enclosed in brackets `[]` is an array literal.
 [1, 2, 3]
@@ -302,15 +318,15 @@ lvar = $gvar = @ivar = @@cvar = nil
 [Object.new(), Object.new(), Object.new()]
 
-Ruby's arrays are a list of arbitrary objects. From a syntactical -standpoint it's characteristic is, that -the elements can be arbitrary expressions. As mentioned earlier, +Ruby's array (`Array`) is a list of arbitrary objects. From a syntactical +standpoint, it's characteristic is that arbitrary expressions can be elements. +As mentioned earlier, an array of hashes of regular expressions can easily be made. -Not just literals but also variables or method calls can also be -put together. +Not just literals but also expressions which variables or method calls combined +together can also be written straightforwardly. -And as with the other literals note that this is really an "expression -which generates an array object" +Note that this is "an expression which generates an array object" as with the +other literals.
 i = 0
@@ -333,8 +349,8 @@ That is `%w`. With an example it's immediately obvious.
     Jul Aug Sep Oct Nov Dec )
 
-There's also `%W` where command embedding can be used. -It's a relatively recent implementation. +There's also `%W` where expressions can be embedded. +It's a feature implemented fairly recently.
 n = 5
@@ -342,12 +358,13 @@ n = 5
 %W( list0 list#{n} )   # ['list0', 'list5']
 
-The author hasn't come up with a good use yet. +The author hasn't come up with a good use of `%W` yet. h3. Hashes Hash tables are data structure which store a one-to-one relation between -arbitrary objects. The following expressions generate a table. +arbitrary objects. +By writing as follows, they will be expressions to generate tables.
 { 'key' => 'value', 'key2' => 'value2' }
@@ -365,7 +382,8 @@ Nametables". They are fast lookup tables which allocate memory slots depending
 on the hash values. In Ruby grammar,
 both keys and values can be arbitrary expressions.
 
-Furthermore inside the argument of a method call the `{...}` can be omitted.
+Furthermore, when used as an argument of a method call,
+the `{...}` can be omitted under a certain condition.
 
 
 
@@ -373,15 +391,15 @@ Furthermore inside the argument of a method call the `{...}` can be omitted.
 # some_method(arg, {key => value, key2 => value2}) # same as above
 
-With this we can imitate named arguments. +With this we can imitate named (keyword) arguments.
 button.set_geometry('x' => 80, 'y' => '240')
 
Of course in this case `set_geometry` must accept a hash as input. -Real keyword arguments will be transformed into parameter variables, though. -With a passed hash it is not quite the real thing. +Though real keyword arguments will be transformed into parameter variables, +it's not the case for this because this is just a "imitation". h3. Ranges @@ -397,25 +415,29 @@ Here are some expressions which generate Range objects. If there are two dots the last element is included. If there are three dots it is not included. Not only integers but also floats -and strings can be made into ranges, even arbitrary objects can -be used in ranges. Syntactically arbitrary expressions can be -used as delimiters of a range object. If the returned object cannot -be made into a range there will be a runtime error. +and strings can be made into ranges, even a range between arbitrary objects can +be created if you'd attempt. +However, this is a specification of `Range` class, which is the class of range +objects, (it means a library), this is not a matter of grammar. +From the parser's standpoint, +it just enables to concatenate arbitrary expressions with `..`. +If a range cannot be generated with the objects as the evaluated results, +it would be a runtime error. -Besides, the precedence of `..` and `...` is quite low. Here's a surprising -interpretation. +By the way, because the precedence of `..` and `...` is quite low, +sometimes it is interpreted in a surprising way.
 1..5.to_a()   # 1..(5.to_a())
 
-I thinks the Ruby grammar is really intuitive, -but I do not like this. +I think my personality is relatively bent for Ruby grammar, +but somehow I don't like only this specification. h3. Symbols -In the first part we talked about symbols at length. -They are something which corresponds one-to-one to strings. +In Part 1, we talked about symbols at length. +It's something corresponds one-to-one to an arbitrary string. In Ruby symbols are expressed with a `:` in front.
@@ -423,8 +445,9 @@ In Ruby symbols are expressed with a `:` in front.
 :abcde
 
-These are pretty standard examples. But all symbol and method -names become symbols with a `:` in front. Like this: +These examples are pretty normal. +Actually, besides them, all variable names and method names +can become symbols with a `:` in front. Like this:
 :$gvar
@@ -433,8 +456,9 @@ names become symbols with a `:` in front. Like this:
 :CONST
 
-We haven't shown any method names so far. Of course `[]` or `attr=` -can be used as symbols too. +Moreover, though we haven't talked this yet, +`[]` or `attr=` can be used as method names, +so naturally they can also be used as symbols.
 :[]
@@ -446,14 +470,18 @@ complicated.
 
 h3. Numerical Values
 
-This is the least interesting. It might be added that
+This is the least interesting.
+One possible thing I can introduce here is that,
+when writing a million,
 
 
 1_000_000
 
-becomes one million and that underscores can be used inside a number. -But that isn't particularly interesting. This is it about numerical -values in this book. We'll completely forget them from here on. + +as written above, we can use underscore delimiters in the middle. +But even this isn't particularly interesting. +From here on in this book, +we'll completely forget about numerical values. h2. Methods @@ -484,9 +512,9 @@ C.new().some_method(0) h3. The Return Value of Methods -The return value of a method is the value of a `return` statement -if it runs across one. -If there is none it's the value of the last statement. +The return value of a method is, +if a `return` is executed in the middle, its value. +Otherwise, it's the value of the statement which was executed last.
 def one()     # 1 is returned
@@ -508,15 +536,16 @@ def three()   # 3 is returned
 end
 
-If the method body is empty `nil` is returned +If the method body is empty, +it would automatically be `nil`, and an expression without a value cannot put at the end. Hence every method has a return value. h3. Optional Arguments Optional arguments can also be defined. If the number of arguments -doesn't suffice the parameters are automatically assigned to a -default value. +doesn't suffice, the parameters are automatically assigned to +default values.
 def some_method( arg = 9 )  # default value is 9
@@ -528,9 +557,9 @@ some_method()     # The default value 9 is shown.
 
There can also be several optional arguments. -But in that case they must all come at the end. It is not -possible to make an argument in the middle optional. -It would be unclear how this should be made sense of. +But in that case they must all come at the end of the argument list. +If elements in the middle of the list were optional, +how the correspondences of the arguments would be very unclear.
 def right_decl( arg1, arg2, darg1 = nil, darg2 = nil )
@@ -543,19 +572,19 @@ def wrong_decl( arg, default = nil, arg2 )  # A middle argument cannot be option
 end
 
-h3. Omitting argument parantheses +h3. Omitting argument parentheses -The parentheses from a method call can be omitted. +In fact, the parentheses of a method call can be omitted.
 puts 'Hello, World!'   # puts("Hello, World")
 obj = Object.new       # obj = Object.new()
 
-In Python leaving out parentheses gets the method object, but -there is no such thing in Ruby. +In Python we can get the method object by leaving out parentheses, +but there is no such thing in Ruby. -We can also omit parentheses within the arguments itself. +If you'd like to, you can omit more parentheses.
   puts(File.basename fname)
@@ -569,25 +598,29 @@ If we like we can even leave out more
 # puts(File.basename(fname))  same as the above
 
-In Ruby 2.0 such an expression will probably not pass anymore. +However, recently this kind of "nested omissions" became a cause of warnings. +It's likely that this will not pass anymore in Ruby 2.0. -Actually let's also leave out the parentheses in the definition +Actually even the parentheses of the parameters definition can also be omitted.
 def some_method param1, param2, param3
 end
 
-def other_method    # without arguments we see this a lot
+def other_method    # without arguments ... we see this a lot
 end
 
Parentheses are often left out in method calls, but leaving out parentheses in the definition is not very popular. -Only if there are no arguments the parentheses are frequently omitted. +However if there are no arguments, the parentheses are frequently omitted. h3. Arguments and Lists -Arguments form a list of objects. If we want to use the elements of a list as arguments we can do this as follows: +Because Arguments form a list of objects, +there's nothing odd if we can do something converse: extracting a list (an +array) as arguments, +as the following example.
 def delegate(a, b, c)
@@ -599,7 +632,7 @@ delegate(*list)   # identical to delegate(1, 2, 3)
 
In this way we can distribute an array into arguments. -We call this device a `*`argument. Here we used a local variable +Let's call this device a `*`argument now. Here we used a local variable for demonstration, but of course there is no limitation. We can also directly put a literal or a method call instead. @@ -610,6 +643,8 @@ m(*mcall()) The @*@ argument can be used together with ordinary arguments, but the @*@ argument must come last. +Otherwise, the correspondences to parameter variables cannot be determined in a +single way. In the definition on the other hand we can handle the arguments in bulk when we put a `*` in front of the parameter variable. @@ -654,10 +689,8 @@ delegate(10, 20, 30) # same as other_method(10, 20, 30) h3. Various Method Call Expressions -There is only one mechanism for 'method call', but there still -can be several representations of the same mechanism. This is -colloquially called syntactic sugar. - +Being just a single feature as 'method call' does not mean its representation +is also single. Here is about so-called syntactic sugar. In Ruby there is a ton of it, and they are really attractive for a person who has a fetish for parsers. For instance the examples below are all method calls. @@ -673,7 +706,7 @@ obj[k] = v # obj.[]=(k,v)
It's hard to believe until you get used to it, but `attr=`, `[]=`, `\`` -are all names of methods. They can appear as names in a method definition +are (indeed) all method names. They can appear as names in a method definition and can also be used as symbols.
@@ -688,9 +721,9 @@ p(:[]=)
 p(:`)
 
-There are people who don't like sweets and there are people who -hate syntactic sugar. Maybe because one cannot tell by the looks -that it's really the same thing. It feels like a deception. +As there are people who don't like sweets, there are also many people who +dislike syntactic sugar. Maybe they feel unfair when the things which are +essentially the same appear in faked looks. (Why's everyone so serious?) Let's see some more details. @@ -705,9 +738,9 @@ obj.name! First a small thing. It's just appending a `?` or a `!`. Call and Definition do not differ, so it's not too painful. There are convention for what to use these method names, but there is no enforcement on language level. -It's just a convention. -These method names are probably an influence from Lisp which has a great variety -of function names. +It's just a convention at human level. +This is probably influenced from Lisp in which a great variety +of characters can be used in procedure names. h4. Binary Operators @@ -744,7 +777,7 @@ h4. Unary Operators
These are the unary operators. There are only three of them: `+ - ~`. -`+` and `-` work as one would imagine ( in the default setting). +`+` and `-` work as they look like (by default). The operator `~` matches a string or a regular expression with the variable `$_`. With an integer it stands for bit conversion. @@ -762,7 +795,7 @@ h4. Attribute Assignment obj.attr = val # obj.attr=(val)
-This is an attribute assignment statement. The above will be translated +This is an attribute assignment fashion. The above will be translated into the method call `attr=`. When using this together with method calls whose parentheses are omitted, we can write code which looks like attribute access. @@ -777,11 +810,11 @@ c.i = 99 p c.i # prints 99 -However both are method calls. +However it will turn out both are method calls. They are similar to get/set property in Delphi or slot accessors in CLOS. -Besides, we cannot define a attribute assignment which takes an argument like -`obj.attr(arg)=`. +Besides, we cannot define a method such as `obj.attr(arg)=`, +which can take another argument in the attribute assignment fashion. h4. Index Notation @@ -796,15 +829,17 @@ Array and hash access are also implemented with this device. obj[i] = val # obj.[]=(i, val) -When assigning to an index the `[]=` method is used. +Index assignment fashion. +This is translated into a call for a method named `[]=`. h3. `super` -Often we don't want to replace a method, but we want to add a little -bit to the behaviour of an already existing method. Here it becomes -necessary to not just overwrite the method in the superclass but -to also call the method in the superclass. -That's what Ruby's `super` is for. +We relatively often have +a situation where we want add a little bit to the behaviour of an already +existing method rather than replacing it. +Here a mechanism to call a method of the superclass when overwriting a method +is required. +In Ruby, that's `super`.
 class A
@@ -814,18 +849,18 @@ class A
 end
 class B < A
   def test
-    super   # launches A#test
+    super   # invokes A#test
   end
 end
 
-Ruby's `super differs from the one in Java. This one here -calls the method with the same name in the superclass. -In other words `super` is a reserved word. +Ruby's `super` differs from the one in Java. This single word +means "call the method with the same name in the superclass". +`super` is a reserved word. -When using super be careful about the difference between the difference -of the zero arguments `super` and the omitted arguments `super. -The super with omitted arguments passes all the parameter variables. +When using `super`, be careful about the difference between +`super` with no arguments and `super` whose arguments are omitted. +The `super` whose arguments are omitted passes all the given parameter variables.
 class A
@@ -849,16 +884,18 @@ B.new.test(1,2,3)
 
 h4. Visibility
 
-Depending on the location ( the object `self`) a method can or
-cannot be called. This function was usually called visibility.
-In Ruby there are three kinds of methods.
+In Ruby, even when calling the same method,
+it can be or cannot be called depending on the location (meaning the
+object). This functionality is usually called "visibility"
+(whether it is visible).
+In Ruby, the below three types of methods can be defined.
 
 * `public`
 * `private`
 * `protected`
 
 `public` methods can be called from anywhere in any form.
-`private` methods can syntactically only be called without a receiver.
+`private` methods can only be called in a form "syntactically" without a receiver.
 In effect they can only be called by instances of the class
 in which they were defined and in instances of its subclass.
 `protected` methods can only be called by instances of the defining class
@@ -888,10 +925,10 @@ end
 
Here `public`, `private` and `protected are method calls without -parentheses. These aren't reserved words. +parentheses. These aren't even reserved words. `public` and `private` can also be used with an argument to set -the visibility of a particular method. But that's not really relevant. +the visibility of a particular method. But its mechanism is not interesting. We'll leave this out. h4. Module functions @@ -918,15 +955,15 @@ sin(5) # If used more often this is more practical It's important that both functions have the same content. With a different `self` but with the same code the behavior should still be the same. Instance variables become extremely difficult to use. -Hence these methods are probably only used -for procedures like `sin`. That's why they are called module functions. +Hence such method is very likely a method in which only procedures are written +(like `sin`). That's why they are called module "functions". h2. Iterators Ruby's iterators differ a bit from Java's or C++'s iterator classes -or 'Iterator' design patterns. Precisely speaking those iterators -are exterior iterators. Ruby's iterators are called interior iterators. -It's difficult to understand from the definition so +or 'Iterator' design pattern. Precisely speaking, those iterators +are called exterior iterators, Ruby's iterators are interior iterators. +Regarding this, it's difficult to understand from the definition so let's explain it with a concrete example.
@@ -955,18 +992,18 @@ end
 Everything from `each do` to `end` is the call to an iterator method.
 More precisely `each` is the iterator method and between
 `do` and `end` is the iterator block.
-The part between the vertical bars are the block parameters.
-They are the arguments passed from the iterator method to the block where
-they become variables.
+The part between the vertical bars are called block parameters,
+which become variables to receive the parameters passed from the iterator method
+to the block.
 
-Saying it quite abstractly, an iterator is something like
+Saying it a little abstractly, an iterator is something like
 a piece of code which has been cut out and passed. In our example the
 piece `print item` has been cut out and is passed to the `each` method.
 Then `each` takes all the elements of the array in order and passes them
 to the cut out piece of code.
 
 We can also think the other way round. The other parts except `print item`
-are being cut out and inserted into the `each` method.
+are being cut out and enclosed into the `each` method.
 
 
 i = 0
@@ -983,7 +1020,7 @@ end
 h3. Comparison with higher order functions
 
 What comes closest in C to iterators are functions which receive function pointers,
-or higher order functions. But there are two points in which iterators in Ruby
+it means higher order functions. But there are two points in which iterators in Ruby
 and higher order functions in C differ.
 
 Firstly, Ruby iterators can only take one block. For instance we can't
@@ -1011,12 +1048,13 @@ That's where iterators are convenient.
 
 But variables can only be shared with the outside. They cannot be shared
 with the inside of the iterator method ( e.g. `each`). Putting it intuitively,
-only the local variables can be seen, which are on the  outside of the code.
+only the variables in the place which looks of the source code continued are
+visible.
 
 h3. Block Local Variables
 
-Local variables which are assigned inside a block stay local to that block.
-They become block local variables. Let's check it out.
+Local variables which are assigned inside a block stay local to that block,
+it means they become block local variables. Let's check it out.
 
 
 [0].each do
@@ -1025,11 +1063,12 @@ They become block local variables. Let's check it out.
 end
 
-For the time being we apply each to an array of length 1. ( We can -leave out the block parameter.) The variable @i@ is first assigned -and declared inside the block. So @i@ becomes a block local variable. +For now, to create a block, we apply `each` on an array of length 1 +(We can fully leave out the block parameter). +In that block, the `i` variable is first assigned .. meaning declared. +This makes `i` block local. -Block local means that it cannot be accessed from the outside. +It is said block local, so it should not be able to access from the outside. Let's test it.
@@ -1043,8 +1082,8 @@ p i     # Here occurs an error.
 for # (NameError)
 
-When we referenced a block local variable from outside the block -an error occured. Without a doubt it stayed local to the block. +When we referenced a block local variable from outside the block, +surely an error occured. Without a doubt it stayed local to the block. Iterators can also be nested repeatedly. Each time the new block creates another scope. @@ -1086,7 +1125,7 @@ variables `i` are different. Inside the block the @i@ inside overshadows the @i@ outside. That's why it's called shadowing. -But what happens in Ruby where there's no shadowing. +But what happens with block local variables of Ruby where there's no shadowing. Let's look at this example.
@@ -1099,11 +1138,12 @@ end
 p i           # 1 the change is preserved
 
-When we assign @i@ inside the block and if there is a variable @i@ -that same variable will be used. Hence if we assign to @i@ inside -the value for @i@ on the outside changes. On this point there +Even when we assign @i@ inside the block, +if there is the same name outside, it would be used. +Therefore when we assign to inside @i@, the value of outside @i@ would be +changed. On this point there came many complains: "This is error prone. Please do shadowing." -Each time there's flaming but till now no conclusion was reached. +Each time there's nearly flaming but till now no conclusion was reached. h3. The syntax of iterators @@ -1123,7 +1163,7 @@ arr.each {|i| # The author likes a four space indentation for }
-But grammaticarly the precedence is different. +But grammatically the precedence is different. The braces bind much stronger than `do`~`end`.
@@ -1131,8 +1171,8 @@ m m do .... end    # m(m) do....end
 m m { .... }       # m(m() {....})
 
-And iterators are of course just methods so they also take -arguments. +And iterators are definitely methods, +so there are also iterators that take arguments.
 re = /^\d/                 # regular expression to match a digit at the beginning of the line
@@ -1172,7 +1212,7 @@ end
 
 @yield@ calls the block. At this point control is passed to the block,
 when the execution of the block finishes it returns back to the same
-location. Think about it like calling a special function. When the
+location. Think about it like a characteristic function call. When the
 present method does not have a block a runtime error will occur.
 
 
@@ -1192,12 +1232,12 @@ twice = Proc.new {|n| n * 2 }
 p twice.call(9)   # 18 will be printed
 
-In short, it is like a function. It can be created with @new@ and -as might be expected, the return value of @Proc.new@ is an instance +In short, it is like a function. As might be expected from the fact it is +created with @new@, the return value of @Proc.new@ is an instance of the @Proc@ class. @Proc.new@ looks surely like an iterator and it is indeed so. -It is an ordinary iterator. There's only some mechanism inside @Proc.new@ +It is an ordinary iterator. There's only some mystic mechanism inside @Proc.new@ which turns an iterator block into an object. Besides there is a function style method @lambda@ provided which @@ -1211,7 +1251,7 @@ h4. Iterators and `Proc` Why did we start talking all of a sudden about @Proc@? Because there is a deep relationship between iterators and @Proc@. -In fact iterators and @Proc@ objects are quite the same thing. +In fact, iterator blocks and @Proc@ objects are quite the same thing. That's why one can be transformed into the other. First, to turn an iterator block into a @Proc@ object @@ -1259,18 +1299,19 @@ end h2. Expressions -Expressions in Ruby can be combined to build new expressions or statements. +"Expressions" in Ruby are things with which we can create other expressions or +statements by combining with the others. For instance a method call can be another method call's argument, -and so it would become an expression. -The same goes for literals. But literals and method calls are not combinations -of other elements. From here on the expressions introduced will always be used -in combination with other expressions. +so it is an expression. The same goes for literals. +But literals and method calls are not always combinations of elements. +On the contrary, "expressions", which I'm going to introduce, +always consists of some elements. h3. `if` We probably do not need to explain the @if@ expression. If the conditional -expression is true the body expression is executed. As explained in the -first part in Ruby every object except @nil@ and @false@ is true. +expression is true, the body is executed. As explained in Part 1, +every object except @nil@ and @false@ is true in Ruby.
 if cond0 then
@@ -1284,10 +1325,10 @@ else
 end
 
-@elsif@ and @else@ can be omitted. Each @then@ can also be omitted -`elsif`・But there are some finer requirements concerning @then@. -It will be apparent by looking at the examples below. -All of them are valid. +`elsif`/`else`-clauses can be omitted. Each `then` as well. +But there are some finer requirements concerning @then@. +For this kind of thing, looking at some examples is the best way to understand. +Here only thing I'd say is that the below codes are valid.
 # 1                                    # 4
@@ -1301,11 +1342,10 @@ if cond then; .... end                   ....
                                        end
 
-Furthermore, as every expression has a return value, there -is also a return value here. It is the return value of the -body expression which holds. For instance if the condition -at the beginning is true it is the return value of the -following expression. +And in Ruby, `if` is an expression, so there is the value of the entire `if` +expression. It is the value of the body where a condition expression is met. +For example, if the condition of the first `if` is true, +the value would be the one of its body.
 p(if true  then 1 else 2 end)   #=> 1
@@ -1313,7 +1353,8 @@ p(if false then 1 else 2 end)   #=> 2
 p(if false then 1 elsif true then 2 else 3 end)   #=> 2
 
-If there's no match, or the match is empty @nil@ is returned. +If there's no match, or the matched clause is empty, +the value would be @nil@.
 p(if false then 1 end)    #=> nil
@@ -1322,8 +1363,8 @@ p(if true  then   end)    #=> nil
 
 h3. `unless`
 
-An @if@ with a negated condition is the same as an @unless@.
-The following two examples have the same meaning.
+An @if@ with a negated condition is an @unless@.
+The following two expressions have the same meaning.
 
 
 unless cond then          if not (cond) then
@@ -1331,17 +1372,19 @@ unless cond then          if not (cond) then
 end                       end
 
-@unless@ can also have an @else@ clause but there cannot be an @elsif@. -Of course @then@ can be omitted. +@unless@ can also have attached @else@ clauses but any @elsif@ cannot be +attached. +Needless to say, @then@ can be omitted. -@unless@ also has a value. Analogous to @if@ it is the value of the of the -clause which matches. If there's no match or the match is empty @nil@ -is returned. +@unless@ also has a value and its condition to decide is completely the same as +`if`. It means the entire value would be the value of the body of the matched +clause. If there's no match or the matched clause is empty, +the value would be @nil@. h3. `and && or ||` -The most useful utilization of the @and@ is probably as a boolean operator. -For instance in the conditional clause of an @if@. +The most likely utilization of the @and@ is probably a boolean operation. +For instance in the conditional expression of an @if@.
 if cond1 and cond2
@@ -1349,7 +1392,7 @@ if cond1 and cond2
 end
 
-But as in Perl, the Shell or Lisp it can also be used as a conditional +But as in Perl, `sh` or Lisp, it can also be used as a conditional branch expression. The two following expressions have the same meaning. @@ -1366,9 +1409,10 @@ method arg0 && arg1 # method(arg0 && arg1) method arg0 and arg1 # method(arg0) and arg1
-Basically the symbolic operator is used in an expression which becomes an argument. -The alphabetical operator is used in an expression which will not become -an argument. +Basically the symbolic operator creates an expression which can be an argument +(`arg`). +The alphabetical operator creates an expression which cannot become +an argument (`expr`). As for @and@, if the evaluation of the left hand side is true, the right hand side will also be evaluated. @@ -1411,7 +1455,7 @@ while cond do end
-This is the most basic loop construct. As long as @cond@ is true +This is the simplest loop syntax. As long as @cond@ is true the body is executed. The @do@ can be omitted.
@@ -1420,13 +1464,14 @@ until io_ready?(id) do
 end
 
-@until@ comes to the exact opposite conclusion as the @while@. -As long as the body expression is false it is executed. +@until@ creates a loop whose condition definition is opposite. +As long as the condition is false it is executed. The @do@ can be omitted. -There is also a jump construct which exits the loop. -As in C/C++/Java it is called @break@. Instead of @continue@ there -is @next@. That seems to have come from Perl. +Naturally there is also jump syntaxes to exit a loop. +@break@ as in C/C++/Java is also @break@, +but @continue@ is @next@. +Perhaps @next@ has come from Perl.
 i = 0
@@ -1452,12 +1497,12 @@ while cond
 end
 
-It will return to @(A)@ and repeat from there. With next there -is a condition @check@, with @redo@ there is none. +It will return to (A) and repeat from there. +What differs from @next@ is it does not check the condition. I might come into the world top 100, if the amount of Ruby programs would be counted, but I haven't used @redo@ yet. It does not seem to be -that necessary after all. +necessary after all because I've lived happily despite of it. h3. `case` @@ -1490,7 +1535,7 @@ to list them all would be tedious, thus we will not cover them in this book. h3. Exceptions -This is a control structure which can pass method boundaries and +This is a control structure which can pass over method boundaries and transmit errors. Readers who are acquainted to C++ or Java will know about exceptions. Ruby exceptions are basically the same. @@ -1506,7 +1551,7 @@ In Ruby exception are instances of the @Exception@ class and it's subclasses. This form takes an exception class as its first argument and an error message as its second argument. In the above case an instance of @ArgumentError@ is created and "thrown". Exception -object ditch the part after the @raise@ and return upwards the +object would ditch the part after the @raise@ and start to return upwards the method call stack.
@@ -1518,8 +1563,9 @@ end
 raise_exception()
 
-If nothing blocks the exception it will move to the top level. -When it reaches the top level, @ruby@ gives out a message and ends +If nothing blocks the exception it will move on and on and +finally it will reach the top level. +When there's no place to return any more, @ruby@ gives out a message and ends with a non-zero exit code.
@@ -1528,9 +1574,10 @@ raise.rb:2:in `raise_exception': wrong number of argument (ArgumentError)
         from raise.rb:7
 
-However, for this an @exit@ would be sufficient, for an exception ther -should be ways to handle it. In Ruby there is the @begin@, @rescue@, @end@ for this. -It resembles the @try@ and @catch@ in C++ and Java. +However an @exit@ would be sufficient for this, and for an exception there +should be a way to set handlers. +In Ruby, @begin@~@rescue@~@end@ is used for this. +It resembles the @try@~@catch@ in C++ and Java.
 def raise_exception
@@ -1545,10 +1592,11 @@ rescue ArgumentError => err then
 end
 
-@rescue@ is a control structure which captures an exception, it catches -the exceptions of the declared class and its subclasses. If in the -above example an instance of @ArgumentError@ comes flying this @rescue@ -matches it. By @=>err@ the exception object will be assigned to the local variable +@rescue@ is a control structure which captures exceptions, it catches +exception objects of the specified class and its subclasses. In the +above example, an instance of @ArgumentError@ comes flying into the place +where @ArgumentError@ is targeted, so it matches this @rescue@. +By @=>err@ the exception object will be assigned to the local variable @err@, after that the @rescue@ part is executed.
@@ -1557,24 +1605,26 @@ exception catched
 #
 
-If the exception is resuced the execution carries on after the rescue -as if nothing happened. We can also make it retry the critical part -with @retry@. +When an exception is rescued, it will go through the `rescue` and +it will start to execute the subsequent as if nothing happened, +but we can also make it retry from the `begin`. +To do so, `retry` is used.
-begin    # return here
+begin    # the place to return
   ....
 rescue ArgumentError => err then
-  retry  # beginning anew
+  retry  # retry your life
 end
 
We can omit the @=>err@ and the @then@ after @rescue@. We can also leave -out the exception class. In this case the class @StandardError@ is matched. +out the exception class. In this case, it means as the same as when the +@StandardError@ class is specified. -If we want to add more exception classes we can just list them after @rescue@. -When we want to handle different errors differently we can use several `rescue`s -in one @begin@~@end@ block. +If we want to catch more exception classes, we can just write them in line. +When we want to handle different errors differently, we can specify several +`rescue` clauses.
 begin
@@ -1585,11 +1635,11 @@ rescue NameError
 end
 
-In this case the exception class is checked in order until there is a match. -Only the one matched part is executed. For instance in the above case only -@IOError@ is executed. +When written in this way, a `rescue` clause that matches the exception class is +searched in order from the top. Only the matched clause will be executed. +For instance, only the clause of @IOError@ will be executed in the above case. -On the othor hand, when there is an @else@ clause, it is executed +On the other hand, when there is an @else@ clause, it is executed only when there is no exception.
@@ -1614,9 +1664,12 @@ ensure   # this part will be executed anyway
 end
 
-Besides, this @begin@ expression also has a value. The value of the +By the way, this @begin@ expression also has a value. The value of the whole @begin@~@end@ expression is the value of the part which was executed -last. The @ensure@ part does not count as it is normally used for cleanup only. +last among @begin@/@rescue@/@else@ clauses. +It means the last statement of the clauses aside from `ensure`. +The reason why the @ensure@ is not counted is probably because +@ensure@ is usually used for cleanup (thus it is not a main line). h3. Variables and Constants @@ -1631,25 +1684,28 @@ CONST $gvar
-I want to add one more thing. The variables starting with @$@ are -of a special kind. Some have strange names, but they are not -necessarily global. +I want to add one more thing. +Among the variables starting with @$@, +there are special kinds. +They are not necessarily global variables and +some have strange names. First the Perlish variables @$_@ and @$~@. @$_@ saves the return value of @gets@ and other methods, @$~@ contains the last match -of a regular expression. They are called local and thread local. -Incredible variables. +of a regular expression. +They are incredible variables which are local variables and simultaneously +thread local variables. -And the variable @$!@ which saves the exceptional object when -an exception has occurred as well as the variable @$?@ which -saves the status of a child process and @$SAFE@ which represents -the security level are all thread local. +And the @$!@ to hold the exception object when an error is occured, +the @$?@ to hold the status of a child process, +the @$SAFE@ to represent the security level, +they are all thread local. h3. Assignment -Variable assignment are all performed by `=`. All variables are -typeless. What is saved is a reference to an object. It is -implemented with `VALUE` (pointer). +Variable assignments are all performed by `=`. All variables are +typeless. What is saved is a reference to an object. +As its implementation, it was a `VALUE` (pointer).
 var = 1
@@ -1659,8 +1715,9 @@ obj = Object.new
 PI = 3.1415926535
 $gvar = {'key' => 'value'}
 
-However, as mentioned earlier `obj.attr=val` is not an assignment. -It is a method call. + +However, as mentioned earlier `obj.attr=val` is not an assignment +but a method call. h3. Self Assignment @@ -1676,10 +1733,10 @@ var = var + 1 it is a shortcut of this code. Differing from C, the Ruby @+@ is a method and thus part of the library. -In the whole meaning of @+=@ is built in the language processor itself. +In C, the whole meaning of @+=@ is built in the language processor itself. And in `C++`, @+=@ and @*=@ can be wholly overwritten, but we cannot do this in Ruby. -In Ruby @`=@ is always defined as an operation of the combination of @`@ and assignment. +In Ruby @+=@ is always defined as an operation of the combination of @+@ and assignment. We can also combine self assignment and an attribute-access-flavor method. The result more looks like an attribute. @@ -1705,37 +1762,40 @@ might easily be broken. That's why there's no @++@ Some people don't want to go without the brevity of @++@. It has been proposed again and again in the mailing list but was always turned down. -I also am in favor of @++@ but I can do without, there has never been -a @++@ in Ruby so let's forget about it. +I am also in favor of @++@ but not as much as I can't do without, +and I have not felt so much needs of @++@ in Ruby in the first place, +so I've kept silent and decided to forget about it. h3. `defined?` -@defined?@ is a strange construct in Ruby. It tells whether an -expression value is defined or not. +@defined?@ is a syntax of a quite different color in Ruby. It tells whether an +expression value is "defined" or not at runtime.
 var = 1
 defined?(var)   #=> true
 
-In other words it tells whether the received argument (is it okay to call -it so?) returns a value after evaluation. But it won't tell you if there's -a parse error or an exception is raised. +In other words it tells whether a value can be obtained from the expression +received as its argument (is it okay to call it so?) when the expression is +evaluated. That said but of course you can't write an expression causing a parse +error, and it could not detect if the expression is something containing a +method call which raises an error in it. I would have loved to tell you more about @defined?@ but it will not appear again in this book. What a pity. h2. Statements -A statement is a syntactic construct which basically -cannot be combined with something else and is written -in a separate line. +A statement is what basically cannot be combined with the other syntaxes, +in other words, they are lined vertically. -But it still can be evaluated. For instance there are return values +But it does not mean there's no evaluated value. +For instance there are return values for class definition statements and method definition statements. -However this is only rarely used, not recommended and isn't useful. -We stick with this informal criteria. -Here we also don't mention the various return values. +However this is rarely recommended and isn't useful, +you'd better regard them lightly in this way. +Here we also skip about the value of each statement. h3. The Ending of a statement @@ -1749,8 +1809,10 @@ Of course then we can write two and more statements in one line. puts 'Hello, World!'; puts 'Hello, World once more!' -On the other hand after opened parentheses, dyadic operators, or commas -when the command apparently continues the sentence continues automatically. +On the other hand, +when the expression apparently continues, +such as just after opened parentheses, dyadic operators, or a comma, +the statement continues automatically.
 # 1 + 3 * method(6, 7 + 8)
@@ -1761,7 +1823,8 @@ when the command apparently continues the sentence continues automatically.
             7 + 8)
 
-But it's also no problem to connect lines explicitly with a backslash. +But it's also totally no problem to use a backslash to explicitly indicate the +continuation.
 p 1 + \
@@ -1780,7 +1843,7 @@ on_true() if cond                if cond
 
The `unless` is the negative version. -Guard statements ( statements which exclude exceptions) can +Guard statements ( statements which exclude exceptional conditions) can be conveniently written with it. h3. The Modifiers `while` and `until` @@ -1810,9 +1873,9 @@ end Defines the class `C` which inherits from `SuperClass` -We talked quite extensively about classes in the first part. -This statement will be executed, within the definition the class will -become @self@, arbitrary expressions can be written within. Class +We talked quite extensively about classes in Part 1. +This statement will be executed, the class to be defined will +become @self@ within the statement, arbitrary expressions can be written within. Class definitions can be nested. They form the foundation of Ruby execution image. @@ -1824,11 +1887,12 @@ end I've already written about method definition and won't add more. -They also belong to statements. +This section is put to make it clear that +they also belong to statements. h3. Singleton method definition -We already talked a lot about singleton methods in the first part. +We already talked a lot about singleton methods in Part 1. They do not belong to classes but to objects, in fact, they belong to singleton classes. We define singleton methods by putting the receiver in front of the method name. Parameter declaration is done @@ -1868,8 +1932,8 @@ end h3. Multiple Assignment -With a multiple assignment several assignments can be combined into one. -The following is a simple example: +With a multiple assignment, several assignments can be done all at once. +The following is the simplest case:
 a, b, c = 1, 2, 3
@@ -1883,15 +1947,17 @@ b = 2
 c = 3
 
-It's not just for brevity's sake. When we bind variables to an elements -of an array it becomes delightful. +Just being concise is not interesting. +in fact, when an array comes in to be mixed, +it becomes something fun for the first time.
 a, b, c = [1, 2, 3]
 
This also has the same result as the above. -Furthermore, the right handside does not need to be a literal. +Furthermore, the right hand side does not need to be a grammatical list or a +literal. It can also be a variable or a method call.
@@ -1900,8 +1966,8 @@ a, b, c = tmp
 ret1, ret2 = some_method()   # some_method might probably return several values
 
-Precisely speaking it is as follows. We will write the value of the -left hand side as @obj@. +Precisely speaking it is as follows. +Here we'll assume @obj@ is (the object of) the value of the left hand side, # `obj` if it is an array # if its `to_ary` method is defined, it is used to convert `obj` to an array. @@ -1912,7 +1978,7 @@ Decide the right-hand side by following this procedure and perform assignments. It means the evaluation of the right-hand side and the operation of assignments are totally independent from each other. -And it goes on, the left and right hand side can be infinitely nested. +And it goes on, both the left and right hand side can be infinitely nested.
 a, (b, c, d) = [1, [2, 3, 4]]
@@ -1943,7 +2009,7 @@ p first  # 0
 p rest   # [1, 2, 3, 4]
 
-If all of them are used all at once, you will easily get confused. +When all of them are used all at once, it's extremely confusing. h4. Block parameter and multiple assignment @@ -1957,10 +2023,12 @@ array.each do |i| end -When the block is called with a `yield`, the provided parameters are multi-assigned to `i`. +Every time when the block is called, +the `yield`ed arguments are multi-assigned to `i`. Here there's only one variable on the left hand side, so it does not look like multi assignment. -But if there are two or more variables we see what's going on. For instance @Hash#each@ -provides a key and a value we usually call it like that: +But if there are two or more variables, it would a little more look like it. +For instance, @Hash#each@ is an repeated operation on the pairs of keys and values, +so usually we call it like this:
 hash.each do |key, value|
@@ -1968,13 +2036,13 @@ hash.each do |key, value|
 end
 
-In this case an array with elements key and value are yielded +In this case, each array consist of a key and a value is `yield`ed from the hash. -Hence we can also use nested multiple assignment as shown below. +Hence we can also does the following thing by using nested multiple assignment.
-# [[key,value],index] are given to yield
+# [[key,value],index] are yielded
 hash.each_with_index do |(key, value), index|
   ....
 end
@@ -1990,10 +2058,11 @@ end
 
 Defining another method `new` with the same body as the already
 defined method `orig`. `alias` are similar to hardlinks in a unix
-file system. They are a means of assigning multiple names to one method body. I other words,
+file system. They are a means of assigning multiple names to one method body.
+To say this inversely,
 because the names themselves are independent of each other,
-if one method name is overwritten by a subclass method, the
-other one still returns the method as before.
+even if one method name is overwritten by a subclass method, the
+other one still remains with the same behavior.
 
 h3. `undef`
 
@@ -2009,15 +2078,15 @@ superclass it would also be forbidden. In other words the method is
 exchanged for a sign which says "This method must not be called".
 
 `undef` is extremely powerful, once it is set it cannot be
-deleted on the Ruby level, because it is used to cover up contradictions
-in the internal structure. One must define a method in the lower class.
-Even then when one calls `super` an
-error occurs.
+deleted from the Ruby level because it is used to cover up contradictions
+in the internal structure.
+Only one left measure is inheriting and defining a method in the lower class.
+Even in that case, calling `super` would cause an error occurring.
 
-By the way the method which corresponds to `unlink` in a file system
+The method which corresponds to `unlink` in a file system
 is `Module#remove_method`. While defining a class, `self` refers
-to that class, we can call it as follows ( Remember that `Class` is a
-subclass of `Module`.
+to that class, we can call it as follows (Remember that `Class` is a
+subclass of `Module`.)
 
 
 class C
@@ -2056,7 +2125,7 @@ Plain and simple.
 An embedded document stretches from
 an `=begin` outside a string at the beginning of a line
 to a `=end`. The interior can be arbitrary.
-The program reads and ignores it like a simple comment.
+The program ignores it as a mere comment.
 
 h3. Multi-byte strings
 

From 92af1a09c7fb3db0ee6c5c23be05d06a048f52b5 Mon Sep 17 00:00:00 2001
From: ocha- 
Date: Wed, 25 Sep 2013 06:35:36 +0900
Subject: [PATCH 074/121] English images for chatper 17

---
 anyeval.textile                |   2 --
 images/ch_anyeval_dynavars.jpg | Bin 8139 -> 8921 bytes
 2 files changed, 2 deletions(-)

diff --git a/anyeval.textile b/anyeval.textile
index e640ed5..a3d06f5 100644
--- a/anyeval.textile
+++ b/anyeval.textile
@@ -503,8 +503,6 @@ from inside of a string to `eval`.
 
(dynavars)
Figure 1: `ruby_dyna_vars` inside `eval` -* パーサで追加 added in the parser -* 評価機で作成 created in the evaluator
diff --git a/images/ch_anyeval_dynavars.jpg b/images/ch_anyeval_dynavars.jpg index f9c84c639e73b455d616d02b5e5fefe3a61015ab..a4494da307efa08760aee6ecdc88bbc1dac5cd47 100644 GIT binary patch literal 8921 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

N6ySZ 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 H-J|~>XXbL@ From 0fac66dee33895f6baa7a225030919a98bae5d84 Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 25 Sep 2013 06:36:27 +0900 Subject: [PATCH 075/121] English images for chapter 18 --- images/ch_load_link.jpg | Bin 12093 -> 12799 bytes images/ch_load_loadwait.jpg | Bin 25118 -> 28730 bytes load.textile | 8 -------- 3 files changed, 8 deletions(-) diff --git a/images/ch_load_link.jpg b/images/ch_load_link.jpg index 54fdc93a8ce23695024150d291cf9e6f697725bf..d83e670fe09ebe8aa002573658691eaeeaac48ce 100644 GIT binary patch literal 12799 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 literal 12093 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 diff --git a/images/ch_load_loadwait.jpg b/images/ch_load_loadwait.jpg index 0cda54375103da2641e50e20173641b466be7c7f..e66ce59bd49329986d15a7a8e5589ca4a3b3956e 100644 GIT binary patch literal 28730 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]r`7u19bA=VLl493XPZ6G8Sqb=@n|aB>`p=jDK-K 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 l$Ot3NBYev>UZ| (loadwait)
Figure 1: Serialisation of loads -* スレッド thread -* ロック lock -* ロード開始 loading is started -* ロード完了 loading is completed -* アンロック unlock

FU13R-zVwI)opA5Z5tO!EX-?Rx>^B2Z@p!9? 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%0AgD+mz!?d~J3~ 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 diff --git a/images/ch_method_mhash.jpg b/images/ch_method_mhash.jpg index bbf99308ce5a25d49bcf88346882e71805a3a931..297d33815b2176659b4c1efa6c61813ee42eec2e 100644 GIT binary patch literal 9056 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 Vcvm_{&F0O0XYJE8IdUCN{67KTul)c3 literal 8248 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ⅆ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 Pv47?BDfxe2=eYj>_?7d` literal 8128 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 P#R8%h|HB0Ec;epxh{{b- diff --git a/method.textile b/method.textile index 8a1c8e6..e476d39 100644 --- a/method.textile +++ b/method.textile @@ -236,15 +236,7 @@ The point is that "in the `else` side the values of arguments are also stored in `args`". If I illustrate, it would look like Figure 1. -

h2. Loading of Ruby programs @@ -813,9 +808,6 @@ it is resolving undefined symbols.
(link)
Figure 2: object files and linking -* 提供する名前 the providing names -* 必要な名前 the necessary names -* オブジェクトファイル object file
Logically this is how it is, but in reality a program can't run only because of From 8d2bb0a3145e21966c39bc2004dcd2ff941ae4e9 Mon Sep 17 00:00:00 2001 From: ocha- Date: Wed, 25 Sep 2013 06:37:50 +0900 Subject: [PATCH 076/121] English images for chapater 19 --- images/ch_thread_fdset.jpg | Bin 4628 -> 4827 bytes images/ch_thread_setjmploop.jpg | Bin 17440 -> 19692 bytes images/ch_thread_twodirection.jpg | Bin 13233 -> 15144 bytes thread.textile | 9 +-------- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/images/ch_thread_fdset.jpg b/images/ch_thread_fdset.jpg index 1919443dfd33d79d981322366c16791612e7f2e4..0773eba3f3b0f57c56c44d8d1ded938441d369b4 100644 GIT binary patch literal 4827 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 literal 17440 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 a<4;B$&d&#CAR`Tfy#J}>^CJS@P5eK~VQ*ak literal 13233 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 DM65l3 diff --git a/thread.textile b/thread.textile index 3c68028..a65125b 100644 --- a/thread.textile +++ b/thread.textile @@ -821,7 +821,6 @@ and when we want to check n-th file descriptor, the n-th bit is set (Figure 2).
(fdset)
Figure 2: fd_set -* インデックス index
@@ -1253,10 +1252,6 @@ In other words, there's a chain of `setjmp`/`longjmp()` as follows. (Figure 3)
(setjmploop)
Figure 3: the backstitch by chaining of `setjmp` -* 外側 outside -* 退避 set aside -* 復元 restore -* スレッド thread
@@ -1322,9 +1317,7 @@ possible. (Figure 4)
(twodirection)
-Fig.4: a stack extending higher and a stack extending lower -* 下にのびるスタック a stack extending lower -* 上にのびるスタック a stack extending higher +Fig.4: a stack extending above and a stack extending below
From 1db040221e65fc452fde40eb99bea42226553c92 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sat, 28 Sep 2013 10:06:42 +0900 Subject: [PATCH 077/121] perhaps "port" is better than "transplant" --- intro.textile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intro.textile b/intro.textile index bdb8ccc..9599b5a 100644 --- a/intro.textile +++ b/intro.textile @@ -804,9 +804,9 @@ There's probably no problem if it is version 6 or .NET. MinGW or Minimalist GNU for Windows, it is what the GNU compiling environment (Namely, @gcc@ and @binutils@) -is transplanted on Windows. -Cygwin transplants the whole UNIX environment. -On the contrary, MinGW transplants only the tools to compile. +is ported on Windows. +Cygwin ports the whole UNIX environment. +On the contrary, MinGW ports only the tools to compile. Moreover, a program compiled with MinGW does not require any special DLL at runtime. It means, the @ruby@ compiled with MinGW can be treated completely the same as the Visual C++ version. From 503e0771911b5d1cbac0ee2f6423935bb3d66918 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 29 Sep 2013 05:50:59 +0900 Subject: [PATCH 078/121] the rest of the final chapter --- fin.textile | 700 ++++++++++++++++++++++++++++------------------------ 1 file changed, 373 insertions(+), 327 deletions(-) diff --git a/fin.textile b/fin.textile index 97e70cc..5c2cf5c 100644 --- a/fin.textile +++ b/fin.textile @@ -8,7 +8,7 @@ h2. Issues to be addressed @ruby@ isn't 'completely finished software'。It's still being developed, there are still a lot of issues. Firstly, we want to try removing -inherent problems in the interpreter. +inherent problems in the current interpreter. The order of the topics is mostly in the same order as the chapters of this book. @@ -16,92 +16,111 @@ this book. h3. Performance of GC -現在のGCの性能は「特に悪くないが、特に良くもない」と言ったところだろう -か。「特に悪くない」というのは「日常生活で困ることはない」ということで、 -「特に良くもない」というのは「高負荷になると弱点が露呈する」という意味 -である。例えば大量にオブジェクトを作ってそのまま保持し続けるアプリケー -ションだと速度が急激に低下してしまう。GCのたびに全オブジェクトをマーク -することになるうえ、オブジェクトが回収できないものでさらにGCの回数まで -増えてしまうからである。この問題には第5章で触れた世代別GCが効 -果的なはずだ(少なくとも理論的にはそういうことになっている)。 +The performance of the current GC might be +"not notably bad, but not notably good". +"not notably bad" means "it won't cause troubles in our daily life", +and "not notably good" means "its downside will be exposed under heavy load". +For example, if it is an application which creates plenty of objects and keeps +holding them, its speed would slow down radically. +Every time doing GC, it needs to mark all of the objects, +and furthermore it would becomes to need to invoke GC more often +because it can't collect them. +To counter this problem, Generational GC, which was mentioned in Chapter 5, +must be effective. (At least, it is said so in theory.) + +Also regarding its response speed, +there are still rooms we can improve. +With the current GC, while it is running, the entire interpretor stops. +Thus, when the program is an editor or a GUI application, +sometimes it freezes and stops to react. +Even if it's just 0.1 second, +stopping when typing characters would give a very bad impression. +Currently, there are few such applications created or, +even if exists, its size might be enough small not to expose this problem. +However, if such application will actually be created in the future, +there might be the necessity to consider Incremental GC. -また反応速度の点でも改善の余地がある。現在のGCの実行中はインタプリタ全 -体が停止するので、エディタだとかGUIアプリケーションだと時々「ぐっ」と -固まって反応が中断することになる。例えそれが0.1秒程度だろうとも、 -文字をタイプしている途中に止まられたりすると非常に印象が悪い。今はそ -ういうアプリケーションはあまり作られていないか、あってもさほど大きくな -いためこの点があまり問題にならないのだろう。だがいずれそういうものが出 -てくればインクリメンタルGCの導入を考える必要もあるかもしれない。 - h3. Implementation of parser -第二部で見たように @ruby@ のパーサの実装は -既に @yacc@ を限界近くまで酷使しており、これ以上の拡張に耐えるとは思えな -い。拡張の予定がないのならいいが、この後には「キーワード引数」という -大物の導入が予定されているし、 @yacc@ の制限のせいで欲しい文法が表現でき -ない、なんてことになったら悲しい。 +As we saw in Part 2, the implementation of @ruby@ parser has already utilized +@yacc@'s ability to almost its limit, thus I can't think it can endure further +expansions. It's all right if there's nothing planned to expand, +but a big name "keyword argument" is planned next +and it's sad if we could not express another demanded grammar because of the +limitation of @yacc@. + h3. Reuse of parser -Rubyのパーサは非常に複雑だ。特に @lex_state@ のあたりを真面目に扱う -のがとても大変である。そのせいで、Rubyプログラムを埋め込んだり、 -Rubyプログラム自体を扱うプログラムを作るのが非常に難しくなっている。 +Ruby's parser is very complex. In particular, dealing with around @lex_state@ +seriously is very hard. Due to this, embedding a Ruby program or creating a +program to deal with a Ruby program itself is quite difficult. + +For example, I'm developing a tool named @racc@, +which is prefixed with R because it is a Ruby-version @yacc@. +With @racc@, the syntax of grammar files are almost the same as @yacc@ +but we can write actions in Ruby. +To do so, it could not determine the end of an action without parsing Ruby code +properly, but "properly" is very difficult. Since there's no other choice, +currently I've compromised at the level that it can parse "almost all". +As another example which requires analyzing Ruby program, +I can enumerate some tools like @indent@ and @lint@, +but creating such tool also requires a lot efforts. +It would be desperate if it is something complex like a refactoring tool. -例えば筆者が開発しているツールで @racc@ というものがある。 @yacc@ のRuby版 -なのでRを付けて @racc@ だ。その @racc@ では文法ファイルの構文などはほとんど -@yacc@ と同じで、 -アクションの部分だけがRubyのコードになっている。そのためにはRubyのコー -ドをちゃんとパースしないとアクションの終わりを判定できないが、「ちゃん -と」パースするのがとても難しい。仕方がないので今は「だいたい」パースで -きるというレベルで妥協している。 +Then, what can we do? If we can't recreate the same thing, +what if @ruby@'s original parser can be used as a component? +In other words, making the parser itself a library. +This is a feature we want by all means. +However, what becomes problem here is, as long as @yacc@ is used, +we cannot make parser reentrant. +It means, say, we cannot call @yyparse()@ recursively, +and we cannot call it from multiple threads. +Therefore, it should be implemented in the way of not returning control to Ruby +while parsing. -他にRubyプログラムの解析が必要になる例としては -@indent@ や @lint@ のようなツールが -挙げられるが、こういうものを作るのにも非常に苦労する。リファクタリング -ツールのような複雑なものになるともはや絶望的である。 -ではどうしようか。同じものを作り直すのが無理なら、 @ruby@ のオリジナルの -パーサを部品として使えるようにすればいいのではないだろうか。つまり処理 -系のパーサ自体をライブラリ化するわけだ。これは是非とも欲しい機能である。 +h3. Hiding Code +With current @ruby@, it does not work without the source code of the program to +run. Thus, people who don't want others to read their source code might have +trouble. -ただここで問題なのは、 @yacc@ を使う限りパーサがリエントラントにできない -ということだ。つまり @yyparse()@ を再帰呼び出ししたり複数のスレッドから -呼んだりできないのである。だからパース中にRubyに制御が戻らないように実 -装しなければならない。 -h3. コード隠蔽 +h3. Interpretor Object -現在の @ruby@ は動かすプログラムのソースコードがないと動かせない。 -つまりソースコードを他人に読ませたくない人達は困るだろう。 +Currently each process cannot have multiple @ruby@ interpretors, +this was discussed in Chapter 13. +If having multiple interpretors is practically possible, it seems better, +but is it possible to implement such thing? -h3. インタプリタオブジェクト -現在の @ruby@ インタプリタはプロセスに一つしか持てない、ということは -第13章で話した。複数のインタプリタを持つことが現実に可能 -ならそのほうがよさそうではあるが、果たしてそういうことは実装可能なのだ -ろうか。 +h3. The structure of evaluator -h3. 評価器の構造 +Current @eval.c@ is, above all, too complex. +Embedding Ruby's stack frames to machine stack could occasionally become the +source of trouble, using @setjmp() longjmp()@ aggressively makes it less easy to +understand and slows down its speed. +Particularly with RISC machine, which has many registers, using @setjmp()@ +aggressively can easily cause slowing down because @setjmp()@ set aside all +things in registers. -いまの @eval.c@ はとにかく複雑すぎる。マシンスタックにRubyのスタックフレー -ムを埋め込むのも何かと厄介の元だし、 @setjmp() longjmp()@ を使いまくるのも -わかりやすさと速度を下げている。特にレジスタの多いRISCマシンだと -@setjmp()@ を使いまくると速度が落ちやすい。 @setjmp()@ ではレジスタを全て -退避するからである。 -h3. 評価器の速度 +h3. The performance of evaluator -@ruby@ は普通に使うぶんには既に十分に高速だ。だがそれでもやはり、言語処理 -系は速ければ速いほどいいのは間違いない。速度を上げる、即ち最適化をする -にはどうしたらいいだろう。そういうときはまずプロファイルを採らねばなら -ない。というわけで採った。 +@ruby@ is already enough fast for ordinary use. +But aside from it, regarding a language processor, +definitely the faster is the better. +To achieve better performance, in other words to optimize, +what can we do? +In such case, the first thing we have to do is profiling. +So I profiled. -p(=emlist). +
   %   cumulative   self              self     total
  time   seconds   seconds    calls  ms/call  ms/call  name
  20.25      1.64     1.64  2638359     0.00     0.00  rb_eval
@@ -115,375 +134,402 @@ p(=emlist).
   2.22      5.73     0.18  3819588     0.00     0.00  call_cfunc
 
-これはとあるアプリケーションを動かしたときのプロファイルなのだが、一般 -的なRubyプログラムのプロファイルにもかなり近い。つまりトップに圧倒的割 -合で @rb_eval()@ が登場し、そのあとにGCと評価器中枢部、加えて処理に特有 -の関数が混じる。例えばこのアプリケーションの場合は正規表現マッチ -( @ruby_re_match@ )にかなり時間がかかっているようだ。 - - -ただそれがわかったとしてどう解決するかが問題だ。単純に考えれば -@rb_eval()@ を速くすればいい、ということになるだろうが、 @ruby@ のコアに -関しては小手先の最適化をやる余地はもうほとんどない。 @NODE_IF@ のところ -で使われていたような「末尾再帰→ @goto@ 変換」もほとんどやり尽くした感が -ある。つまり根本的に考えかたを変えない限り向上の余地がないのだ。 - -h3. スレッドの実装 - -これは第19章でも話した。現在のrubyのスレッドの実装は非常に -問題が多い。特にネイティブスレッドとの相性の悪さはどうしようもない。 -@ruby@ スレッドの(1)移植性が高く(2)どこでも同じ挙動、という二点は確 -かに他に代え難い長所なのだが、さすがにあの実装はずっと使い続けるには無 -理があるのではなかろうか。 - -h2. @ruby@ 2 - -続いて今度はこれらの問題点に対するオリジナルの @ruby@ の動向を示す。 - -h3. Rite +This is a profile when running some application but +this is approximately the profile of a general Ruby program. +@rb_eval()@ appeared in the overwhelming percentage being at the top, +after that, in addition to functions of GC, evaluator core, +functions that are specific to the program are mixed. +For example, in the case of this application, +it takes a lot of time for regular expression match (@ruby_re_match@). -現時点でのrubyの最新バージョンは安定版が1.6.7、開発版が1.7.3だ。 -だがそう遠くないうちに次の安定版1.8が出そうである。そうすると同時に -開発版の1.9.0がスタートする。そしてその次はちょっと変則的に1.9.1が -安定版となる。 +However, even if we understood this, the question is how to improve it. +To think simply, it can be archived by making @rb_eval()@ faster. +That said, but as for @ruby@ core, there are almost not any room which can be +easily optimized. For instance, apparently "tail recursive -> @goto@ conversion" +used in the place of @NODE_IF@ and others has already applied almost all +possible places it can be applied. +In other words, without changing the way of thinking fundamentally, +there's no room to improve. -安定版開発版開始時期 -1.6.x1.7.x2000-09-19に1.6.0リリース -1.8.x1.9.0半年以内には出るだろう -1.9.1〜2.0.0二年後くらいか +h3. The implementation of thread +This was also discussed in Chapter 19. There are really a lot of issues about +the implementation of the current ruby's thread. Particularly, it cannot mix +with native threads so badly. The two great advantages of @ruby@'s thread, +(1) high portability (2) the same behavior everywhere, +are definitely incomparable, but probably that implementation is something we +cannot continue to use eternally, isn't it? -そして次々世代の開発版が @ruby@ 2、コードネームRite、である。 -この名前はLとRの区別がつけられない日本人へのオマージュらしい。 - - -一言で2.0はどこが変わるかと言うと、コアほとんど全部だ。スレッド、評価 -器、パーサ、これが全部変わる。もっとも、コードがカケラも出てきていない -のであくまでここに書くのは全て「予定」である。あまり期待しすぎると失望 -するかもしれない。そういうわけで、軽く期待、ということにしておこう。 - -h3. 記述言語 - -まず使う言語。間違いなくCだろう。Rubyの英語メーリングリスト -@ruby-talk@でのまつもとさんの発言によると - -bq. -I hate C++. - - -だそうなので、C++を使うというのはまずありえない。いくら全面作り直しと -言ってもオブジェクトシステムはほぼそのまま残ると考えられるので、そのあ -たりでの手間が増えないようする必要もある。ただしCはCでも今度はANSI Cに -なる可能性は高いだろう。 - -h3. GC -GCの実装では、 -まず @Boehm GC@\footnote{Boehm GC `http://www.hpl.hp.com/personal/Hans_Boehm/gc`}から -試してみるということだ。Boehm GCは -conservativeかつincrementalかつgenerationalなGCで、しかも -ネイティブスレッドが動いてい -ても全スレッドのスタック領域をマークできるというかなりの優れものGCであ -る。一度導入したとしてそのままBoehm GCをそのまま使い続けるのかどうか -はわからないが、どちらにしてもなんらかの速度向上が期待できる方向に -進むだろう。 -h3. パーサ -仕様の点では、括弧を省略したメソッド呼び出しのネストが一律禁止になりそ -うである。見てきたように @command_call@ は文法全域にかなりの影響を与えてい -た。これが簡略化されればパーサもスキャナも随分すっきりするはずだ。 -ただし括弧の省略自体がなくなることはありえない。 +h2. `ruby` 2 +Subsequently, on the other hand, I'll introduce the trend of the original `ruby`, +how it is trying to counter these issues. -また実装面では @yacc@ を使い続けるかどうかでまだ思案中ということだ。使わ -ないとすれば手書きで、ということだが、あれだけ複雑なものを手で実装でき -るか、不安は残る。どちらを選んでも茨の道には違いない。 -h3. 評価器 - -評価器は完全に作り直しとなる。目的は主に高速化と実装の簡略化であり、 -主眼は二点だ。 +h3. Rite +At the present time, ruby's edge is 1.6.7 as the stable version and 1.7.3 as the +development version, but perhaps the next stable version 1.8 will come out in +the near future. Then at that point, the next development version 1.9.0 will +start at the same time. And after that, this is a little irregular but 1.9.1 +will be the next stable version. -@rb_eval()@ のような再帰呼び出しをなくす -バイトコードインタプリタへの移行 +|_. stable |_. development |_. when to start | +| 1.6.x | 1.7.x | 1.6.0 was released on 2000-09-19 | +| 1.8.x | 1.9.x | probably it will come out within 6 months | +| 1.9.1~ | 2.0.0 | maybe about 2 years later | -まず @rb_eval()@ の再帰呼び出しをなくす。なくす方法については「末尾再帰 -→ @goto@ 変換」のような感じ、と言うのが一番直感的だろうか。一つの -@rb_eval()@ の中で @goto@ を使い、ぐるぐる回るわけだ。するとまず関数呼び -出しが減るし、 @return@ や @break@ のために使っていた @setjmp()@ も不要にな -る。ただしCで定義されたメソッドの呼び出しが入れば嫌でも関数を呼ばざ -るを得ないので、その区切りではやはり @setjmp()@ が必要だ。 +And the next-to-next generational development version is `ruby` 2, whose code +name is Rite. Apparently this name indicates a respect for the inadequacy that +Japanese cannot distinguish the sounds of L and R. +What will be changed in 2.0 is, in short, almost all the entire core. +Thread, evaluator, parser, all of them will be changed. +However, nothing has been written as a code yet, so things written here is +entirely just a "plan". If you expect so much, it's possible it will turn out +disappointments. Therefore, for now, let's just expect slightly. -バイトコード(byte code)というのはようするに機械語のプログラムみたい -なものである。Smalltalk80の仮想マシンで有名になった用語で、命令がバイ -ト単位で構成されているのでバイトコードと呼ばれる。上のレベルばかりいじっ -ている人間からするとバイト単位なんてのはあたりまえに思えてしまうのだが、 -機械語では命令がビット単位になっていることは多い。例えばAlphaだと命令 -コード32ビットのうち先頭6ビットが命令種を表している。 +h3. The language to write -バイトコード型にする利点は主に高速化である。理由は二つで、一つめは構文 -木のようにポインタをたぐる必要がないこと。もう一つは局所的な最適化 -(peephole optimization)がやりやすいことだ。 +Firstly, the language to use. Definitely it will be C. Mr. Matsumoto said to +`ruby-talk`, which is the English mailing list for Ruby, +
+I hate C++. +
-またバイトコードを保存しておいて読み込む場合はパースがなくなるのでそ -こでも多少は速くなると考えられる。しかしパースはプログラムの開始時点に -一回しか行われない作業だし、元々パースにはあまり時間がかかっていない -ので、そう大きな影響はない。 +So, C++ is most unlikely. Even if all the parts will be recreated, +it is reasonable that the object system will remain almost the same, +so not to increase extra efforts around this is necessary. +However, chances are good that it will be ANSI C next time. -バイトコードの評価器がどんなふうになるか知りたければ @regex.c@ を見てみ -るとよい。あとはPythonがバイトコードインタプリタだ。 +h3. GC -h3. スレッド +Regarding the implementation of GC, +the good start point would be +`Boehm GC`\footnote{Boehm GC `http://www.hpl.hp.com/personal/Hans_Boehm/gc`}. +Bohem GC is a conservative and incremental and generational GC, +furthermore, it can mark all stack spaces of all threads even while native +threads are running. It's really an impressive GC. +Even if it is introduced once, it's hard to tell whether it will be used +perpetually, but anyway it will proceed for the direction to which we can expect +somewhat improvement on speed. -スレッドはネイティブスレッド対応。Rubyが誕生した1994年当時に比べると -スレッドを取り巻く環境は格段に良くなっているし、ネイティブスレッドで -いける、と判断されたのだろう。 +h3. Parser -ネイティブスレッドを使うということはCレベルでもプリエンプティブになる -わけだからインタプリタ自体をマルチスレッドセーフにしなければならないが、 -その点はとりあえずグローバルロックをかけて解決するようである。 +Regarding the specification, it's very likely that the nested method calls +without parentheses will be forbidden. As we've seen, `command_call` has a great +influence on all over the grammar. If this is simplified, both the parser and +the scanner will also be simplified a lot. +However, the ability to omit parentheses itself will never be disabled. +And regarding its implementation, whether we continue to use `yacc` is still +under discussion. If we won't use, it would mean hand-writing, but is it +possible to implement such complex thing by hand? Such anxiety might left. +Whichever way we choose, the path must be thorny. -それと知る人ぞ知る「継続」だが、どうもなくなりそうな気配だ。 @ruby@ の -継続はスレッドの実装に大きく依存しているので、スレッドがネイティブスレッ -ドになれば継続も自然と消滅する。あれが付いているのは「実装できて -しまった」からだし、ほとんど使われていないので問題ないだろう。 -h3. M17N +h3. Evaluator -ついでにクラスライブラリについても少しだけ触れておこう。多言語化 -(Multilingualization、略してM17N)についてだ。プログラミングに -おいてM17Nとは何をすることか有体に言うと、複数の文字コードを扱えるよう -にすることである。 +The evaluator will be completely recreated. +Its aims are mainly to improve speed and to simplify the implementation. +There are two main viewpoints: -似た話題では他に国際化(Internationalization、略してI18N)と -いうのもあ -る。こちらの例を挙げれば、エラーメッセージをユーザの好みの言語で出した -り、日付の表現を国の慣習に合わせたりすることである。この例えでわかると -おり、I18Nを実現するためにはM17Nの実現が必須である。しかし逆は成立しな -い。 +* remove recursive calls like `rb_eval()` +* switch to a bytecode interpretor +First, removing recursive calls of `rb_eval()`. The way to remove is, +maybe the most intuitive explanation is that it's like the "tail recursive -> +`goto` conversion". Inside a single `rb_eval()`, circling around by using +`goto`. That decreases the number of function calls and removes the necessity of +`setjmp()` that is used for `return` or `break`. +However, when a function defined in C is called, calling a function is +inevitable, and at that point `setjmp()` will still be required. -具体的にRubyを多言語化するためには何が必要か。一つにはパーサの対応、も -う一つは文字列関係のライブラリ、具体的には @String@ と @Regexp@ の対応、の -二つが必要である。 +Bytecode is, in short, something like a program written in machine language. +It became famous because of the virtual machine of Smalltalk90, +it is called bytecode because each instruction is one-byte. +For those who are usually working at more abstract level, byte would seem +so natural basis in size to deal with, +but in many cases each instruction consists of bits in machine languages. +For example, in Alpha, among a 32-bit instruction code, the beginning 6-bit +represents the instruction type. -パーサの対応とは、コメントや文字列リテラル、正規表現リテラルに任意言語 -(正確にはエンコーディング)を許すことだ。これが易しそうで難しい。 -まず、 @ruby@ のパーサに -エンコーディングを伝える方法が必要である。これまで見てきたよ -うにRubyのプログラムは例外なくパーサを抜けたあとに評価される。つまりパー -サにエンコーディングを伝えるのに通常の構文を使うことはできない。だから -エンコーディングを指定するためになんらかの構文を追加する必要がある。 +The advantage of bytecode interpretors is mainly for speed. There are two +reasons: Firstly, unlike syntax trees, there's no need to traverse pointers. +Secondly, it's easy to do peephole optimization. -ライブラリでの対応はわりと簡単だ。現在ある @mbclen()@ という仕組みを -素直に拡張したものになっている。 +And in the case when bytecode is saved and read in later, +because there's no need to parse, we can naturally expect better performance. +However, parsing is a procedure which is done only once at the beginning of a +program and even currently it does not take so much time. Therefore, its +influence will not be so much. -M17N対応 @ruby@ は既に実装されており、CVSレポジトリの -@ruby_m17n@ ブランチから -取得可能だ。実装されたのに取り込まれていないのは仕様が成熟していな -いと判断されたためである。いいインターフェイスさえ設計できれば1.9の途中 -にでも入るのではないだろうか。 -h3. IO +If you'd like to know about how the bytecode evaluator could be, +`regex.c` is worth to look at. +For another example, Python is a bytecode interpretor. -現在のRubyの @IO@ クラスは単純な @stdio@ のラッパーなのだが、 -このアプローチは -プラットフォーム間の微妙な挙動の違いが多すぎる -バッファリングを細かく制御したい +h3. Thread -という二点で不満があった。そこでRiteでは @stdio@ を自前で持つ -ことになりそうである。 +Regarding thread, the thing is native thread support. +The environment around thread has been significantly improved, +comparing with the situation in 1994, the year of Ruby's birth. +So it might be judged that +we can get along with native thread now. -h2. Ruby Hacking Guide -ここまで我々は常に @ruby@ を外から観察する者として行動してきた。だがもち -ろん @ruby@ は展示ケースに収められた製品とは違う。即ち我々の行動いかんに -よってはこちらから影響を与えることができるのである。本書最後の節はコミュ -ニティから提案された @ruby@ に対する働きかけについて話し、現在と未来の -Ruby Hackerたちに対する餞とする。 +Using native thread means being preemptive also at C level, +thus the interpretor itself must be multi-thread safe, +but it seems this point is going to be solved by using a global lock +for the time being. -h3. 世代別GC -まず、第5章でも触れた、木山真人さんによる世代別GC。 -既に述べた通り現在のパッチだと +Additionally, that somewhat arcane "continuation", it seems likely to be removed. +`ruby`'s continuation highly depends on the implementation of thread, +so naturally it will disappear if thread is switched to native thread. +The existence of that feature is because "it can be implemented" +and it is rarely actually used. Therefore there might be no problem. -思ったより速度が出ない -最新の @ruby@ に合わせてアップデートが必要 +h3. M17N -という点が問題なのだが、この場では初めての大型非公式パッチで -あるという点を何より高評価したい。 +In addition, I'd like to mention a few things about class libraries. +This is about multi-lingualization (M17N for short). +What it means exactly in the context of programming is +being able to deal with multiple character encodings. -h3. 鬼車 -いまのRubyが使っている正規表現エンジンはGNU regexの改造版である。その -GNU regexはもともとEmacsのために書かれたもので、それをマルチバイト対応 -にしたものをさらにまつもとさんがPerl互換に改造した。という経緯から容易 -に想像できるように、非常に複雑怪奇な構造になってしまっている。またこの -GNU regexpのライセンスがLGPLであるために @ruby@ のライセンスが非常にやや -こしくなっており、かねてからこのエンジンの置き換えが課題になってきた。 +`ruby` with Multi-lingualization support has already implemented and you can +obtain it from the `ruby_m17m` branch of the CVS repository. +It is not absorbed yet because it is judged that its specification is immature. +If good interfaces is designed, +it will be absorbed at some point in the middle of 1.9. -そこでいきなり登場したのが小迫清美さんの手による正規表現エンジン「鬼車」 -である。これがかなり出来がよいらしく、すぐにでも本体に取りこまれそうだ。 -鬼車は @ruby@ のCVSレポジトリから以下のようにして入手できる。 +h3. IO -
 
-% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma
-
-h3. ripper +The `IO` class in current Ruby is a simple wrapper of `stdio`, +but in this approach, -続いて拙作のripper。 @parse.y@ を改造して拡張ライブラリにしたものだ。 -@ruby@ 本体に対する変更というわけではないが、パーサのコンポーネント化の -一つの方向性としてここで紹介しておく。 +* there are too many but slight differences between various platforms. +* we'd like to have finer control on buffers. +these two points cause complaints. +Therefore, it seems Rite will have its own `stdio`. -ストリーム系のインターフェイスで実装しており、トークンのスキャンだの -パーサでの還元だのをイベント形式で拾うことができる。添付CD-ROMに入れて -おいた\footnote{ripper: 添付 CD-ROM の @archives/ripper-0.0.5.tar.gz@ }ので -使ってみてほしい。なお、このバージョンは半年ほど前の @ruby@ 1.7ベース -なので今の文法とは少し違う。 -これを作ったのはただ「アイデアを思い付いてしまった」というのが理由だっ -たりするだが、そのわりにはうまくいったと思う。実装時間も三日くらいで実 -にお手軽であった。 -h3. 代替パーサ -まだ影も形もないプロダクトではあるが、 @ruby@ とは全く独立に使える -RubyのパーサをC++で書いている人もいるようだ ( @[ruby-talk:50497]@ )。 -h3. JRuby +h2. Ruby Hacking Guide -さらに過激に、インタプリタ全体を書き直してしまえー、 -という動きもある。例えばJavaで書いたRuby -「JRuby \footnote{JRuby `http://jruby.sourceforge.net`}」 -というものが登場している。Jan Arne Petersenさん以下、 -かなりの大所帯で実装しているようだ。 +So far, we've always acted as observers who look at `ruby` from outside. +But, of course, `ruby` is not a product which displayed in in a showcase. +It means we can influence it if we take an action for it. +In the last section of this book, +I'll introduce the suggestions and activities for `ruby` from community, +as a farewell gift for Ruby Hackers both at present and in the future. -ちょっといじってみた感想としては +h3. Generational GC -パーサはかなりちゃんとできている。ヒアドキュメントや空白の微妙な挙動まで正確に再現されている。 -@instance_eval@ が効かないようだ(これは仕方ないか) -組み込みライブラリはまだ少ない(これも仕方ない) -拡張ライブラリは使えない(あたりまえ) -RubyのUNIX centricなところが全部削られているので既存のスクリプトがそのまま動く可能性は低いと思われる -遅い +First, as also mentioned in Chapter 5, +the generational GC made by Mr. Kiyama Masato. +As described before, with the current patch, +* it is less fast than expected. +* it needs to be updated to fit the edge `ruby` -ということは言えそうだ。ちなみに最後の「遅い」がどのくらいかと言うと、 -オリジナルの @ruby@ の20倍くらい(実行時間が)である。ここまで遅いとさす -がに苦しい。やはりJava VMの上でRuby VMが動いているわけだから、遅くない -はずがないのだ。マシンが20倍速になってくれるのを待つしかあるまい。 +these points are problems, but here I'd like to highly value it because, +more than anything else, it was the first large non-official patch. -しかし全体としては想像よりずっとよくできている、という印象を受けた。 -h3. NETRuby -Javaで動くならC#でも動くだろう。というわけでC#で書いたRuby、 -「NETRuby\footnote{NETRuby `http://sourceforge.jp/projects/netruby/`}」 -というのが登場した。作者はartonさんである。 +h3. Oniguruma +The regular expression engine used by current Ruby is a remodeled version of GNU +regex. That GNU regex was in the first place written for Emacs. And then it was +remodeled so that it can support multi-byte characters. And then Mr. Matsumoto +remodeled so that it is compatible with Perl. +As we can easily imagine from this history, +its construction is really intricate and spooky. +Furthermore, due to the LPGL license of this GNU regex, +the license of `ruby` is very complicated, +so replacing this engine has been an issue from a long time ago. -筆者の手元には.NET環境がないのでソースコードしか見ていないのだが、 -本人の弁によると +What suddenly emerged here is the regular expression engine "Oniguruma" by +Mr. K. Kosako. I heard this is written really well, it is likely being +absorbed as soon as possible. +You can obtain Oniguruma from the `ruby`'s CVS repository in the following way. -何より遅い -クラスライブラリがあまりない -例外処理の互換性がいまいち +
+% cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co oniguruma
+
-というあたりが問題らしい。しかし @instance_eval@ は動くらしい(驚愕)。 -h3. @ruby@ の開発に参加するには +h3. ripper -@ruby@ の開発者はあくまでまつもとゆきひろさん個人であり、最終的な -@ruby@ の方向については絶対的な権限がある。だが同時に @ruby@ は -オープンソースソフトウェアであり、誰でも開発に参加できる。参加できる、 -というのは、意見を提案したりパッチを出したりできるということだ。 -以下、具体的な参加方法について話す。 +Next, ripper is my product. It is an extension library made by remodeling +`parse.y`. It is not a change applied to the `ruby`'s main body, but I +introduced it here as one possible direction to make the parser a component. +It is implemented with kind of streaming interface and +it can pick up things such as token scan or parser's reduction as events. +It is put in the attached CD-ROM +\footnote{ripper:`archives/ripper-0.0.5.tar.gz` of the attached CD-ROM}, +so I'd like you to give it a try. +Note that the supported grammar is a little different from the current one +because this version is based on `ruby` 1.7 almost half-year ago. -@ruby@ の場合はメーリングリストを中心に開発が進んでいるので、各メーリン -グリストに参加するのがよい。現在コミュニティの中心となっているメーリ -ングリストは -@ruby-list@, @ruby-dev@, @ruby-talk@ の三つである。 @ruby-list@ は -「Rubyに関係することならなんでもOK」のメーリングリストで、日本語である。 -@ruby-dev@ は開発版 @ruby@ の話をするメーリングリストで、これも日本語であ -る。 @ruby-talk@ は英語のメーリングリストだ。参加方法はRubyの -公式サイト\footnote{Rubyの公式サイト `http://www.ruby-lang.org/ja/`} -の「メーリングリスト」のページに載っている。これらのメーリングリストは -どれも読むだけのメンバーも歓迎なので、とりあえずしばらく参加してみて -議論を眺め、雰囲気を捕むといいのではないだろうか。 +I created this just because "I happened to come up with this idea", +if this is accounted, I think it is constructed well. +It took only three days or so to implement, really just a piece of cake. -日本から活動が始まったRubyだが、最近は「主導権は @ruby-talk@ に移った」 -と言われてしまったりすることもある。 -だが開発の中心が相変わらず @ruby-dev@ であることに変わりはない。なにしろ -@ruby@ のコミット権を持っている人間(即ちコアメンバー)はほとんど日本語 -ユーザなのでわざわざ英語で話すのも面倒だし、自然と @ruby-dev@ に足が向い -てしまう。将来英語を使うコアメンバーが増えてくれば状況も変わるかもしれ -ないが、当分の間は @ruby@ 開発のコアは @ruby-dev@ だろう。 +h3. A parser alternative +This product has not yet appeared in a clear form, +there's a person who write a Ruby parser in C++ which can be used totally +independent of `ruby`. (`[ruby-talk:50497]`). -ただ日本語が使えないと開発に参加できないというのも困るので、今は -@ruby-dev@ の要約を一週間に一度英訳して @ruby-talk@ に流すようになってい -る。筆者もその要約に参加しているのだが、現在は三人の持ち回りで -やっているため非常に厳しい。要約を手伝ってくれるメンバーは常時 -募集中である。我こそはと思うかたは是非 @ruby-list@ で参加表明して -いただきたい。 +h3. JRuby -そして最後に、ソフトウェアはソースコードがあればいいというものでもない。 -各種ドキュメントやウェブサイトの整備も必要である。そしてそういうことを -してくれる人は常に不足ぎみだ。 -ドキュメント関連の活動にもいちおう専用メーリングリストがあるが、とりあえ -ずは @ruby-list@ で「何かやりたい」と言ってくれればいい。筆者もできるだ -け答えるようにするし、他のメンバーも反応してくれるだろう。 +More aggressively, there's an attempt to rewrite entire the interpretor. +For example, a Ruby written in Java, +Ruby\footnote{JRuby `http://jruby.sourceforge.net`}, +has appeared. +It seems it is being implemented by a large group of people, +Mr. Jan Arne Petersen and many others. -h3. 最後に -さて、長かった本書もこれで終わりだ。ページ数との兼ね合いもあるのであら -ゆる部分を懇切丁寧にというわけにはいかなかったが、 @ruby@ の根幹について -は全て語り尽くした。これ以上ウダウダと付け加えるのはよそう。まだわから -ないことがあれば納得するまで自分でソースコードを読んで確かめてほしい。 +I tried it a little and as my reviews, +* the parser is written really well. It does precisely handle even finer + behaviors such as spaces or here document. +* `instance_eval` seems not in effect (probably it couldn't be helped). +* it has just a few built-in libraries yet (couldn't be helped as well). +* we can't use extension libraries with it (naturally). +* because Ruby's UNIX centric is all cut out, + there's little possibility that we can run already-existing scripts without + any change. +* slow +perhaps I could say at least these things. +Regarding the last one "slow", its degree is, +the execution time it takes is 20 times longer than the one of the original +`ruby`. Going this far is too slow. +It is not expected running fast because that Ruby VM runs on Java VM. +Waiting for the machine to become 20 times faster seems only way. -御意見・御感想・誤殖の指摘などは -"青木峰郎 ":mailto:aamine@loveruby.net -までお願いします。 +However, the overall impression I got was, it's way better than I imagined. -"『Rubyソースコード完全解説』 -はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721 -Copyright (c) 2002-2004 Minero Aoki, All rights reserved. +h3. NETRuby +If it can run with Java, it should also with C#. +Therefore, a Ruby written in C# appeared, +"NETRuby\footnote{NETRuby `http://sourceforge.jp/projects/netruby/`}". +The author is Mr. arton. + +Because I don't have any .NET environment at hand, +I checked only the source code, +but according to the author, + +* more than anything, it's slow +* it has a few class libraries +* the compatibility of exception handling is not good + +such things are the problems. +But `instance_eval` is in effect (astounding!). + + +h3. How to join `ruby` development + +`ruby`'s developer is really Mr. Matsumoto as an individual, +regarding the final decision about the direction `ruby` will take, +he has the definitive authority. +But at the same time, `ruby` is an open source software, +anyone can join the development. +Joining means, you can suggest your opinions or send patches. +The below is to concretely tell you how to join. + +In `ruby`'s case, the mailing list is at the center of the development, +so it's good to join the mailing list. +The mailing lists currently at the center of the community are three: +`ruby-list`, `ruby-dev`, `ruby-talk`. +`ruby-list` is a mailing list for "anything relating to Ruby" in Japanese. +`ruby-dev` is for the development version `ruby`, this is also in Japanese. +`ruby-talk` is an English mailing list. +The way to join is shown on the page "mailing lists" at Ruby's official site +\footnote{Ruby's official site: `http://www.ruby-lang.org/ja/`}. +For these mailing lists, read-only people are also welcome, +so I recommend just joining first and watching discussions +to grasp how it is. + +Though Ruby's activity started in Japan, +recently sometimes it is said "the main authority now belongs to `ruby-talk`". +But the center of the development is still `ruby-dev`. +Because people who has the commit right to `ruby` (e.g. core members) are mostly +Japanese, the difficulty and reluctance of using English +naturally lead them to `ruby-dev`. +If there will be more core members who prefer to use English, +the situation could be changed, +but meanwhile the core of `ruby`'s development might remain `ruby-dev`. + +However, it's bad if people who cannot speak Japanese cannot join the +development, so currently the summary of `ruby-dev` is translated once a week +and posted to `ruby-talk`. +I also help that summarising, but only three people do it in turn now, +so the situation is really harsh. +The members to help summarize is always in demand. +If you think you're the person who can help, +I'd like you to state it at `ruby-list`. + +And as the last note, +only its source code is not enough for a software. +It's necessary to prepare various documents and maintain web sites. +And people who take care of these kind of things are always in short. +There's also a mailing list for the document-related activities, +but as the first step you just have to propose "I'd like to do something" to `ruby-list`. +I'll answer it as much as possible, +and other people would respond to it, too. + + +h3. Finale + +The long journey of this book is going to end now. +As there was the limitation of the number of pages, +explaining all of the parts comprehensively was impossible, +however I told everything I could tell about the `ruby`'s core. +I won't add extra things any more here. +If you still have things you didn't understand, +I'd like you to investigate it by reading the source code by yourself as much as +you want. From ab9ea11b847d310a4188b5ef8d89a2c86cf9d58b Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 29 Sep 2013 05:59:18 +0900 Subject: [PATCH 079/121] tweak the epub file name --- script/publish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/publish b/script/publish index 0a81ec2..35de4f8 100755 --- a/script/publish +++ b/script/publish @@ -105,5 +105,5 @@ end FileUtils.mkdir_p EBOOK_DIR sha = `git rev-parse HEAD`[0..5] -epub.save("#{EBOOK_DIR}/rgh-#{today}_#{sha}.epub") +epub.save("#{EBOOK_DIR}/rhg-#{today}_#{sha}.epub") FileUtils.rm_rf("#{TEMP_DIR}") From 17cd468cbc4a215ded99d941131ee9a6cc197f0d Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 29 Sep 2013 06:10:09 +0900 Subject: [PATCH 080/121] add information about the script to generate EPUB --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index fcc4ea5..22239bb 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,19 @@ $ jekyll serve # this compiles files and starts a server on localhost:4000. [Jekyll usage](https://github.com/mojombo/jekyll/wiki/usage) +Reading in EPUB +========= + +Thanks to @avsej, we can read this book in EPUB. + +To genearte an EPUB file, you need to install eeepub additionally. + +```sh +$ gem install eeepub +$ ruby script/publish +``` + + About the version of ruby explained ========== From 7d723107924294bea6789a398a03366bbf1e6b0d Mon Sep 17 00:00:00 2001 From: ocha- Date: Mon, 30 Sep 2013 09:51:46 +0900 Subject: [PATCH 081/121] write the author's email address on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22239bb..2183e00 100644 --- a/README.md +++ b/README.md @@ -81,4 +81,4 @@ This translation work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike2.5 License](http://creativecommons.org/licenses/by-nc-sa/2.5/) If you'd like to translate this work to another language, -please contact the author Minero Aoki. +please contact the author Minero Aoki . From b7e0ef78fae061044ff441af6b390c8b4e0ae3ca Mon Sep 17 00:00:00 2001 From: Mark Burns Date: Wed, 2 Oct 2013 19:13:35 +0100 Subject: [PATCH 082/121] Correct typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2183e00..c159037 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Reading in EPUB Thanks to @avsej, we can read this book in EPUB. -To genearte an EPUB file, you need to install eeepub additionally. +To generate an EPUB file, you need to install eeepub additionally. ```sh $ gem install eeepub From 7a0e26547743a843df35c72c16b425ad03d8952f Mon Sep 17 00:00:00 2001 From: Sergey Avseyev Date: Thu, 3 Oct 2013 09:08:07 +0300 Subject: [PATCH 083/121] Fix most errors reported by epubcheck Likely fixes #29 --- _layouts/default.html | 4 ++-- load.textile | 2 +- minimum.textile | 2 +- script/publish | 20 +++++++++++--------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/_layouts/default.html b/_layouts/default.html index 9b3e1b2..f28bf83 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -1,7 +1,7 @@ - + {% if page.title %} {{ page.title }} | {% endif %} Ruby Hacking Guide @@ -11,7 +11,7 @@

3ETo(XNJ9Sr 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 Wd9-xX=PKj|ES~GfawG{3&ut}Zi{U^P2TCy?5 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 literal 9332 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 K$!&9tHZ5ltD$d!H~5mH5IaCpCS7;gTbg6JEf34 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 diff --git a/images/ch_module_stack.jpg b/images/ch_module_stack.jpg index 8923bc1064fa62c0549d5da3dc59f8ec721b5a83..99f69ff28940eb450094c9492b7fbc8b0d224b7d 100644 GIT binary patch literal 9261 zcmcIp2Ut_twmzXt?_Ck3B?=Ns5RfwT7D_^qssafeArt{o5D{r2kU*%?Lx+(LBH{=N zp*Mj5D$&F-~08o;VQP7;AWT2v;{>CIDr=SE;v9JoUQF94GrP*;K9F{+ss{0pOpvB}7XKFcN z4&h1FLo(Rs!e)MT0atHhBJR@oX8}}!!?3KH zZ2e9ilKjOUQ;0e?9co%)O1OL$Qjx6U7#c;zxLWWes7cl6WhvlAG8oIiep(66IiZ|I zl4s~e|D1mFrmag;P-SVvPXQ>SG)_~Y`MyC7jDfK@rRcKAjkab*4aNdcbC>iuRQr9+4~RliV0MIOE9ZpHRJa5tnagm8&g!COg(NRpR7`To?2yt zgd73YsCh1(C`yYz^ud64FuT!#Up46Flq&=maYrbbBMsMFe~sM>FOipS#YzZm2I>5N zLjNroV)>pn(FQvXua!5v)37u<=S>l1GNpBeR64FfUFY9jj9c1kOk8QY=TkupU+GTc+{L6$qzf46Ql9!-0sal; zA1xWVR!y1x+s2ispoWIpy=wyXkZukRt3gFRXp;hopHlLVB2V=jGo?Y|Y`DGG2lSI| zA3~;VxJUX@3L0rHQ~lEml#J}Wv+Y!7^93Mx+Nmm#OGo$WNSM6U+1HeVL)`wS8D8ms zzU}81c~Y0$Kk3O^yOVbD(9!CI$@e3)sFn|f5@yxziN@B`pJ+$bd?4&yVt0h5HtMue8NBo`vGnbm& zmdwus<%WlLn=C6`MDKa^0{xpCVd~a4fsd-_23}P(qTYyWFEt@FM3C3QwZRy?N?KE> z7;y3&K%G$}F6U8G*qcZ}gECj)sH6~);cZ0nj?p69$S{1aoDq*j1gia>qJ>8KA3$cX zFM5KSq)Or~WAm`SsKP)O>&m^pR9fn9_Xy`TPmw8XJrrqLS|*zArDy0God_*?Zp_V;VxwMn z*`R{C!&&lmy}-^*x!)2zBfKsU zYr&M6OlbyYw8IqVDyH0Gf)AK@|rd?SLJKt%nnA!zd?#d`WGu`mcctV8@I z`!#Ed*64NqNrmj>MlOs^lYB>-TOG?8A<^mdK2}9NT**=o{3qWGSc)8IgCo$k#BgF0 ztPk&!ZxqoVTwbggbfuqv9ARND=`?->)Qask^PCCND)i+Z$5GeVly0YFMMa+@ts-yw zPnlM7Xhw}3bi}xy6z)z*BQDDGy_%4G;rL;Yk`r?%VnV1 zh9lrkgY&xRfkW7!wA%|hmsi1@JxTq{4_(%`IG`R-U@RY!-VO4|h%4|g6v54hg zBe55GKa8~PWZ&cMm7pgnG^r`Tb1Vn>jOw`wy}CG*(3`9+6zaa{%mHjDn|E<8G z+|0h;5s-fbya7$*N>DQ^T@We0b4OQlNZBH)QCU1KSplm|XFWtv2H$tzY`fBBg-Ocb z6v?yZC@;xPa4v&xCRDO$;!4q`=f*jUM3LO7>)yl60x)>(G)$IDP#7v_TQYQ?7^ zOzI#n1(Wq28Sd^-R3N~mj){t6wB9~%1%9@0YFdeH2JJwX`#O!&O6L^}9dd=|eNWdx z^fPGZEFz!BKjd{Fw{x&+8B%B8w3w^0qA`OY^e$#v?UPBEL2fS%HodO0#?3)X3|EJ{ zjRD$NR!(*BiRxAj6XzNPlgW@^O|mIqo4&I-O=s=s63A?h3f%wDQfBMC28ph2}{Msk#QtNqB3U8;0`^s zjbi#hFDi=f1z!!;@0Ep5{s>C|2(nIZ=yrLe?3JxnR#dmd1# zse7o-M9A-E7nYNy)*qNUk7h%-4bF|kvHN6BNer0~lP@+^V@9AgsFx8`O%MA$sXPUF z1qJkB4K5`PEYdOjB^-;1OYBtEq_dSAUI5gavdSf^qqUF>;EFC-K2 z;BM2B!X{x|-dOC}X(r#QbmUVQ)GQYDAixmwhPY!j#owIx-%nZE58Ml^hB(yeQL*w@ zlI9r~1kDZS_w%w@Q>mI^y|wwarpwOL#W~{_ zHrO5?0lg5i_hc<7q1UrFR4}qJnPpLD!j5LO!R=AbZJZ>lwD6B4UX|5XYY^~&ynpZ zR}zW2|H=`>KZuT5PA|S=hLCncb)_Z?`oZyffZ!A11X^4ggfgY!x$; zXab7KmPX&~MO6%rAomV*k6MmLp0UqC!pn#Mt5Bm`E3zm{4jc_n)@T3pvcnqa13=+= zw!^WSTk;~KFugI=(m+|2IxV)5MB6}f(K2Z4J&>XG7d7W^M#nDHSG<(&G;E4N*FLtV z8iL5{t|1BBE)s~5`L|W!Ik3~;qyRv{v&z#maw6gy^{I-M$D(LUlhT8IYlkeyvqg9f zSSmxqQzrCHA<)O?6WO|9H`aHYhfbe5P)_?4Mg3<3-QQ+>epFGG8!`P%!Kb|aBRXyv zV!F3#N;}9Vas=2IKx=?H0MxM)`lOYZxc6lIWb!1E_hD$i!V9m#%PO8m_s%o3A07cW zao?=HK`9@@_&i~J4CCt#@)*Wn8zHy5deifDR_}I3&AvvpkoQV&K#^rt5PoYf=uz(x zaQdX~aROcF&3>XX)S^&DGt{#_r2f zuYAeS&#^=)x*ULZ1DG9{?Acqr`PFj89yLj`{1}f-Jg5^>WKcX)?HBo|Rrs`>E2xrJ3Hdtx{-9)nLz!-af{JCa%T6EVyk3bq^&)8O-l z?A_T0unXQ{ML*vv{>Z=Iy70zAiR%bRUs+KoQeC82NZSsT@2gW>MJong&2A$vZVl{WvWzMf)I}aD`wC7D-lygB0JyaZ_hE7mq#VxJ2nm4@GGS?Z>R0=R9!ukR# ztn)M!MssZqHJYsSmoNBK1b$KTSNop9f7JcH@@P7KwGnl_f@T+He(7#tsk4=6ot#{x zVI*ujSvFRN3c5BKVpR%+(W! zsU;~b`A&lO^WPS#p^l}F+uf8e-JZMgmp`0Sv-{5YlP+@n^MrHjjf_K=x73wmUMI?K zJr4rYK4Qk6i4r&nk~X=->G_=c{OV3ptajVWfIGzIfQOzAq!HV^*w6$d zH$k2e4=@4&gkLML9PJ+>1e6_>@10DygC7+*sd)4sSR zo8TEx(B$OUGr^vyaF}{0R@i=(Lr^Kb~xCXJ*cPdF=C8?=ZAX9rqFvtUd3|-jaV+jk#WA zR;7Nh#H%qOAt}~}wjjp6`(=up+XX$MD{nD-i99q>!F(<={Q^>#+U6hOEvC5{9RjWo z4Hui`rfdVK!zf_=t)rgQ{n4Rk(d3@BJkANPL^{qr(-+=TfzH+!RfxNBIGI4ZtZ`Gp zTA=p@IrM;+9-YOQ z%!k?9kZmi?0ww4@C0x+N8qOmz112QNqT9@qa$L=3kl}IUn*$_{ehEPrxm$$VrG6vr zi{{VG2JJLw(?bJ5!!784C=PnJi*T z!(Zm1J3V?+gg$%-y)P8De%(c*Ipd~uiP>T`OGmViwE)=`qByTvWSviXVF*-U;Ph(P zpEoOJlV0I5=b*u0en-Nh1UFuY^0JtCJGj)ggXqQk0oc6yXi^z>H9uNM%yYu{bhH*{ zkAu!rlhWd7IKB(&NAD>#KuMMoA|1c_Srq)fq9MEb)0evYJtGr`mc86mU%q+rA4-9f z-CiBG36)n-Y|`afs8<8`piCOf^QJPmxwZ}{qdqs`u#NXpMTX|fDZ@3$#Uy{JQA(>V zyw}L(OVic^q-1?h{sO2=Fsi$77W9w58h=(LXs*a86kE|;ACa@tgIVP#B{jjz>=X+^ z2%GM>HmMR9O@tAv0eH8E97WQxRJqUMZPppmu~}A8TUHVsHu8Fj2tov z(Aqdp$N~r#*}GaGk!s^3J6hmD7uh%4Z4O1m$Re#%e1ojjAZ_2`rrsTbsy}#n{!_|n z$*^yXKWUg)m0JO04u>Ms*{}~rqd0FJ30Ai}i0J%McY#Cd8d6nIKj^ghb-dt`a@XL5 z|IZBboxu+5}LSrJpA>8E>_XdkKZgMUX&>Q`t|9=`t_hBZMl9W zNF|$Hz=E9whBuGRA{PNeav=F)p$74QqGj0e$B!Jr9g%gy#34;~+!d~WbNRo%<#-1= zQT=C1ZwjY67;eKQWNGes3f-W{egJd*ms`HSs^&{}Vh7Cci$ zqN(P~!+>P=noOwOP!l{kSjH(I$)SqPB%+5v1K{@KWc~LSv;TDn{$;{(l{gomGH@=H zy1|#HYXMqy>rv;~-subQGfVwtL=S?zFs1#M9rI;B9YdYXF!`6&RW^Bw4yrg%t8#Mi zG|Mo{K@P*lO4+OT@u?5yfol&?_6?eT?V;l2AvYk~&1VQ_cGdW1CoC%lPeKKVz?)OV zCtgt>q7F@{zU&~EJ&eC8bzITyfDt8P@DX(mS*~BSL70C*_M_-V(`47H@Cg`$?X42=16*DaUF~`jDgH zBw_|biaQK7GS|s@uOpe+YWD3Xri490lD6V9Yq8!LXg8SO_$Ot?I%ZQhi&9*j9yuRJ zob{Lp*o1upGl*DWO^6AMxI?++W-n(JD-;r0!jP=F4s3KPByPT^t{+nnfUX0N;MAwq7;g|B|ll;0-mUpY*}=|B?i^! zc#DR?KTAa9?6umI;4~B2M3+^nyR%x9v01`B*T9CU&Q-(;HAn3!FK~!1=_4l1-X*iZ zVV+>yYnYp0F2gl1RANv#&pxsNOoHWDBbu3siiXu*NlKBc5I1-FByF$}20w?F13c7z zT`S*Ro33`1k%6d?t#f>-I@0WFU1$Ycc}!9;m7s5GbAILvNj&Ej&iixuQ!k5zrhjpJ zWUh?y!a@zRkR`roaLF^gID>NX#kH9T{UC%}8u8X3cOZMK$Xi6)($H5Vf^!iOb7ouyqB)IM!iFYD&Q-&GjQtw+vG%^B!vL%r-o<04WT zY9{$7%xp67(oJ;pPT(3~JnUD@gFUZdEoZ~)aagax!9>$%%x0g!OEI=J?5!3ir>LHu z+sv8nMNN)UyReYXn(W5*j=&I=j$F58dp!AHv^9k}rtdwF_~ec#K-yy|-jr9cUg{v! zc_L6fi23e(JIT{LvQNv2FN#Da8C;&}@OM_a5fHv{6LPjH7B~5GRGjMXIcYU|le9fE zoX_orKFt(sBYj$#QoJ9;;Y8thSkwJ19%sIe;z9x~+ zBjhbtxt#s2wietz^!QnS)ZZ)5klZkPKc9;=B&D>QJ8~&YRp{%_JfJx-ouk;8Wz?CM zgy_x7QfEy>N5$$9`|*e}bBiiYztJumc3g>cBHU7(bZH&w?fA&Gxx#8P4 zWU9Aph8X&}R}X%gwLM*eHRib5%@DA$qtMyV@lo zSb%gf+q7<*@5H6jQtT^9OC#%hMg-l?EX9*-Vs_HF-Pppe-rJ#X+1q|y)6=33MJ6Qd z*{qhUbB;E@G(M;>RTMF+ydQo`KUd_MP^L|LnITk0eJQHs7Q$WBT3jRa8nI9< zQ0als`MRjF56n|9#^VE%x@T}j*M*!gd6$zDg=GZh7R2JHh?tO`wS5fak?jWsdp~QU z$%h3ur^HwDqn3spW`#sYF3lF6CNq%HuRf4xy*81SRx+q|>f$VGY}D5^pG-IBk1pO| z%}d5)sq;@@_+W_l>%buVlCNiF*~9z!cB=JWkqkVd5jK&Yw9~NOo~hpCv-hot(L}e@ zNDY{+dmi}}8_ZhdQ)}Ihj=^C$&mF0jxjr^&&t#WXEq3W`1+10&Qt|+l#*uqus1Se~ zkt}BPux*O&c_G^6p3VnWF zYH{IUOm*}F#-CKaeRz=ij$G=uiR57bmDq}Mjv=Wvv{a>vUyjt$@#^YKcf17kp@0)h~+ARvUIbfh&a+mO0+a5^>WDp{iwoP_=c&;c*tX>|F2&K1(ZiI}0lX7bnMC z<{tdV4#xq?04fj&3_3~$27{@osgBVy)6vq<(6TWdhcLt0IXU3$Fc^YIgcos2h#Lmu zli?Q<6_b>dgX}bqesaa6o4b-UPcfT z*Ky{PVrX5%h<@;iQ@k?PZfPvi=8?tX`mT6?QenyKUhebZ&scegcV{Fd^=?j+jWPcj z;}@{+t&D#{{MqDE4IZy>&^_1y-^C`zl)6OX$p& z<@}Llt$heJFnsW8;XuL`2NU%Q_l-&{otP>vXDF5=mpMM>pnslSbXU?s?05%Qo&Fuy z2c&Bb^0PcMz4DOz>=lo7Pd?cFyp^V`wW)O-If%)4i0-@kspMN6#pUd&wZwYVdj%UO zDOEpkfPV|2YXTek4RRD1ww+Kh2tVLB2L20kvOAAXcjfB8bG-Ede%?HJ=HPgRvHN4H z*Rx6Mg&yn zwOoADW`oCcsuGrd_%D$D)5Nz71>?4(+Pc14WF=^8UewlUW-}ib3GX{XJyrM^W#NIL z-{sD!vdBg*%JTqIb2he{^*nk!FY#_|-&-QMO?2mN!+f;nq8dgsWpnr8Qk|T9;oB-3^i6px6XH51Uvt}9>Bj7rdKs^|AnvYNpHHY zC6C&Ejl69roAYx=c{5l~0LDCI&;8~?d$+WVIoRg^i}fE12IiG#bk5Pnsf5ldD@j}b zqOQ*FIb(NXD*lGWfsjSN+~feU`Y#qZeP_z(>HMf3wOjcWEb_I1c{tcc1zmX2P_WbT z65lzhpX4ZIQiQh6PWOIo(AJ3kB7r*-*aBPo9srl@ZN4oSzJA6#NENFJz|`oX#m+R-v-B&OA#>dup zdGvJY5yM!AwWkU(wsmhY+Gw^e1{dL)D+0N8D@AHf4@0uOX%=jwde_gN+Iu@8nS}aS zp6T_@KY-XH>>(?%C7hRj+y%mG-q*0$-mHAbg|cLm*vDXd=|=L zFr;7o$$-Jaf#Q92os0{TbCoFd#BliPS_$)+py-pG=l9#5Hmv%TOhr?TO&0+*${yCg zyF&;wN=6`_9QQ&d zWjRZDw+45%W>cKDcVEu4G+jA1VnypfXV2w5hUo#dLV>)I`Jt8s9^dY~8t~b)GhIcYM2R&9VGZ!@78;&cxz-9|!AUisRQX zz2OyiCYyKG(E6#%xiQ`YWtg1359Vcq7skA>qL#FzlP#D9fOLUcJ+kM!3kU?Mz#BDq z2-vxPSI00J5&7x%HX(N=>JZS;LKLaa4|=5D!IN0Vtt)h;V@BKlw0Gh<5IA|K&g)T; zD7F0JnJv@IXP@r7l^!!kYtFauN(#Mj(>LJ?UlBR|jx-|{c21O_L(uyX8%K^%t3$9d zwSl_6Jc|N75OHb+y6$X6q`_A{F)xE1^DMtBN)3p)eq~MTVRoz_+-IBirGD23B3y6j zZef||ycU`l> z$^KG6TA9W&%-Pmm?JafJ)gA^y+wbfT0a$76K*Mi5R03V=#D>yCKsZfeaxQ7sX&_2U zf9+J_5|<~Z1&0#P?Kq`UaH5?yPh~)=k%mRJs)-GKrcX$&rMIJdd)&)>Fj(#bdQoY8 zV=c&lif#o59nUg&wF*K)H z$nAhXv*nEJEIytK)`6VV9t|~9P(eH%w#fJS|_zBJwR6~b39zOdSpxM`wSG7 zRPW19)VX75KqywUYmVJ>B5J5T^Qwjvf5J9|d5!73rB{36fh=8g#A}Ng!)OX71$1`EDF$U-PM_R1R zyOc4YZ>d$D$a-{huhjAGtGO5Y)eu2ngk0}eB-~pUgNG-YlRR!`$<^rCJ!7Gu|mD2hfcl1wub;g z(;Z2=#WUOK67%)LpshnufbIP#NWW(>;=P?(FpK_na@!-JJ@l4dq z3)T`Z!Sw>g_x_+!UnJ{b5%`FR2Bj*o3o`YC# zr82+41Eb`%N1Df-#jiFfZT9JxMfI(~H%c4pE4t(+v|JMwCGEDNNYSx_+9#+O#)yqj zICnfZ#N5Kab*pHYamgkD6d|8vHxkGf8l9d(QfXJ0{n(&ifpfW0OABX(7QO@>ubMQgCpZ=5V)u%E(<9?@W(;d0&OWNpCDGEC0mc!1~84!_|+oe0z~j_CR(Q zEf71|XScskhRjiT{NUD$^t{ZVltlFXMhW29^bWBixj(hP%+zN?`=Z^mjOa6R;We!6 zuZI#{s9=p?%^&%doMF?!rOZQF0!mNo@QM(Tkjv@jO~VF~LIa zVqvHW*Oy?E-wFDaLU~{3`Y}a>NGe5$EdbI(yfW%&eNuUTS&N#)hUucH;#%->VQumqU>jA|fLlfdX9Sk&NlI-} z)p_5UKRWRqu^*7gZhKcp8KxVc)!<0S#>+G1MpB2g5zb+aE-w>2pW#2TS&0?M-1P#m zAYlst+Qej{I7pOuEhT`Ie<>|H{hmz&4w@D$Td*Cxi5PiJ%h0RWuM88_S7z3&co`fj zI#d!*LcyB74gq?^#eURvXouL73u?h1g9{Rx;U?&)@AVFx)R`~&H3NDTR!P8k(tMU_ zf3p&H?P@KwxEgc_$b-21ngfTxRZ61%AApldPf^?ctKA(4Lfx*-JcGgw@8V4=jsk_z zy}J-&j*kbg!M_fGkOvSIpB7(T%pZP~K96C!Vg{#YQ!Ov(h0^$S*7EZ4hcS4CM$Em4 zv-jz3{dRgmeKJ($jZ4fdlMNF2@)NP@1NWph87zD?lML3ft4{{A^v))O6)6mm!Av-o zeaK*s-4w~}R4bFn?EW-hpzkeV|3b~)X6J!@XNl(w(i@7zS$x`ENctLf4Z&f_VUxLM z-n`8lBj4C4ze|qQ>gfv27ph7TRa8jde**9?j0(S!8L_>Jb-WETb|*(LG#-bGB(EHB z3^;Cl&!nx>bpEXPhM$~-^JAAPZ?kJ6jv*sWN|WI0KNJ5KyMIdr-I+4S*>^j)`x~}9 zcKNdi*K3?h*n++Djs+(cqWoK-`ZrHB|NAe?+eVFohk%&yqnIN{XjL*mgW{2$tXbZ0 z?wcY|En5T&MfV*uadK@e@FT5088w z@Nb1FQM=}afsbD8UJQfP@GkbtnaA1rW$G=tP$_xW>W>iH@t9yaI5J*Ga{}w8pqN%Q znmW+;Ap5x@J`|@0ImThOv+fsBWYI3sSy~Idq{x|*Z*J`kRDY zw910rm&-U4P92`(wZ89R%eUPKxyALj&iY4zFBwdf#nE_ZHJ5;CgJ&~s;=VF?WUW5g z7hEOHK5>$v`y>a|*RmUFy0AeJc}^VQ@>W#&VHbgc@b@!%ZY*~Cbgt&`P@{o{8jmhh z>vFwVK|)>F|1}mKq(LWfqeeyXcp`uS-JR>^5YsM8Yy<(1-+FYaJjx)-h^y$ab4>&WvU9`+f z=uCTrP3SERZIE-CT0IVSK*o6}P7S9FKEbRYZ%7$s_74oG8McLTE59)qSQoF9emYBw z!^l{5akJII7L_Ew}}_=?m;+$Lz?B9RTv0G-`%2C|5LHm^V7*>U)p$E(V@vg?!%Tkea);4_RazGS>!W&0g<$Y)fK|ew%F5muuY%emx7S~Pmc;~Rs+B{_ zKgz;KD1lYb{T|&PMLc;cQlnX&U|eh9yul|B#&C{7-A+3X(>#;+4a3aLg7jhWHn1wo zlIGC_8G#Z7AFOtvu2c9*-YiRNd%{Zjp~b`33@Q_)EtB+dHv) zYkO!m({_1fn;o-wfeHu8bb6?&5^J4$*U44<=L zMcE&H(^k1QbmV?EhklWH-PC2M-22r~(3jhiC6YZVg6vH%S1sm5>g*G$`l*C;AmR{- z{{2{QP50D{$C}qxg*PWPDzJR1c<&t#t8TmQkLZcH!Rt4rv?r&?5N<{zA^N+X@>l4u z8tiai`T7=e0{Fz>_Jcts4Wx(mvx8G=E zH7{BAKM88d6^xOW&{KszonL1xKIjI^*)5{`{XE*-dXM>J%TK2}KR2+#Fa4Vfg_3XKDG`15%g$0z^jrW4tb?jsrecMo zfxs-p4L3?!`ec9q0R}2KnzH=Q`$uv|+P}H}ZN~aZ0oW0st&CgN4juGUr_ax-Dc7{i z`O-cmQ5MS0^#EyEvhU@P zre#A)uMsb^+K)|vI3p6C;Bi~YW91(z+oG42E2|jO%ifu_ETzw)KZ&cVT$?O&@Gnx< zqH>iV1CG+QrDCxMeN23%Q+P#dxdKcIZG)6IU}(9tU{U+7$@O!9akB& zOQuh_*tk`bag!fk07c6@&=Va!_3X&`@3($I=UOY2`6hy!I}< z?hNiKkF!n+!<}b!9Y?G)Nk$*z)wu(E!`|jSu^}AW==jh3Ex)FTtyZ$i9l)1s3?7B6 zCN5vE*G3wzL=+PPyuv)bg_U^Nt#EqV?4tJ1_fBS(++InV1TN92x+nJTmigf!X~OU^ zZ`HS>Uwah)x2j5HtLR6qh2YlC2O(2^l8?8)XNP|v;(we~{(q>LAa{>bzJ=75Bznwc`5xM!*n{k3SGu^5!H>h(J$0IBe9k3Ck*TTSR5UNLRiNhR1|h{KhFpHU2<7Q_ulRb5{x$- z9%vXFO~n_!zPcnAf?xvcw4lp=%d7$CYjr#AKRu+Y%*m4;m&(E9(>6Y#X5)rd_>-hH z9zyqu0#XFput8@GmE~{gE5vhKTlm{KNrVv!h;bSD5!ZzoClh^{SXz~ z6@=^7sKr)@zh`uku~&4OWV3<#a*iCJev8JG8*)uLc8c&24tXz!{{vbz;aUGC;bb033mk&QtNL_bxm}Q?XP|9ntsF0SoQP}5K7IRwUEjcovYGq zkk`5MplHl4oryM-CA7M8)H`uvA0Z)R$Lhk9=-42I--)j18L;E+woc91v=R!=isg^p zU3nT?pL78izsW@G`B7p0h;y&9yu$1G!*I2u3fVIP%M==F1{#uLW!mc#5LOX+t~c>6 z>|&w5x9hdq&32u6^NR=T_W73`^V3LjuwmBL$2ZpO5ZkMK(vs;HNaTV&=M-KF-z%M% z!ApBmz3I;MPRJ-YjX?*ul+Ba>DN5Jf!i?Y6aRMbDOnurXK-GVUoxM)m^uZ#Z%(7EH z(O74!v)D0;nbbDcvlGE)=VWZ!MbYxEGak|d|9v~iB*RVUBABC ze@3-sI2g=WMO&}*_5K)9F}lBaT#`pxeOFTb^ZfJ$r!mI$7v5#)B|1p+M|6a;H1;a5 zGB(#dv}pLaZH77PJJwNpxFZhbqU3DMC#tP>y1z|<&Xj#s*d`_6aRe)U?9C2Qx9Pmr z&3NpsAx8_F`1=$AD$`Z+(_qJ6kCG@T-BU{qjO@?9rw@b+SnO z4V1X9OvMw>G0S_4uHL44%q>B|>S%?w))y&-+Ccn@u>VHef^031+#9R$2b3h4JH-3= zf@NvDsufaVvoJcl271?xHWAVMdO5oN4h^xajuml727b`OXZx|=z)R)T#D|aFGg5fT zt@U=@o^DbZ*roG=XYxLZ5eCA1#df} tcYga5-MQm`my#34Y;7(U@`}&S*0(#2;;jmy9J2LiojGp<*8l8%etVyDcFuqAbN2a%GDH~%oVe=a zU<&|fX$b=k0e&r%1;9}aPb)`X01!ZZ0ABLO!LU^2yI@L&bP+DSI0gFN55l52>ce9FLv~ zJag*Ui`^F~bgl>)2@>5-L7U+L@P^sba>x7!br0-knMs3xrTWW-LjMttf zjY7EMml6_c@$~WaH%_Phv@Cy>g!NGXU^%*$2iy54j-UB`FZF3>zhQ~G;vo4G$A2&R z)7BxB>U#N&0LAXK@9(<(UYq)o?N(vjm-ekSi@Pqr7yW7Lzt$cs(f{MM1rjsFs%~WI zmMn*3nc7#3_<}W#N!e=LvlpH7^R_ zAmWI7;8V-F}81k=}DD;RVcH_y3PJNri#%1GTS6jSbNCue#_nUyLx{o zG+0PMv$oGZyJpC#Q%(L}=TJcBvWdV};_`G0)%&j^kb;b#ipR171rYX3di~XCrQwQP zVSIAV;Gm> zc2+ouZG@foIvj4st&*?_m>=43mwnT|d2zNIHehYr+UJ(;XuL`?^yzjV3PR+a^Dul4;jy@&yEC@rm?Kz7NN> zZ@zdZ7{1}gS{zTpmeCbUHI8Hkg$ITzcbqB`ZxdC%bLL_i)T1lu@qC{26NE2R6mJ*p z7U690_<3%TF7Hc>Dz9RHt9RoXj9sFq=}?P=^;w$sNd!OJ4= zI>Tt1zIq}p+IHPrz`q&5O4>cJB4h{x} z`y=KjxQA8s`DR25ojZNw=G`9!)wiMF_opNuK5B9=RcNfT;~Lz6Q``7T?o(Dsgi+BM z!JB+$Xn#JN1p@DELUcfb@lx3d&ySI*CJ2Ya4pTy*ya8gp>~+G6m3K{%m4f_p5WEE3 zrrle7S|ng*)+v#9HXzA}MrNa+mRIjWLQV2qqTq3q+C_q{^zc)=Fb`eiB+Og(R z=cwxl_YmfTY6q2;yz@HD`}r596kUVDTHkCbQUI%4w_H}#TH5hiekFSiD$_dmD|6+Q z1DnU4zxxuqZ9V_p(<=!d3JRH)ICYTYDB+yL2#N245mN;?o^x+%mWr9MVoOH_q7Z|R z<0i#AIT~H@W3I38B6?l)wGe~GEN0o>g5h(ib2I~+2BGANpqu*b@mlLm} zeZ^WfyVPR)mMc&t!HuJ>F95yaS}iAS;$^=nr*Qg0>Xmp_aJT%{kwIjlka&-<{=7jx zd3acD?p6f`>Z5c_bwhXSebLQktfDVWC~`9Ba|SHLKWZufpgD`a+&EHEF5KK`nuw@A z7On61Iz<}|C!U(Rj#MsQ=6*>!r40!c#b^&}On`c7bO^Po&1L~w-qTI$w-&Z57c)Gm zJR=usxkb_|`zI2eUD4zFDcyro^+thxuUn1wEIITC^n`(?39>cBBn%?{)Z$*YXXQIb zG{gOIUaUL10wXknkW*lwT%KW-gXpiN1A5S@L}>G1^O$fH}Q3F zgwCBd?jvW9wOfMn*fjYC#WgGHJuOHibj+xz!N_;Xl5V)VoS~GKBE|5x4F(k}E+X$g zbEqjh_G+4jK$JWkqWWNmw!j`KH&UZn&-SopeSbbWqBTzhj2-*nmk%8y1qZ>N$aie{ z=qoEr-z0a6ONzT--$3>*T_}9$3`gbq@A^QC$FTkp=A&xz7t|}HHdw7jVL}a{c1wb% zA<~tb13iD8kj))fO#kdQ_>IK0u~POTx~fP3uQW^nWD%k-yyHz3ts>}4_PqwTKde(V zE6_4Th_`V7)gDKeQ2>ePid6mmQd%QUx!OGnKnN9vPbm#FJFQDvX<)gydQH9Ymb>j! zk`rDQ^Tp3y6oWwA&#|Hay0mQe2#W&!E_Z5~mkrIBB!)q~Zg*~&h9wIbOb<-?)@x09 zYi*#TZ=!iCD*8~ei4tCYVhS1<#YA%w=(~?y*nx4r%IYM3lTr$x9eHN*QrnB-P53K2$&$&8_q%t~d`y6Y7?HseD6GrR20p_CPlUpkI1B z2|JRVN>~ru9FX|@G`V&JyXE1yZy`(pjKYJ4=;~%OY6J4#`v>jVHtjE`8sHIclAHsw zqhS)SZGCzT~5Kd6Cn*vgV8BQnuq z5zxgffdCH6=8U(r2$WbC6v~aW;hvky6rV82G?`ShbuVSbS(>AahY`<;NmlhU2B)aRfEw zOFvWhl!|APwI`U#@n*B+D1r?PqqPkZhcJL90^BbDB(jCJ71`~26phDMKTH;lfag9o z7eW+=l7U8r8l{pr$py!n5oEr4ly1^o7V-M~JT3Uy+Xg|SAPj@>@Y-oxf5q;rwyk~) zUh}B3ahf)cljnW)8Ya?`(j?djEzM0&=^e0vGM9Gm=3)ag9aDFVJ$G`aLO*!lJj1qr=6tV7;+y1?ZG}Qso_w;EHoUEd3DtG_ z{T3}RKCAVI#+O$-g)qoZUr(NA|Jc=1wC$10`;lxfiT?M?3b%rnO=U4{{3N?ca`S3ydml~h6HBRoZC_01=yh*Y_>711UFn~)CKD4vkEx+`!h?#5HFkn3WY+bK45U+VPPQ!&O#3o z;$pd$ZxiBQc5~he3ZS?1^2&!x$S|7MzrbIaKgcRhw4poU@>Wu9jc@@rM-)k6t>~s^$+N7yWI0cY8 z=wFAx^p2Zw5BHu9tGV{BD(v+8hNQTAc@4~mmCq*v=e9L_z^Xpi_UY9Ie>Mp;LB*wC zFWk?=BsX1k8xj07{(E|Gs_qycoT_%6H@-bpsd!}k2i^ou`EQprRsGnjvtumARJoG^ z7|&&_m)b%l>>fEt=d_2|n*cz;l!~QS0d;(<^W~QMlOtj3Z!t<-LCl;_MwCM;_2gh1 zkm1GPmJX=>vC6W_r{wg>VfbcxXugNWAZxY6`Yh8p7~58{(s1MW3ZE1$yN?cPqz%Q0 zudHJt>oCAf`7?-Y%#O5(!wn5ZC8 z;o%`_q8HRU1I^zll3^D?GuKZRW9MhMkTbzwQS%>AU@xuX+|G6zsro%rtc*EquuGoU z4e_iqlpEYkasyO>toPWAEUckvDV z=OXuOXCU+A`uDRGz@3qcLo0vfGuFQ{$99G(PVi>gQqdFvRmOPuJj&xya{j!&a8b1q z=CUh(MY*{dCxUBPdCS}@<-qrdq!XE4#(Hl#A<{_~RvsFbk;%gS{+plrx6R*Nvj5!U ze(b(l53kTled4imwMO~%Z6S1 z8I>x(@+p?nBPzzL_nFbB3$``r@XXMF=OA)8_R>w@Vhb_jeDHs02RgHWLR2`tMr)s# z*in*6zOHJnWfAoR1<*{Z4<2-`9a`u56w_S%iDxBflqy_*PxN4GlbO!_c54GNr`FF~ zH>}q04&6rl<~6ZwcaJe;Y%R8Qx&eOL&VD2PmbIOB)+~B5O#!U*)6Hb;$kG)bI4LGA zWV|ha$jA`;dv)G5g?gvtF<4_dBSY}7A}SuGFE9G`_o{r0)c)MH8Am!lZuHf?+vg14 zU84Z51#j&A(;sPdYQ?x5BGam}1tGY(bg3 zg9As_B604Lr+B6tN}L}Dnqadcv;hb8XDgP+?SVFB!N>&kg-A~=Wl~?ErGOKce&5T}1e+h(rdnYBZ zb2IhH5Z&b+i!B9`t@rIybhF_j?;KJ`gFSe%dE5iD?Yw~hw`xoqA>cB3v+C@5dmJVz z1XY-&3N!aKLUpF}KADeNEV)77^!Hc$k0orrgp1AX@A}^E9!@@aT;ViQ)JMn$Txj*m z%`n}2sU*$NtGz+>9#fKO|Ge3493jIQH)53gI&w`izfbOwK*Y!A6Ahg#b3NBab-fln zujhNgPO+6R`Rv5l>_72Mc8?bB+6bXRCvDrK+_*CHUUuHRUZjN@U2cjd5i9Fs!b@oN zyt@^KNUmwgu7)(#t>GcZC*y$9 zBg)y#B!ntx_Q88z=Ae{?TJ>IY52$G4Ofls2{ftZ0;9esvN1GK&{^i1XY%Qm@smaGe zxGps9B1t%_4<&yWPCbghDCJ(G%*v7P|Mq0UI-P_Tm?J_)dj)kt zZL3+rH;zk#`@s!xcae^)Lt>W=-B_#GO^gygd_;uL8{=Mf+IO-?%0^ae-@Fx%KLQwR znE5!Ml%U((=Zfyr9KOHt1;idk?u90$Kab0a7t+E$6gcs=`B7y(zNJJ-+;{9ExMed1 znzt2kBeoAO+@vn70UaY7LE7u)PY{i=^GD0C7Tdj9=(E>H$Z=L8D1e|4k61jav~Uwg zLOE50YWX?6vJucNc@kj~<@O+_1Y@DsS;vXWJsoV`aVLxlllj_jq?CNt5^NbAggh%-}B`vfo2OeHZ z8$@?8y^ATK247G~<7_{;=@9uCmJE&|B6sC#cC2(TsWs0Lb^}SJnDEU7T^A9QvbEC! zu-mDJ9L;OH$!*zVf!@VBr5lMTBMa=~#3J7*z}RY{G#whRu;=#(z0$3}clTA;_~RR3k_>^7kU_;--KUCv&<&#USv79+GWz+Q>2tf$PzJ>a+jG)yxLl&75jl< zQddLW=Qyp(u{7cX2$X+;Od7PaRuW5dcR}~W7nVP@(Y>|6Y>ZBH0F!X_$1eKiMH1Ob zPYOiJ3gkX313aZ^QwPPhD;3U)OeGN=tvq!IGzG_x4}@(wxVzuV8!2pu*0!%EE-vgp zZSuQuI#4Iv7wR7qU@KPB-(tv}d|?W>eLmg=rBj$Cb?)>cV?c$FULJ7(cUAsex)1O7 zi2BrLNdA#l6q22Qnif6eO|2ETVE3VyEe2X7ouC;TUdpGB#NdZ>P{U-k$j%E2Dd;tE zq>c%Hwe-@$$i%cU(G@0dr682E&ES#cxfDxc$r8BkZ)5l(Ul9VK>RD(^7c+kT$%~M8 zSNM`efwwJAWhMpTdvsU_wdS9lk@?0@48H-v1}1FoiZ@x<7M@M@?}8zE`@{H54QZ*Q zJ6jd!c8yD(_!5Z@E#+>TpANz8^C$F#p}~GC)i4^hhuFB2=y7OYJNW@lvE6jICDRdZ ZVh|tozR*zn?!Vxh|HyCuTn3^H{}0-oRT=;Q literal 7822 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 diff --git a/images/ch_module_vars.jpg b/images/ch_module_vars.jpg index 81d353aa779b7a3772409a309eb44be375efa05e..89876844af8e87403687c5abad342b7b61da2089 100644 GIT binary patch literal 15799 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 N|3f}KO=nI<{}*&)bw&UH From 06c670e1de08e1aaac3b482d98bcdcf8970f953e Mon Sep 17 00:00:00 2001 From: ocha- Date: Fri, 20 Sep 2013 15:37:31 +0900 Subject: [PATCH 070/121] edit chapter 15 a little --- method.textile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/method.textile b/method.textile index def8c46..8a1c8e6 100644 --- a/method.textile +++ b/method.textile @@ -238,7 +238,7 @@ The point is that "in the `else` side the values of arguments are also stored in

 VALUE rb_cv_get(VALUE klass, char *name)
@@ -83,17 +83,18 @@ These last functions are for accessing global variables.  They are a
 little different from the others due to the use of `struct
 global_entry`. We'll explain this while describing the implementation.
 
-h3. Important points
+h3. Points of this chapter
 
-The most important topic of this chapter is "Where and how are variables
+The most important point when talking about variables is "Where and how are variables
 stored?", in other words: data structures.
 
 The second most important matter is how we search for the values. The scopes
 of Ruby variables and constants are quite complicated because
 variables and constants are sometimes inherited, sometimes looked for
 outside of the local scope... To have a better understanding, you
-should first try to guess from the behavior how it could be
-implemented, then compare that with what is really done.
+should think by comparing the implementation with the specification,
+like "It behaves like this in this situation so its implementation
+couldn't be other then this!"
 
 h2. Class variables
 
@@ -150,8 +151,9 @@ function for raising an exception, so it can be ignored for the same
 reasons. In `ruby`, you can assume that all functions ending with
 `_error` raise an exception.
 
-After removing all this, we can see that while following the `klass`'s
-superclass chain we only search in `iv_tbl`. At this point you should
+After removing all this, we can see that it is just following the `klass`'s
+superclass chain one by one and searching in each `iv_tbl`.
+... At this point, I'd like you to
 say "What? `iv_tbl` is the instance variables table, isn't it?" As a
 matter of fact, class variables are stored in the instance variable
 table.
@@ -256,8 +258,8 @@ really work.
 
 h4. `rb_const_get()`
 
-We'll now look at `rconst_get()`, the function to read a
-constant. This functions returns the constant referred to by `id` from the class
+We'll now look at `rb_const_get()`, the function to read a
+constant. This function returns the constant referred to by `id` from the class
 `klass`.
 
 ▼ `rb_const_get()`
@@ -392,8 +394,9 @@ top-level. Built-in classes like `String` or `Array` have for example
 an entry in it. That's why we should not forget to search in this
 table when looking for top-level constants.
 
-The next block is related to autoloading. This allows us to automatically
-load a library when accessing a top-level constant for the first
+The next block is related to autoloading.
+It is designed to be able to register a library that is loaded automatically
+when accessing a particular top-level constant for the first
 time. This can be used like this:
 
 
@@ -407,7 +410,9 @@ an efficient approach, when a library is too big and a lot of time is spent on l
 
 This autoload is processed by `rb_autoload_xxxx()`. We won't discuss
 autoload further in this chapter because there will probably be a big
-change in how it works soon (The way autoload works _did_ change in
+change in how it works soon.
+
+(translator's note: The way autoload works _did_ change in
 1.8: autoloaded constants do not need to be defined at top-level
 anymore).
 
@@ -436,7 +441,8 @@ there's no need to do any check. Therefore implementation is very
 simple.
 
 But there is still quite a lot of code. The reason for this is that global
-variables are quite different from normal variables. Functions like
+variables of Ruby are equipped with some gimmicks which make it hard to regard
+them as mere variables. Functions like
 the following are only available for global variables:
 
 * you can "hook" access of global variables
@@ -468,12 +474,14 @@ h4. Hooks
 
 You can "hook" read and write of global variables.
 
-Hooks can be also be set at the Ruby level, but I was thinking: why not
-instead look at C level special variables for system use like
-`$KCODE`? `$KCODE` is the variable containing the encoding the
-interpreter currently uses to handle strings. It can only be set to
-special values like `"EUC"` or `"UTF8"`. But this is too bothersome so
-it can also be set it to `"e"` or `"u"`.
+Although hooks can be also be set at the Ruby level,
+I think the purpose of it seems rather to prepare the special variables
+for system use like `$KCODE` at C level.
+`$KCODE` is the variable containing the encoding the
+interpreter currently uses to handle strings.
+Essentially only special strings like `"EUC"` or `"UTF8"` can be assigned to
+it, but this is too bothersome so it is designed so that `"e"` or `"u"` can
+also be used.
 
 
 p($KCODE)      # "NONE" (default)
@@ -490,14 +498,14 @@ from "kanji" (the name of Chinese characters in Japanese).
 You might say that even with `alias` or hooks,
 global variables just aren't used much, so it's functionality that doesn't
 really mater. It's adequate not to talk much about unused
-functions, and I need some pages for the analysis of the parser and
-evaluator. That's why I'll proceed with the explanation below throwing
-away what's not really important.
+functions, and I'd like to use more pages for the analysis of the parser and
+evaluator. That's why I'll proceed with the explanation below
+whose degree of half-hearted is 85%.
 
 h3. Data structure
 
-When we were looking at how variables work, I said that the way they
-are stored is important. That's why I'd like you to firmly grasp the
+I said that the point when looking at how variables work is the way they
+are stored. First, I'd like you to firmly grasp the
 structure used by global variables.
 
 ▼ Data structure for global variables
@@ -622,16 +630,15 @@ created, `rb_global_entry()` will never return NULL.
 
 This was mainly done for speed. When the parser finds a global
 variable, it gets the corresponding `struct global_entry`. When
-reading the value of the variable, the parser just has to get the
-value from the entry (using `rb_gv_get()`), and has no need to do any
-check.
+reading the value of the variable, the value is just obtained from the entry
+(using `rb_gv_get()`).
 
 Let's now continue a little with the code that follows. `var->getter`
-and others are set to `undef_xxxx`. `undef` means that the global
-`setter/getter/marker` for the variable are currently undefined.
+and others are set to `undef_xxxx`. `undef` probably means that they are
+the `setter/getter/marker` for a global variable whose state is undefined.
 
 `undef_getter()` just shows a warning and returns `nil`, as even
-undefined global variables can be read. `undef_setter()` is quite
+undefined global variables can be read. `undef_setter()` is a little bit
 interesting so let's look at it.
 
 ▼ `undef_setter()`

From deddbf865c7cfcb264ed1626df787e1e4e76b8bc Mon Sep 17 00:00:00 2001
From: ocha- 
Date: Sun, 8 Sep 2013 03:18:15 +0900
Subject: [PATCH 041/121] edit chapter 06

because the code syntax spanning multilines cannot be compiled.
---
 variable.textile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/variable.textile b/variable.textile
index 3a3a019..957e3a5 100644
--- a/variable.textile
+++ b/variable.textile
@@ -80,8 +80,8 @@ VALUE rb_gvar_set(struct global_entry *ent, VALUE val)
 
These last functions are for accessing global variables. They are a -little different from the others due to the use of `struct -global_entry`. We'll explain this while describing the implementation. +little different from the others due to the use of `struct global_entry`. +We'll explain this while describing the implementation. h3. Points of this chapter @@ -532,8 +532,8 @@ structure used by global variables. `rb_global_tbl` is the main table. All global variables are stored in this table. The keys of this table are of course variable names -(`ID`). A value is expressed by a `struct global_entry` and a `struct -global_variable` (figure 1). +(`ID`). A value is expressed by a `struct global_entry` and +a `struct global_variable` (figure 1). !images/ch_variable_gvar.png(Global variables table at execution time)! From 8acf3fc5564e3b0c7962372e22ec644f29cce287 Mon Sep 17 00:00:00 2001 From: Yohei YASUKAWA Date: Sun, 8 Sep 2013 20:41:23 +0900 Subject: [PATCH 042/121] Translate the first half of 'Static Analysis' chapter in Intro --- intro.textile | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/intro.textile b/intro.textile index c81268e..99bb6ed 100644 --- a/intro.textile +++ b/intro.textile @@ -518,38 +518,40 @@ which is really important information (e.g. @rb_str_length@). h4. Read documents -内部構造を解説したドキュメントが入っていることもある。 -特に「@HACKING@」といった名前のファイルには注意だ。 +Sometimes a document describes the internal structure is included. +Especially be careful of a file named @HACKING@ etc. -h4. ディレクトリ構造を読む +h4. Read the directory structure -どういう方針でディレクトリが分割されているのか見る。 -そのプログラムがどういう作りになっているのか、 -どういうパートがあるのか、概要を把握する。 +You should read in what policy the directories are devided. +You can grasp the overview about how the program is structured, and what the parts are. -h4. ファイル構成を読む +h4. Read the configuration of the files -ファイルの中に入っている関数(名)も合わせて見ながら、 -どういう方針でファイルが分割されているのか見る。ファイル名は -有効期間が非常に長いコメントのようなものであり、注目すべきである。 +While browsing the name of the functions, see how the file files are divided. +You should pay attention to the file names because they are like comments +whose lifetime is very long. +Another important viewpoint is to locate a module in the file. +Functions for the module are thought to be located in a series. +So, you can understand the module's structure from the order of functions. -さらに、ファイルの中にまたモジュールがある場合、モジュールを構成する関 -数は近くにまとまっているはずだ。つまり関数の並び順からモジュール構成 -を見付けることができる。 +h4. Investigate abbreviations -h4. 略語の調査 - -わかりにくい略語があればリストアップしておいて早めに調べる。 -例えば「GC」と書いてあった場合、それがGarbage Collectionなのか -それともGraphic Contextなのかで随分と話が違ってしまう。 +As you encounter ambiguous abbreviations, make a list of them and investigate +each of them as early as possible. For example, suppose @GC@ is short for Garbage Collection. +But the context will be very different if it's actually short for Graphic Context. +Abbreviations for a program are generally made by the methods like taking +the initial letters or dropping the vowels. Note especially the fact that +popular abbreviations in the fields of the program's target are used without notice. +You should be familiar with them at an early stage. プログラム関係の略語はたいてい単語の頭文字を取るとか、単語から母音を落とす、 という方法で作られる。特に対象プログラムの分野で有名な略語は問答無用で 使われるのであらかじめチェックしておこう。 -h4. データ構造を知る +h4. Understand data structure データとコードが並んでいたら、まずデータ構造から調べるべきである。つま りCならヘッダファイルから眺めるほうが、たぶんいい。そのときはファイル @@ -562,7 +564,7 @@ h4. データ構造を知る リストだろうと想像できる。同様に、@parent@・@children@・@sibling@と言った要 素があれば十中八九ツリーだ。@prev@ならスタックだろう。 -h4. 関数同士の呼び出し関係を把握する +h4. Understand the relationship between functions 関数同士の関係は名前の次に重要な情報だ。呼び出し関係を表現したものを 特に「コールグラフ」と言うが、これは非常に便利である。このへんは @@ -574,7 +576,7 @@ h4. 関数同士の呼び出し関係を把握する 筆者が本書のために@ruby@を解析したときは、小さなコマンド言語と パーサを適当にRubyで書き、@graphviz@というツールに渡して半自動生成した。 -h4. 関数を読む +h4. Read functions 動作を読んで、関数のやることを一言で説明できるようにする。関数関連図を 見ながらパートごとに読んでいくのがいい。 From a8117823452da339a1403cbd5b5aaa4de1255abe Mon Sep 17 00:00:00 2001 From: Johnny Mukai & Yohei Yasukawa Date: Mon, 9 Sep 2013 08:27:44 -0400 Subject: [PATCH 043/121] Add translations for two sections of intro. --- intro.textile | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/intro.textile b/intro.textile index 99bb6ed..413ae32 100644 --- a/intro.textile +++ b/intro.textile @@ -547,34 +547,28 @@ the initial letters or dropping the vowels. Note especially the fact that popular abbreviations in the fields of the program's target are used without notice. You should be familiar with them at an early stage. -プログラム関係の略語はたいてい単語の頭文字を取るとか、単語から母音を落とす、 -という方法で作られる。特に対象プログラムの分野で有名な略語は問答無用で -使われるのであらかじめチェックしておこう。 - h4. Understand data structure -データとコードが並んでいたら、まずデータ構造から調べるべきである。つま -りCならヘッダファイルから眺めるほうが、たぶんいい。そのときはファイル -名から想像力を最大限に働かせよう。例えば言語処理系で@frame.h@というファ -イルがあったら恐らくスタックフレームの定義だ。 - - -また構造体の型とメンバ名だけでも随分といろいろなことがわかる。例え -ば構造体の定義中に自分の型へのポインタで@next@というメンバがあればリンク -リストだろうと想像できる。同様に、@parent@・@children@・@sibling@と言った要 -素があれば十中八九ツリーだ。@prev@ならスタックだろう。 +If you find both data and code, you should first investigate the data structure. +In other words, when exploring code in C, it's better to start with the header file. +When reading filenames, you should use your imagination as much as possible. +For example, if you find @frame.h@, it would probably be the stack frame definition. -h4. Understand the relationship between functions +Also, you can understand many things from the type and member name in a structure. +For example, if you find the member @next@, which points to its own type, then it +will be a linked list. Similarly, when you find members such as @parent@, @children@, +and @sibling@, then it must be a tree structure. When @prev@, it will be a stack. -関数同士の関係は名前の次に重要な情報だ。呼び出し関係を表現したものを -特に「コールグラフ」と言うが、これは非常に便利である。このへんは -ツールを活用したい。 +h4. Understanding the relationship between functions +After names, the next most important thing to understand is the relationships between +functions. It's very useful to visualize the relationship between functions and +their callers with a tool called a "call graph". I highly recommend you use one. -ツールはテキストベースで十分だが、図にしてくれれば文句無しだ。 -ただそういう便利なものはなかなかない(特にフリーのものは少ない)。 -筆者が本書のために@ruby@を解析したときは、小さなコマンド言語と -パーサを適当にRubyで書き、@graphviz@というツールに渡して半自動生成した。 +A text-based tool is sufficient, but call graph tool that generates an actual graph is even better. +There are not so many tools that generate these graphs, though and most are shareware, not OSS or freeware. +I often use graphviz to generate these graphs. +I also implemented a small Ruby parser to generate output for graphviz, then graphviz generates the graph. h4. Read functions From 25c8cdf8cfa2c367d1191213c0d074ebd4ceb291 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 10 Sep 2013 17:17:13 +0900 Subject: [PATCH 044/121] edit intro --- intro.textile | 118 ++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 51 deletions(-) diff --git a/intro.textile b/intro.textile index 413ae32..da80023 100644 --- a/intro.textile +++ b/intro.textile @@ -432,17 +432,20 @@ considered as "one set goal", but apparently it will not be useful for reading t actually. It will not be a trigger of any concrete action. Therefore, your first job will be to drag down the vague goal to the level of a concrete thing. -Then, what will the method be? Firstly, it's good if you pretend that you are the composer of +Then how can we do it? The first way is thinking as if you are the person who wrote the program. You can utilize your knowledge in writing a program, in this case. For example, when you are reading a traditional "structured" programming by somebody, you will analyze it hiring the strategies of structured programming too. That is, you will divide the target into -pieces, little by little. For another example, suppose you are reading a GUI program that walks -around in an event loop, you can just start looking at the event loop before studying the roles -of the event handlers. In another case, you will look up what "M" is for in MVC (Model View Controller). +pieces, little by little. +If it is something circulating in a event loop such as a GUI program, +first roughly browse the event loop then try to find out the role of each event +handler. Or, try to investigate the "M" of MVC (Model View Controller) first. -Secondly, keep in mind the methods of analysis. Everybody might have certain analysis methods, -but they are often done based on experience and relying inspiration. It's crucially important -to give it to the notion how to read source code well. +Second, it's good to be aware of the method to analyze. +Everybody might have certain analysis methods, +but they are often done relying on experience or intuition. +In what way can we read source codes well? +Thinking about the way itself and being aware of it are crucially important. Well, what are such methods like? I will explain it in the next section. @@ -464,20 +467,22 @@ should at least be closer to the fact than dynamic analysis. h3. Dynamic analysis -h4. Use the target program +h4. Using the target program You can't start without the target program. First of all, you need to know in advance what the program is like, and what are expected behaviors. -h4. Follow the behavior using the debugger +h4. Following the behavior using the debugger If you want to see the paths of code execution and the data structure produced as a result, it's quicker to look at the result by running the program actually than to emulate the behavior in your brain. In order to do so easily, use the debugger. -However, there is not adequate tools unfortunately, especially in free software, -that can generate the picture of the data structure at execution. A snapshot of the comparatively -simpler structure may be obtained by converting text data obtained instantly into a picture using +I would be more happy if the data structure at runtime can be seen as a picture, +but unfortunately we can nearly scarcely find a tool for that purpose +(especially few tools are available for free). +If it is about a snapshot of the comparatively simpler structure, +we might be able to write it out as a text and convert it to a picture by using a tool like graphviz\footnote{graphviz……See doc/graphviz.html in the attached CD-ROM}. But it's very difficult to find a way for general purpose and real time analysis. @@ -492,85 +497,96 @@ If you are watching the history of one variable, for example, it may be easier t to look at the dump of the result of the print statements embed, than to track the variable with a debugger. -h4. Understanding code by modifying it +h4. Modifying the code and running it -Say for example, you do not understand some part of the code or a particular parameter, -just make a small change and then re-run the program. -By trying out small changes and seeing how they affect the code you will understand how it works. +Say for example, in the place where it's not easy to understand its behavior, +just make a small change in some part of the code or a particular parameter +and then re-run the program. +Naturally it would change the behavior, thus you would be able to infer the +meaning of the code from it. -It goes without saying, you should have an original binary to compare your changes to. +It goes without saying, you should also have an original binary +and do the same thing on both of them. h3. Static analysis h4. The importance of names -Static analysis is simply source code analysis. Therefore, source code analysis is +Static analysis is simply source code analysis. And source code analysis is really an analysis of names. File names, function names, variable names, type names, -member names -- A program is just a bunch of names. +member names -- A program is a bunch of names. -One of the most powerful tools for creating abstractions in programming is naming. -This may seem obvious but keeping this in mind will make reading much more efficient. +This may seem obvious because +one of the most powerful tools for creating abstractions in programming is naming, +but keeping this in mind will make reading much more efficient. -Also, I'd like to mention something about coding rules. +Also, we'd like to know about coding rules beforehand to some extent. For example, in C language, @extern@ function often uses prefix to distinguish the type of functions. -And in object-oriented programs, the name of member fields in a function often includes prefix, -which is really important information (e.g. @rb_str_length@). +And in object-oriented programs, function names sometimes contain the +information about where they belong to in prefixes, +and it becomes valuable information (e.g. @rb_str_length@). -h4. Read documents +h4. Reading documents Sometimes a document describes the internal structure is included. Especially be careful of a file named @HACKING@ etc. -h4. Read the directory structure +h4. Reading the directory structure -You should read in what policy the directories are devided. -You can grasp the overview about how the program is structured, and what the parts are. +Looking at in what policy the directories are divided. +Grasping the overview such as how the program is structured, and what the parts are. -h4. Read the configuration of the files +h4. Reading the file structure -While browsing the name of the functions, see how the file files are divided. +While browsing (the names of) the functions, +also looking at the policy of how the files are divided. You should pay attention to the file names because they are like comments whose lifetime is very long. -Another important viewpoint is to locate a module in the file. -Functions for the module are thought to be located in a series. -So, you can understand the module's structure from the order of functions. +Additionally, if a file contains some modules in it, +for each module the functions to compose it should be grouped together, +so you can find out the module structure from the order of the functions. -h4. Investigate abbreviations + +h4. Investigating abbreviations As you encounter ambiguous abbreviations, make a list of them and investigate -each of them as early as possible. For example, suppose @GC@ is short for Garbage Collection. -But the context will be very different if it's actually short for Graphic Context. +each of them as early as possible. For example, when it is written "GC", +things will be very different depending on whether it means "Garbage Collection" +or "Graphic Context". Abbreviations for a program are generally made by the methods like taking -the initial letters or dropping the vowels. Note especially the fact that -popular abbreviations in the fields of the program's target are used without notice. -You should be familiar with them at an early stage. +the initial letters or dropping the vowels. Especially, +popular abbreviations in the fields of the target program are used +unconditionally, thus you should be familiar with them at an early stage. + -h4. Understand data structure +h4. Understanding data structure If you find both data and code, you should first investigate the data structure. -In other words, when exploring code in C, it's better to start with the header file. -When reading filenames, you should use your imagination as much as possible. +In other words, when exploring code in C, it's better to start with header files. +And in this case, let's make the most of our imagination from their filenames. For example, if you find @frame.h@, it would probably be the stack frame definition. -Also, you can understand many things from the type and member name in a structure. +Also, you can understand many things from the member names of a struct and their types. For example, if you find the member @next@, which points to its own type, then it will be a linked list. Similarly, when you find members such as @parent@, @children@, and @sibling@, then it must be a tree structure. When @prev@, it will be a stack. -h4. Understanding the relationship between functions +h4. Understanding the calling relationship between functions After names, the next most important thing to understand is the relationships between -functions. It's very useful to visualize the relationship between functions and -their callers with a tool called a "call graph". I highly recommend you use one. +functions. A tool to visualize the calling relationships is especially called a +"call graph", and this is very useful. For this, we'd like to utilize tools. -A text-based tool is sufficient, but call graph tool that generates an actual graph is even better. -There are not so many tools that generate these graphs, though and most are shareware, not OSS or freeware. -I often use graphviz to generate these graphs. -I also implemented a small Ruby parser to generate output for graphviz, then graphviz generates the graph. +A text-based tool is sufficient, +but it's even better if a tool can generate diagrams. +However such tool is seldom available (especially few tools are for free). +When I analyzed @ruby@ to write this book, +I wrote a small command language and a parser in Ruby and +generated diagrams half-automatically by passing the results to the tool named @graphviz@. -h4. Read functions +h4. Reading functions 動作を読んで、関数のやることを一言で説明できるようにする。関数関連図を 見ながらパートごとに読んでいくのがいい。 From a54abd40c34731c7aac4c7f598f7e51e4ccfe104 Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 10 Sep 2013 17:28:53 +0900 Subject: [PATCH 045/121] the rest of intro --- intro.textile | 1067 +++++++++++++++++++++++++++---------------------- 1 file changed, 586 insertions(+), 481 deletions(-) diff --git a/intro.textile b/intro.textile index da80023..caa8ea3 100644 --- a/intro.textile +++ b/intro.textile @@ -588,63 +588,71 @@ generated diagrams half-automatically by passing the results to the tool named @ h4. Reading functions -動作を読んで、関数のやることを一言で説明できるようにする。関数関連図を -見ながらパートごとに読んでいくのがいい。 +Reading how it works to be able to explain things done by the function concisely. +It's good to read it part by part as looking at the figure of the function +relationships. +What is important when reading functions is not "what to read" +but "what not to read". The ease of reading is decided by how much we can cut +out the codes. What should exactly be cut out? It is hard to understand without +seeing the actual example, thus it will be explained in the main part. -関数を読むときに重要なのは「何を読むか」ではなく「何を読まないか」であ -る。どれだけコードを削るかで読みやすさが決まると言ってよい。具体的に何 -を削ればいいか、というのは実際に見せてみないとわかりづらいので本文で解 -説する。 +Additionally, when you don't like its coding style, +you can convert it by using the tool like @indent@. -それとコーディングスタイルが気にいらないときは@indent@のようなツールを -使って変換してしまえばいい。 +h4. Experimenting by modifying it as you like -h4. 好みに書き換えてみる +It's a mystery of human body, +when something is done using a lot of parts of your body, +it can easily persist in your memory. +I think the reason why +not a few people prefer using manuscript papers to a keyboard +is not only they are just nostalgic +but such fact is also related. -人間の身体というのは不思議なもので、できるだけ身体のいろんな場所を使い -ながらやったことは記憶に残りやすい。パソコンのキーボードより原稿用紙の -ほうがいい、という人が少なからずいるのは、単なる懐古趣味ではなくそうい -うことも関係しているのではないかと思う。 +Therefore, because merely reading on a monitor is very ineffective to remember +with our bodies, rewrite it while reading. +This way often helps our bodies get used to the code relatively soon. +If there are names or code you don't like, rewrite them. +If there's a cryptic abbreviation, +substitute it so that it would be no longer abbreviated. +However, it goes without saying but you should also keep the original source +aside and check the original one when you think it does not make sense along the +way. Otherwise, you would be wondering for hours because of a simple your own +mistake. And since the purpose of rewriting is getting used to and not rewriting +itself, please be careful not to be enthusiastic very much. -そういうわけで単にモニタで読むというのは非常に身体に残りにくいので、 -書き換えながら読む。そうするとわりと早く身体がコードに馴染んでくること -が多い。気にくわない名前やコードがあったら書き換える。わかりづらい略語 -は置換して省略しないようにしてしまえばよい。 +h3. Reading the history -ただし当然のことだが書き換えるときはオリジナルのソースは別に残しておき、 -途中で辻褄が合わないと思ったら元のソースを見て確認すること。でないと自 -分の単純ミスで何時間も悩む羽目になる。それに書き換えるのはあくまで馴染 -むためであって書き換えること自体が目的ではないので熱中しすぎないように -注意してほしい。 +A program often comes with a document which is about the history of changes. +For example, if it is a software of GNU, there's always a file named +@ChangeLog@. This is the best resource to know about "the reason why the +program is as it is". -h3. 歴史を読む +Alternatively, when a version control system like CVS or SCCS is used and you +can access it, its utility value is higher than @ChangeLog@. +Taking CVS as an example, @cvs annotate@, which displays the place which +modified a particular line, and @cvs diff@, which takes difference from the +specified version, and so on are convenient. -プログラムにはたいてい変更個所の履歴を書いた文書が付いている。例えば -GNUのソフトウェアだと必ず@ChangeLog@というファイルがある。これは -「プログラムがそうなっている理由」を知るのには最高に役に立つ。 +Moreover, in the case when there's a mailing list or a news group for +developers, you should get the archives so that you can search over them any +time because often there's the information about the exact reason of a certain +change. Of course, if you can search online, it's also sufficient. -またCVSやSCCSのようなバージョン管理システムを使っていてしかもそれにア -クセスできる場合は、@ChangeLog@以上に利用価値が高い。CVSを例に取ると、特 -定の行を最後に変更した場所を表示する@cvs annotate@、指定した版からの差分 -を取る@cvs diff@などが便利だ。 +h3. The tools for static analysis - -さらに、開発用のメーリングリストやニュースグループがある場合はその過去 -ログを入手してすぐに検索できるようにしておく。変更の理由がズバリ載って -いることが多いからだ。もちろんWeb上で検索できるならそれでもいい。 - -h3. 静的解析用ツール - -いろいろな目的のためにいろいろなツールがあるので一口には言えないが、筆 -者が一つだけ選ぶとしたら@global@をお勧めする。なんと言っても他の用途に応 -用しやすい作りになっているところがポイントだ。例えば同梱されている -@gctags@は本当はタグファイルを作るためのツールなのだが、 -これを使ってファイルに含まれる関数名のリストを取ることもできる。 +Since various tools are available for various purposes, +I can't describe them as a whole. +But if I have to choose only one of them, I'd recommend @global@. +The most attractive point is that its structure allows us to easily use it for +the other purposes. For instance, @gctags@, which comes with it, is actually a +tool to create tag files, but you can use it to create a list of the function +names contained in a file.
 ~/src/ruby % gctags class.c | awk '{print $1}'
@@ -660,47 +668,62 @@ method_list
         :
 
-とは言えこれはあくまでも筆者のお勧めなので読者は自分の好きなツールを使っ -てもらえばいい。ただその時は最低でも次の機能を備えているものを選ぶように -すべきだ。 +That said, but this is just a recommendation of this author, +you as a reader can use whichever tool you like. +But in that case, you should choose a tool equipped with at least the following +features. +* list up the function names contained in a file +* find the location from a function name or a variable name +(It's more preferable if you can jump to the location) +* function cross-reference -ファイルに含まれる関数名をリストアップする -関数名や変数名から位置を探す(さらにそこに飛べるとなおよい) -関数クロスリファレンス -h2. ビルド -h3. 対象バージョン -本書で解説している@ruby@のバージョンは1.7の2002-09-12版である。@ruby@はマ -イナーバージョンが偶数だと安定版で奇数だと開発版だから、1.7は開発版と -いうことになる。しかも9月12日は特に何かの区切りというわけではないの -で、該当バージョンの公式パッケージは配布されていない。従ってこの版を入 -手するには本書添付のCD-ROMまたはサポートサイト -footnote{本書のサポートサイト......@http://i.loveruby.net/ja/rhg/@} -から入手するか、後述のCVSを使うしかない。 +h2. Build -安定版の1.6でなく1.7にした理由は、1.7のほうが仕様・実装ともに整理され -ていて扱いやすいことが一つ。次に、開発版先端のほうがCVSが使いやすい。 -さらに、わりと近いうちに次の安定版の1.8が出そうな雰囲気になってきたこと。 -そして最後に、最先端を見ていくほうが気分的に楽しい。 +h3. Target version -h3. ソースコードを入手する +The version of @ruby@ described in this book is 1.7 (2002-09-12). +Regarding @ruby@, +it is a stable version if its minor version is an even number, +and it is a developing version if it is an odd number. +Hence, 1.7 is a developing version. +Moreover, 9/12 does not indicate any particular period, +thus this version is not distributed as an official package. +Therefore, in order to get this version, +you can get from the CD-ROM attached to this book or the support site +\footnote{The support site of this book……http://i.loveruby.net/ja/rhg/} +or you need to use the CVS which will be described later. -添付CD-ROMに解説対象の版のアーカイブを収録した。 -CD-ROMのトップディレクトリに +There are some reasons why it is not 1.6, which is the stable version, but 1.7. +One thing is that, +because both the specification and the implementation are organized, +1.7 is easier to deal with. +Secondly, it's easier to use CVS if it is the edge of the developing version. +Additionally, it is likely that 1.8, which is the next stable version, will be +out in the near future. +And the last one is, investigating the edge would make our mood more pleasant. -
 
+
+h3. Getting the source code
+
+The archive of the target version is included in the attached CD-ROM.
+In the top directory of the CD-ROM,
+
+
+
 ruby-rhg.tar.gz
 ruby-rhg.zip
 ruby-rhg.lzh
 
-の三種類が置いてあるので、便利なものを選んで使ってほしい。 -もちろん中身はどれも同じだ。例えば@tar.gz@のアーカイブなら -次のように展開すればいいだろう。 +these three versions are placed, +so I'd like you to use whichever one that is convenient for you. +Of course, whichever one you choose, the content is the same. +For example, the archive of @tar.gz@ can be extracted as follows.
 ~/src % mount /mnt/cdrom
@@ -708,24 +731,30 @@ ruby-rhg.lzh
 ~/src % umount /mnt/cdrom
 
-h3. コンパイルする -ソースコードを見るだけでも「読む」ことはできる。しかしプログラムを知る -ためには実際にそれを使い、改造し、実験してみることが必要だ。実験をする -なら見ているソースコードと同じものを使わなければ意味がないので、当然自 -分でコンパイルすることになる。 +h3. Compiling + +Just by looking at the source code, you can "read" it. +But in order to know about the program, you need to actually use it, remodel it +and experiment with it. +When experimenting, +there's no meaning if you didn't use the same version you are looking at, +thus naturally you'd need to compile it by yourself. -そこでここからはコンパイルの方法を説明する。まずはUNIX系OSの場合から話 -を始めよう。Windows上ではいろいろあるので次の項でまとめて話す。ただし -CygwinはWindows上ではあるがほとんどUNIXなので、こちらの話を読んでほし -い。 +Therefore, from now on, I'll explain how to compile. +First, let's start with the case of Unix-like OS. +There's several things to consider on Windows, +so it will be described in the next section altogether. +However, Cygwin is on Windows but almost Unix, +thus I'd like you to read this section for it. -h4. UNIX系OSでのビルド -さて、UNIX系OSなら普通Cコンパイラは標準装備なので、次の手順でやれば -たいがい通ってしまう。 -@~/src/ruby@にソースコードが展開されているとする。 +h4. Building on a Unix-like OS + +When it is a Unix-like OS, because generally it is equipped with a C +compiler, by following the below procedures, it can pass in most cases. +Let us suppose @~/src/ruby@ is the place where the source code is extracted.
 ~/src/ruby % ./configure
@@ -734,176 +763,205 @@ h4. UNIX系OSでのビルド
 ~/src/ruby # make install
 
-以下、いくつか注意すべき点を述べる。 +Below, I'll describe several points to be careful about. -Cygwin、UX/4800など一部のプラットフォームでは@configure@の段階で -@--enable-shared@オプションを付けないとリンクに失敗する。 -@--enable-shared@というのは@ruby@のほとんどを共有ライブラリ -(@libruby.so@)としてコマンドの外に出すオプションである。 +On some platforms like Cygwin, UX/4800, +you need to specify the @--enable-shared@ option at the phase of @configure@, +or you'd fail to link. +@--enable-shared@ is an option to put the most of @ruby@ out of the command +as shared libraries (@libruby.so@).
 ~/src/ruby % ./configure --enable-shared
 
-ビルドに関するより詳しいチュートリアルを添付CD-ROMの -@doc/build.html@に入れたので、それを読みながらやってみてほしい。 +The detailed tutorial about building is included in @doc/build.html@ of the +attached CD-ROM, I'd like you to try as reading it. + -h4. Windowsでのビルド -Windowsでのビルドとなるとどうも話がややこしくなる。 -問題の根源はビルド環境が複数あることだ。 +h4. Building on Windows -Visual C++ -MinGW -Cygwin -Borland C++ Compiler +If the thing is to build on windows, it becomes way complicated. +The source of the problem is, there are multiple building environments. -まずCygwin環境はWindowsよりもUNIXに条件が近いのでUNIX系のビルド手順に -従えばいい。 +* Visual C++ +* MinGW +* Cygwin +* Borland C++ Compiler -Visual C++でコンパイルする場合はVisual C++ 5.0以上が -必要である。バージョン6か.NETならまず問題ないだろう。 +First, the condition of the Cygwin environment is closer to UNIX than Windows, +you can follow the building procedures for Unix-like OS. +If you'd like to compile with Visual C++, +Visual C++ 5.0 and later is required. +There's probably no problem if it is version 6 or .NET. -MinGW、Minimalist GNU for WindowsというのはGNUのコンパイル環境(ようするに -@gcc@と@binutils@)をWindowsに移植したものだ。CygwinがUNIX環境全体を移植し -たのに対し、MinGWはあくまでコンパイルのためのツールだけを移植してある。 -またMinGWでコンパイルしたプログラムは実行時に特別なDLLを必要としない。 -つまりMinGWでコンパイルした@ruby@はVisual C++版と全く同じに扱える。 +MinGW or Minimalist GNU for Windows, +it is what the GNU compiling environment (Namely, @gcc@ and @binutils@) +is transplanted on Windows. +Cygwin transplants the whole UNIX environment. +On the contrary, MinGW transplants only the tools to compile. +Moreover, a program compiled with MinGW does not require any special DLL at +runtime. It means, the @ruby@ compiled with MinGW can be treated completely the +same as the Visual C++ version. +Alternatively, if it is personal use, you can download the version 5.5 of +Borland C++ Compiler for free from the site of Boarland. +\footnote{The Borland site: http://www.borland.co.jp} +Because @ruby@ started to support this environment fairly recently, +there's more or less anxiety, +but there was not any particular problem on the build test done before the +publication of this book. -また個人利用ならばBorland C++ Compilerのバージョン5.5がBorlandのサイト -footnote{Borlandのサイト:@http://www.borland.co.jp@} -から無料でダウンロードできる。@ruby@がサポートしたのがかなり最近なのが -多少不安だが、本書出版前に行ったビルドテストでは特に問題は出ていない。 +Then, among the above four environments, which one should we choose? +First, basically the Visual C++ version is the most unlikely to cause a problem, +thus I recommend it. +If you have experienced with UNIX, +installing the whole Cygwin and using it is good. +If you have not experienced with UNIX and you don't have Visual C++, +using MinGW is probably good. -さて以上四つの環境のうちどれを選べばいいだろうか。まず基本的には -Visual C++版が最も問題が出にくいのでそれをお勧めする。UNIXの経験がある -ならCygwin一式入れてCygwinを使うのもよい。UNIXの経験がなくVisual C++も -持っていない場合はMinGWを使うのがいいだろう。 +Below, I'll explain how to build with Visual C++ and MinGW, +but only about the outlines. +For more detailed explanations and how to build with Borland C++ Compiler, +they are included in @doc/build.html@ of the attached CD-ROM, +thus I'd like you to check it when it is necessary. -以下ではVisual C++とMinGWでのビルド方法について説明するが、 -あくまで概要だけに留めた。より細かい解説とBorland C++ Compilerでの -ビルド方法は添付CD-ROMの@doc/build.html@に収録したので適宜そちらも -参照してほしい。 h4. Visual C++ -Visual C++と言っても普通はIDEは使わず、DOSプロンプトからビルドする。そ -のときはまずVisual C++自体を動かせるようにするために環境変数の初期化を -しなければいけない。Visual C++にそのためのバッチファイルが付いてくるの -で、まずはそれを実行しよう。 +It is said Visual C++, but usually IDE is not used, we'll build from DOS prompt. +In this case, first we need to initialize environment variables to be able to +run Visual C++ itself. +Since a batch file for this purpose came with Visual C++, +let's execute it first.
-C:> cd "Program FilesMicrosoft Visual Studio .NETVc7bin"
-C:Program FilesMicrosoft Visual Studio .NETVc7bin> vcvars32
+C:\> cd "\Program Files\Microsoft Visual Studio .NET\Vc7\bin"
+C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin> vcvars32
 
-これはVisual C++.NETの場合だ。バージョン6なら以下の場所にある。 -
 
-C:Program FilesMicrosoft Visual StudioVC98bin
+This is the case of Visual C++ .NET.
+If it is version 6, it can be found in the following place.
+
+
+C:\Program Files\Microsoft Visual Studio\VC98\bin\
 
-@vcvars32@を実行したらその後は@ruby@のソースツリーの中のフォルダ -@win32@に移動してビルドすればいい。以下、ソースツリーは@C:src@に -あるとしよう。 + +After executing @vcvars32@, +all you have to do is to move to the @win32\@ folder of the source tree of +@ruby@ and build. Below, let us suppose the source tree is in @C:\src@.
-C:> cd srcruby
-C:srcruby> cd win32
-C:srcrubywin32> configure
-C:srcrubywin32> nmake
-C:srcrubywin32> nmake DESTDIR="C:Program Filesruby" install
+C:\> cd src\ruby
+C:\src\ruby> cd win32
+C:\src\ruby\win32> configure
+C:\src\ruby\win32> nmake
+C:\src\ruby\win32> nmake DESTDIR="C:\Program Files\ruby" install
 
-これで@C:Program Filesrubybin@に@ruby@コマンドが、 -@C:Program Filesrubylib@以下にRubyのライブラリが、 -それぞれインストールされる。@ruby@はレジストリなどは一切使わない -ので、アンインストールするときは@C:ruby@以下を消せばよい。 -h4. MinGW +Then, @ruby@ command would be installed in @C:\Program Files\ruby\bin\@, +and Ruby libraries would be in @C:\Program Files\ruby\lib\@. +Because @ruby@ does not use registries and such at all, +you can uninstall it by deleting @C:\Program Files\ruby@ and below. -前述のようにMinGWはコンパイル環境のみなので、一般的なUNIXのツール、 -例えば@sed@や@sh@が存在しない。しかし@ruby@のビルドにはそれが必要なので -それをどこかから調達しなければならない。それにはまた二つの方法が -存在する。CygwinとMSYS(Minimal SYStem)である。 +h4. MinGW -だがMSYSのほうは本書の出版前に行ったビルド大会でトラブルが続出してしまっ -たのでお勧めできない。対照的にCygwinを使う方法だと非常に素直に通った。 -従って本書ではCygwinを使う方法を説明する。 +As described before, MinGW is only an environment to compile, +thus the general UNIX tools like @sed@ or @sh@ are not available. +However, because they are necessary to build @ruby@, +you need to obtain it from somewhere. +For this, there are also two methods: +Cygwin and MSYS (Minimal SYStem). +However, I can't recommend MSYS because troubles were continuously happened at +the building contest performed before the publication of this book. +On the contrary, in the way of using Cygwin, it can pass very straightforwardly. +Therefore, in this book, I'll explain the way of using Cygwin. -まずCygwinの@setup.exe@でMinGWと開発ツール一式を入れておく。 -CygwinとMinGWは添付CD-ROMにも収録した -footnote{CygwinとMinGW......添付CD-ROMの@doc/win.html@を参照}。 -あとはCygwinの@bash@プロンプトから以下のように打てばよい。 +First, install MinGW and the entire developing tools by using @setup.exe@ of +Cygwin. Both Cygwin and MinGW are also included in the attached CD-ROM. +\footnote{Cygwin and MinGW……See also doc/win.html of the attached CD-ROM} +After that, all you have to do is to type as follows from @bash@ prompt of Cygwin.
-~/src/ruby % ./configure --with-gcc='gcc -mno-cygwin' 
+~/src/ruby % ./configure --with-gcc='gcc -mno-cygwin' \
                                  --enable-shared i386-mingw32
 ~/src/ruby % make
 ~/src/ruby % make install
 
-これだけだ。ここでは@configure@の行を折り返しているが実際には一行に -入れる。またバックスラッシュを入れる必要はない。インストール先は -コンパイルしたドライブの@usrlocal@以下になる。このあたりはかなり -ややこしいことが起こっていて説明が長くなるので、 -添付CD-ROMの@doc/build.html@で徹底的に説明しよう。 +That's it. Here the line of @configure@ spans multi-lines but in practice +we'd write it on one line and the backslash is not necessary. +The place to install is @\usr\local\@ and below of the drive on which it is +compiled. Because really complicated things occur around here, the explanation +would be fairly long, so I'll explain it comprehensively in @doc/build.html@ of +the attached CD-ROM. -h2. ビルド詳細 -ここまでが@README@的な解説である。今度はこれまでやったことが具体的に -何をしているのか、つっこんで見ていこう。ただしここの話は部分的に -かなり高度な知識が必要になる。わからない場合はいきなり次の節に -飛んでほしい。本書全体を読んでから戻ってきてもらえばわかるように -なっているはずだ。 -さて、どのプラットフォームでも@ruby@のビルドは三段階に分かれている。 -即ち@configure@、@make@、@make install@だ。@make install@はいいとして、 -@configure@と@make@の段階について解説しよう。 - -h3. @configure@ - -まず@configure@である。この中身はシェルスクリプトになっており、これ -でシステムのパラメータを検出する。例えば「ヘッダファイル@setjmp.h@が存 -在するか」とか、「@alloca()@は使えるか」ということを調べてくれる。調べ -る方法は意外と単純である。 +h2. Building Details +Until here, it has been the @README@-like description. +This time, let's look at exactly what is done by what we have been done. +However, the talks here partially require very high-level knowledge. +If you can't understand, I'd like you to skip this and directly jump to the next +section. This should be written so that you can understand by coming back after +reading the entire book. -チェック対象方法 -コマンド実際に実行してみて@$?@を見る -ヘッダファイル@if [ -f $includedir/stdio.h ]@ -関数小さいプログラムをコンパイルしてみてリンクが成功するかどうか試す +Now, on whichever platform, building @ruby@ is separated into three phases. +Namely, @configure@, @make@ and @make install@. +As considering the explanation about @make install@ unnecessary, +I'll explain the @configure@ phase and the @make@ phase. -違いを検出したら、それをどうにかしてこちらに伝えてもらわないと -いけない。その方法は、まず@Makefile@が一つ。パラメータを@@PARAM@@の -ように埋め込んだ@Makefile.in@を置いておくと、それを実際の値に変換 -した@Makefile@を生成してくれる。例えば次のように。 +h3. @configure@ -
 
+First, @configure@. Its content is a shell script, and we detect the system
+parameters by using it. For example, "whether there's the header file
+@setjmp.h@" or "whether @alloca()@ is available", these things are checked.
+The way to check is unexpectedly simple.
+
+|_. Target to check |_. Method |
+| commands | execute it actually and then check @$?@ |
+| header files | if [ -f $includedir/stdio.h ] |
+| functions | compile a small program and check whether linking is success |
+
+When some differences are detected, somehow it should be reported to us.
+The way to report is,
+the first way is @Makefile@.
+If we put a @Makefile.in@ in which parameters are embedded in the form of
+`@param@`, it would generate a @Makefile@ in which they are substituted
+with the actual values.
+For example, as follows,
+
+
 Makefile.in:  CFLAGS = @CFLAGS@
                      ↓
 Makefile   :  CFLAGS = -g -O2
 
-もう一つ、関数やヘッダファイルがあるかどうかといった情報を -ヘッダファイルにして出力してくれる。出力ファイルの名前は変更 -できるのでプログラムによって違うが、@ruby@では@config.h@である。 -@configure@を実行した後にこのファイルができていることを確かめてほしい。 -中身はこんな感じだ。 -▼@config.h@ +Alternatively, it writes out the information about, for instance, whether +there are certain functions or particular header files, into a header file. +Because the output file name can be changed, it is different depending on each +program, but it is @config.h@ in @ruby@. +I'd like you to confirm this file is created after executing @configure@. +Its content is something like this. + +

config.h

          :
          :
@@ -924,174 +982,193 @@ Makefile   :  CFLAGS = -g -O2
          :
 
-どれも意味はわかりやすい。@HAVE_xxxx_H@ならヘッダファイルが存在するか -どうかのチェックだろうし、@SIZEOF_SHORT@ならCの@short@型が何バイトかを -示しているに違いない。同じく@SIZEOF_INT@なら@int@のバイト長だし、 -@HAVE_OFF_T@は@offset_t@型が定義されているかを示している。これに限らず -@configure@では「ある/ない」の情報は@HAVE_xxxx@というマクロで定義される -(する)。 +Each meaning is easy to understand. +@HAVE_xxxx_H@ probably indicates whether a certain header file exists, +@SIZEOF_SHORT@ must indicate the size of the @short@ type of C. +Likewise, @SIZEOF_INT@ indicates the byte length of @int@, +@HAVE_OFF_T@ indicates whether the @offset_t@ type is defined or not. -以上のことからわかるように、@configure@は違いを検出してはくれるが、 -その違いを自動的に吸収してくれるわけではない。ここで定義された値を -使って差を埋めるのはあくまで各プログラマの仕事である。例えば次の -ように。 +As we can understand from the above things, +@configure@ does detect the differences but it does not automatically absorb the +differences. Bridging the difference is left to each programmer. +For example, as follows, -▼@HAVE_@マクロの典型的な使いかた +▼ A typical usage of the `HAVE_` macro
   24  #ifdef HAVE_STDLIB_H
-  25  # include 
+  25  # include 
   26  #endif
+
 (ruby.h)
 
-h3. @autoconf@ -@configure@は@ruby@の専用ツールではない。関数があるか、ヘッダファイルが -あるか......といったテストには明らかに規則性があるのだから、プログラムを -書く人がみんなでそれぞれに別のものを書くのは無駄だ。 -そこで登場するのが@autoconf@というツールである。@configure.in@とか -@configure.ac@というファイルに「こういうチェックがしたいんだ」と -書いておき、それを@autoconf@で処理すると適切な@configure@を作ってくれる。 -@configure.in@の@.in@は@input@の略だろう。@Makefile@と@Makefile.in@の関係と -同じである。@.ac@のほうはもちろん@AutoConf@の略だ。 -ここまでを絵にすると図1のようになる。 +h3. @autoconf@ + +@configure@ is not a `ruby`-specific tool. +Whether there are functions, there are header files, ... +it is obvious that these tests have regularity. +It is wasteful if each person who writes a program wrote each own distinct tool. + +Here a tool named @autoconf@ comes in. +In the files named @configure.in@ or @configure.ac@, +write about "I'd like to do these checks", +process it with @autoconf@, +then an adequate @configure@ would be generated. +The @.in@ of @configure.in@ is probably an abbreviation of @input@. +It's the same as the relationship between @Makefile@ and @Makefile.in@. +@.ac@ is, of course, an abbreviation of @AutoConf@. -!images/ch_abstract_build.jpg([build])! -図1: @Makefile@ができるまで +To illustrate this talk up until here, +it would be like Figure 1. +!images/ch_abstract_build.jpg(The process until @Makefile@ is created)! -もっと詳しいことが知りたい読者には『GNU Autoconf/Automake/Libtool』 -footnote{『GNU Autoconf/Automake/Libtool』Gary V.Vaughan, Ben Elliston, Tom Tromey, Ian Lance Taylor共著、でびあんぐる監訳、オーム社} -をお勧めする。 +For the readers who want to know more details, +I recommend "GNU Autoconf/Automake/Libtool" Gary V.Vaughan, Ben Elliston, Tom +Tromey, Ian Lance Taylor. +By the way, `ruby`'s `configure` is, as said before, generated by using +@autoconf@, but not all the @configure@ in this world are generated with +@autoconf@. It can be written by hand or another tool to automatically generate +can be used. Anyway, it's sufficient if ultimately there are @Makefile@ and +@config.h@ and many others. -ところで@ruby@の@configure@は言ったとおり@autoconf@を使って生成してい -るのだが、世の中にある@configure@が必ずしも@autoconf@で生成されている -とは限らない。手書きだったり、別の自動生成ツールを使っていたりすること -もある。なんにせよ、最終的に@Makefile@や@config.h@やその他いろいろがで -きればそれでいいのだ。 h3. @make@ -第二段階、@make@では何をするのだろうか。もちろん@ruby@のソースコードを -コンパイルするわけだが、@make@の出力を見ているとどうもその他にいろいろ -やっているように見える。その過程を簡単に説明しておこう。 +At the second phase, @make@, what is done? +Of course, it would compile the source code of @ruby@, +but when looking at the output of @make@, +I feel like there are many other things it does. +I'll briefly explain the process of it. + +# compile the source code composing @ruby@ itself +# create the static library @libruby.a@ gathering the crucial parts of @ruby@ +# create "@miniruby@", which is an always statically-linked @ruby@ +# create the shared library @libruby.so@ when @--enable-shared@ +# compile the extension libraries (under @ext/@) by using @miniurby@ +# At last, generate the real @ruby@ + +There are two reasons why it creates @miniruby@ and @ruby@ separately. +The first one is that compiling the extension libraries requires @ruby@. +In the case when @--enable-shared@, @ruby@ itself is dynamically linked, +thus there's a possibility not be able to run instantly because of the load +paths of the libraries. Therefore, create @miniruby@, which is statically +linked, and use it during the building process. + +The second reason is, in a platform where we cannot use shared libraries, +there's a case when the extension libraries are statically linked to @ruby@ +itself. In this case, it cannot create @ruby@ before compiling all extension +libraries, but the extension libraries cannot be compiled without @ruby@. +In order to resolve this dilemma, it uses @miniruby@. + + -@ruby@自体を構成するソースコードをコンパイルする。 -@ruby@の主要部分を集めたスタティックライブラリ@libruby.a@を作る。 -常にスタティックリンクされる@ruby@「@miniruby@」を作る。 -@--enable-shared@のときは共有ライブラリ@libruby.so@を作る。 -@miniruby@を使って拡張ライブラリ(@ext/@以下)をコンパイルする。 -最後に、本物の@ruby@を生成する。 +h2. @CVS@ +The @ruby@ archive included in the attached CD-ROM is, +as the same as the official release package, +just a snapshot which is an appearance at just a particular moment of @ruby@, +which is a continuously changing program. +How @ruby@ has been changed, why it has been so, these things are not described +there. Then what is the way to see the entire picture including the past. +We can do it by using CVS. -@miniruby@と@ruby@の生成が分かれているのには二つ理由がある。一つめは拡張ラ -イブラリのコンパイルに@ruby@が必要になることだ。@--enable-shared@の場合は -@ruby@自身がダイナミックリンクされるので、ライブラリのロードパスの関係で -すぐに動かせないかもしれない。そこでスタティックリンクした@miniruby@を作り、 -ビルドの過程ではそちらを使うようにする。 +h3. About CVS -二つめの理由は、共有ライブラリが使えないプラットフォームでは拡張ライブ -ラリを@ruby@自体にスタティックリンクしてしまう場合があるということだ。そ -の場合、@ruby@は拡張ライブラリを全てコンパイルしてからでないと作れないが、 -拡張ライブラリは@ruby@がないとコンパイルできない。そのジレンマを解消する -ために@miniruby@を使うのである。 +CVS is shortly an undo list of editors. +If the source code is under the management of CVS, +the past appearance can be restored anytime, +and we can understand who and where and when and how changed it immediately any +time. Generally a program doing such job is called source code management +system and CVS is the most famous open-source source code management system in +this world. -h2. CVS -本書の添付CD-ROMに入っている@ruby@のアーカイブにしても公式のリリースパッ -ケージにしても、それは@ruby@という、変化しつづているプログラムのほんの一 -瞬の姿をとらえたスナップショットにすぎない。@ruby@がどう変わってきたか、 -どうしてそうだったのか、ということはここには記述されていない。では過去 -も含めた全体を見るにはどうしたらいいだろうか。CVSを使えばそれができる。 +Since @ruby@ is also managed with CVS, +I'll explain a little about the mechanism and usage of CVS. +First, the most important idea of CVS is repository and working-copy. +I said CVS is something like an undo list of editor, +in order to archive this, the records of every changing history should be saved +somewhere. The place to store all of them is "CVS repository". -h3. CVSとは -CVSを一言で言うとエディタのundoリストである。 -ソースコードをCVSの管理下に入れておけばいつでも昔の姿に戻せるし、誰が、 -どこを、いつ、どう変えたのかすぐにわかる。一般にそういうことをしてくれ -るプログラムのことをソースコード管理システムと言うが、オープンソースの -世界で一番有名なソースコード管理システムがCVSである。 +Directly speaking, repository is what gathers all the past source codes. +Of course, this is only a concept, in reality, in order to save spaces, +it is stored in the form of +one recent appearance and the changing differences (namely, batches). +In any ways, it is sufficient if we can obtain the appearance of a particular +file of a particular moment any time. -@ruby@もやはりCVSで管理されているのでCVSの仕組みと使いかたについて少し説 -明しよう。まずCVSの最重要概念はレポジトリとワーキングコピーである。 -CVSはエディタのundoリストのようなものと言ったが、そのためには歴代の変更の -記録を -どこかに残しておかないといけない。それを全部まとめて保存しておく場所が -「CVSレポジトリ」である。 +On the other hand, "working copy" is the result of taking files from the +repository by choosing a certain point. +There's only one repository, +but you can have multiple working copies. (Figure 2) -ぶっちゃけて言うと、過去のソースコードを全部集めてあるのがレポジトリで -ある。もちろんそれはあくまで概念であって、実際には容量を節約するために、 -最新の姿一つと、そこに至るまでの変更差分(ようするにパッチ)の形で集積 -されている。なんにしてもファイルの過去の姿をどの時点だろうと取り出せる -ようになっていればそれでいいのだ。 +!images/ch_abstract_repo.jpg(Repository and working copies)! -一方、レポジトリからある一点を選んでファイルを取り出したものが -「ワーキングコピー」だ。レポジトリは一つだけだがワーキングコピーは -いくつあってもいい(図2)。 +When you'd like to modify the source code, +first take a working copy, +edit it by using editor and such, and "return" it. +Then, the change is recorded to the repository. +Taking a working copy from the repository is called "checkout", +returning is called "checkin" or "commit" (Figure 3). +By checking in, the change is recorded to the repository, +then we can obtain it any time. -!images/ch_abstract_repo.jpg([repo])! -図2: レポジトリとワーキングコピー +!images/ch_abstract_ci.jpg(Checkin and Checkout)! -自分がソースコードを変更したいときはまずワーキングコピーを取り出して、 -それをエディタなどで編集してからレポジトリに「戻す」。するとレポジトリ -に変更が記録される。レポジトリからワーキングコピーを取り出すことを -「チェックアウト(checkout)」、戻すことを「チェックイン -(checkin)」 -または「コミット(commit)」と言う(図3)。チェックインするとレ -ポジトリに変更が記録されて、いつでもそれを取り出せるようになる。 +The biggest trait of CVS is we can access it over the networks. +It means, if there's only one server which holds the repository, +everyone can checkin/checkout over the internet any time. +But generally the access to check in is restricted and we can't do it freely. -!images/ch_abstract_ci.jpg([ci])! -図3: チェックインとチェックアウト +h4. Revision -そしてCVS最大の特徴はCVSレポジトリにネットワーク越しにアクセスできると -いうところだ。つまりレポジトリを保持するサーバが一つあればインターネッ -ト越しに誰でもどこからでもチェックアウト・チェックインすることができる。 -ただし普通はチェックインにはアクセス制限がかかっているので無制限 -にできるというわけではない。 +How can we do to obtain a certain version from the repository? +One way is to specify with time. By requiring "give me the edge version of that +time", it would select it. But in practice, we rarely specify with time. +Most commonly, we use something named "revision". -h4. リビジョン -レポジトリから特定の版を取り出すにはどうしたらいいだろうか。一つには時 -刻で指定する方法がある。「この当時の最新版をくれ」と要求するとそれを選 -んでくれるわけだ。しかし実際には時刻で指定することはあまりない。普通は -「リビジョン(revision)」というものを使う。 +"Revision" and "Version" have the almost same meaning. +But usually "version" is attached to the project itself, +thus using the word "version" can be confusing. +Therefore, the word "revision" is used to indicate a bit smaller unit. -「リビジョン」は「バージョン」とほとんど同じ意味である。ただ普通はプロ -ジェクト自体に「バージョン」が付いているので、バージョンという言葉を使 -うと紛らわしい。そこでもうちょっと細かい単位を意図してリビジョンという -言葉を使う。 +In CVS, the file just stored in the repository is revision 1.1. +Checking out it, modifying it, checking in it, then it would be revision 1.2. +Next it would be 1.3 then 1.4. -CVSでは、レポジトリに入れたばかりのファイルはリビジョン1.1である。 -チェックアウトして、変更して、チェックインするとリビジョン1.2になる。 -その次は1.3になる。その次は1.4になる。 -h4. CVSの簡単な使用例 -以上をふまえてごくごく簡単にCVSの使いかたを話す。まず@cvs@コマンドがな -いとどうにもならないのでインストールしておいてほしい。添付CD-ROMにも -@cvs@のソースコードを収録した -footnote{@cvs@:@archives/cvs-1.11.2.tar.gz@}。 -@cvs@のインストールの方法はあまりにも本筋から外れるのでここでは書かな -い。 +h4. A simple usage example of CVS +Keeping in mind the above things, +I'll talk about the usage of CVS very very briefly. +First, @cvs@ command is essential, so I'd like you to install it beforehand. +The source code of @cvs@ is included in the attached CD-ROM +\footnote{cvsarchives/cvs-1.11.2.tar.gz}. +How to install @cvs@ is really far from the main line, +thus it won't be explained here. -インストールしたら試しに@ruby@のソースコードをチェックアウトしてみよう。 -インターネットに接続中に次のように打つ。 +After installing it, let's checkout the source code of @ruby@ as an experiment. +Type the following commands when you are online.
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
@@ -1099,47 +1176,55 @@ CVS Password: anonymous
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby
 
-何もオプションを付けないと自動的に最新版がチェックアウトされるので、 -@ruby/@以下に@ruby@の真の最新版が現れているはずだ。 +Any options were not specified, +thus the edge version would be automatically checked out. +The truly edge version of @ruby@ must appear under @ruby/@. -また、とある日の版を取り出すには@cvs checkout@に@-D@オプションをつけれ -ばいい。次のように打てば本書が解説しているバージョンのワーキングコピー -が取り出せる。 +Additionally, if you'd like to obtain the version of a certain day, +you can use @-D@ option of @cvs checkout@. +By typing as follows, you can obtain a working copy of the version which is +being explained by this book.
 % cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout -D2002-09-12 ruby
 
-このとき、オプションは必ず@checkout@の直後に書かないといけないことに注 -意。先に「@ruby@」を書いてしまうと「モジュールがない」という変なエラー -になる。 +At this moment, you have to write options immediately after @checkout@. +If you wrote "@ruby@" first, it would cause a strange error complaining "missing +a module". +And, with the anonymous access like this example, we cannot check in. +In order to practice checking in, it's good to create a (local) repository and +store a "Hello, World!" program in it. +The concrete way to store is not explained here. +The manual coming with @cvs@ is fairly friendly. +Regarding books which you can read in Japanese, +I recommend translated "Open Source Development with CVS" Karl Fogel, Moshe Bar. -ちなみにこの例のようなanonymousアクセスだとチェックインはできないようになっている。 -チェックインの練習をするには適当に(ローカルの)レポジトリを作って -Hello, World!プログラムでも入れてみるのがいいだろう。具体的な入れかた -はここには書かない。@cvs@に付いてくるマニュアルが結構親切だ。日本語の書 -籍ならオーム社の『CVSによるオープンソース開発』 -footnote{『CVSによるオープンソース開発』Karl Fogel, Moshe Bar共著、竹内利佳訳、オーム社} -をお勧めする。 -h2. @ruby@の構成 -h3. 物理構造 -さてそろそろソースコードを見ていこうと思うのだが、まず最初にしなければ -ならないことはなんだろうか。それはディレクトリ構造を眺めることである。 -たいていの場合ディレクトリ構造すなわちソースツリーはそのままプログラム -のモジュール構造を示している。いきなり@grep@で@main()@を探して頭から処理順 -に読んでいく、なんていうのは賢くない。もちろん@main()@を探すのも大切だが、 -まずはのんびりと@ls@したり@head@したりして全体の様子をつかもう。 +h2. The composition of @ruby@ -以下はCVSレポジトリからチェックアウトした直後の -トップディレクトリの様子だ。 -スラッシュで終わっているのはサブディレクトリである。 +h3. The physical structure -
 
+Now it is time to start to read the source code,
+but what is the thing we should do first?
+It is looking over the directory structure.
+In most cases, the directory structure, meaning the source tree, directly
+indicate the module structure of the program.
+Abruptly searching @main()@ by using @grep@ and reading from the top in its
+processing order is not smart.
+Of course finding out @main()@ is also important,
+but first let's take time to do @ls@ or @head@ to grasp the whole picture.
+
+Below is the appearance of the top directory immediately after checking out from
+the CVS repository.
+What end with a slash are subdirectories.
+
+
+
 COPYING        compar.c       gc.c           numeric.c      sample/
 COPYING.ja     config.guess   hash.c         object.c       signal.c
 CVS/           config.sub     inits.c        pack.c         sprintf.c
@@ -1160,219 +1245,239 @@ bignum.c       ext/           mkconfig.rb    rubysig.h
 class.c        file.c         node.h         rubytest.rb
 
-最近はプログラム自体が大きくなってきてサブディレクトリが細かく分割され -ているソフトウェアも多いが、@ruby@はかなり長いことトップディレクトリ -一筋である。あまりにファイル数が多いと困るが、この程度なら慣れればな -んでもない。 +Recently the size of a program itself has become larger, +and there are many softwares whose subdirectories are divided into pieces, +but @ruby@ has been consistently used the top directory for a long time. +It becomes problematic if there are too many files, +but we can get used to this amount. -トップレベルのファイルは六つに分類できる。即ち +The files at the top level can be categorized into six: +* documents +* the source code of @ruby@ itself +* the tool to build @ruby@ +* standard extension libraries +* standard Ruby libraries +* the others -ドキュメント -@ruby@自身のソースコード -@ruby@ビルド用のツール -標準添付拡張ライブラリ -標準添付Rubyライブラリ -その他 +The source code and the build tool are obviously important. +Aside from them, +I'll list up what seems useful for us. -である。ソースコードとビルドツールが重要なのは当然として、その他に -我々の役に立ちそうなものを挙げておこう。 +* @ChangeLog@ +The records of changes on @ruby@. +This is very important when investigating the reason of a certain change. -@ChangeLog@ +* @README.EXT README.EXT.ja@ +How to create an extension library is described, +but in the course of it, things relating to the implementation of @ruby@ itself +are also written. -@ruby@への変更の記録。変更の理由を調べるうえでは非常に重要。 -@README.EXT README.EXT.ja@ +h3. Dissecting Source Code -拡張ライブラリの作成方法が書いてあるのだが、その一環として -@ruby@自身の実装に関することも書いてある。 +From now on, I'll further split the source code of @ruby@ itself into more tiny +pieces. As for the main files, its categorization is described in @README.EXT@, +thus I'll follow it. Regarding what is not described, I categorized it by myself. -h3. ソースコードの腑分け -ここからは@ruby@自身のソースコードについてさらに細かく分割していく。 -主要なファイルについては@README.EXT@に分類が書いてあったので -それに従う。記載がないものは筆者が分類した。 +h4. Ruby Language Core -h4. Ruby言語のコア +| @class.c@ | class relating API | +| @error.c@ | exception relating API | +| @eval.c@ | evaluator | +| @gc.c@ | garbage collector | +| @lex.c@ | reserved word table | +| @object.c@ | object system | +| @parse.y@ | parser | +| @variable.c@ | constants, global variables, class variables | +| @ruby.h@ | The main macros and prototypes of @ruby@ | +| @intern.h@ | the prototypes of C API of @ruby@. +@intern@ seems to be an abbreviation of internal, but the functions written here +can be used from extension libraries. | +| @rubysig.h@ | the header file containing the macros relating to signals | +| @node.h@ | the definitions relating to the syntax tree nodes | +| @env.h@ | the definitions of the structs to express the context of the evaluator | -@class.c@クラス関連API -@error.c@例外関連API -@eval.c@評価器 -@gc.c@ガーベージコレクタ -@lex.c@予約語テーブル -@object.c@オブジェクトシステム -@parse.y@パーサ -@variable.c@定数、グローバル変数、クラス変数 -@ruby.h@@ruby@の主要マクロとプロトタイプ -@intern.h@@ruby@のC APIのプロトタイプ。@intern@はinternalの略だと思われるが、ここに載っている関数を拡張ライブラリで使うのは別に構わない。 -@rubysig.h@シグナル関係のマクロを収めたヘッダファイル -@node.h@構文木ノード関連の定義 -@env.h@評価器のコンテキストを表現する構造体の定義 +The parts to compose the core of the @ruby@ interpretor. +The most of the files which will be explained in this book are contained here. +If you consider the number of the files of the entire @ruby@, +it is really only a few. But if you think based on the byte size, +50% of the entire amount is occupied by these files. +Especially, @eval.c@ is 200KB, @parse.y@ is 100KB, these files are large. -@ruby@インタプリタのコアを構成する部分。本書が解説するのは -ここのファイルがほとんどである。@ruby@全体のファイル数と比べれば -非常に少ないが、バイトベースでは全体の50%近くを占める。 -特に@eval.c@は200Kバイト、@parse.y@が100Kバイトと大きい。 -h4. ユーティリティ +h4. Utility -@dln.c@動的ローダ -@regex.c@正規表現エンジン -@st.c@ハッシュテーブル -@util.c@基数変換やソートなどのライブラリ +| dln.c | dynamic loader | +| regex.c | regular expression engine | +| st.c | hash table | +| util.c | libraries for radix conversions and sort and so on | +It means utility for @ruby@. +However, some of them are so large that you cannot imagine it from the word +"utility". For instance, @regex.c@ is 120 KB. -@ruby@にとってのユーティリティという意味。ただしユーティリティという -言葉からは想像できないほど大きいものもある。例えば@regex.c@は120Kバイトだ。 -h4. @ruby@コマンドの実装 -@dmyext.c@拡張ライブラリ初期化ルーチンのダミー(DumMY EXTention) -@inits.c@コアとライブラリの初期化ルーチンのエントリポイント -@main.c@コマンドのエントリポイント(@libruby@には不要) -@ruby.c@@ruby@コマンドの主要部分(@libruby@にも必要) -@version.c@@ruby@のバージョン +h4. Implementation of @ruby@ command +| @dmyext.c@ | dummy of the routine to initialize extension libraries ( DumMY EXTension ) | +| @inits.c@ | the entry point for core and the routine to initialize +extension libraries | +| @main.c@ | the entry point of @ruby@ command (this is unnecessary for +@libruby@ ) | +| @ruby.c@ | the main part of @ruby@ command (this is also necessary for +@libruby@ ) | +| @version.c@ | the version of @ruby@ | -コマンドラインで@ruby@と打って実行するときの@ruby@コマンドの実装。コマンドライン -オプションの解釈などを行っている部分だ。@ruby@コマンド以外に@ruby@コアを利 -用するコマンドとしては@mod_ruby@や@vim@が挙げられる。これらのコマンドは -ライブラリ@libruby@(@.a@/@.so@/@.dll@など)とリンクして動作する。 -h4. クラスライブラリ +The implementation of @ruby@ command, +which is of when typing @ruby@ on the command line and execute it. +This is the part, for instance, to interpret the command line options. +Aside from @ruby@ command, as the commands utilizing @ruby@ core, +there are @mod_ruby@ and @vim@. +These commands are functioning by linking to the @libruby@ library +(@.a@/@.so@/@.dll@ and so on). -@array.c@@class Array@ -@bignum.c@@class Bignum@ -@compar.c@@module Comparable@ -@dir.c@@class Dir@ -@enum.c@@module Enumerable@ -@file.c@@class File@ -@hash.c@@class Hash@(実体は@st.c@) -@io.c@@class IO@ -@marshal.c@@module Marshal@ -@math.c@@module Math@ -@numeric.c@@class Numeric@、@Integer@、@Fixnum@、@Float@ -@pack.c@@Array#pack@、@String#unpack@ -@prec.c@@module Precision@ -@process.c@@module Process@ -@random.c@@Kernel#srand()@、@rand()@ -@range.c@@class Range@ -@re.c@@class Regexp@(実体は@regex.c@) -@signal.c@@module Signal@ -@sprintf.c@@ruby@専用の@sprintf()@ -@string.c@@class String@ -@struct.c@@class Struct@ -@time.c@@class Time@ -Rubyのクラスライブラリの実装。ここにあるものは基本的に通常の -Ruby拡張ライブラリと全く同じ方法で実装されている。つまりこの -ライブラリが拡張ライブラリの書きかたの例にもなっているということだ。 +h4. Class Libraries -h4. プラットフォーム依存ファイル +| @array.c@ | @class Array@ | +| @bignum.c@ | @class Bignum@ | +| @compar.c@ | @module Comparable@ | +| @dir.c@ | @class Dir@ | +| @enum.c@ | @module Enumerable@ | +| @file.c@ | @class File@ | +| @hash.c@ | @class Hash@ (Its actual body is @st.c@) | +| @io.c@ | @class IO@ | +| @marshal.c@ | @module Marshal@ | +| @math.c@ | @module Math@ | +| @numeric.c@ | @class Numeric@, @Integer@, @Fixnum@, @Float@ | +| @pack.c@ | @Array#pack@, @String#unpack@ | +| @prec.c@ | @module Precision@ | +| @process.c@ | @module Process@ | +| @random.c@ | @Kernel#srand()@, @rand()@ | +| @range.c@ | @class Range@ | +| @re.c@ | @class Regexp@ (Its actual body is @regex.c@) | +| @signal.c@ | @module Signal@ | +| @sprintf.c@ | @ruby@-specific @sprintf()@ | +| @string.c@ | @class String@ | +| @struct.c@ | @class Struct@ | +| @time.c@ | @class Time@ | -@bcc32/@Borland C++(Win32) -@beos/@BeOS -@cygwin/@Cygwin(Win32でのUNIXエミュレーションレイヤー) -@djgpp/@djgpp(DOS用のフリーな開発環境) -@vms/@VMS(かつてDECがリリースしていたOS) -@win32/@Visual C++(Win32) -@x68/@Sharp X680x0系(OSはHuman68k) +The implementations of the Ruby class libraries. +What listed here are basically implemented in the completely same way as the +ordinary Ruby extension libraries. It means that these libraries are also +examples of how to write an extension library. -各プラットフォーム特有のコードが入っている。 -h4. フォールバック関数 -
 
-missing/
-
- -各種プラットフォームにない関数を補うためのファイル。 -主に@libc@の関数が多い。 - -h3. 論理構造 +h4. Files depending on a particular platform -さて、以上四つのグループのうちコアはさらに大きく三つに分けられる。 -一つめはRubyのオブジェクト世界を作りだす「オブジェクト空間(object space)」。 -二つめはRubyプログラム(テキスト)を内部形式に変換する「パーサ(parser)」。 -三つめはRubyプログラムを駆動する「評価器(evaluator)」。 -パーサも評価器もオブジェクト空間の上に成立し、 -パーサがプログラムを内部形式に変換し、 -評価器がプログラムを駆動する。 -順番に解説していこう。 +| @bcc32/@ | Borland C++ (Win32) | +| @beos/@ | BeOS | +| @cygwin/@ | Cygwin (the UNIX simulation layer on Win32) | +| @djgpp/@ | djgpp (the free developing environment for DOS) | +| @vms/@ | VMS (an OS had been released by DEC before) | +| @win32/@ | Visual C++ (Win32) | +| @x68/@ | Sharp X680x0 series (OS is Human68k) | + +Each platform-specific code is stored. + + +h4. fallback functions -h4. オブジェクト空間 +
+missing/
+
-一つめのオブジェクト空間。これは非常に、理解しやすい。なぜならこれが扱 -うものは基本的にメモリ上のモノが全てであり、関数を使って直接表示したり -操作したりすることができるからだ。従って本書ではまずここから解説を -始める。第2章から -第7章までが第一部である。 +Files to offset the functions which are missing on each platform. +Mainly functions of @libc@. -h4. パーサ -二つめのパーサ。これは説明が必要だろう。 -@ruby@コマンドはRuby言語のインタプリタである。つまり起動時にテキストの入 -力を解析し、それに従って実行する。だから@ruby@はテキストとして書かれたプ -ログラムの意味を解釈できなければいけないのだが、不幸にしてテキストとい -うのはコンピュータにとっては非常に理解しづらいものである。コンピュータ -にとってはテキストファイルはあくまでバイト列であって、それ以上ではない。 -そこからテキストの意味を読みとるには何か特別な仕掛けが必要になる。そ -の仕掛けがパーサだ。このパーサを通すことでRubyプログラム(であるテキス -ト)は@ruby@専用の、プログラムから扱いやすい内部表現に変換される。 +h3. Logical Structure -その内部表現とは具体的には「構文木」というものだ。構文木はプログラムを -ツリー構造で表現したもので、例えば@if@文ならば図4のように -表現される。 +Now, there are the above four groups and the core can be divided further into +three: +First, "object space" which creates the object world of Ruby. +Second, "parser" which converts Ruby programs (in text) to the internal format. +Third, "evaluator" which drives Ruby programs. +Both parser and evaluator are composed above object space, +parser converts a program into the internal format, +and evaluator actuates the program. +Let me explain them in order. -!images/ch_abstract_syntree.jpg([syntree])! -図4: @if@文と、それに対応する構文木 +h4. Object Space -パーサの解説は第二部『構文解析』で行う。 -第二部は第10章から第12章までだ。 -対象となるファイルは@parse.y@だけである。 +The first one is object space. This is very easy to understand. It is because +all of what dealt with by this are basically on the memory, +thus we can directly show or manipulate them by using functions. +Therefore, in this book, the explanation will start with this part. +Part 1 is from chapter 2 to chapter 7. -h4. 評価器 -オブジェクトは実際に触ることができるのでわかりやすい。パーサにしてもやっ -ていること自体はようするにデータ形式の変換なんだから、まあわかる。しか -し三つめの評価器、こいつはつかみどころが全くない。 +h4. Parser +The second one is parser. Probably some preliminary explanations are necessary +for this. -評価器がやるのは構文木に従ってプログラムを「実行」していくことだ。と言 -うと簡単そうに見えるのだが、では「実行する」とはどういうことか、ちゃん -と考えるとこれが結構難しい。@if@文を実行するとはどういうことだろうか。 -@while@文を実行するとはどういうことだろうか。ローカル変数に代入するとは -どういうことだろうか。メソッドを呼ぶとはどういうことだろうか。その -全てにキチンキチンと答えを出していかなければ評価器はわからないのだ。 +@ruby@ command is the interpretor of Ruby language. +It means that it analyzes the input which is a text on invocation +and executes it by following it. +Therefore, @ruby@ needs to be able to interpret the meaning of the program +written as a text, but unfortunately text is very hard to understand for +computers. For computers, text files are merely byte sequences and nothing more than +that. In order to comprehend the meaning of text from it, some special gimmick +is necessary. And the gimmick is parser. By passing through parser, (a text as) a +Ruby program would be converted into the `ruby`-specific internal expression +which can be easily handled from the program. +The internal expression is called "syntax tree". +Syntax tree expresses a program by a tree structure, +for instance, figure 4 shows how an @if@ statement is expressed. -本書では第三部『評価』で評価器を扱う。対象ファイルは@eval.c@だ。 -「評価器」は英語でevaluatorと言うので、それを省略して@eval@である。 +!images/ch_abstract_syntree.jpg(an @if@ statement and its corresponding syntax tree)! -さて、@ruby@の作りについて簡単に説明してきたが、プログラムの動作なんてい -くら概念を説明してもわかりにくいものだ。次の章ではまず実際に@ruby@を使う -ことから始めるとしよう。 +Parser will be described in Part 2 "Syntactic Analysis". +Part 2 is from chapter 10 to chapter 12. +Its target file is only @parse.y@. -御意見・御感想・誤殖の指摘などは -"青木峰郎 ":mailto:aamine@loveruby.net -までお願いします。 +h4. Evaluator +Objects are easy to understand because they are tangible. +Also regarding parser, +What it does is ultimately converting a data format into another one, +so it's reasonably easy to understand. +However, the third one, evaluator, this is completely elusive. -"『Rubyソースコード完全解説』 -":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721"はインプレスダイレクトで御予約・御購入いただけます (書籍紹介ページへ飛びます)。":http://direct.ips.co.jp/directsys/go_x_TempChoice.cfm?sh_id=EE0040&spm_id=1&GM_ID=1721 +What evaluator does is "executing" a program by following a syntax tree. +This sounds easy, but what is "executing"? +To answer this question precisely is fairly difficult. +What is "executing an @if@ statement"? +What is "executing a @while@ statement"? +What does "assigning to a local variable" mean? +We cannot understand evaluator without answering all of such questions clearly +and precisely. -Copyright (c) 2002-2004 Minero Aoki, All rights reserved. +In this book, evaluator will be discussed in Part 3 "Evaluate". +Its target file is @eval.c@. +@eval@ is an abbreviation of "evaluator". +Now, I've described briefly about the structure of @ruby@, +however even though the ideas were explained, +it does not so much help us understand the behavior of program. +In the next chapter, we'll start with actually using @ruby@. From 4c82c702283170b729fcbd66e525a5d4a2b758d7 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 12 Sep 2013 09:32:12 +0900 Subject: [PATCH 046/121] intro is now fully translated --- index.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.textile b/index.textile index a9c163d..4ba9839 100644 --- a/index.textile +++ b/index.textile @@ -10,7 +10,7 @@ rough. But it also means they are in open review, so do not hesitate to address issues on the mailing list. * "Preface":preface.html -* "Introduction - translation in progress":intro.html +* "Introduction":intro.html h3. Part 1: Objects From 0ac55c0f586e33d3c1851b313cc337677671d41b Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 12 Sep 2013 09:41:09 +0900 Subject: [PATCH 047/121] fix the title of intro --- intro.textile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intro.textile b/intro.textile index caa8ea3..bdb8ccc 100644 --- a/intro.textile +++ b/intro.textile @@ -1,9 +1,10 @@ --- layout: default +title: Introduction --- -h1. Preface: Introduction +h1. Introduction h2. Characteristics of Ruby From 865dfad2de36d9da29c3cc321227d2d84c992e01 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 12 Sep 2013 09:44:23 +0900 Subject: [PATCH 048/121] use the same title for chapter 11 --- index.textile | 2 +- script/publish | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.textile b/index.textile index 4ba9839..a41eeea 100644 --- a/index.textile +++ b/index.textile @@ -27,7 +27,7 @@ h3. Part 2: Syntax analysis * "Chapter 8: Ruby Language Details":spec.html * "Chapter 9: yacc crash course":yacc.html * "Chapter 10: Parser":parser.html -* "Chapter 11: Context-dependent scanner":contextual.html +* "Chapter 11: Finite-state scanner":contextual.html * "Chapter 12: Syntax tree construction":syntree.html h3. Part 3: Evaluation diff --git a/script/publish b/script/publish index 8ea6758..0a81ec2 100755 --- a/script/publish +++ b/script/publish @@ -56,7 +56,7 @@ navigation = [ {:label => "Chapter 8: Ruby Language Details", :content => "spec.html"}, {:label => "Chapter 9: yacc crash course", :content => "yacc.html"}, {:label => "Chapter 10: Parser", :content => "parser.html"}, - {:label => "Chapter 11: Context-dependent scanner", :content => "contextual.html"}, + {:label => "Chapter 11: Finite-state scanner", :content => "contextual.html"}, {:label => "Chapter 12: Syntax tree construction", :content => "syntree.html"} ]}, {:label => "Part 3: Evaluation", :content => "evaluator.html", :nav => [ From 5e54ac7deac4473af3ff67d18e7b2ee12e800a99 Mon Sep 17 00:00:00 2001 From: ocha- Date: Thu, 12 Sep 2013 10:04:26 +0900 Subject: [PATCH 049/121] edit index.textile 1. to remove not or no longer accurate information about this book and this translation project 2. to add the information about the original support site and this translation project. --- index.textile | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/index.textile b/index.textile index a41eeea..32c8037 100644 --- a/index.textile +++ b/index.textile @@ -7,7 +7,7 @@ h2. Table of contents Some chapters are previews. It means they have not been fully reviewed, some diagrams may be missing and some sentences may be a little rough. But it also means they are in open review, so do not hesitate -to address issues on the mailing list. +to address issues. * "Preface":preface.html * "Introduction":intro.html @@ -47,34 +47,31 @@ h3. Part 4: Around the evaluator h1. About this Guide -This is a new effort to gather efforts to help translate into English the "Ruby -Hacking Guide":http://i.loveruby.net/ja/rhg/book/. The RHG is a book -that explains how the ruby interpreter (the official -C implementation of the "Ruby language":http://www.ruby-lang.org/) works -internally. +This is a new effort to gather efforts to help translate +"Ruby Hacking Guide":http://i.loveruby.net/ja/rhg/book/ into English. +The official support site of the original book is +http://i.loveruby.net/ja/rhg/ -To fully understand it, you need a good knowledge of C and Ruby. +You can download the version of the source code explained and +the tool used in the book +from the official support site of the original book. +* "ruby (1.7.3 2002-09-12) in tar.gz format":http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz +* "ruby (1.7.3 2002-09-12) in zip format":http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz +* "Pragmatic Programmers' nodeDump 0.1.7":http://i.loveruby.net/ja/rhg/ar/nodeDump-0.1.7.tgz +* "RHG-version nodedump":http://i.loveruby.net/ja/rhg/ar/nodedump-rhg.tar.gz -Please note that this book was based on the source code of ruby 1.7.3 -so there are a few small differences to the current version of -ruby. However, these differences may make the source code simpler to -understand and the Ruby Hacking Guide is a good starting point before -looking into the ruby source code. The version of the source code used -can be downloaded here: http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz. +The original translating project is hosted at RubyForge +http://rubyforge.org/projects/rhg Many thanks to "RubyForge":http://rubyforge.org for hosting us and to Minero AOKI for letting us translate his work. -h2. Help us! +You can get further information about this project from +"the archives of rhg-discussion mailing list":http://rubyforge.org/pipermail/rhg-discussion/ -The original is available "here":http://i.loveruby.net/ja/rhg/book/ -or hosted within this repo "here":http://ruby-hacking-guide.github.com/original_repo/ja_html/ -(currently with broken formatting) -This translation is done during our free time, do not expect too -much. The book is quite big (more than 500 pages) so we need help to -translate it. +h2. Help us! People who are good at Ruby, C and Japanese or English are needed. Those good at Japanese (native Japanese speakers are of course @@ -94,7 +91,7 @@ https://github.com/ruby-hacking-guide/ruby-hacking-guide.github.com There is a mostly derelict mailing list at "rhg-discussion mailing list":http://rubyforge.org/mailman/listinfo/rhg-discussion feel free to introduce yourself (who you are, your skills, how much free time you -have), but I think the best way to propose or send corrections/improvements +have), but we think the best way to propose or send corrections/improvements is to send a pull request. If you start a feature branch along with a pull request at the start of your work then people can comment as you work. From 8f5653493b04e865c92a283353aec173585acde4 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 15 Sep 2013 14:18:37 +0900 Subject: [PATCH 050/121] English images for chapter 01 --- images/ch_minimum_Kernel.jpg | Bin 7246 -> 7965 bytes images/ch_minimum_modclass2.jpg | Bin 5507 -> 6289 bytes images/ch_minimum_objimage.jpg | Bin 5280 -> 6085 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/ch_minimum_Kernel.jpg b/images/ch_minimum_Kernel.jpg index 78f5a4010fe6eecf85c4f9d5e832a376b8b27162..5093e6e7b3de7085632054f0f1988d0c27f0beba 100644 GIT binary patch literal 7965 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 diff --git a/images/ch_minimum_modclass2.jpg b/images/ch_minimum_modclass2.jpg index 1547dacd254428c9b7be9529ed179afc241371fc..34efbf9a117cd222870d0fc8a3ece54ec38ec547 100644 GIT binary patch literal 6289 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 literal 5507 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 trA?9O(JNX;PO6e@9yK2kB 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 literal 5280 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 WkBI7jh5V}r@D$m1`#bRFyZ-{H%}=2K From c80d6d1ebb57698c9cdb0e0cdfca599116563b57 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 15 Sep 2013 14:29:53 +0900 Subject: [PATCH 051/121] edit chapter 01 --- minimum.textile | 484 ++++++++++++++++++++++++++---------------------- 1 file changed, 266 insertions(+), 218 deletions(-) diff --git a/minimum.textile b/minimum.textile index 3873d06..b910ae2 100644 --- a/minimum.textile +++ b/minimum.textile @@ -6,7 +6,7 @@ Translated by Sebastian Krause h1. Chapter 1: Introduction -h2. A Minimal Introdution to Ruby +h2. A Minimal Introduction to Ruby Here the Ruby prerequisites are explained, which one needs to know in order to understand the first section. @@ -45,7 +45,8 @@ another string object is generated. Here three string objects with content `content` are generated. -Besides, a program won't do any good without some output. Let's show how to print on the terminal. +By the way, objects just existing there can't be seen by programmers. +Let's show how to print them on the terminal.
 p("content")   # Shows "content"
@@ -59,6 +60,7 @@ It's basically a debugging function.
 
 Precisely speaking, there are no functions in Ruby, but just for now
 we can think of it as a function.
+You can use functions wherever you are.
 
 h3. Various Literals
 
@@ -102,8 +104,8 @@ And finally, a hash table is generated by the expression below.
 {"key"=>"value", "key2"=>"value2", "key3"=>"value3"}
 
-A hash table is a structure which establishes a one-on-one relation between pairs of -arbitrary objects. The above line creates a table which stores the following table. +A hash table is a structure which expresses one-to-one relationships between arbitrary objects. +The above line creates a table which stores the following relationships.
 "key"   →  "value"
@@ -111,7 +113,7 @@ arbitrary objects. The above line creates a table which stores the following tab
 "key3"  →  "value3"
 
-If we ask the hash table above "What's corresponding to `key`?", it'll +If we ask a hash table created in this way "What's corresponding to `key`?", it'll answer "That's `value`." How can we ask? We use methods. h3. Method Calls @@ -126,7 +128,7 @@ the notation. Here the `upcase` method is called on a string object ( with content `content`). As `upcase` is a method which -returns a new string with the small letters replaced by capital letters +returns a new string with the small letters replaced by capital letters, we get the following result.
@@ -141,7 +143,7 @@ Method calls can be chained.
 
 Here the method `downcase` is called on the return value of `"content".upcase()`.
 
-There are no public fields (member variables) as in Java or C++ (Note: need to check this). The object interface consists of methods only.
+There are no public fields (member variables) as in Java or C++. The object interface consists of methods only.
 
 h2. The Program
 
@@ -169,10 +171,10 @@ With the `-e` option of the `ruby` program we don't even need to create a file.
 "content"
 
-By the way, the place where `p` is written is the lowest level of the program, -or the highest level from the program's standpoint. Hence it's called the -toplevel. -The existence of a toplevel is a characteristic trait of a scripting language. +By the way, the place where `p` is written is the lowest nesting level of the program, +it means the highest level from the program's standpoint, +thus it's called "top-level". +Having top-level is a characteristic trait of Ruby as a scripting language. In Ruby, one line is usually one statement. A semicolon at the end isn't necessary. Therefore the program below is interpreted as three statements. @@ -196,12 +198,13 @@ h3. Local Variables In Ruby all variables and constants store references to objects. That's why one can't copy the content by assigning one variable to another variable. -Think of object type variables in Java or pointers in C++. But you can't change the value -of these pointers. +Variables of type Object in Java or pointers to objects in C++ are good to think of. +However, you can't change the value of each pointer itself. -In Ruby one can tell the scope of a variable by its name's first letter. -Local variables start with a small letter or an underscore. One can write -an "=" for variable assignment. +In Ruby one can tell the classification (scope) of a variable +by the beginning of the name. +Local variables start with a small letter or an underscore. +One can write assignments by using "`=`".
 str = "content"
@@ -209,8 +212,9 @@ arr = [1,2,3]
 
An initial assignment serves as declaration, an explicit declaration is -not necessary. Because variables don't have a type we can assign any type without -distinction. The program below is completely legal. +not necessary. Because variables don't have types, +we can assign any kind of objects indiscriminately. +The program below is completely legal.
 lvar = "content"
@@ -218,19 +222,19 @@ lvar = [1,2,3]
 lvar = 1
 
-But just because we can we shouldn't necessarily do it. If different -objects are put in one variable it tends to become difficult to read. In a +But even if we can, we don't have to do it. If different kind of +objects are put in one variable, it tends to become difficult to read. In a real world Ruby program one doesn't do this kind of things without a good reason. The above was just an example for the sake of it. -Variable reference has also a pretty straightforward notation. +Variable reference has also a pretty sensible notation.
 str = "content"
 p(str)           # Shows "content"
 
-Now let's look at how a variable stores a reference. +In addition let's check the point that a variable hold a reference by taking an example.
 a = "content"
@@ -240,11 +244,13 @@ c = b
 
 After we execute this program all three local variables `a b c`
 point to the same object, a string object with content `"content"`
+created on the first line (Figure 1).
 
 
-!images/ch_minimum_reference.jpg(Ruby variables store references to objects)!
+!images/ch_minimum_reference.png(Ruby variables store references to objects)!
 
-Besides, these variables are called local. Hence there should be a scope
+By the way, as these variables are called local,
+they should be local to somewhere,
 but we cannot talk about this scope without reading a bit further.
 Let's say for now that the top level is one local scope.
 
@@ -261,11 +267,14 @@ p(Const)   # Shows "content"
 
I'd like to say that if we assign twice an error occurs. But there -is just a warning, not an error. That's because of applications -which use Ruby, for instance development environments. There shouldn't -be an error when they load the same file twice. I recognize that -it had to be that way for practicality but there really should be an error. -Up until version 1.1 there really was an error. +is just a warning, not an error. +It is in this way in order to avoid raising an error +even when the same file is loaded twice +in applications that manipulate Ruby program itself, +for instance in development environments. +Therefore, it is allowed due to practical requirements and there's no other choice, +but essentially there should be an error. +In fact, up until version 1.1 there really was an error.
-Next, let's focus on the actions, surprisingly, @elsif@ uses the same @NEW_IF()@ as @if@ . +Next, let's focus on the actions, surprisingly, @elsif@ uses the same @NEW_IF()@ as @if@. It means, the below two programs will lose the difference after they become syntax trees. @@ -759,7 +759,7 @@ end else Come to think of it, in C language and such, there's no distinction between the two also at the syntax level. Thus this might be a matter of course. -Alternatively, the conditional operator ( @a?b:c@ ) becomes indistinguishable +Alternatively, the conditional operator (@a?b:c@) becomes indistinguishable from @if@ statement after they become syntax trees. @@ -773,7 +773,7 @@ are the same in its syntax tree expression. I'll introduce a few more examples. @add@ and @&&@ become the same. -@or@ and @||@ are also equal to each other. @not@ and @!@ , @if@ and modifier @if@ , +@or@ and @||@ are also equal to each other. @not@ and @!@, @if@ and modifier @if@, and so on. These pairs also become equal to each other. @@ -809,16 +809,16 @@ list: END_ITEM when you write in this way, it becomes the list that contains continuous zero -or more number of @ITEM@ and ends with @END_ITEM@ . +or more number of @ITEM@ and ends with @END_ITEM@. As an expression of a list, whichever is used it does not create a so much difference, but the way that the actions are executed is fatally different. With the form that @list@ is written at the right, the actions are sequentially -executed from the last @ITEM@ . We've already learned about the behavior of the +executed from the last @ITEM@. We've already learned about the behavior of the stack of when @list@ is at the left, so let's try the case that @list@ is at the right. -The input is 4 @ITEM@ s and @END_ITEM@ . +The input is 4 @ITEM@ s and @END_ITEM@. | | empty at first | @@ -849,10 +849,10 @@ Thus, @if_tail@ is constructed in the "@list@ at the right" manner. Finally, the meaning of the headline is, in grammar terms, -"the left is @list@ " is called left-recursive, -"the right is @list@ " is called right-recursive. +"the left is @list@" is called left-recursive, +"the right is @list@" is called right-recursive. These terms are used mainly when reading papers about processing grammars or -writing a book of @yacc@ . +writing a book of @yacc@. @@ -920,8 +920,8 @@ Fig.5: @NODE_BLOCK@ and @NODE_NEWLINE@

-It means, for each statement ( @stmt@ ) @NODE_NEWLINE@ is attached, -and when they are multiple, it will be a list of @NODE_BLOCK@ . +It means, for each statement (@stmt@) @NODE_NEWLINE@ is attached, +and when they are multiple, it will be a list of @NODE_BLOCK@. Let's also see the code. @@ -942,9 +942,9 @@ Let's also see the code.
 C = 1
@@ -274,7 +283,8 @@ C = 2   # There is a warning but ideally there should be an error.
 
 A lot of people are fooled by the word constant.
 A constant only does not switch objects once it is assigned.
-But the object itself might as well change. The term "read only"
+But it does not mean the pointed object itself won't change.
+The term "read only"
 might capture the concept better than "constant".
 
 By the way, to indicate that an object itself shouldn't be changed
@@ -282,13 +292,14 @@ another means is used: `freeze`.
 
 !images/ch_minimum_const.jpg(constant means read only)!
 
-And we cannot talk about the scope yet. We talk about it later in
-the context of classes.
+And the scope of constants is actually also cannot be described yet.
+It will be discussed later in the next section mixing with classes.
 
 h3. Control Structures
 
-Unfortunately Ruby has a wide abundance of control structures.
-For the time being we pretend there are just `if` and `while`.
+Since Ruby has a wide abundance of control structures,
+just lining up them can be a huge task.
+For now, I just mention that there are `if` and `while`.
 
 
 if i < 10 then
@@ -299,29 +310,35 @@ while i < 10 do
   # body
 end
 
-Only `false` and `nil` are false in a conditional expression, all + +In a conditional expression, +only the two objects, `false` and `nil`, are false and all other various objects are true. 0 or the empty string are also true of course. -By the way, it wouldn't be wise if there were just `false`, there is also `true`. +It wouldn't be wise if there were just `false`, there is also `true`. And it is of course true. h2. Classes and Methods h3. Classes -In object orientation methods belong to objects, in a perfect -world, though. But in a normal program there are a lot of objects which have the -same set of methods. Usually a mechanism like classes or +In object oriented system, essentially methods belong to objects. +It can hold only in a ideal world, though. +In a normal program there are a lot of objects which have the +same set of methods, it would be an enormous work if each object remember the +set of callable methods. +Usually a mechanism like classes or multimethods is used to get rid of the duplication of definitions. -In Ruby the traditional concept of classes is used to bind objects and -methods together. Namely every object belongs to a class, the methods -which can be called are determined by the class. Hence a method is -called an instance of a class. +In Ruby, as the traditional way to bind objects and methods together, +the concept of classes is used. +Namely every object belongs to a class, the methods +which can be called are determined by the class. +And in this way, an object is called "an instance of the XX class". -For example the string `"str"` is called an instance of the class `String`. -And in this class `String` the methods `upcase`, `downcase`, `strip` and -many others are defined. So it looks as if each string object has all these +For example the string `"str"` is an instance of the `String` class. +And on this `String` class the methods `upcase`, `downcase`, `strip` and +many others are defined. So it looks as if each string object can respond to all these methods.
@@ -348,7 +365,7 @@ is a runtime exception. Let's try it out. For this kind of programs the
 
 When the method isn't found there's apparently a `NoMethodError`.
 
-Always talking about "the upcase method of String" and such is cumbersome.
+Always saying "the upcase method of String" and such is cumbersome.
 Let's introduce a special notation `String#upcase` refers to the method
 `upcase` defined in the class `String`.
 
@@ -360,7 +377,7 @@ h3. Class Definition
 
 Up to now we talked about already defined classes.
 We can of course also define our own classes.
-To define classes we use the word `class`.
+To define classes we use the `class` statement.
 
 
 class C
@@ -381,8 +398,9 @@ The astute reader might think:
 Hmm, this `C.new()` really looks like a method call.
 In Ruby the object generating expressions are indeed just methods.
 
-In Ruby class names and constant names are the same. But what is
-contained in a class name, where there's a constant with the same name? It's the class.
+In Ruby class names and constant names are the same.
+Then, what is stored in the constant whose name is the same as a class name?
+In fact, it's the class.
 In Ruby all things which a program can manipulate are objects. So
 of course classes are also expressed as objects. Let's call these
 class objects. Every class is an instance of the class `Class`.
@@ -404,9 +422,9 @@ S.upcase()  # Get the object the constant S points to and call upcase
 C.new()     # Get the object the constant C points to and call new
 
-So `new` is not a keyword in Ruby. +So `new` is not a reserved word in Ruby. -And we can also use `p` for an instance of a created class. +And we can also use `p` for an instance of a class even immediately after its creation.
 class C
@@ -420,8 +438,8 @@ It won't display as nicely as a string or an integer but it shows
 its respective class and it's internal ID. This ID is the pointer value
 which points to the object.
 
-Oh, I completely forgot but about the notation of method names:
-`Object.new` calls the method `new` of the class object `Object` itself.
+Oh, I completely forgot to mention about the notation of method names:
+`Object.new` means the class object `Object` and the `new` method called on the class itself.
 So `Object#new` and `Object.new` are completely different things, we have
 to separate them strictly.
 
@@ -431,11 +449,13 @@ obj.new()            # Object#new
 
In practice a method `Object#new` is almost never defined so the -second line will return an error. Please keep this example in mind. +second line will return an error. +Please regard this as an example of the notation. h3. Method Definition -If we can define classes we should also be able to define methods. +Even if we can define classes, +it is useless if we cannot define methods. Let's define a method for our class `C`.
@@ -446,13 +466,13 @@ class C
 end
 
-To define a method we use the word `def`. In this example we +To define a method we use the `def` statement. In this example we defined the method `myupcase`. The name of the only parameter is `str`. -As with variables it's not necessary to write down the type of the parameter. +As with variables, it's not necessary to write parameter types or the return type. And we can use any number of parameters. Let's use the defined method. Methods are usually called from the -outside. +outside by default.
 c = C.new()
@@ -460,7 +480,7 @@ result = c.myupcase("content")
 p(result)   # Shows "CONTENT"
 
-Of course if you get used to it you don't need to assign everything. +Of course if you get used to it you don't need to assign every time. The line below gives the same result.
@@ -469,8 +489,9 @@ p(C.new().myupcase("content"))   # Also shows "CONTENT"
 
 h3. `self`
 
-During the execution of a method the information about itself (the instance
-which called the method) is saved and can be picked up in `self`.
+During the execution of a method the information about
+who is itself (the instance on which the method was called) is always saved
+and can be picked up in `self`.
 Like the `this` in C++ or Java. Let's check this out.
 
 
@@ -485,11 +506,11 @@ p(c)              # #
 p(c.get_self())   # #
 
-As we see, the exact same object is returned. -We ascertained that for the called method `self` is `c`. +As we see, the above two expressions return the exact same object. +We could confirm that `self` is `c` during the method call on `c`. -How should a method against oneself be called? -It comes to mind to do this also via `self`. +Then what is the way to call a method on itself? +What first comes to mind is calling via `self`.
 class C
@@ -506,12 +527,13 @@ C.new().my_p(1)   # Output 1
 
But always adding the `self` when calling an own method is tedious. -Hence, whenever one calls `self` one can omit the called object ( the receiver) by convention. +Hence, it is designed so that one can omit the called method (the receiver) +whenever one calls a method on `self`.
 class C
   def my_p( obj )
-    real_my_p(obj)   # Calling without writing down the receiver.
+    real_my_p(obj)   # You can call without specifying the receiver
   end
 
   def real_my_p( obj )
@@ -524,14 +546,15 @@ C.new().my_p(1)   # Output 1
 
 h3. Instance Variables
 
-The saying goes "Objects are data and code". So the definition
-of methods alone would be useless. Objects must also be able
+As there are a saying "Objects are data and code",
+just being able to define methods alone would be not so useful.
+Each object must also be able to
 to store data. In other words instance variables.
-Or in C++ jargon member variables. (Note: Check this.)
+Or in C++ jargon member variables.
 
-In the fashion of Ruby's variable naming convention, the first
-letter determines the variable type. For instance variables it's
-an `@`.
+In the fashion of Ruby's variable naming convention,
+the variable type can be determined by the first a few characters.
+For instance variables it's an `@`.
 
 
 class C
@@ -550,7 +573,7 @@ p(c.get_i())   # Shows "ok"
 
Instance variables differ a bit from the variables seen before: -We can reference them without assigning or defining them. +We can reference them without assigning (defining) them. To see what happens we add the following lines to the code above.
@@ -559,8 +582,9 @@ p(c.get_i())   # Shows nil
 
Calling `get` without `set` gives `nil`. `nil` is the object -which indicates "nothing". It's mysterious why there's an object -where there should be nothing, but that's just the way it is. +which indicates "nothing". +It's mysterious that there's really an object but it means nothing, +but that's just the way it is. We can use `nil` like a literal as well. @@ -571,10 +595,11 @@ p(nil) # Shows nil h3. `initialize` As we saw before, when we call 'new' on a freshly defined class, -we can create an instance. That's surely a good thing, but +we can create an instance. That's sure, but sometimes we might want to have a peculiar instantiation. -In this case we don't change method `new`, we change the method `initialize`. -When we do this it get's called within `new`. +In this case we don't change the `new` method, +we define the `initialize` method. +When we do this, it gets called within `new`.
 class C
@@ -589,23 +614,23 @@ c = C.new()
 p(c.get_i())   # Shows "ok"
 
-Strictly speaking this is the work of the `new` method not the -work of the language itself. +Strictly speaking this is the specification of the `new` method +but not the specification of the language itself. h3. Inheritance Classes can inherit from other classes. For instance `String` -inherits from `Object`. In this text we''ll indicate this relation +inherits from `Object`. In this book, we'll indicate this relation by a vertical arrow as in Fig.3. !images/ch_minimum_supersub.jpg(Inheritance)! -In the illustration the inherited class (`Object`) is called +In the case of this illustration, the inherited class (`Object`) is called superclass or superior class. The inheriting class (`String`) is called subclass or inferior class. This point differs from C++ jargon, be careful. But it's the same as in Java. -Anyway let's try it out. Let's inherit for our created class from another +Anyway let's try it out. Let our created class inherit from another class. To inherit from another class ( or designate a superclass) write the following. @@ -636,7 +661,7 @@ sub = Sub.new() p(sub.hello()) # Shows "hello"
-`hello` was defined in the class `C` but we could call it from +`hello` was defined in the class `C` but we could call it on an instance of the class `Sub` as well. Of course we don't need to assign variables. The above is the same as the line below. @@ -644,9 +669,9 @@ The above is the same as the line below. p(Sub.new().hello())
-When we define a method with the same name we overwrite a method. +By defining a method with the same name, we can overwrite the method. In C++ and Object Pascal (Delphi) it's only possible to overwrite -explicitly with the keyword `virtual` but in Ruby every method +functions explicitly defined with the keyword `virtual` but in Ruby every method can be overwritten unconditionally.
@@ -670,34 +695,34 @@ We can inherit over several steps. For instance as in Fig.4
 `Fixnum` inherits every method from `Object`, `Numeric` and `Integer`.
 When there are methods with the same name the nearer classes take
 preference. As type overloading isn't there at all the requisites are
-extremely straigtforward.
+extremely straightforward.
 
-!images/ch_minimum_multiinherit.jpg(Inheitance over multiple steps)!
+!images/ch_minimum_multiinherit.jpg(Inheritance over multiple steps)!
 
 In C++ it's possible to create a class which inherits nothing.
 While in Ruby one has to inherit from the `Object` class either
 directly or indirectly. In other words when we draw the inheritance
 relations it becomes a single tree with `Object` at the top.
+For example, when we draw a tree of the inheritance relations among the
+important classes of the basic library, it would look like Fig.5.
 
 !images/ch_minimum_classtree.jpg(Ruby's class tree)!
-(Note: changed in 1.9: `Socket` isn't builtin anymore, might want to add
-`Fiber`, `String`, `Symbol`)
 
-When the superclass is appointed ( in the definition statement ) it's
-not possible to change it anymore. In other words, one can add to the class tree
+Once the superclass is appointed ( in the definition statement ) it's
+impossible to change it. In other words, one can add a new class to the class tree
 but cannot change a position or delete a class.
 
 h3. Inheritance of Variables……?
 
 In Ruby (instance) variables aren't inherited.
-Even when inheriting, there's no information what variables that class
-uses.
-
+Even though trying to inherit,
+a class does not know about what variables are going to be used.
 
 But when an inherited method is called ( in an instance of a subclass),
 assignment of instance variables happens. Which means they
 become defined. Then, since the namespace of instance variables
-is completely flat, it can be accessed by whichever method.
+is completely flat based on each instance,
+it can be accessed by a method of whichever class.
 
 
 class A
@@ -715,22 +740,20 @@ end
 B.new().print_i()   # Shows "ok"
 
-If you can't agree with this behavior let's think more about classses -and inheritance. When there's an instance `obj` of the -the class `C` then all the methods of the superclass of `C` are as if +If you can't agree with this behavior, let's forget about classes +and inheritance. When there's an instance `obj` of +the class `C`, then think as if all the methods of the superclass of `C` are defined in `C`. Of course we keep the overwrite rule in mind. Then the methods of `C` get attached to the instance `obj` (Fig.6). This strong palpability is a specialty of Ruby's object orientation. !images/ch_minimum_objimage.jpg(A conception of a Ruby object)! -(メソッド:method) - h3. Modules Only a single superclass can be designated. So Ruby looks like single inheritance. But because of modules it has in practice -the same abilities as a multiple inheritance language. +the ability which is identical to multiple inheritance. Let's explain these modules next. In short, modules are classes for which a superclass cannot be @@ -753,10 +776,9 @@ module M end
-But because instances cannot be directly created we cannot call -these directly. What can we do about it? We can use these methods -by including the module into other classes. When doing so it's as if -the module inherits to the class. +But because we cannot create instances, we cannot call them directly. +To do that, we use the module by "including" it into other classes. +Then we become to be able to deal with it as if a class inherited the module.
 module M
@@ -773,11 +795,12 @@ p(C.new().myupcase("content"))  # "CONTENT" is shown
 
Even though no method was defined in the class `C` we can call -the method `myupcase`. It was inherited from the module `M`. +the method `myupcase`. +It means it "inherited" the method of the module `M`. Inclusion is functionally completely the same as inheritance. -There's no limit on the access of methods and instance variables. +There's no limit on defining methods or accessing instance variables. -A superclass cannot be assigned to a module, but +I said we cannot specify any superclass of a module, but other modules can be included.
@@ -820,11 +843,11 @@ C.new().method_OneMore()   # Output "OneMore"
 
 As with classes when we sketch inheritance it looks like Fig.7
 
-!images/ch_minimum_modinherit.jpg(multilevel inheritance )!
+!images/ch_minimum_modinherit.jpg(multilevel inclusion)!
 
-Besides, the class `C` also has a superclass. What might be its
-relationship with the included modules. For instance we could write
-as follows.
+Besides, the class `C` also has a superclass.
+How is its relationship to modules?
+For instance, let's think of the following case.
 
 
 # modcls.rb
@@ -848,10 +871,10 @@ end
 p(B.new().test())   # "class"? "module"?
 
-`C` inherits from `Cls` and includes `Mod`. What will be shown? -`"class"` or `"module"`? In other words which one is closer? -The superclass or the module? -We can ask Ruby about Ruby: +`C` inherits from `Cls` and includes `Mod`. +Which will be shown in this case, `"class"` or `"module"`? +In other words, which one is "closer", class or module? +We'd better ask Ruby about Ruby, thus let's execute it:
 % ruby modcls.rb
@@ -860,24 +883,24 @@ We can ask Ruby about Ruby:
 
 Apparently a module takes preference before the superclass.
 
-Broadly speaking, in Ruby an included module inherits by going in between
+In general, in Ruby when a module is included, it would be inherited by going in between
 the class and the superclass. As a picture it might look like Fig.8.
 
 !images/ch_minimum_modclass.jpg(The relation between modules and classes)!
 
-And modules included in modules look like Fig.9
 
+And if we also taking the modules included in the module into accounts,
+it would look like Fig.9.
 
 !images/ch_minimum_modclass2.jpg(The relation between modules and classes(2))!
 
-(SomeClassのスーパークラス:superclass of SomeClass)
-
 h2. The Program revisited
 
-Caution. Now I explain an extremely important element which is probably
-hard to get used to for programmers who have only used static languages before.
-You can skip the rest but please read this carefully. I'll
-explain this also in relative depth.
+Caution. This section is extremely important and explaining the elements which are
+not easy to mix with for programmers who have only used static languages before.
+For other parts just skimming is sufficient,
+but for only this part I'd like you to read it carefully.
+The explanation will also be relatively attentive.
 
 h3. Nesting of Constants
 
@@ -902,8 +925,8 @@ p(::Const)   # Shows 3 in the same way.
 
 The `::` in front shows that it's a constant defined at the top level.
 You can think of the path in a filesystem. Assume there is a file `vmunix`
-at rootlevel. Being at `/` one can write `vmunix` to access the file. One
-can also write `/vmunix`. It's the same with `Const` and `::Const`.
+in the root directory. Being at `/` one can write `vmunix` to access the file. One
+can also write `/vmunix` as its full path. It's the same with `Const` and `::Const`.
 At top level it's okay to write only `Const` or to write the full path `::Const`
 
 And what corresponds to a filesystem's directories in Ruby?
@@ -922,10 +945,12 @@ p(  SomeClass::Const)   # The same. Shows 3
 
`SomeClass` is defined at toplevel. Hence one can reference it by writing -either `SomeClass` or `::SomeClass`. And in class is the constant -`Const`. It becomes `::SomeClass::Const`. +either `SomeClass` or `::SomeClass`. +And as the constant `Const` nested in the class definition is a `Const` "inside `SomeClass`", +It becomes `::SomeClass::Const`. -A class inside a class is like a directory in a directory. +As we can create a directory in a directory, +we can create a class inside a class. For instance like this:
@@ -937,7 +962,8 @@ class C        # ::C
 end
 
-Is it always necessary to reference a constant inside a class by its +By the way, for a constant defined in a class definition statement, +should we always write its full name? Of course not. As with the filesystem, if one is inside the same class definition one can skip the `::`. It becomes like that: @@ -948,7 +974,9 @@ class SomeClass end
-"What?" you might think. Why's the code inside a class definition executed? +"What?" you might think. +Surprisingly, even if it is in a class definition statement, +we can write a program which is going to be executed. People who are used to only static languages will find this quite exceptional. I was also flabbergasted the first time I saw it. @@ -970,12 +998,12 @@ C.new().test() # Shows "ok" h3. Everything is executed Looking at the big picture I want to write one more thing. -In Ruby almost the whole program is executed. +In Ruby almost the whole parts of program is "executed". Constant definitions, class definitions and method definitions -and the rest is executed in the apparent order. +and almost all the rest is executed in the apparent order. Look for instance at the following code. -I used various constructions which haven't been used before. +I used various constructions which have been used before.
  1:  p("first")
@@ -1010,8 +1038,9 @@ h3. The Scope of Local Variables
 At last we can talk about the scope of local variables.
 
 The toplevel, the interior of a class definition, the interior of a module definition and a method body are all
-scopes for independent local variables. In other words in the following program all variables
-`lvar` are different. There's no connection between them.
+have each completely independent local variable scope.
+In other words, the `lvar` variables in the following program are all different variables,
+and they do not influence each other.
 
 
 lvar = 'toplevel'
@@ -1034,38 +1063,40 @@ p(lvar)   # Shows "toplevel"
 
 h3. `self` as context
 
-I said before, that oneself is `self` during method execution.
-That's true but only half true. It's really so that during execution
-self is always set up. So also  at toplevel and also in a class definition.
+Previously, I said that during method execution oneself (an object on which the
+method was called) becomes self.
+That's true but only half true.
+Actually during the execution of a Ruby program,
+`self` is always set wherever it is.
+It means there's `self` also at the top level or in a class definition statement.
 
 For instance the `self` at the toplevel is `main`. It's an instance
-of the `Object` class, as might be expected. `main` is provided
+of the `Object` class which is nothing special. `main` is provided
 to set up `self` for the time being. There's no deeper meaning attached
 to it.
 
 Hence the toplevel's `self` i.e. `main` is an instance of `Object`,
 such that one can call the methods of `Object` there. And in `Object`
-the module `Kernel` is included. In there the function type methods
+the module `Kernel` is included. In there the function-flavor methods
 like `p` and `puts` are defined (Fig.10). That's why one can
 call `puts` and `p` also at the toplevel.
 
 !images/ch_minimum_Kernel.jpg(`main`, `Object` and `Kernel`)!
 
-(トップレベル:toplevel)
-
-Thus `p` isn't a function, it's a method. It's just
-defined in `Kernel` and thus can be called from everywhere. Or no matter what `self` is,
- `p` is a method of `self` and can be called.
-That's why there aren't really functions in Ruby. There are only methods.
+Thus `p` isn't a function, it's a method. Just because
+it is defined in `Kernel` and thus can be called like a function as "its own"
+method wherever it is or no matter what the class of `self` is.
+Therefore, there aren't functions in the true sense, there are only methods.
 
-By the way, besides `p` and `puts` there are the function type
+By the way, besides `p` and `puts` there are the function-flavor
 methods `print`, `puts`, `printf`, `sprintf`, `gets`, `fork`, and `exec`
 and many more with somewhat familiar names. When you look at the choice
-of names you might imagine Ruby's character.
+of names you might be able to imagine Ruby's character.
 
-I mentioned that `self` is set up everywhere, so it should also
-be in a class definition. There it is the class ( class object)
-itself. Hence we get this.
+Well, since `self` is setup everywhere,
+`self` should also be in a class definition in the same way.
+The `self` in the class definition is the class itself (the class object).
+Hence it would look like this.
 
 
 class C
@@ -1074,7 +1105,7 @@ end
 
What should this be good for? -Let's look at a much more useful example. +In fact, we've already seen an example in which it is very useful. This one.
 module M
@@ -1083,13 +1114,14 @@ class C
   include M
 end
 
-This `include` is a method call to the class object `C`. + +This `include` is actually a method call to the class object `C`. I haven't mentioned it yet but the parentheses around arguments -can be omitted for method calls. And I omitted the parantheses -around `include` such that it doesn't look like a method call, which might -have been confusing without knowing the whole story. +can be omitted for method calls. And I omitted the parentheses +around `include` such that it doesn't look like a method call +because we have not finished the talk about class definition statement. -h3. Loading Libraries +h3. Loading In Ruby the loading of libraries also happens at runtime. Normally one writes this. @@ -1099,21 +1131,26 @@ require("library_name")
The impression isn't false, `require` is a method. It's not even -a reserved word. When one writes that line the loaded library will be -executed where the line is written. As there is no concept like Java packages in Ruby, -one has to use files and directories to separate the namespace. +a reserved word. When it is written this way, +loading is executed on the line it is written, +and the execution is handed over to (the code of) the library. +As there is no concept like Java packages in Ruby, +when we'd like to separate namespaces, +it is done by putting files into a directory.
 require("somelib/file1")
 require("somelib/file2")
 
-And in the library file there are usually class and module statements. The toplevel constant scope -is independent of the file, so one can see at once classes which where defined in another file. +And in the library usually classes and such are defined with `class` statements +or `module` statements. The constant scope of the top level is flat without the +distinction of files, so one can see classes defined in another file without +any special preparation. To partition the namespace of class names one has to explicitly nest modules as shown below.
-# example of the namespace partion of the net library
+# example of the namespace partition of net library
 module Net
   class SMTP
     # ...
@@ -1129,13 +1166,13 @@ end
 
 h2. More about Classes
 
-h3. Constants revisited
+h3. The talk about Constants still goes on
 
 Up to now we used the filesystem metaphor for
 the scope of constants, but I want you to completely forget that.
 
-There is more about constants. Firstly one can also see constants outside
-the class.
+There is more about constants. Firstly one can also see constants
+in the "outer" class.
 
 
 Const = "ok"
@@ -1144,8 +1181,9 @@ class C
 end
 
-This becomes useful, when modules are used as namespaces. -Let's explain this by looking at the net library from before. +The reason why this is designed in this way is because +this becomes useful when modules are used as namespaces. +Let's explain this by adding a few things to the previous example of `net` library.
 module Net
@@ -1157,11 +1195,11 @@ module Net
 end
 
-In this case it's convenient to just refer to `SMTPHelper` -from within `SMTP`. That's the reason why it's convenient to -be able to see outside a class. +In such case, it's convenient if we can refer to it also from the `SMTP` class +just by writing `SMTPHelper`, isn't it? +Therefore, it is concluded that "it's convenient if we can see the outer classes". -The outer class can be referenced over several levels. +The outer class can be referenced no matter how many times it is nesting. When the same name is defined on different levels, the one which will first be found from within will be referred to. @@ -1192,8 +1230,8 @@ end Really, that's pretty complicated. -Let's summarize. When looking up a constant, first the outer class is -searched then the superclass. This is quite contrived, +Let's summarize. When looking up a constant, first the outer classes is +searched then the superclasses. This is quite contrived, but let's assume a class hierarchy as follows.
@@ -1227,20 +1265,21 @@ Fig.11.
 Be careful about one point. The superclasses of the classes outside,
 for instance `A1` and `B2`, aren't searched at all.
 If it's outside once it's always outside and if it's superclass once
-it's always superclass. If it weren't so the number of classes would
-become to big and the behavior would become unpredictable.
+it's always superclass. Otherwise, the number of classes searched would
+become too big and the behavior of such complicated thing would become unpredictable.
 
 h3. Metaclasses
 
-We said, that one can call methods on objects.
-We also said that the methods which we can call
-are determined by the object's class. Then shouldn't there be
+I said that a method can be called on if it is an object.
+I also said that the methods that can be called are determined by the class of an object.
+Then shouldn't there be
 a class for class objects? (Fig.12)
 
 !images/ch_minimum_classclass.jpg(A class of classes?)!
 
-For this we can check Ruby.
-The method which returns the class of oneself is `Object#class`
+In this kind of situation, in Ruby, we can check in practice.
+It's because there's "a method which returns the class (class object) to which
+an object itself belongs", `Object#class`.
 
 
 p("string".class())   # String is shown
@@ -1248,25 +1287,27 @@ p(String.class())     # Class is shown
 p(Object.class())     # Class is shown
 
-`String` belongs to the class `Class`. Then what's the class of `Class`? +Apparently `String` belongs to the class named `Class`. +Then what's the class of `Class`?
 p(Class.class())      # Class is shown
 
-Again `Class`. In other words if one applies to any class -`.class().class().class()` long enough one reaches `Class`. -There the loop will stall. (Fig.13) +Again `Class`. In other words, whatever object it is, +by following like `.class().class().class()` ..., +it would reach `Class` in the end, +then it will stall in the loop (Fig.13). !images/ch_minimum_ccc.jpg(The class of the class of the class...)! -`Class` is the class of classes. And whenever there is a -recursive structure from the form X of Xs we call it a meta-X. +`Class` is the class of classes. And what has a recursive structure as "X of X" +is called a meta-X. Hence `Class` is a metaclass. h3. Metaobjects -Let's change the subject and talk about modules. +Let's change the target and think about modules. As modules are also objects, there also should be a class for them. Let's see. @@ -1287,7 +1328,7 @@ It's again `Class` Now we change the direction and examine the inheritance relationships. What's the superclass of `Class` and `Module`? -We can find it out with Ruby's `Class#superclass`. +In Ruby, we can find it out with `Class#superclass`.
 p(Class.superclass())    # Module
@@ -1296,31 +1337,35 @@ p(Object.superclass())   # nil
 
So `Class` is a subclass of `Module`. -A diagram of the important Ruby classes is in Fig.14. +Based on these facts, +Figure 14 shows the relationships between the important classes of Ruby. !images/ch_minimum_metaobjects.jpg(The class relationship between the important Ruby classes)! -Up to now we used `new` and `include` without an explanation of +Up to now we used `new` and `include` without any explanation, but finally I can explain their true form. `new` is really a method defined for the class `Class`. -That's why `new` can be used in any class because it's an instance -of `Class`. But `new` isn't defined in `Module`. Hence it's not -possible to create instances in a module. And `include` is defined -in the `Module` class. It can be called on modules and classes. +Therefore on whatever class, (because it is an instance of `Class`), +`new` can be used immediately. +But `new` isn't defined in `Module`. Hence it's not +possible to create instances in a module. And since `include` is defined +in the `Module` class, it can be called on both modules and classes. -These three classes `Object`, `Module` and `class` are the centerpiece -of Ruby's object world, they describe it. They are objects -describing objects. So `Object`, `Module` and `Class` are Ruby's -metaobjects. +These three classes `Object`, `Module` and `class` are objects that support the +foundation of Ruby. We can say that these three objects describe the Ruby's +object world itself. Namely they are objects which describe objects. +Hence, `Object Module Class` are Ruby's "meta-objects". h3. Singleton Methods -Methods can be called on objects. We said that the callable methods -are determined by the object's class. But we also said that ideally, methods should -belong to the object. Classes are a means to +I said that methods can be called if it is an object. +I also said that the methods that can be called are determined by the object's class. +However I think I also said that ideally methods belong to objects. +Classes are just a means to eliminate the effort of defining the same method more than once. -In Ruby there's also a means to define methods for individual objects. -One writes this. +Actually In Ruby there's also a means to define methods for individual objects (instances) +not depending on the class. +To do this, you can write this way.
 obj = Object.new()
@@ -1331,21 +1376,23 @@ obj.my_first()   # Shows My first singleton method
 
As you already know `Object` is the root for every class. -One sholdn't add a weird method like `my_first` to such an important +It's very unlikely that a method whose name is so weird like `my_first` is +defined in such important class. And `obj` is an instance of `Object`. However the method `my_first` -can be called from `obj`. Hence we have created without doubt +can be called on `obj`. Hence we have created without doubt a method which has nothing to do with the class the object belongs to. These methods which are defined for each object individually are called singleton methods. -When are singleton methods used? They are used in place of Java or C++ static -methods. In other words methods which can be used +When are singleton methods used? +First, it is used when defining something like static methods of Java or C++. +In other words methods which can be used without creating an instance. These methods are expressed in Ruby as singleton methods of a class object. For example in UNIX there's a system call `unlink`. This command deletes a file entry from the filesystem. In Ruby it can be used -directly as the singleton method `unlink` from the `File` class. +directly as the singleton method `unlink` of the `File` class. Let's try it out.
@@ -1359,14 +1406,15 @@ for the method `write` defined in `File`.
 
 ▼ A summary of the method notation
 
-|notation|called on object|example|
+|_. notation |_. the target object |_. example |
 |`File.unlink`|the `File`class itself|`File.unlink("core")`|
 |`File#write`|an instance of `File`|`f.write("str")`|
 
 h3. Class Variables
 
 Class variables were added to Ruby from 1.6 on, they are a relatively new mechanism.
-They can be referenced and assigned from both the class and its instances.
+As with constants, they belong to a class,
+and they can be referenced and assigned from both the class and its instances.
 Let's look at an example. The beginning of the name is `@@`.
 
 
@@ -1383,7 +1431,7 @@ C.new().print_cvar()  # "ok" is shown
 
As the first assignment serves as the definition, a reference -before an assignment leads to an error. This is shown below. +before an assignment like the one shown below leads to a runtime error. There is an ´@´ in front but the behavior differs completely from instance variables. @@ -1428,8 +1476,8 @@ $gvar = "global variable" p($gvar) # Shows "global variable"
-As with instance variables all kinds of names are considered defined -for global variables. +As with instance variables, all kinds of names can be considered defined +for global variables before assignments. In other words a reference before an assignment gives a `nil` and doesn't raise an error. From 938ff7642d21eaf3c2eb73b9889238510ea5b2de Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 15 Sep 2013 14:54:56 +0900 Subject: [PATCH 052/121] English images for chapter 05 --- gc.textile | 67 ++++++++------------------------------ images/ch_gc_calloca.jpg | Bin 14001 -> 16852 bytes images/ch_gc_gcimage.jpg | Bin 15200 -> 14334 bytes images/ch_gc_gengc.jpg | Bin 8999 -> 10653 bytes images/ch_gc_macstack.jpg | Bin 11123 -> 14575 bytes images/ch_gc_mostcopy.jpg | Bin 17033 -> 19466 bytes images/ch_gc_objid.jpg | Bin 10763 -> 11440 bytes 7 files changed, 13 insertions(+), 54 deletions(-) diff --git a/gc.textile b/gc.textile index e3e1232..5fea1e9 100644 --- a/gc.textile +++ b/gc.textile @@ -41,15 +41,7 @@ is a function call, one stack frame is pushed. When doing `return`, one stack frame will be popped. Figure 1 shows the really simplified appearance of the machine stack. -
-(macstack)
-Figure 1: Machine Stack -* 上(先端)above (top) -* 下(末端)below (bottom) -* スタックフレーム stack frame -* 現在実行中の関数フレーム presently executing function frame -
- +!images/ch_gc_macstack.jpg(Machine Stack)! In this picture, "above" is written above the top of the stack, but this it is not necessarily always the case that the machine stack goes @@ -89,13 +81,7 @@ if there are the memories allocated for the functions already finished, free them by using `free()`. -
-(calloca)
-Figure 2: The behavior of an `alloca()` implemented in C -* D->alloca(8)の対応を記録 record the relation D-> alloca(8) -* B->alloca(32)の対応を記録 record the relation B-> alloca(32) -* Dで割り当てたメモりを解放 release the memory allocated in D -
+!images/ch_gc_calloca.jpg(The behavior of an `alloca()` implemented in C)! The @missing/alloca.c@ of @ruby@ is an example of an emulated @alloca()@ . @@ -159,7 +145,7 @@ To make descriptions more concrete, let's simplify the structure by assuming that there are only objects and links. This would look as shown in Figure 3. -!images/ch_gc_objects.jpg(Figure 3: Objects)! +!images/ch_gc_objects.jpg(Objects)! The objects pointed to by global variables and the objects on the stack of a @@ -177,14 +163,7 @@ These objects colored black are the necessary objects. The rest of the objects can be released. -
-(gcimage)
-Figure 4: necessary objects and unnecessary objects -* ルートオブジェクト root objects -* 不要なオブジェクト unnecessary objects -* ルートオブジェクトから参照されているオブジェクト objects referenced by the - root objects -
+!images/ch_gc_gcimage.jpg(necessary objects and unnecessary objects)! In technical terms, "the surely necessary objects" are called "the roots of GC". @@ -233,7 +212,7 @@ areas. To simplify this description, assume there are two areas @A@ and @B@ here And put an "active" mark on the one of the areas. When creating an object, create it only in the "active" one. (Figure 5) -!images/ch_gc_stop2.jpg(Figure 5: Stop and Copy (1))! +!images/ch_gc_stop2.jpg(Stop and Copy (1))! When the GC starts, follow links from the roots in the same manner as @@ -241,7 +220,7 @@ mark-and-sweep. However, move objects to another area instead of marking them (Figure 6). When all the links have been followed, discard the all elements which remain in @A@, and make @B@ active next. -!images/ch_gc_stop3.jpg(Figure 6: Stop and Copy (2))! +!images/ch_gc_stop3.jpg(Stop and Copy (2))! Stop and Copy also has two advantages: @@ -270,7 +249,7 @@ increased. When quitting to refer, decrease the counter. When the counter of an object becomes zero, release the object. This is the method called reference counting (Figure 7). -!images/ch_gc_refcnt.jpg(Figure 7: Reference counting)! +!images/ch_gc_refcnt.jpg(Reference counting)! This method also has two advantages: @@ -288,7 +267,7 @@ a cycle of references as shown in Figure 8. If this is the case the counters will never decrease and the objects will never be released. -!images/ch_gc_cycle.jpg(Figure 8: Cycle)! +!images/ch_gc_cycle.jpg(Cycle)! By the way, latest Python(2.2) uses reference counting GC but it can free cycles. @@ -422,14 +401,14 @@ Hereafter, let's call this an object heap. the each contained array is probably each @heap@. Each element of @heap@ is each @slot@ (Figure 9). -!images/ch_gc_heapitems.jpg(Figure 9: `heaps`, `heap`, `slot`)! +!images/ch_gc_heapitems.jpg(`heaps`, `heap`, `slot`)! The length of @heaps@ is @heap_length@ and it can be changed. The number of the slots actually in use is @heaps_used@. The length of each heap is in the corresponding @heaps_limits[index]@. Figure 10 shows the structure of the object heap. -!images/ch_gc_heaps.jpg(Figure 10: conceptual diagram of `heaps` in memory)! +!images/ch_gc_heaps.jpg(conceptual diagram of `heaps` in memory)! This structure has a necessity to be this way. For instance, if all structs are stored in an array, @@ -1705,13 +1684,7 @@ However, when there are links from old-generation to new-generation, the new-generation objects will not be marked. (Figure 11) -
-(gengc)
-Figure 11: reference over generations -* ルートオブジェクト the root objects -* 新世代 new-generation -* 旧世代 old-generation -
+!images/ch_gc_gengc.jpg(reference over generations)! This is not good, so at the moment when an old-generational object refers to a new-generational object, @@ -1752,13 +1725,7 @@ But as trade-offs, accessing speed slows down and the compatibility of extension libraries is lost. -
-(objid)
-Figure 12: reference through the object ID -* アドレスを入れる store addresses -* インデックスを入れる store indexes -* 移動できる can be moved -
+!images/ch_gc_objid.jpg(reference through the object ID)! Then, the next way is to allow moving the struct only when they are pointed @@ -1769,15 +1736,7 @@ In the ordinary programs, there are not so many objects that object structs is quite high. -
-(mostcopy)
-Figure 13: Mostly-copying garbage collection -* (above) Since there's a possibility of being referred to by non-VALUE, - this object is not moved. -* (bottom) Since it is sure that this is referred only VALUEs, - this object can be moved. -* 移動 move -
+!images/ch_gc_mostcopy.jpg(Mostly-copying garbage collection)! Moreover and moreover, by enabling to move the struct, diff --git a/images/ch_gc_calloca.jpg b/images/ch_gc_calloca.jpg index b77dcd6f8ac9780d35fc2cb3d00881ffe111d510..de47db7eca509cc9a1573a58f99935f116149e02 100644 GIT binary patch literal 16852 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 literal 14001 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 diff --git a/images/ch_gc_gengc.jpg b/images/ch_gc_gengc.jpg index ac2ae0172b95b8cd44107ca03b3d23577a6d4bdd..319a4fd9af08367be29995084fd55eee3320ac87 100644 GIT binary patch literal 10653 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 literal 8999 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 diff --git a/images/ch_gc_macstack.jpg b/images/ch_gc_macstack.jpg index 6f9149447f88c11fe300b921c76138a5b4606378..44ab52232fbcd6ce557c89e8cf5dfc0ab20e56ea 100644 GIT binary patch literal 14575 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 IGoDTS58nr2G5`Po literal 11123 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 Wmy+Pg@3Va!|DDA8Papnt;(q}W?dJyo diff --git a/images/ch_gc_mostcopy.jpg b/images/ch_gc_mostcopy.jpg index 6f0f6b453e43ec8be70330283207b387b60145b7..3ae46a96af0b566b091d9d7858ab9e593881cde8 100644 GIT binary patch literal 19466 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 IQ2qa#00;y9g8%>k literal 17033 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 Xx4Y1aj|+ZtQor|B{uTd^e@^@_074*6 literal 10763 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 Date: Sun, 15 Sep 2013 14:59:55 +0900 Subject: [PATCH 053/121] fix a typo --- gc.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc.textile b/gc.textile index 5fea1e9..d77a918 100644 --- a/gc.textile +++ b/gc.textile @@ -1887,7 +1887,7 @@ First, `C.new` is actually `Class#new`. Its actual body is this:

-`rb_obj_alloc()` calles the `allocate` method against the `klass`. +`rb_obj_alloc()` calls the `allocate` method against the `klass`. In other words, it calls `C.allocate` in this example currently explained. It is `Class#allocate` by default and its actual body is `rb_class_allocate_instance()`. From 4eabf80e66e317aa1857efa957910cf554aa9523 Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 15 Sep 2013 15:14:58 +0900 Subject: [PATCH 054/121] update the license section of README to be more precise --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8111490..d98b890 100644 --- a/README.md +++ b/README.md @@ -59,5 +59,10 @@ http://i.loveruby.net/ja/rhg/ar/ruby-rhg.tar.gz License ======= -This work is licensed under a +Copyright (c) 2002-2004 Minero Aoki, All rights reserved. + +This translation work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike2.5 License](http://creativecommons.org/licenses/by-nc-sa/2.5/) + +If you'd like to translate this work to another language, +please contact the author Minero Aoki first. From bfead837b44e2b2f64796214388e41a0729a0d4a Mon Sep 17 00:00:00 2001 From: ocha- Date: Sun, 15 Sep 2013 15:50:10 +0900 Subject: [PATCH 055/121] An English image for chatper 10 --- images/ch_parser_scanner.jpg | Bin 7483 -> 9482 bytes parser.textile | 41 ++++++++++------------------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/images/ch_parser_scanner.jpg b/images/ch_parser_scanner.jpg index 5feb5e951890b66d452906ce956380df936bded6..04bae41118ab829453c248b82cd01a0cd650365b 100644 GIT binary patch literal 9482 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 z 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 b{Cxo-j=p+^EY=Lv`iMyRW9k|mdqDj!n0|_N diff --git a/parser.textile b/parser.textile index 63a926a..2fd1994 100644 --- a/parser.textile +++ b/parser.textile @@ -25,7 +25,7 @@ using Windows who may not be aware, the `mv` (move) command creates a new copy of a file and removes the original. `cc` is, of course, the C compiler and `cpp` the C pre-processor. -!images/ch_parser_build.jpg(Figure 1: Parser construction process)! +!images/ch_parser_build.jpg(Parser construction process)! h3. Dissecting `parse.y` @@ -256,7 +256,7 @@ of this rule is demote an `expr` to a `primary`. This creates a cycle which can the seen in Figure 2, and the arrow shows how this rule is reduced during parsing. -!images/ch_parser_exprloop.jpg(Figure 2: `expr` demotion)! +!images/ch_parser_exprloop.jpg(`expr` demotion)! The next rule is also particularly interesting. @@ -270,7 +270,7 @@ primary : literal A `compstmt`, which equals to the entire program (`program`), can be demoted to a `primary` with this rule. The next figure illustrates this rule in action. -!images/ch_parser_progloop.jpg(Figure 3: `program` demotion)! +!images/ch_parser_progloop.jpg(`program` demotion)! This means that for any syntax element in Ruby, if we surround it with parenthesis it will become a `primary` and can be passed as an argument to a @@ -915,10 +915,7 @@ them are going to appear, replace them to a single `o` when they appear. All we have to do is repeating this procedure. Figure 4 shows the consequence. -

-(ablist)
-Figure 4: parse a list which starts with A and ends with B -

+!images/ch_parser_ablist.jpg(parse a list which starts with A and ends with B)! However, if the ending `B` is missing, ... @@ -954,10 +951,7 @@ let's follow it as an experiment and parse the input with shift (meaning interior) which takes precedence. (Figure 5) -

-(alist)
-Figure 5: parse a list of lists which start with A -

+!images/ch_parser_alist.jpg(parse a list of lists which start with A)! It could be parsed. However, this is completely different from the intention of @@ -988,10 +982,7 @@ I'll explain about the outline of the parser before moving on to the scanner. Take a look at Figure 6. -

-(interf)
-Figure 6: Parser Interface (Call Graph) -

+!images/ch_parser_interf.jpg(Parser Interface (Call Graph))! There are three official interfaces of the parser: `rb_compile_cstr()`, @@ -1028,14 +1019,7 @@ and keeps them until it will form a token. Therefore, the whole structure of `yylex` can be depicted as Figure 7. -
-(scanner)
-Figure 7: The whole picture of the scanner -* 入力バッファ input buffer -* バイト列 byte sequence -* トークンバッファ token buffer -* 記号列 symbol sequence -
+!images/ch_parser_scanner.jpg(The whole picture of the scanner)! @@ -1066,7 +1050,7 @@ The beginning, the current position and the end of the buffer. Apparently, this buffer seems a simple single-line string buffer (Figure 8). -!images/ch_parser_ibuffer.jpg(Figure 8: The input buffer)! +!images/ch_parser_ibuffer.jpg(The input buffer)! @@ -1321,7 +1305,7 @@ This is also simply structured. If depicting it, it would look like Figure 9. -!images/ch_parser_tbuffer.jpg(Figure 9: The token buffer)! +!images/ch_parser_tbuffer.jpg(The token buffer)! Let's continuously go to the interface and @@ -2245,7 +2229,7 @@ The part which reads the starting symbol (`< @@ -2347,7 +2331,4 @@ It means it can continue to scan from the just after the starting symbol as if there was nothing happened. (Figure 11) -

-(heredoc)
-Figure 11: The picture of assignation of scanning Here Document -

+!images/ch_parser_heredoc.jpg(The picture of assignation of scanning Here Document)! From e56ed8f2310d6f4f2952d54e1ab4137ab5d97c4d Mon Sep 17 00:00:00 2001 From: ocha- Date: Tue, 17 Sep 2013 16:57:08 +0900 Subject: [PATCH 056/121] use a little higher line-height for

---
 css/styles.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/css/styles.css b/css/styles.css
index 93e4f9c..e4af49b 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -76,7 +76,7 @@ p.caption {
 }
 
 pre {
-    line-height: 110%;
+    line-height: 120%;
     padding: 8px;
     background: #eee;
 }

From 3c4f52642ae9aadbe194cee028fb756da747888a Mon Sep 17 00:00:00 2001
From: ocha- 
Date: Tue, 17 Sep 2013 17:01:09 +0900
Subject: [PATCH 057/121] erase unnecessary white-spaces from chapter 12

---
 syntree.textile | 222 ++++++++++++++++++++++++------------------------
 1 file changed, 111 insertions(+), 111 deletions(-)

diff --git a/syntree.textile b/syntree.textile
index 889297b..8ef108d 100644
--- a/syntree.textile
+++ b/syntree.textile
@@ -13,7 +13,7 @@ h3. @NODE@
 
 As I've already described, a Ruby program is first converted to a syntax tree.
 To be more precise, a syntax tree is a tree structure made of structs called "nodes".
-In @ruby@ , all nodes are of type @NODE@ .
+In @ruby@, all nodes are of type @NODE@.
 
 
 

▼ @NODE@

@@ -49,20 +49,20 @@ In @ruby@ , all nodes are of type @NODE@ .
-Although you might be able to infer from the struct name @RNode@ , nodes are Ruby objects. -This means the creation and release of nodes are taken care of by the @ruby@ 's garbage collector. +Although you might be able to infer from the struct name @RNode@, nodes are Ruby objects. +This means the creation and release of nodes are taken care of by the `ruby`'s garbage collector. Therefore, @flags@ naturally has the same role as @basic.flags@ of the object struct. It means that @T_NODE@ which is the type of a struct and flags such as @FL_FREEZE@ are stored in it. -As for @NODE@ , in addition to these, its node type is stored in @flags@ . +As for @NODE@, in addition to these, its node type is stored in @flags@. What does it mean? Since a program could contain various elements such as @if@ and @while@ and @def@ and so on, there are also various corresponding node types. The three available union are complicated, but how these unions are used is decided to only one specific way for each node. -For example, the below table shows the case when it is @NODE_IF@ that is the node of @if@ . +For example, the below table shows the case when it is @NODE_IF@ that is the node of @if@. |_. member |_. union member |_. role | @@ -71,7 +71,7 @@ For example, the below table shows the case when it is @NODE_IF@ that is the nod | @u3@ | @u3.node@ | the body of false | -And, in @node.h@ , the macros to access each union member are available. +And, in @node.h@, the macros to access each union member are available.

▼ the macros to access @NODE@

@@ -104,7 +104,7 @@ head->nd_next = tail; /* head->u3.node = tail */ In the source code, it's almost certain that these macros are used. A very few exceptions are only the two places where creating @NODE@ in @parse.y@ -and where marking @NODE@ in @gc.c@ . +and where marking @NODE@ in @gc.c@. By the way, what is the reason why such macros are used? @@ -112,10 +112,10 @@ For one thing, it might be because it's cumbersome to remember numbers like @u1@ that are not meaningful by just themselves. But what is more important than that is, there should be no problem if the corresponding number is changed and it's possible that it will actually be changed. -For example, since a condition clause of @if@ does not have to be stored in @u1@ , +For example, since a condition clause of @if@ does not have to be stored in @u1@, someone might want to change it to @u2@ for some reason. But if @u1@ is directly used, he needs to modify a lot of places all over the source codes, it is inconvenient. -Since nodes are all declared as @NODE@ , it's hard to find nodes that represent @if@ . +Since nodes are all declared as @NODE@, it's hard to find nodes that represent @if@. By preparing the macros to access, this kind of trouble can be avoided and conversely we can determine the node types from the macros. @@ -126,7 +126,7 @@ h3. Node Type I said that in the @flags@ of a @NODE@ struct its node type is stored. We'll look at in what form this information is stored. -A node type can be set by @nd_set_type()@ and obtained by @nd_type()@ . +A node type can be set by @nd_set_type()@ and obtained by @nd_type()@.

▼ @nd_type nd_set_type@

@@ -151,7 +151,7 @@ A node type can be set by @nd_set_type()@ and obtained by @nd_type()@ .
-It won't be so much trouble if we'll keep focus on around @nd_type@ . +It won't be so much trouble if we'll keep focus on around @nd_type@. Fig.1 shows how it seems like. @@ -214,13 +214,13 @@ in the first place. -The first thing is @NODE_LSHIFT@ , as you can guess from the description of the -node types of the previous section, it is the number of used bits in @flags@ . -@FL_USHIFT@ is reserved by system of @ruby@ (11 bits, @ruby.h@ ), 8 bits are for +The first thing is @NODE_LSHIFT@, as you can guess from the description of the +node types of the previous section, it is the number of used bits in @flags@. +@FL_USHIFT@ is reserved by system of @ruby@ (11 bits, @ruby.h@), 8 bits are for its node type. -The next thing is @NODE_LMASK@ . +The next thing is @NODE_LMASK@. @@ -230,7 +230,7 @@ sizeof(NODE*) * CHAR_BIT - NODE_LSHIFT This is the number of the rest of the bits. -Let's assume it is @restbits@ . This makes the code a lot simpler. +Let's assume it is @restbits@. This makes the code a lot simpler. @@ -324,7 +324,7 @@ Lastly let's look at the function @rb_node_newnode()@ that creates a node. We've seen @rb_newobj()@ in the Chapter 5: Garbage collection. It is the function to get a -vacant @RVALUE@ . By attaching the @T_NODE@ struct-type flag to it, +vacant @RVALUE@. By attaching the @T_NODE@ struct-type flag to it, the initialization as a @VALUE@ will complete. Of course, it's possible that some values that are not of type @NODE*@ are passed for @u1 u2 u3@, but received as @NODE*@ for the time being. @@ -385,7 +385,7 @@ Let's look at the @%union@ of @ruby@ first. @struct RVarmap@ is a struct used by the evaluator and holds a block local variable. -You can tell the rest. The most used one is of course @node@ . +You can tell the rest. The most used one is of course @node@. @@ -408,7 +408,7 @@ but this remodeled version deeply and directly displays the appearance of the syntax tree. -For example, in order to dump the simple expression @m(a)@ , you can do as follows: +For example, in order to dump the simple expression @m(a)@, you can do as follows: @@ -438,9 +438,9 @@ Then, the syntax tree expression of the program will be dumped. I'll briefly explain about how to see the content. @NODE_NEWLINE@ and @NODE_FCALL@ and such are the node types. What are written at the same indent level of each node are the contents of its node members. -For example, the root is @NODE_NEWLINE@ , and it has the three members: +For example, the root is @NODE_NEWLINE@, and it has the three members: @nd_file nd_nth nd_next@. @nd_file@ points to the @"-e"@ string of C, -and @ng_nth@ points to the 1 integer of C, and @nd_next@ holds the next node @NODE_CALL@ . +and @ng_nth@ points to the 1 integer of C, and @nd_next@ holds the next node @NODE_CALL@. But since these explanation in text are probably not intuitive, I recommend you to also check Fig.4 at the same time. @@ -458,9 +458,9 @@ undefined local variable will become this. Then, what is @NODE_NEWLINE@ ? This is the node to join the name of the currently -executed file and the line number at runtime and is set for each @stmt@ . +executed file and the line number at runtime and is set for each @stmt@. Therefore, when only thinking about the meaning of the execution, this node can -be ignored. When you @require@ @nodedump-short@ instead of @nodedump@ , +be ignored. When you @require@ @nodedump-short@ instead of @nodedump@, distractions like @NODE_NEWLINE@ are left out in the first place. Since it is easier to see if it is simple, @nodedump-short@ will be used later on except for when particularly written. @@ -494,7 +494,7 @@ nd_lit = 1:Fixnum 1 as a numeric value. There's not any twist. However, notice that what is -stored in the node is not 1 of C but 1 of Ruby (1 of @Fixnum@ ). This is because ... +stored in the node is not 1 of C but 1 of Ruby (1 of @Fixnum@). This is because ... @@ -568,11 +568,11 @@ h4. @if@ I feel like @if@ is always used as an example, that's because its structure is -simple and there's not any reader who don't know about @if@ , so it is convenient +simple and there's not any reader who don't know about @if@, so it is convenient for writers. -Anyway, this is an example of @if@ . +Anyway, this is an example of @if@. For example, let's convert this code to a syntax tree. @@ -627,7 +627,7 @@ Then, let's look at the code to build this.
-It seems that @NEW_IF()@ is the macro to create @NODE_IF@ . Among the values of +It seems that @NEW_IF()@ is the macro to create @NODE_IF@. Among the values of the symbols, @$2 $4 $5@ are used, thus the correspondences between the symbols of the rule and @$n@ are: @@ -642,11 +642,11 @@ NEW_IF(expr_value, compstmt, if_tail) this way. In other words, @expr_value@ is the condition expression, @compstmt@ -( @$4@ ) is the case of true, @if_tail@ is the case of false. +(@$4@) is the case of true, @if_tail@ is the case of false. -On the other hand, the macros to create nodes are all named @NEW_xxxx@ , and they -are defined @node.h@ . Let's look at @NEW_IF()@ . +On the other hand, the macros to create nodes are all named @NEW_xxxx@, and they +are defined @node.h@. Let's look at @NEW_IF()@. @@ -673,8 +673,8 @@ action is a semantic analysis function. This will be described later. Additionally, @fixpos()@ corrects the line number. @NODE@ is initialized with the file name and the line number of the time when it is "created". However, for instance, the code of @if@ should already be parsed by @end@ by the time -when creating @NODE_IF@ . Thus, the line number would go wrong if it remains -untouched. Therefore, it needs to be corrected by @fixpos()@ . +when creating @NODE_IF@. Thus, the line number would go wrong if it remains +untouched. Therefore, it needs to be corrected by @fixpos()@. @@ -683,8 +683,8 @@ fixpos(dest, src)
-This way, the line number of the node @dest@ is set to the one of the node @src@ . -As for @if@ , the line number of the condition expression becomes the line number +This way, the line number of the node @dest@ is set to the one of the node @src@. +As for @if@, the line number of the condition expression becomes the line number of the whole @if@ expression. @@ -694,7 +694,7 @@ of the whole @if@ expression. h4. @elsif@ -Subsequently, let's look at the rule of @if_tail@ . +Subsequently, let's look at the rule of @if_tail@.

▼ @if_tail@

@@ -735,7 +735,7 @@ if_tail: kELSIF .... kELSIF .... kELSIF .... kELSE compstmt
-@newline_node()@ caps @NODE_NEWLINE@ , @block_append()@ appends it to the list. +@newline_node()@ caps @NODE_NEWLINE@, @block_append()@ appends it to the list. It's straightforward. -Let's look at the content only of the @block_append()@ . +Let's look at the content only of the @block_append()@. @@ -993,8 +993,8 @@ Thus I'll show the code without that part.
-According to the previous syntax tree dump, @NEW_BLOCK@ was a linked list uses @nd_next@ . -Being aware of it while reading, it can be read "if either @head@ or @tail@ is not @NODE_BLOCK@ , +According to the previous syntax tree dump, @NEW_BLOCK@ was a linked list uses @nd_next@. +Being aware of it while reading, it can be read "if either @head@ or @tail@ is not @NODE_BLOCK@, wrap it with @NODE_BLOCK@ and join the lists each other." @@ -1023,9 +1023,9 @@ But before ending, there's one more thing I'd like to talk about. It is about the two general-purpose lists. -The two general-purpose lists mean @BLOCK@ and @LIST@ . +The two general-purpose lists mean @BLOCK@ and @LIST@. @BLOCK@ is, as previously described, a linked list of @NODE_BLOCK@ to join the statements. -@LIST@ is, although it is called @LIST@ , a list of @NODE_ARRAY@ . +@LIST@ is, although it is called @LIST@, a list of @NODE_ARRAY@. This is what is used for array literals. @LIST@ is used to store the arguments of a method or the list of multiple assignments. @@ -1042,9 +1042,9 @@ looking at the usage of the nodes is helpful to understand. | | @nd_next@ | pointing to the next @NODE_ARRAY@ | -The usage differs only in the second elements that are @nd_end@ and @nd_alen@ . +The usage differs only in the second elements that are @nd_end@ and @nd_alen@. And this is exactly the significance of the existence of each type of the two nodes. -Since its size can be stored in @NODE_ARRAY@ , we use an @ARRAY@ list +Since its size can be stored in @NODE_ARRAY@, we use an @ARRAY@ list when the size of the list will frequently be required. Otherwise, we use a @BLOCK@ list that is very fast to join. I don't describe this topic in details because the codes that use them is @@ -1060,7 +1060,7 @@ h2. Semantic Analysis As I briefly mentioned at the beginning of Part 2, there are two types of analysis that are appearance analysis and semantic analysis. -The appearance analysis is mostly done by @yacc@ , the rest is doing the semantic +The appearance analysis is mostly done by @yacc@, the rest is doing the semantic analysis inside actions. @@ -1079,9 +1079,9 @@ These are part of the semantic analysis. What kind of semantic analysis is done in the current @ruby@ ? -Since the error checks occupies almost all of semantic analysis in @ruby@ , +Since the error checks occupies almost all of semantic analysis in @ruby@, searching the places where generating errors seems a good way. -In a parser of @yacc@ , @yyerror()@ is supposed to be called when an error occurs. +In a parser of @yacc@, @yyerror()@ is supposed to be called when an error occurs. Conversely speaking, there's an error where @yyerror()@ exists. So, I made a list of the places where calling @yyerror()@ inside the actions. @@ -1120,7 +1120,7 @@ allowed respectively. But this is in any way cumbersome and rejecting it in an action is far more concise. -And, "an assignment to @self@ " seems a check for the better error message. +And, "an assignment to @self@" seems a check for the better error message. In comparison to "@return@ outside of methods", rejecting it by grammar is much easier, but if it is rejected by the parser, the output would be just @"parse error"@. Comparing to it, the current @@ -1242,9 +1242,9 @@ h4. Algorithm Summary: It sequentially checks the nodes of the tree, if it hits "an expression certainly not having its value", it means the tree does not have any value. -Then it warns about that by using @rb_warning()@ and return @Qfalse@ . If it +Then it warns about that by using @rb_warning()@ and return @Qfalse@. If it finishes to traverse the entire tree without hitting any "an expression not -having its value", it means the tree does have a value. Thus it returns @Qtrue@ . +having its value", it means the tree does have a value. Thus it returns @Qtrue@. Here, notice that it does not always need to check the whole tree. @@ -1265,9 +1265,9 @@ Here:
-Inside of this argument @$1@ , there can also be other nesting method calls again. +Inside of this argument @$1@, there can also be other nesting method calls again. But, the argument of the inside method must have been already checked with -@value_expr()@ , so you don't have to check it again. +@value_expr()@, so you don't have to check it again. Let's think more generally. Assume an arbitrary grammar element @A@ exists, @@ -1312,7 +1312,7 @@ end So, in this case, the @if@ statement must be checked when checking the entire assignment expression. This kind of things are laid out in the @switch@ -statement of @value_expr()@ . +statement of @value_expr()@. @@ -1320,7 +1320,7 @@ statement of @value_expr()@ . h4. Removing Tail Recursion -By the way, when looking over the whole @value_expr@ , we can see that there's +By the way, when looking over the whole @value_expr@, we can see that there's the following pattern appears frequently: @@ -1348,15 +1348,15 @@ return value_expr(node->nd_xxxx) A code like this which does a recursive call just before @return@ is called a -tail recursion. It is known that this can generally be converted to @goto@ . +tail recursion. It is known that this can generally be converted to @goto@. This method is often used when optimizing. As for Scheme, it is defined in specifications that tail recursions must be removed by language processors. This is because recursions are often used instead of loops in Lisp-like languages. -However, be careful that tail recursions are only when "calling just before @return@ ". -For example, take a look at the @NODE_IF@ of @value_expr()@ , +However, be careful that tail recursions are only when "calling just before @return@". +For example, take a look at the @NODE_IF@ of @value_expr()@, @@ -1368,7 +1368,7 @@ break; As shown above, the first time is a recursive call. -Rewriting this to the form of using @return@ , +Rewriting this to the form of using @return@, @@ -1378,9 +1378,9 @@ return value_expr(node->nd_body) && value_expr(node->nd_else); If the left @value_expr()@ is false, the right @value_expr()@ is also executed. -In this case, the left @value_expr()@ is not "just before" @return@ . +In this case, the left @value_expr()@ is not "just before" @return@. Therefore, it is not a tail recursion. -Hence, it can't be extracted to @goto@ . +Hence, it can't be extracted to @goto@. @@ -1390,7 +1390,7 @@ h3. The whole picture of the value check As for value checks, we won't read the functions further. You might think it's too early, but all of the other functions are, as the same -as @value_expr()@ , step-by-step one-by-one only traversing and checking nodes, +as @value_expr()@, step-by-step one-by-one only traversing and checking nodes, so they are completely not interesting. However, I'd like to cover the whole picture at least, so I finish this section by just showing the call graph of the relevant functions (Fig.7). @@ -1483,7 +1483,7 @@ It has completely nothing to do with the order of evaluations. For example, for the next code, naturally the condition expression is evaluated first, but in the symbol sequence, at the moment when @p@ appears the assignment to @lvar@ has not appeared yet. -Therefore, this produces @NameError@ . +Therefore, this produces @NameError@. @@ -1497,7 +1497,7 @@ by the appearances. When a symbol sequence that expresses an assignment appears, it will be defined in the appearance order. Based on this information, we can infer that @ruby@ seems to define local variables while parsing because the order of the symbol sequence does not exist after leaving the parser. -And in fact, it is true. In @ruby@ , the parser defines local variables. +And in fact, it is true. In @ruby@, the parser defines local variables. @@ -1542,7 +1542,7 @@ The simultaneously declared global variable @lvtbl@ points to @local_vars@ that is the top of that stack. -And, @struct RVarmap@ is defined in @env.h@ , +And, @struct RVarmap@ is defined in @env.h@, and is available to other files and is also used by the evaluator. This is used to store the block local variables. @@ -1582,7 +1582,7 @@ Fig.8: The image of local variable tables at runtime h3. Local Variable Scope -When looking over the list of function names of @parse.y@ , +When looking over the list of function names of @parse.y@, we can find functions such as @local_push() local_pop() local_cnt()@ are laid out. In whatever way of thinking, they appear to be relating to a local variable. Moreover, because the names are @push pop@, it is clearly a stack. @@ -1618,7 +1618,7 @@ So first, let's find out the places where using these functions.
-At @def@ , I could find the place where it is used. It can also be found in class +At @def@, I could find the place where it is used. It can also be found in class definitions and singleton class definitions, and module definitions. In other words, it is the place where the scope of local variables is cut. Moreover, as for how they are used, @@ -1628,7 +1628,7 @@ This means, as we expected, it is almost certain that the functions start with between @push@ and @pop@ is probably a local variable scope. -Moreover, I also searched @local_cnt()@ . +Moreover, I also searched @local_cnt()@.

▼ @NEW_LASGN()@

@@ -1640,7 +1640,7 @@ Moreover, I also searched @local_cnt()@ .
-This is found in @node.h@ . Even though there are also the places where using in @parse.y@ , +This is found in @node.h@. Even though there are also the places where using in @parse.y@, I found it in the other file. Thus, probably I'm in desperation. @@ -1732,18 +1732,18 @@ Subsequently, we'll look at @local_pop()@ and @local_tbl()@ at the same time.

Ruby Hacking Guide

-
+