crystalizer 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/Changelog +27 -0
  2. data/README +79 -0
  3. data/Rakefile +24 -0
  4. data/TODO +14 -0
  5. data/VERSION +1 -0
  6. data/benchmarks/bench.rb +129 -0
  7. data/benchmarks/concretize_test.rb +26 -0
  8. data/benchmarks/extconf.rb +10 -0
  9. data/benchmarks/tak_rb.rb +7 -0
  10. data/benchmarks/tak_so.rb +7 -0
  11. data/benchmarks/tak_source.rb +16 -0
  12. data/bin/rb2cx +162 -0
  13. data/doc/eval2c.txt +246 -0
  14. data/doc/gen_html.rb +26 -0
  15. data/doc/html_template +10 -0
  16. data/doc/index.txt +169 -0
  17. data/doc/limitations.txt +529 -0
  18. data/doc/optimizations.txt +185 -0
  19. data/doc/rb2cx.txt +130 -0
  20. data/doc/style.css +27 -0
  21. data/lib/concretizer.rb +3 -0
  22. data/lib/ruby2cext/c_function.rb +617 -0
  23. data/lib/ruby2cext/common_node_comp.rb +1412 -0
  24. data/lib/ruby2cext/compiler.rb +311 -0
  25. data/lib/ruby2cext/concretize.rb +269 -0
  26. data/lib/ruby2cext/error.rb +15 -0
  27. data/lib/ruby2cext/eval2c.rb +126 -0
  28. data/lib/ruby2cext/parser.rb +36 -0
  29. data/lib/ruby2cext/plugin.rb +24 -0
  30. data/lib/ruby2cext/plugins/builtin_methods.rb +817 -0
  31. data/lib/ruby2cext/plugins/cache_call.rb +293 -0
  32. data/lib/ruby2cext/plugins/case_optimize.rb +102 -0
  33. data/lib/ruby2cext/plugins/const_cache.rb +36 -0
  34. data/lib/ruby2cext/plugins/direct_self_call.rb +70 -0
  35. data/lib/ruby2cext/plugins/inline_builtin.rb +797 -0
  36. data/lib/ruby2cext/plugins/inline_methods.rb +68 -0
  37. data/lib/ruby2cext/plugins/ivar_cache.rb +147 -0
  38. data/lib/ruby2cext/plugins/require_include.rb +69 -0
  39. data/lib/ruby2cext/plugins/util.rb +154 -0
  40. data/lib/ruby2cext/plugins/warnings.rb +121 -0
  41. data/lib/ruby2cext/scopes.rb +225 -0
  42. data/lib/ruby2cext/str_to_c_strlit.rb +12 -0
  43. data/lib/ruby2cext/tools.rb +80 -0
  44. data/lib/ruby2cext/version.rb +22 -0
  45. data/results +68 -0
  46. data/setup.rb +1585 -0
  47. data/stuff/builtin_methods.rb +69 -0
  48. data/stuff/builtin_methods_test.rb +37 -0
  49. data/test/bootstrap.rb +10 -0
  50. data/test/causes_crash_all_opts.rb +1165 -0
  51. data/test/eval2c/test_eval2c.rb +37 -0
  52. data/test/temp_17.rb +16 -0
  53. data/test/temp_18.rb +8 -0
  54. data/test/temp_19.rb +8 -0
  55. data/test/temp_2.rb +7 -0
  56. data/test/temp_20.rb +5 -0
  57. data/test/temp_21.rb +161 -0
  58. data/test/temp_22.rb +7 -0
  59. data/test/temp_23.rb +7 -0
  60. data/test/temp_24.rb +219 -0
  61. data/test/temp_25.rb +7 -0
  62. data/test/temp_26.rb +11 -0
  63. data/test/temp_27.rb +11 -0
  64. data/test/temp_28.rb +9 -0
  65. data/test/temp_29.rb +9 -0
  66. data/test/temp_3.rb +0 -0
  67. data/test/temp_30.rb +0 -0
  68. data/test/temp_31.rb +10 -0
  69. data/test/temp_32.rb +10 -0
  70. data/test/temp_33.rb +15 -0
  71. data/test/temp_34.rb +15 -0
  72. data/test/temp_35.rb +7 -0
  73. data/test/temp_36.rb +7 -0
  74. data/test/temp_37.rb +10 -0
  75. data/test/temp_38.rb +10 -0
  76. data/test/temp_39.rb +0 -0
  77. data/test/temp_4.rb +7 -0
  78. data/test/temp_40.rb +50 -0
  79. data/test/temp_41.rb +50 -0
  80. data/test/temp_42.rb +8 -0
  81. data/test/temp_43.rb +8 -0
  82. data/test/temp_44.rb +0 -0
  83. data/test/temp_48.rb +7 -0
  84. data/test/temp_49.rb +7 -0
  85. data/test/temp_5.rb +7 -0
  86. data/test/temp_59.rb +7 -0
  87. data/test/temp_6.rb +7 -0
  88. data/test/temp_60.rb +7 -0
  89. data/test/temp_68.rb +239 -0
  90. data/test/temp_7.rb +7 -0
  91. data/test/temp_70.rb +7 -0
  92. data/test/temp_71.rb +7 -0
  93. data/test/temp_72.rb +13 -0
  94. data/test/temp_73.rb +7 -0
  95. data/test/temp_74.rb +7 -0
  96. data/test/temp_76.rb +7 -0
  97. data/test/temp_77.rb +13 -0
  98. data/test/temp_79.rb +7 -0
  99. data/test/temp_8.rb +14 -0
  100. data/test/temp_81.rb +14 -0
  101. data/test/temp_83.rb +0 -0
  102. data/test/temp_84.rb +7 -0
  103. data/test/temp_85.rb +7 -0
  104. data/test/temp_86.rb +14 -0
  105. data/test/temp_87.rb +7 -0
  106. data/test/temp_88.rb +7 -0
  107. data/test/temp_89.rb +7 -0
  108. data/test/temp_9.rb +14 -0
  109. data/test/temp_90.rb +0 -0
  110. data/test/temp_91.rb +7 -0
  111. data/test/temp_92.rb +7 -0
  112. data/test/temp_93.rb +7 -0
  113. data/test/temp_94.rb +7 -0
  114. data/test/temp_95.rb +7 -0
  115. data/test/temp_96.rb +0 -0
  116. data/test/temp_97.rb +0 -0
  117. data/test/temp_98.rb +7 -0
  118. data/test/temp_99.rb +7 -0
  119. data/test/test_concretize.rb +132 -0
  120. data/test/test_concretize_all.rb +15 -0
  121. data/test/test_crystalize_block.rb +73 -0
  122. data/test/test_files/test.rb +615 -0
  123. data/test/test_files/vmode_test.rb +73 -0
  124. data/test/test_files/warn_test.rb +35 -0
  125. data/test/test_syntax.rb +25 -0
  126. metadata +268 -0
@@ -0,0 +1,246 @@
1
+
2
+ h1. Eval2C
3
+
4
+ Eval2C is a class that allows the compilation of Ruby code to a C extension at
5
+ runtime. The compiled C extension will be <code>require</code>d automatically
6
+ and the compiled code will be available as a Proc.
7
+
8
+ It is easy to integrate Eval2C into existing scripts or libraries to improve
9
+ performance. It is also pretty simple to provide fallback code for when
10
+ Ruby2CExtension is not available.
11
+
12
+
13
+ h2. Basic Usage
14
+
15
+ Here is an example:
16
+
17
+ PRE
18
+ require "ruby2cext/eval2c"
19
+
20
+ $e2c = Ruby2CExtension::Eval2C.new
21
+
22
+ $e2c.toplevel_eval("puts 'hello'") # prints hello
23
+ PREEND
24
+
25
+ First you need to create an Eval2C instance, this instance basically stores
26
+ the options/configuration. In the above example no options were given, so the
27
+ defaults are used. The available options are explained below.
28
+
29
+ The last line of the example does what the method name suggests: the string of
30
+ Ruby code is evaluated at the toplevel (i.e. not inside any class scope). To
31
+ be more precise, that last line is equivalent to this Ruby code:
32
+
33
+ PRE
34
+ $some_global_var = proc { puts 'hello' }
35
+ $some_global_var.call
36
+ PREEND
37
+
38
+ The proc is compiled to a C extension, that C expension is then
39
+ <code>require</code>d and finally the proc is called.
40
+
41
+ The implementation of @toplevel_eval@ is actually pretty simple:
42
+
43
+ PRE
44
+ def toplevel_eval(code_str)
45
+ compile_to_proc(code_str).call
46
+ end
47
+ PREEND
48
+
49
+ So the main work is done by @compile_to_proc@, which can also be used
50
+ directly:
51
+
52
+ PRE
53
+ $e2c.compile_to_proc("|a,b| a+b").call(2, 3) # => 5
54
+ PREEND
55
+
56
+ There are some things to note: The proc won't have access to local variables
57
+ and it will be defined at toplevel, which is important for constant lookup:
58
+
59
+ PRE
60
+ SOME_CONST = :toplevel
61
+
62
+ class A
63
+ SOME_CONST = :A
64
+ $e2c.compile_to_proc("SOME_CONST").call # => :toplevel, not :A!
65
+ end
66
+ PREEND
67
+
68
+ Eval2C also offers equivalents to Ruby's @module_eval@/@class_eval@ and
69
+ @instance_eval@:
70
+
71
+ PRE
72
+ class A
73
+ $e2c.module_eval(self, %{
74
+ def initialize(x)
75
+ @x = x
76
+ end
77
+ def foo(y)
78
+ @x + y
79
+ end
80
+ })
81
+ end
82
+
83
+ A.new(5).foo(6) # => 11
84
+
85
+ $e2c.instance_eval("4321", "reverse") # => "1234"
86
+ PREEND
87
+
88
+ Their implementations also use @compile_to_proc@ and they are very similar to
89
+ the implementation of @toplevel_eval@:
90
+
91
+ PRE
92
+ def module_eval(mod, code_str)
93
+ mod.module_eval(&compile_to_proc(code_str))
94
+ end
95
+ alias :class_eval :module_eval
96
+
97
+ def instance_eval(object, code_str)
98
+ object.instance_eval(&compile_to_proc(code_str))
99
+ end
100
+ PREEND
101
+
102
+ With @module_eval@/@class_eval@ it is possible to selectively compile some
103
+ performance critical methods to C and leave the rest in Ruby.
104
+
105
+ But there is one more thing: @compile_methods@.
106
+
107
+ Defining the methods using @module_eval@ as in the last example, has at least
108
+ one downside: it won't play nice with syntax-highlighting text editors,
109
+ because the code of the methods is actually in a string. It would be much
110
+ nicer to @def@ the methods the normal way and then just compile them
111
+ afterwards.
112
+
113
+ Thanks to @compile_methods@ this is possible:
114
+
115
+ PRE
116
+ class A
117
+ def initialize(x)
118
+ @x = x
119
+ end
120
+ def foo(y)
121
+ @x + y
122
+ end
123
+
124
+ $e2c.compile_methods(self, :initialize, :foo)
125
+ end
126
+
127
+ A.new(5).foo(6) # => 11
128
+ PREEND
129
+
130
+ @compile_methods@ will grab the methods' node trees using RubyNode, compile
131
+ them to C and then replace the old methods with the C versions. The visibility
132
+ of the old methods will be preserved.
133
+
134
+ There are some limitations: @compile_methods@ only works with methods defined
135
+ using @def@ and the methods must not need a cref (for more informations on
136
+ what crefs are please see the respective section in
137
+ "limitations":limitations.html). This mainly means that constants must be
138
+ prefixed with a double colon: @Array@ needs a cref, while @::Array@ does not.
139
+
140
+
141
+ h2. Options
142
+
143
+ Eval2C is configured with an option hash, the available options are:
144
+
145
+ * @:path@: this is the path where the compiled extensions are stored, the
146
+ default is the directory @.ruby2cext@ in the current users home dir.
147
+ * @:prefix@: this is the prefix for the names of the generated extensions, the
148
+ names of the extensions are generated from this prefix and a SHA1 digest of
149
+ the code and options. The default is @"eval2c"@ and it is generally not
150
+ necessary to change it.
151
+ * @:plugins@: this is used to configure the options for the compilation
152
+ (compare "rb2cx":rb2cx.html) and it is another option hash. The default is
153
+ <code>{:optimizations => :all}</code>, but all of the following keys are
154
+ possible:
155
+ ** @:warnings@: if set to @true@, then warnings about possible problems will
156
+ be sent to the logger (see below).
157
+ ** @:require_include@: can be set to a single search path or an array of
158
+ search paths (equivalent to the @-I@ option of @rb2cx@).
159
+ ** @:optimizations@: yet another option hash to configure the
160
+ "optimizations":optimizations.html. The valid keys are @:const_cache@,
161
+ @:builtin_methods@, @:inline_methods@ and @:case_optimize@, each with
162
+ @true@ or @false@ as value. To just use all optimizations it is also
163
+ possible to just use the symbol @:all@ instead of the hash.
164
+ * @:logger@: used for log messages, can be either @nil@ or an instance of
165
+ @Logger@ (<code>require "logger"</code>). The default is @nil@, which means
166
+ that no output is generated.
167
+ * @:force_recompile@: if this is set to @true@, then each generated extension
168
+ is (re)compiled, even if it is already available from a previous run. The
169
+ default is @false@.
170
+
171
+ Some examples:
172
+
173
+ PRE
174
+ Eval2C.new(:path => ".", :plugins => {})
175
+ Eval2C.new(:plugins => {:require_include=>[".", "../lib"], :optimizations=>:all})
176
+ Eval2C.new(:plugins => {:warnings=>true, :optimizations=>{:builtin_methods=>true}})
177
+ Eval2C.new(:prefix => "my_lib_name", :logger => Logger.new(STDOUT))
178
+ PREEND
179
+
180
+
181
+ h2. Implementation Details
182
+
183
+ The @compile_to_proc@ method works as follows:
184
+
185
+ # The name of the extension is determined from the given prefix combined with
186
+ the SHA1 digest of the Ruby code and some extra data (Ruby version,
187
+ Ruby2CExtension version and plugin options). So the code determines the
188
+ extension name and if the same code is compiled with the same version and
189
+ settings, the name will be the same. This allows very simple and efficient
190
+ caching of the compiled extensions.
191
+ # From the extension name a global variable name is constructed. The compiled
192
+ proc will be stored in that global variable by the generated C extension.
193
+ # If the extension with the generated name already exists, then we are
194
+ basically done and can skip this step. Otherwise the Ruby proc code is
195
+ translated to C and compiled to a C extension in the specified path.
196
+ # The generated or already existing C extension is <code>require</code>d.
197
+ # The global variable that now contains the compiled proc is read and the
198
+ result is returned.
199
+
200
+ The @compile_methods@ method works similar.
201
+
202
+ As mentioned above, this scheme allows very efficient caching of the C
203
+ extensions. Basically each extension is only compiled once when the
204
+ program/library is executed for the first time. In later runs the extension
205
+ will already exist and just be <code>require</code>d.
206
+
207
+ Adding the Ruby version and the Ruby2CExtension version to the digest avoids
208
+ problems if multiple versions of Ruby or Ruby2CExtension are installed and
209
+ used in parallel and it also guarantees that the extensions are automatically
210
+ recompiled if Ruby or Ruby2CExtension are updated.
211
+
212
+
213
+ h2. Using Eval2C Only When It Is Available
214
+
215
+ Having Ruby2CExtension as a hard dependency just for some speedup might not
216
+ be acceptable for many projects, in particular since Ruby2CExtension requires
217
+ that a C compiler is available at runtime.
218
+
219
+ An alternative that avoids the hard dependency is to use Ruby2CExtension only
220
+ if it is installed anyway and otherwise just execute the Ruby code as usual.
221
+ This works works very well if Eval2C and @compile_methods@ is used, for
222
+ example:
223
+
224
+ PRE
225
+ begin
226
+ require "ruby2cext/eval2c"
227
+ $e2c = Ruby2CExtension::Eval2C.new
228
+ rescue LoadError
229
+ $e2c = nil
230
+ end
231
+
232
+ class A
233
+ def initialize(x)
234
+ @x = x
235
+ end
236
+ def foo(y)
237
+ @x + y
238
+ end
239
+
240
+ $e2c && $e2c.compile_methods(self, :initialize, :foo)
241
+ end
242
+ PREEND
243
+
244
+ So if Ruby2CExtension is available, then the methods will be compiled and
245
+ fast, otherwise the Ruby code will just work as usual (but it might be a bit
246
+ slower of course).
@@ -0,0 +1,26 @@
1
+ require "redcloth"
2
+
3
+ Dir.chdir(File.dirname(__FILE__))
4
+
5
+ template = File.read("html_template")
6
+
7
+ Dir["*.txt"].each { |fn|
8
+ txt = File.read(fn)
9
+ title = txt[/^h1. (.+?)$/, 1]
10
+ txt.gsub!(/^PRE\n/m, "<pre><code>")
11
+ txt.gsub!(/^PREEND$/, "</code></pre>")
12
+ cnt = 0
13
+ sections = []
14
+ txt.gsub!(/^h2\.\s(.+)$/) { sections << $1; "h2(#section#{cnt+=1}). #$1" }
15
+ unless sections.empty?
16
+ sect_list = "\nSections: "
17
+ cnt = 0
18
+ sect_list << sections.map { |s| "\"#{s}\":#section#{cnt+=1}" }.join(", ")
19
+ sect_list << ".\n\n"
20
+ txt.sub!(/\nh2\(/m, sect_list << "h2(")
21
+ end
22
+ html = RedCloth.new(txt).to_html
23
+ File.open("#{File.basename(fn, ".txt")}.html", "w") { |f|
24
+ f.puts(template % [title, html])
25
+ }
26
+ }
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2
+ <html>
3
+ <head>
4
+ <title>%s</title>
5
+ <link href="style.css" media="all" rel="Stylesheet" type="text/css">
6
+ </head>
7
+ <body>
8
+ %s
9
+ </body>
10
+ </html>
@@ -0,0 +1,169 @@
1
+
2
+ h1. Ruby2CExtension
3
+
4
+ Ruby2CExtension is a Ruby to C extension translator/compiler. It takes any
5
+ Ruby source file, parses it using Ruby's builtin parser and then translates
6
+ the abstract syntax tree into "equivalent" C extension code.
7
+
8
+ Let's say you have a Ruby file @foo.rb@. To translate it to a C extension and
9
+ then compile it, just run:
10
+
11
+ PRE
12
+ rb2cx foo.rb
13
+ PREEND
14
+
15
+ This will produce the files @foo.c@ and @foo.so@ (on Linux). @foo.c@ is the
16
+ generated C extension source code and @foo.so@ is the compiled C extension.
17
+
18
+ If @foo.rb@ is a library, you can just rename, move or delete @foo.rb@ (only
19
+ if you have a backup, of course) and your Ruby program will just use @foo.so@
20
+ instead.
21
+
22
+ If @foo.rb@ is a script, then it isn't possible to just run @foo.so@, because
23
+ Ruby does not support running C extensions directly, but you can do this:
24
+
25
+ PRE
26
+ ruby -r foo.so -e ""
27
+ PREEND
28
+
29
+ which should produce the same output as
30
+
31
+ PRE
32
+ ruby -r foo.rb -e ""
33
+ PREEND
34
+
35
+
36
+ h2. Why?
37
+
38
+ Well, like everybody else I wanted a faster Ruby and I also wanted to learn
39
+ about Ruby's internals, so I thought translating Ruby to C might be worth a
40
+ try...
41
+
42
+ The initial results were not as good as I had hoped, but they weren't bad
43
+ either: without optimizations the generated C extension is practically never
44
+ slower than the Ruby code and I found cases where it is more than twice as
45
+ fast, usually it is somewhere in between. But, starting from version 0.2.0,
46
+ Ruby2CExtension can use "optimizations":optimizations.html to *significantly
47
+ speedup* execution in many cases (*sometimes more than five times faster* than
48
+ normal Ruby).
49
+
50
+ Of course Ruby2CExtension can also be used as an obfuscator for Ruby code,
51
+ though this was not my main motivation.
52
+
53
+
54
+ h2. Requirements
55
+
56
+ Ruby2CExtension is developed for the Ruby 1.8 versions (only 1.8.4 and later).
57
+ It is currently tested with *Ruby 1.8.4, 1.8.5 and 1.8.6*. Only those versions
58
+ should be used, because Ruby2CExtension depends on Ruby internals that can
59
+ change between Ruby versions. If an untested Ruby version is used, then there
60
+ will be a warning. It might work for later 1.8 versions, but it definitely
61
+ won't work with Ruby 1.9.
62
+
63
+ Ruby2CExtension requires RubyNode to access Ruby's node trees (the AST).
64
+ RubyNode is available at
65
+ "http://rubynode.rubyforge.org/":http://rubynode.rubyforge.org/.
66
+
67
+ Ruby2CExtension is pure Ruby code, so it should work on all platforms that
68
+ Ruby supports, but it is currently only tested on Linux. There might be
69
+ problems with the automatic compilation of the generated C code on some
70
+ platforms (in particular on Windows).
71
+
72
+
73
+ h2. Download
74
+
75
+ * "Project page":http://rubyforge.org/projects/ruby2cext/
76
+ * "Download":http://rubyforge.org/frs/?group_id=1799
77
+
78
+
79
+ h2. Installation
80
+
81
+ Just run (as root):
82
+
83
+ PRE
84
+ gem install ruby2cext
85
+ PREEND
86
+
87
+ Or if you do not use the gem:
88
+
89
+ PRE
90
+ ruby setup.rb
91
+ PREEND
92
+
93
+ This will install Ruby2CExtension to the default locations. Optionally you
94
+ can supply some options to @setup.rb@ to customize the installation (see
95
+ @"ruby setup.rb --help"@).
96
+
97
+
98
+ h2. Features
99
+
100
+ Ruby2CExtension supports a very large subset of Ruby's features:
101
+
102
+ * all the basics (classes, methods, ...)
103
+ * blocks, closures
104
+ * @instance_eval@, @define_method@, ... (only when the block is given directly)
105
+ * correct constant and class variable lookup
106
+ * @raise@, @rescue@, @retry@, @ensure@
107
+ * ...
108
+
109
+ Things that (currently) don't work:
110
+
111
+ * @break@ with a value from inside a block
112
+ * @return@ from inside a block
113
+ * @return@, @break@, @next@, @redo@ inside @ensure@
114
+ * @defined?@ is not implemented for all cases
115
+ * block pass (passing a proc as block to a method) works, but only through a
116
+ hack and it doesn't work (correctly) for things like @instance_eval@
117
+
118
+ Some of the above things might be fixed in future versions.
119
+
120
+ Things that don't work as expected and probably never will:
121
+
122
+ * methods like @local_variables@, that depend on a Ruby SCOPE
123
+ * interoperability with @eval(str)@ and similar methods that parse a string and
124
+ eval it; these methods work, but they might not behave as expected (i.e.
125
+ access to local variables and similar things won't work, see above)
126
+ * @callcc@ works but might behave strangely (in particular local variables
127
+ might behave wrong)
128
+ * some more things, please see "limitations":limitations.html
129
+
130
+ Ruby2CExtension will translate and compile Ruby files using one or more of the
131
+ above functionalities without a warning (for some cases warnings can be
132
+ enabled, see "rb2cx":rb2cx.html), so if your Ruby code uses such
133
+ functionality, please verify that the compiled C extension works as expected.
134
+
135
+ For more details please see "limitations":limitations.html.
136
+
137
+
138
+ h2. Usage
139
+
140
+ There are two "interfaces" to use Ruby2CExtension:
141
+
142
+ * "rb2cx":rb2cx.html: the command line compiler.
143
+ * "Eval2C":eval2c.html: a class that allows dynamic compilation of Ruby code
144
+ at runtime.
145
+
146
+ Please see their respective documentations.
147
+
148
+
149
+ h2. Feedback
150
+
151
+ If you find a bug, think that something doesn't work as it should or have
152
+ other suggestions, then please don't hesitate to "contact
153
+ me":mailto:dbatml@remove_nospam.gmx.de and tell me about it.
154
+
155
+ I am also interested to know if Ruby2CExtension works under Windows (or other
156
+ non Linux platforms).
157
+
158
+
159
+ h2. Thanks
160
+
161
+ I would like to thank Eric Mahurin for various good ideas for
162
+ "optimizations":optimizations.html and for inspiring "Eval2C":eval2c.html.
163
+
164
+
165
+ h2. License
166
+
167
+ Copyright 2006-2007 "Dominik Bathon":mailto:dbatml@remove_nospam.gmx.de.
168
+
169
+ Ruby2CExtension is licensed under the same terms as Ruby.