ruby2cext 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +27 -0
- data/README +44 -0
- data/bin/rb2cx +178 -0
- data/doc/eval2c.html +281 -0
- data/doc/index.html +218 -0
- data/doc/limitations.html +581 -0
- data/doc/optimizations.html +222 -0
- data/doc/rb2cx.html +151 -0
- data/doc/style.css +27 -0
- data/lib/ruby2cext/c_function.rb +621 -0
- data/lib/ruby2cext/common_node_comp.rb +1409 -0
- data/lib/ruby2cext/compiler.rb +242 -0
- data/lib/ruby2cext/error.rb +15 -0
- data/lib/ruby2cext/eval2c.rb +129 -0
- data/lib/ruby2cext/parser.rb +36 -0
- data/lib/ruby2cext/plugin.rb +24 -0
- data/lib/ruby2cext/plugins/builtin_methods.rb +820 -0
- data/lib/ruby2cext/plugins/case_optimize.rb +105 -0
- data/lib/ruby2cext/plugins/const_cache.rb +38 -0
- data/lib/ruby2cext/plugins/inline_methods.rb +69 -0
- data/lib/ruby2cext/plugins/require_include.rb +71 -0
- data/lib/ruby2cext/plugins/warnings.rb +123 -0
- data/lib/ruby2cext/scopes.rb +227 -0
- data/lib/ruby2cext/str_to_c_strlit.rb +12 -0
- data/lib/ruby2cext/tools.rb +84 -0
- data/lib/ruby2cext/version.rb +22 -0
- data/testfiles/bench.rb +116 -0
- data/testfiles/eval2c/test_eval2c.rb +37 -0
- data/testfiles/test.rb +615 -0
- data/testfiles/vmode_test.rb +73 -0
- data/testfiles/warn_test.rb +35 -0
- metadata +87 -0
data/doc/index.html
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Ruby2CExtension</title>
|
5
|
+
<link href="style.css" media="all" rel="Stylesheet" type="text/css">
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1>Ruby2CExtension</h1>
|
9
|
+
|
10
|
+
|
11
|
+
<p>Ruby2CExtension is a Ruby to C extension translator/compiler. It takes any
|
12
|
+
Ruby source file, parses it using Ruby’s builtin parser and then translates
|
13
|
+
the abstract syntax tree into “equivalent” C extension code.</p>
|
14
|
+
|
15
|
+
|
16
|
+
<p>Let’s say you have a Ruby file <code>foo.rb</code>. To translate it to a C extension and
|
17
|
+
then compile it, just run:</p>
|
18
|
+
|
19
|
+
|
20
|
+
<pre><code>rb2cx foo.rb
|
21
|
+
</code></pre>
|
22
|
+
|
23
|
+
<p>This will produce the files <code>foo.c</code> and <code>foo.so</code> (on Linux). <code>foo.c</code> is the
|
24
|
+
generated C extension source code and <code>foo.so</code> is the compiled C extension.</p>
|
25
|
+
|
26
|
+
|
27
|
+
<p>If <code>foo.rb</code> is a library, you can just rename, move or delete <code>foo.rb</code> (only
|
28
|
+
if you have a backup, of course) and your Ruby program will just use <code>foo.so</code>
|
29
|
+
instead.</p>
|
30
|
+
|
31
|
+
|
32
|
+
<p>If <code>foo.rb</code> is a script, then it isn’t possible to just run <code>foo.so</code>, because
|
33
|
+
Ruby does not support running C extensions directly, but you can do this:</p>
|
34
|
+
|
35
|
+
|
36
|
+
<pre><code>ruby -r foo.so -e ""
|
37
|
+
</code></pre>
|
38
|
+
|
39
|
+
<p>which should produce the same output as</p>
|
40
|
+
|
41
|
+
|
42
|
+
<pre><code>ruby -r foo.rb -e ""
|
43
|
+
</code></pre>
|
44
|
+
|
45
|
+
<p>Sections: <a href="#section1">Why?</a>, <a href="#section2">Requirements</a>, <a href="#section3">Download</a>, <a href="#section4">Installation</a>, <a href="#section5">Features</a>, <a href="#section6">Usage</a>, <a href="#section7">Feedback</a>, <a href="#section8">Thanks</a>, <a href="#section9">License</a>.</p>
|
46
|
+
|
47
|
+
|
48
|
+
<h2 id="section1">Why?</h2>
|
49
|
+
|
50
|
+
|
51
|
+
<p>Well, like everybody else I wanted a faster Ruby and I also wanted to learn
|
52
|
+
about Ruby’s internals, so I thought translating Ruby to C might be worth a
|
53
|
+
try…</p>
|
54
|
+
|
55
|
+
|
56
|
+
<p>The initial results were not as good as I had hoped, but they weren’t bad
|
57
|
+
either: without optimizations the generated C extension is practically never
|
58
|
+
slower than the Ruby code and I found cases where it is more than twice as
|
59
|
+
fast, usually it is somewhere in between. But, starting from version 0.2.0,
|
60
|
+
Ruby2CExtension can use <a href="optimizations.html">optimizations</a> to <strong>significantly
|
61
|
+
speedup</strong> execution in many cases (<strong>sometimes more than five times faster</strong> than
|
62
|
+
normal Ruby).</p>
|
63
|
+
|
64
|
+
|
65
|
+
<p>Of course Ruby2CExtension can also be used as an obfuscator for Ruby code,
|
66
|
+
though this was not my main motivation.</p>
|
67
|
+
|
68
|
+
|
69
|
+
<h2 id="section2">Requirements</h2>
|
70
|
+
|
71
|
+
|
72
|
+
<p>Ruby2CExtension is developed for the Ruby 1.8 versions (only 1.8.4 and later).
|
73
|
+
It is currently tested with <strong>Ruby 1.8.4, 1.8.5 and 1.8.6</strong>. Only those versions
|
74
|
+
should be used, because Ruby2CExtension depends on Ruby internals that can
|
75
|
+
change between Ruby versions. If an untested Ruby version is used, then there
|
76
|
+
will be a warning. It might work for later 1.8 versions, but it definitely
|
77
|
+
won’t work with Ruby 1.9.</p>
|
78
|
+
|
79
|
+
|
80
|
+
<p>Ruby2CExtension requires RubyNode to access Ruby’s node trees (the <span class="caps">AST</span>).
|
81
|
+
RubyNode is available at
|
82
|
+
<a href="http://rubynode.rubyforge.org/">http://rubynode.rubyforge.org/</a>.</p>
|
83
|
+
|
84
|
+
|
85
|
+
<p>Ruby2CExtension is pure Ruby code, so it should work on all platforms that
|
86
|
+
Ruby supports, but it is currently only tested on Linux. There might be
|
87
|
+
problems with the automatic compilation of the generated C code on some
|
88
|
+
platforms (in particular on Windows).</p>
|
89
|
+
|
90
|
+
|
91
|
+
<h2 id="section3">Download</h2>
|
92
|
+
|
93
|
+
|
94
|
+
<ul>
|
95
|
+
<li><a href="http://rubyforge.org/projects/ruby2cext/">Project page</a></li>
|
96
|
+
<li><a href="http://rubyforge.org/frs/?group_id=1799">Download</a></li>
|
97
|
+
</ul>
|
98
|
+
|
99
|
+
|
100
|
+
<h2 id="section4">Installation</h2>
|
101
|
+
|
102
|
+
|
103
|
+
<p>Just run (as root):</p>
|
104
|
+
|
105
|
+
|
106
|
+
<pre><code>gem install ruby2cext
|
107
|
+
</code></pre>
|
108
|
+
|
109
|
+
<p>Or if you do not use the gem:</p>
|
110
|
+
|
111
|
+
|
112
|
+
<pre><code>ruby setup.rb
|
113
|
+
</code></pre>
|
114
|
+
|
115
|
+
<p>This will install Ruby2CExtension to the default locations. Optionally you
|
116
|
+
can supply some options to <code>setup.rb</code> to customize the installation (see
|
117
|
+
<code>"ruby setup.rb --help"</code>).</p>
|
118
|
+
|
119
|
+
|
120
|
+
<h2 id="section5">Features</h2>
|
121
|
+
|
122
|
+
|
123
|
+
<p>Ruby2CExtension supports a very large subset of Ruby’s features:</p>
|
124
|
+
|
125
|
+
|
126
|
+
<ul>
|
127
|
+
<li>all the basics (classes, methods, ...)</li>
|
128
|
+
<li>blocks, closures</li>
|
129
|
+
<li><code>instance_eval</code>, <code>define_method</code>, ... (only when the block is given directly)</li>
|
130
|
+
<li>correct constant and class variable lookup</li>
|
131
|
+
<li><code>raise</code>, <code>rescue</code>, <code>retry</code>, <code>ensure</code></li>
|
132
|
+
<li>...</li>
|
133
|
+
</ul>
|
134
|
+
|
135
|
+
|
136
|
+
<p>Things that (currently) don’t work:</p>
|
137
|
+
|
138
|
+
|
139
|
+
<ul>
|
140
|
+
<li><code>break</code> with a value from inside a block</li>
|
141
|
+
<li><code>return</code> from inside a block</li>
|
142
|
+
<li><code>return</code>, <code>break</code>, <code>next</code>, <code>redo</code> inside <code>ensure</code></li>
|
143
|
+
<li><code>defined?</code> is not implemented for all cases</li>
|
144
|
+
<li>block pass (passing a proc as block to a method) works, but only through a
|
145
|
+
hack and it doesn’t work (correctly) for things like <code>instance_eval</code></li>
|
146
|
+
</ul>
|
147
|
+
|
148
|
+
|
149
|
+
<p>Some of the above things might be fixed in future versions.</p>
|
150
|
+
|
151
|
+
|
152
|
+
<p>Things that don’t work as expected and probably never will:</p>
|
153
|
+
|
154
|
+
|
155
|
+
<ul>
|
156
|
+
<li>methods like <code>local_variables</code>, that depend on a Ruby <span class="caps">SCOPE</span></li>
|
157
|
+
<li>interoperability with <code>eval(str)</code> and similar methods that parse a string and
|
158
|
+
eval it; these methods work, but they might not behave as expected (i.e.
|
159
|
+
access to local variables and similar things won’t work, see above)</li>
|
160
|
+
<li><code>callcc</code> works but might behave strangely (in particular local variables
|
161
|
+
might behave wrong)</li>
|
162
|
+
<li>some more things, please see <a href="limitations.html">limitations</a></li>
|
163
|
+
</ul>
|
164
|
+
|
165
|
+
|
166
|
+
<p>Ruby2CExtension will translate and compile Ruby files using one or more of the
|
167
|
+
above functionalities without a warning (for some cases warnings can be
|
168
|
+
enabled, see <a href="rb2cx.html">rb2cx</a>), so if your Ruby code uses such
|
169
|
+
functionality, please verify that the compiled C extension works as expected.</p>
|
170
|
+
|
171
|
+
|
172
|
+
<p>For more details please see <a href="limitations.html">limitations</a>.</p>
|
173
|
+
|
174
|
+
|
175
|
+
<h2 id="section6">Usage</h2>
|
176
|
+
|
177
|
+
|
178
|
+
<p>There are two “interfaces” to use Ruby2CExtension:</p>
|
179
|
+
|
180
|
+
|
181
|
+
<ul>
|
182
|
+
<li><a href="rb2cx.html">rb2cx</a>: the command line compiler.</li>
|
183
|
+
<li><a href="eval2c.html">Eval2C</a>: a class that allows dynamic compilation of Ruby code
|
184
|
+
at runtime.</li>
|
185
|
+
</ul>
|
186
|
+
|
187
|
+
|
188
|
+
<p>Please see their respective documentations.</p>
|
189
|
+
|
190
|
+
|
191
|
+
<h2 id="section7">Feedback</h2>
|
192
|
+
|
193
|
+
|
194
|
+
<p>If you find a bug, think that something doesn’t work as it should or have
|
195
|
+
other suggestions, then please don’t hesitate to <a href="mailto:dbatml@remove_nospam.gmx.de">contact
|
196
|
+
me</a> and tell me about it.</p>
|
197
|
+
|
198
|
+
|
199
|
+
<p>I am also interested to know if Ruby2CExtension works under Windows (or other
|
200
|
+
non Linux platforms).</p>
|
201
|
+
|
202
|
+
|
203
|
+
<h2 id="section8">Thanks</h2>
|
204
|
+
|
205
|
+
|
206
|
+
<p>I would like to thank Eric Mahurin for various good ideas for
|
207
|
+
<a href="optimizations.html">optimizations</a> and for inspiring <a href="eval2c.html">Eval2C</a>.</p>
|
208
|
+
|
209
|
+
|
210
|
+
<h2 id="section9">License</h2>
|
211
|
+
|
212
|
+
|
213
|
+
<p>Copyright 2006-2007 <a href="mailto:dbatml@remove_nospam.gmx.de">Dominik Bathon</a>.</p>
|
214
|
+
|
215
|
+
|
216
|
+
<p>Ruby2CExtension is licensed under the same terms as Ruby.</p>
|
217
|
+
</body>
|
218
|
+
</html>
|
@@ -0,0 +1,581 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Ruby2CExtension Limitations</title>
|
5
|
+
<link href="style.css" media="all" rel="Stylesheet" type="text/css">
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1>Ruby2CExtension Limitations</h1>
|
9
|
+
|
10
|
+
|
11
|
+
<p>Ruby2CExtension has some limitations. Some things do not work “by design”
|
12
|
+
other things don’t work because they are not (yet) implemented.</p>
|
13
|
+
|
14
|
+
|
15
|
+
<p>Generally Ruby2CExtension tries to match Ruby’s semantics as close as
|
16
|
+
possible, so if a Ruby file doesn’t fail to compile and doesn’t have any of
|
17
|
+
the issues described below, then the compiled C extension should just work and
|
18
|
+
behave exactly as the Ruby code would.</p>
|
19
|
+
|
20
|
+
|
21
|
+
<p>Sections: <a href="#section1">Warnings and Exceptions</a>, <a href="#section2">C Extension Limitations</a>, <a href="#section3">Arity</a>, <a href="#section4">Continuations</a>, <a href="#section5">Scope</a>, <a href="#section6">Vmode</a>, <a href="#section7">Cref</a>, <a href="#section8">Block Pass</a>, <a href="#section9">Block Argument Semantics</a>, <a href="#section10"><code>super</code> with implicit arguments and optional arguments</a>, <a href="#section11">Not Supported Features</a>.</p>
|
22
|
+
|
23
|
+
|
24
|
+
<h2 id="section1">Warnings and Exceptions</h2>
|
25
|
+
|
26
|
+
|
27
|
+
<p>Not all warnings that Ruby code might emit are reproduced in the compiled C
|
28
|
+
extension.</p>
|
29
|
+
|
30
|
+
|
31
|
+
<p>Ruby2CExtension also omits some checks that might raise exceptions for Ruby
|
32
|
+
code (it won’t warn or raise exceptions on wrong argument count in lambdas for
|
33
|
+
example).</p>
|
34
|
+
|
35
|
+
|
36
|
+
<p>As a rule of thumb: if Ruby code works without warnings then the compiled C
|
37
|
+
extension will also work without warnings, but if the Ruby code emits
|
38
|
+
warnings, then the compiled C extension might emit less warnings.</p>
|
39
|
+
|
40
|
+
|
41
|
+
<p>Also, sometimes the compiled C extension will raise slightly different
|
42
|
+
exceptions than the Ruby code would.</p>
|
43
|
+
|
44
|
+
|
45
|
+
<h2 id="section2">C Extension Limitations</h2>
|
46
|
+
|
47
|
+
|
48
|
+
<p>Because the compiled code is a C extension, it will also behave like a C
|
49
|
+
extension:</p>
|
50
|
+
|
51
|
+
|
52
|
+
<ul>
|
53
|
+
<li>backtraces will look like backtraces of C extensions (i.e. no line
|
54
|
+
numbers, ...)</li>
|
55
|
+
<li>a trace proc set with <code>set_trace_func</code> will only get C extension events
|
56
|
+
(<code>"c-call"</code>, <code>"c-return"</code>, <code>"raise"</code>), instead of the usual Ruby code events</li>
|
57
|
+
</ul>
|
58
|
+
|
59
|
+
|
60
|
+
<h2 id="section3">Arity</h2>
|
61
|
+
|
62
|
+
|
63
|
+
<p>All methods and procs defined in Ruby code that is compiled to a C extension
|
64
|
+
will return <code>-1</code> as <code>arity</code>. So if your Ruby code depends on the method
|
65
|
+
<code>arity</code>, you might have to change it.</p>
|
66
|
+
|
67
|
+
|
68
|
+
<h2 id="section4">Continuations</h2>
|
69
|
+
|
70
|
+
|
71
|
+
<p>Continuations (<code>callcc</code>) are possible in compiled Ruby code, but you might see
|
72
|
+
wrong behavior with local variables (i.e. they will have an old value),
|
73
|
+
depending on whether these local variables are needed for a closure or not.</p>
|
74
|
+
|
75
|
+
|
76
|
+
<p>In short, you probably should not use continuations in Ruby code that you want
|
77
|
+
to compile to a C extension.</p>
|
78
|
+
|
79
|
+
|
80
|
+
<h2 id="section5">Scope</h2>
|
81
|
+
|
82
|
+
|
83
|
+
<p>In Ruby every scope (class scope, methods, ...) has an associated C struct
|
84
|
+
<span class="caps">SCOPE</span>, which stores the local variables (including <code>$~</code> and <code>$_</code>) for that
|
85
|
+
scope. Methods that are implemented in a C extension don’t get such a <span class="caps">SCOPE</span>,
|
86
|
+
because it is expensive to set up and they don’t need it (they just use
|
87
|
+
variables on the stack).</p>
|
88
|
+
|
89
|
+
|
90
|
+
<p>That means that the methods in Ruby code that is compiled to a C extension
|
91
|
+
won’t get a <span class="caps">SCOPE</span> either, which is usually no problem because local variables
|
92
|
+
are handled differently anyway. It only gets a problem, if the code uses
|
93
|
+
methods that work with the current <span class="caps">SCOPE</span>. Here are some of these methods:</p>
|
94
|
+
|
95
|
+
|
96
|
+
<ul>
|
97
|
+
<li><code>local_variables</code></li>
|
98
|
+
<li><code>eval</code></li>
|
99
|
+
<li><code>binding</code></li>
|
100
|
+
</ul>
|
101
|
+
|
102
|
+
|
103
|
+
<p>These methods will work, but they will see the <span class="caps">SCOPE</span> of the nearest Ruby code
|
104
|
+
scope. This is also true for <code>$_</code> and <code>$~</code> (and the derived <code>$&</code>, <code>$`</code>, <code>$'</code>,
|
105
|
+
<code>$1</code>, ...). Example:</p>
|
106
|
+
|
107
|
+
|
108
|
+
<pre><code>def bar
|
109
|
+
a = 2
|
110
|
+
"xxx" =~ /./ # changes $~ of the nearest Ruby code scope
|
111
|
+
p eval("a") # won't return 2 (a's value), instead it will be evaled in the
|
112
|
+
# nearest Ruby code scope
|
113
|
+
local_variables # returns local variables of the nearest Ruby code scope
|
114
|
+
end
|
115
|
+
</code></pre>
|
116
|
+
|
117
|
+
<p>If bar is compiled into a C extension and then called from the following Ruby
|
118
|
+
code:</p>
|
119
|
+
|
120
|
+
|
121
|
+
<pre><code>a = b = 42
|
122
|
+
$~ = nil
|
123
|
+
p bar
|
124
|
+
p $~
|
125
|
+
</code></pre>
|
126
|
+
|
127
|
+
<p>Then it will output</p>
|
128
|
+
|
129
|
+
|
130
|
+
<pre><code>42
|
131
|
+
["a", "b"]
|
132
|
+
#<MatchData: ...>
|
133
|
+
</code></pre>
|
134
|
+
|
135
|
+
<p>instead of the expected</p>
|
136
|
+
|
137
|
+
|
138
|
+
<pre><code>2
|
139
|
+
["a"]
|
140
|
+
nil
|
141
|
+
</code></pre>
|
142
|
+
|
143
|
+
<p>Another consequence is that if compiled methods call each other, they will all
|
144
|
+
share the same <code>$_</code> and <code>$~</code> (those of the nearest Ruby code scope). This
|
145
|
+
might make some code behave unexpectedly.</p>
|
146
|
+
|
147
|
+
|
148
|
+
<h2 id="section6">Vmode</h2>
|
149
|
+
|
150
|
+
|
151
|
+
<p>The so called vmode is also associated with the Ruby <span class="caps">SCOPE</span> (though not
|
152
|
+
directly stored inside the <span class="caps">SCOPE</span> struct). The vmode is set by the methods
|
153
|
+
<code>private</code>, <code>protected</code>, <code>public</code> and <code>module_function</code> and determines which
|
154
|
+
visibility newly defined methods get.</p>
|
155
|
+
|
156
|
+
|
157
|
+
<p>Ruby2CExtension can not (easily) access Ruby’s internal vmode, instead it
|
158
|
+
tries to figure out at compile time what visibility a method defined using
|
159
|
+
<code>def</code> will get. But be careful with <code>Module#define_method</code> and
|
160
|
+
<code>Module#attr*</code>: those methods will use Ruby’s internal vmode.</p>
|
161
|
+
|
162
|
+
|
163
|
+
<p>So, there are actually two different vmodes at work for compiled Ruby
|
164
|
+
code: the vmode that Ruby2CExtension uses at compile time to guess which
|
165
|
+
visibility methods defined with <code>def</code> get and Ruby’s internal vmode at
|
166
|
+
runtime which is used by <code>Module#define_method</code> and <code>Module#attr*</code>.</p>
|
167
|
+
|
168
|
+
|
169
|
+
<p>Ruby2CExtension’s compile time vmode heuristic works by replacing calls to the
|
170
|
+
vmode changing methods with <code>nil</code> and instead changing the compile time vmode.
|
171
|
+
The calls are only replaced if they are without receiver and without
|
172
|
+
arguments. And it also depends on where the calls are made:</p>
|
173
|
+
|
174
|
+
|
175
|
+
<p>In the <strong>toplevel scope</strong> only calls to <code>private</code> and <code>public</code> are replaced, the
|
176
|
+
default vmode in the toplevel scope is private.</p>
|
177
|
+
|
178
|
+
|
179
|
+
<p>In a <strong>module scope</strong> calls to <code>private</code>, <code>protected</code>, <code>public</code> and
|
180
|
+
<code>module_function</code> are replaced, the default vmode in a module scope is public.</p>
|
181
|
+
|
182
|
+
|
183
|
+
<p>In a <strong>class scope</strong> calls to <code>private</code>, <code>protected</code> and <code>public</code> are replaced,
|
184
|
+
the default vmode in a class scope is public.</p>
|
185
|
+
|
186
|
+
|
187
|
+
<p>In <strong>methods</strong> and <strong>blocks</strong> no calls are replaced and all methods defined with
|
188
|
+
<code>def</code> will be public.</p>
|
189
|
+
|
190
|
+
|
191
|
+
<p>If your code doesn’t do anything tricky, then the compile time heuristic
|
192
|
+
should just work as expected. Here is an example:</p>
|
193
|
+
|
194
|
+
|
195
|
+
<pre><code># start of file
|
196
|
+
# default vmode is private
|
197
|
+
def m1; end # private
|
198
|
+
|
199
|
+
public # this call will be replaced with nil
|
200
|
+
# vmode is now public
|
201
|
+
def m2; end # public
|
202
|
+
|
203
|
+
class A
|
204
|
+
# default vmode is public
|
205
|
+
def m2; end # public
|
206
|
+
|
207
|
+
private # this call will be replaced with nil
|
208
|
+
# vmode is now private
|
209
|
+
def m3 # private
|
210
|
+
def foo # public, because it is in a method
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
protected # this call is not replaced and will probably fail because
|
217
|
+
# #protected is not defined at toplevel
|
218
|
+
|
219
|
+
# end of file
|
220
|
+
</code></pre>
|
221
|
+
|
222
|
+
<p>Here is an example, where it fails:</p>
|
223
|
+
|
224
|
+
|
225
|
+
<pre><code>class A
|
226
|
+
def pub; end # public
|
227
|
+
|
228
|
+
private if nil # Ruby2CExtension replaces the call to private with nil
|
229
|
+
# vmode is now private
|
230
|
+
|
231
|
+
def pub2; end # will be private in the compiled C extension
|
232
|
+
end
|
233
|
+
</code></pre>
|
234
|
+
|
235
|
+
<p>But this should be a pretty uncommon case. The visibility of methods defined
|
236
|
+
using <code>def</code> should be correct for most Ruby code.</p>
|
237
|
+
|
238
|
+
|
239
|
+
<p>It is a bit more complicated for methods/attributes defined using
|
240
|
+
<code>define_method</code> or the <code>attr*</code> methods. Their visibility is determined by
|
241
|
+
Ruby’s internal vmode at run time.</p>
|
242
|
+
|
243
|
+
|
244
|
+
<p>As explained above, C extension code does not get its own <span class="caps">SCOPE</span>, so it also
|
245
|
+
doesn’t get its own vmode. When a C extension is <code>require</code>d, Ruby
|
246
|
+
sets the vmode to public before loading the C extension. All the class/module
|
247
|
+
scopes that are executed during the <code>require</code> are executed in the same <span class="caps">SCOPE</span>
|
248
|
+
and so also with the same vmode.</p>
|
249
|
+
|
250
|
+
|
251
|
+
<p>Because all the vmode changing method calls are replaced with <code>nil</code>, Ruby’s
|
252
|
+
internal vmode will probably stay public all the time and so all
|
253
|
+
methods/attributes defined using <code>define_method</code> or the <code>attr*</code> methods will
|
254
|
+
be public. Here is an example:</p>
|
255
|
+
|
256
|
+
|
257
|
+
<pre><code># Ruby's internal vmode is public
|
258
|
+
class A
|
259
|
+
# still the same internal vmode, still public
|
260
|
+
define_method(:a) {} # public
|
261
|
+
|
262
|
+
private # is replaced with nil, does not affect Ruby's internal vmode
|
263
|
+
def b; end # private
|
264
|
+
|
265
|
+
# but Ruby's internal vmode is still public
|
266
|
+
define_method(:c) {} # public
|
267
|
+
attr_accessor :d, :e # also public
|
268
|
+
end
|
269
|
+
</code></pre>
|
270
|
+
|
271
|
+
<p>If those methods really need another visibility, then it can be changed
|
272
|
+
explicitly:</p>
|
273
|
+
|
274
|
+
|
275
|
+
<pre><code>class A
|
276
|
+
define_method(:a) {}
|
277
|
+
private :a
|
278
|
+
end
|
279
|
+
</code></pre>
|
280
|
+
|
281
|
+
<p>In methods the internal vmode is that of the nearest Ruby <span class="caps">SCOPE</span> (as explained
|
282
|
+
above), so it is usually unpredictable. And additionally calling one of the
|
283
|
+
vmode changing methods will also affect the <span class="caps">SCOPE</span> of the caller:</p>
|
284
|
+
|
285
|
+
|
286
|
+
<pre><code># in compiled C extension
|
287
|
+
def my_private
|
288
|
+
private
|
289
|
+
end
|
290
|
+
</code></pre>
|
291
|
+
|
292
|
+
<pre><code># in Ruby code
|
293
|
+
class A
|
294
|
+
def a;end # public
|
295
|
+
my_private
|
296
|
+
def b;end # private, but would be public if the above code was not compiled
|
297
|
+
end
|
298
|
+
</code></pre>
|
299
|
+
|
300
|
+
<p>To be save, don’t use the vmode changing methods without arguments inside
|
301
|
+
methods, instead set the visibility explicitly (e.g. <code>private :a</code>).</p>
|
302
|
+
|
303
|
+
|
304
|
+
<h2 id="section7">Cref</h2>
|
305
|
+
|
306
|
+
|
307
|
+
<p>The so called cref is another Ruby internal that Ruby2CExtension has to
|
308
|
+
emulate. The cref is a linked list that describes the current lexical
|
309
|
+
class/module nesting. Example:</p>
|
310
|
+
|
311
|
+
|
312
|
+
<pre><code>class A
|
313
|
+
class B
|
314
|
+
# cref here is B -> A -> Object
|
315
|
+
end
|
316
|
+
# cref here is A -> Object
|
317
|
+
module C
|
318
|
+
# cref here is C -> A -> Object
|
319
|
+
end
|
320
|
+
end
|
321
|
+
# cref here is Object
|
322
|
+
</code></pre>
|
323
|
+
|
324
|
+
<p>The current cref is used for constant and class variable lookup and for <code>def</code>,
|
325
|
+
<code>undef</code> and <code>alias</code>.</p>
|
326
|
+
|
327
|
+
|
328
|
+
<p>Ruby2CExtension emulates cref with the same semantics as Ruby. There are only
|
329
|
+
two problems.</p>
|
330
|
+
|
331
|
+
|
332
|
+
<p>First, when a method is defined in Ruby code, it saves the current cref for
|
333
|
+
later use. From C it isn’t possible to store an extra value when defining a
|
334
|
+
method, so Ruby2CExtension works around this problem by storing the cref in a
|
335
|
+
global variable. But there is still a problem when a <code>def</code> is used/run
|
336
|
+
multiple times, because the cref can differ each time.</p>
|
337
|
+
|
338
|
+
|
339
|
+
<p>So if a <code>def</code> that requires a cref is used multiple times, then the compiled C
|
340
|
+
extension will raise an exception (this is the only case where code compiled
|
341
|
+
with Ruby2CExtension raises an exception that Ruby wouldn’t raise). If a <code>def</code>
|
342
|
+
doesn’t need a cref, then everything is fine and it can be used multiple
|
343
|
+
times. Examples:</p>
|
344
|
+
|
345
|
+
|
346
|
+
<pre><code>["a", "b"].each { |s|
|
347
|
+
class << s
|
348
|
+
def bar; self; end # is OK, doesn't need cref
|
349
|
+
end
|
350
|
+
}
|
351
|
+
|
352
|
+
["a", "b"].each { |s|
|
353
|
+
class << s
|
354
|
+
def baz; Array.new(self); end # fails the 2nd time
|
355
|
+
end
|
356
|
+
}
|
357
|
+
</code></pre>
|
358
|
+
|
359
|
+
<p>The second case fails because the constant lookup for <code>Array</code> needs a cref. If
|
360
|
+
you really need this to work, then you can use <code>::Array</code> instead of <code>Array</code>,
|
361
|
+
because that won’t need a cref.</p>
|
362
|
+
|
363
|
+
|
364
|
+
<p>Again in the usual case everything should be fine and if you really need to
|
365
|
+
use a <code>def</code> that requires a cref multiple times, then you might be able to
|
366
|
+
modify it so that it won’t need a cref.</p>
|
367
|
+
|
368
|
+
|
369
|
+
<p>The second problem that arises from Ruby2CExtension emulating crefs is that
|
370
|
+
methods that access Ruby’s internal cref, will see the wrong cref and thus
|
371
|
+
not behave as expected. Those methods are <code>Module.nesting</code>, <code>Module.constants</code>
|
372
|
+
(but <code>Module#constants</code> works), <code>autoload</code> and <code>autoload?</code> (use
|
373
|
+
<code>Module#autoload</code> and <code>Module#autoload?</code> instead).</p>
|
374
|
+
|
375
|
+
|
376
|
+
<h2 id="section8">Block Pass</h2>
|
377
|
+
|
378
|
+
|
379
|
+
<p>There currently is no way to pass a Proc instance as the block parameter to a
|
380
|
+
method call on the C side, i.e. there is no way to do the following from C:</p>
|
381
|
+
|
382
|
+
|
383
|
+
<pre><code>def foo(proc)
|
384
|
+
bar(&proc)
|
385
|
+
end
|
386
|
+
</code></pre>
|
387
|
+
|
388
|
+
<p>Ruby2CExtension works around this by compiling the above to something similar
|
389
|
+
to this:</p>
|
390
|
+
|
391
|
+
|
392
|
+
<pre><code>def foo(proc)
|
393
|
+
tmp_proc = proc.to_proc
|
394
|
+
bar { |*arg| tmp_proc.call(*arg) }
|
395
|
+
end
|
396
|
+
</code></pre>
|
397
|
+
|
398
|
+
<p>The downside of this workaround is that it doesn’t work (as expected) with
|
399
|
+
methods like <code>instance_eval</code> and it is problematic if a proc is passed deep
|
400
|
+
into a recursive method, because that block will then be wrapped multiple
|
401
|
+
times.</p>
|
402
|
+
|
403
|
+
|
404
|
+
<p>This issue might be fixed if a future Ruby version provides a way to cleanly
|
405
|
+
pass a proc to a method call.</p>
|
406
|
+
|
407
|
+
|
408
|
+
<h2 id="section9">Block Argument Semantics</h2>
|
409
|
+
|
410
|
+
|
411
|
+
<p>Block argument semantics are a bit tricky, but Ruby2CExtension should get it
|
412
|
+
right for most cases, here are two cases where the result is wrong:</p>
|
413
|
+
|
414
|
+
|
415
|
+
<pre><code>def t1(*a); yield *a; end
|
416
|
+
p t1([1, 2]) { |a| a }
|
417
|
+
|
418
|
+
def bl_pa_tst(); p yield([1, 2]); end
|
419
|
+
pc = proc { |*a| a }
|
420
|
+
bl_pa_tst(&pc)
|
421
|
+
bl_pa_tst { |*a| a }
|
422
|
+
</code></pre>
|
423
|
+
|
424
|
+
<p>Ruby outputs:</p>
|
425
|
+
|
426
|
+
|
427
|
+
<pre><code>[1, 2]
|
428
|
+
[[1, 2]]
|
429
|
+
[[1, 2]]
|
430
|
+
</code></pre>
|
431
|
+
|
432
|
+
<p>The compiled C extension outputs:</p>
|
433
|
+
|
434
|
+
|
435
|
+
<pre><code>[[1, 2]]
|
436
|
+
[1, 2]
|
437
|
+
[1, 2]
|
438
|
+
</code></pre>
|
439
|
+
|
440
|
+
<p>But again, for most cases it should just work and maybe it will get better in
|
441
|
+
future Ruby2CExtension versions.</p>
|
442
|
+
|
443
|
+
|
444
|
+
<h2 id="section10"><code>super</code> with implicit arguments and optional arguments</h2>
|
445
|
+
|
446
|
+
|
447
|
+
<p>In a compiled C extension <code>super</code> with implicit arguments will not use
|
448
|
+
optional arguments that have not been given by the original caller. Example:</p>
|
449
|
+
|
450
|
+
|
451
|
+
<pre><code>class A
|
452
|
+
def foo(*a)
|
453
|
+
p a
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
class B < A
|
458
|
+
def foo(a = nil)
|
459
|
+
super
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
B.new.foo
|
464
|
+
</code></pre>
|
465
|
+
|
466
|
+
<p>In Ruby this code will output <code>[nil]</code>, in the compiled form it will output
|
467
|
+
<code>[]</code>.</p>
|
468
|
+
|
469
|
+
|
470
|
+
<h2 id="section11">Not Supported Features</h2>
|
471
|
+
|
472
|
+
|
473
|
+
<p>Ruby files that use one or more of the above described problematic things will
|
474
|
+
usually compile just fine and fail or behave wrong at runtime. In contrast,
|
475
|
+
the following things will be catched at compile time. Most of them are just
|
476
|
+
not supported yet and might be added later.</p>
|
477
|
+
|
478
|
+
|
479
|
+
<h3>Control Flow</h3>
|
480
|
+
|
481
|
+
|
482
|
+
<p>Most of the things that are not supported are related to control flow. Ruby
|
483
|
+
implements most of its control flow using <code>setjmp()</code> and <code>longjmp()</code>. Most of
|
484
|
+
this is in <code>eval.c</code> and there is no real <span class="caps">API</span> to access it, so Ruby2CExtension
|
485
|
+
has to do some tricks to make control flow work. For most cases workarounds
|
486
|
+
are implemented, but some of the harder cases are not (yet) supported.</p>
|
487
|
+
|
488
|
+
|
489
|
+
<p>The first thing that isn’t supported is <code>return</code> from inside a block. Also
|
490
|
+
<code>break</code> with a value from inside a block is not supported (but <code>break</code> without
|
491
|
+
a value is):</p>
|
492
|
+
|
493
|
+
|
494
|
+
<pre><code>def foo
|
495
|
+
bar(1, 2, 3) {
|
496
|
+
next # works
|
497
|
+
next 42 # works
|
498
|
+
redo # works
|
499
|
+
break # works
|
500
|
+
break 42 # does not work
|
501
|
+
return # does not work
|
502
|
+
return 42 # does not work
|
503
|
+
}
|
504
|
+
return # works
|
505
|
+
return 42 # works
|
506
|
+
end
|
507
|
+
</code></pre>
|
508
|
+
|
509
|
+
<p>For <code>while</code>/<code>until</code> loops everything works.</p>
|
510
|
+
|
511
|
+
|
512
|
+
<p>Another problematic area in Ruby2CExtension 0.1.0 was control flow “through” a
|
513
|
+
<code>rescue</code> or <code>ensure</code> clause. This is mostly implemented now, only in <code>ensure</code>
|
514
|
+
clauses it still does not work (it <em>does</em> work in <code>ensure</code> bodies):</p>
|
515
|
+
|
516
|
+
|
517
|
+
<pre><code>def foo
|
518
|
+
while bar?
|
519
|
+
begin
|
520
|
+
next # works
|
521
|
+
next 42 # works
|
522
|
+
redo # works
|
523
|
+
break # works
|
524
|
+
break 42 # works
|
525
|
+
return # works
|
526
|
+
return 42 # works
|
527
|
+
rescue
|
528
|
+
next # works
|
529
|
+
next 42 # works
|
530
|
+
redo # works
|
531
|
+
break # works
|
532
|
+
break 42 # works
|
533
|
+
return # works
|
534
|
+
return 42 # works
|
535
|
+
ensure
|
536
|
+
next # does not work
|
537
|
+
next 42 # does not work
|
538
|
+
redo # does not work
|
539
|
+
break # does not work
|
540
|
+
break 42 # does not work
|
541
|
+
return # does not work
|
542
|
+
return 42 # does not work
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
</code></pre>
|
547
|
+
|
548
|
+
<h3><code>defined?</code></h3>
|
549
|
+
|
550
|
+
|
551
|
+
<p>The <code>defined?</code> statement is also not fully supported, it works for most of the
|
552
|
+
common cases like constants, global variables, instance variables, class
|
553
|
+
variables and <code>$~</code> (and derived). Ruby2CExtension fails at compile time if a
|
554
|
+
case is not supported.</p>
|
555
|
+
|
556
|
+
|
557
|
+
<h3><code>super</code> with implicit arguments in Ruby 1.8.5 and later</h3>
|
558
|
+
|
559
|
+
|
560
|
+
<p>For Ruby 1.8.5 <code>super</code> with implicit arguments is only supported in methods (not in blocks or
|
561
|
+
<code>rescue</code>/<code>ensure</code> clauses). For Ruby 1.8.4 <code>super</code> with implicit arguments is
|
562
|
+
supported everywhere.</p>
|
563
|
+
|
564
|
+
|
565
|
+
<p>To work around this problem, just specify the arguments explicitly:</p>
|
566
|
+
|
567
|
+
|
568
|
+
<pre><code>def foo(a, b)
|
569
|
+
3.times { super(a, b) }
|
570
|
+
end
|
571
|
+
</code></pre>
|
572
|
+
|
573
|
+
<p>instead of:</p>
|
574
|
+
|
575
|
+
|
576
|
+
<pre><code>def foo(a, b)
|
577
|
+
3.times { super }
|
578
|
+
end
|
579
|
+
</code></pre>
|
580
|
+
</body>
|
581
|
+
</html>
|