rubybreaker 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +7 -0
- data/LICENSE +26 -0
- data/README.md +403 -0
- data/Rakefile +90 -0
- data/TODO +30 -0
- data/bin/gen_stub_rubylib +64 -0
- data/bin/rubybreaker +67 -0
- data/lib/rubybreaker/context.rb +122 -0
- data/lib/rubybreaker/debug.rb +48 -0
- data/lib/rubybreaker/error.rb +59 -0
- data/lib/rubybreaker/rubylib/core.rb +2316 -0
- data/lib/rubybreaker/rubylib.rb +3 -0
- data/lib/rubybreaker/runtime/inspector.rb +57 -0
- data/lib/rubybreaker/runtime/monitor.rb +235 -0
- data/lib/rubybreaker/runtime/object_wrapper.rb +77 -0
- data/lib/rubybreaker/runtime/overrides.rb +42 -0
- data/lib/rubybreaker/runtime/pluggable.rb +57 -0
- data/lib/rubybreaker/runtime/type_placeholder.rb +27 -0
- data/lib/rubybreaker/runtime/type_system.rb +228 -0
- data/lib/rubybreaker/runtime/typesig_parser.rb +45 -0
- data/lib/rubybreaker/runtime.rb +103 -0
- data/lib/rubybreaker/test/testcase.rb +39 -0
- data/lib/rubybreaker/test.rb +1 -0
- data/lib/rubybreaker/type/type.rb +241 -0
- data/lib/rubybreaker/type/type_comparer.rb +143 -0
- data/lib/rubybreaker/type/type_grammar.treetop +285 -0
- data/lib/rubybreaker/type/type_unparser.rb +142 -0
- data/lib/rubybreaker/type.rb +2 -0
- data/lib/rubybreaker/typing/rubytype.rb +47 -0
- data/lib/rubybreaker/typing/subtyping.rb +480 -0
- data/lib/rubybreaker/typing.rb +3 -0
- data/lib/rubybreaker/util.rb +31 -0
- data/lib/rubybreaker.rb +193 -0
- data/test/integrated/tc_method_missing.rb +30 -0
- data/test/integrated/tc_simple1.rb +77 -0
- data/test/runtime/tc_obj_wrapper.rb +73 -0
- data/test/runtime/tc_typesig_parser.rb +33 -0
- data/test/ts_integrated.rb +4 -0
- data/test/ts_runtime.rb +5 -0
- data/test/ts_type.rb +5 -0
- data/test/ts_typing.rb +4 -0
- data/test/type/tc_comparer.rb +211 -0
- data/test/type/tc_parser.rb +219 -0
- data/test/type/tc_unparser.rb +276 -0
- data/test/typing/tc_rubytype.rb +63 -0
- data/test/typing/tc_typing.rb +219 -0
- data/webpage/footer.html +5 -0
- data/webpage/generated_toc.js +319 -0
- data/webpage/header.html +14 -0
- data/webpage/images/logo.png +0 -0
- data/webpage/index.html +439 -0
- data/webpage/rubybreaker.css +53 -0
- metadata +119 -0
data/webpage/index.html
ADDED
@@ -0,0 +1,439 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>RubyBreaker</title>
|
4
|
+
<LINK REL=StyleSheet HREF="rubybreaker.css" TYPE="text/css">
|
5
|
+
<script type="text/javascript" src="generated_toc.js"> </script>
|
6
|
+
</head>
|
7
|
+
<body onLoad="createTOC()">
|
8
|
+
<center>
|
9
|
+
<div id="content">
|
10
|
+
<div id="logo">
|
11
|
+
<img src="images/logo.png" border="0">
|
12
|
+
</div>
|
13
|
+
<hr />
|
14
|
+
<div id="generated-toc"></div>
|
15
|
+
<hr />
|
16
|
+
|
17
|
+
<h1>Introduction</h1>
|
18
|
+
|
19
|
+
<p>RubyBreaker is a dynamic type documentation tool written purely in Ruby. It
|
20
|
+
provides the framework for dynamically instrumenting a Ruby program to
|
21
|
+
monitor objects during executions and document the observed type
|
22
|
+
information. The type documentation generated by RubyBreaker is also an
|
23
|
+
executable Ruby code. It contains type signatures that can be interpreted by
|
24
|
+
RubyBreaker Runtime Library and can be used in future documentation of the
|
25
|
+
program.</p>
|
26
|
+
|
27
|
+
<p>The primary goal of RubyBreaker is to assign a type signature to every
|
28
|
+
method in designated modules and classes. A type signature is written in
|
29
|
+
the RubyBreaker Type Annotation Language which resembles the documentation
|
30
|
+
style used in RubyDoc. Overall, this tool should help Ruby programmers
|
31
|
+
document their code more rigorously and effectively. Currently, manual
|
32
|
+
modification of the user program is required to run RubyBreaker, but this is
|
33
|
+
kept minimal.</p>
|
34
|
+
|
35
|
+
<h2>Limitations</h2>
|
36
|
+
|
37
|
+
<ul>
|
38
|
+
<li>It only works on toy Ruby programs so far :)</li>
|
39
|
+
<li>Block argument cannot be auto-documented. (Inherent)</li>
|
40
|
+
<li>Manual modification (minimal) of code is required.</li>
|
41
|
+
<li>No parametric polymorphic types are supported.</li>
|
42
|
+
</ul>
|
43
|
+
|
44
|
+
|
45
|
+
<h2>Requirements</h2>
|
46
|
+
|
47
|
+
<p>Ruby 1.9.x and TreeTop 1.x</p>
|
48
|
+
|
49
|
+
<p>If the most recent Ruby 1.9 is installed on the computer, it will probably
|
50
|
+
work. If TreeTop is not installed, use RubyGems or download from the
|
51
|
+
following URL: <a href="http://treetop.rubyforge.org/">TreeTop</a></p>
|
52
|
+
|
53
|
+
<h2>Installation</h2>
|
54
|
+
|
55
|
+
<p>It is as simple as running the following:</p>
|
56
|
+
|
57
|
+
<pre><code>$ gem install rubybreaker
|
58
|
+
</code></pre>
|
59
|
+
|
60
|
+
<p>You probably want to test out your installation by running
|
61
|
+
<code>rake test</code> in your RubyBreaker directory:</p>
|
62
|
+
|
63
|
+
<pre><code>$ rake test
|
64
|
+
</code></pre>
|
65
|
+
|
66
|
+
<hr />
|
67
|
+
|
68
|
+
<h1>Tutorial</h1>
|
69
|
+
|
70
|
+
<p>This tutorial will describe the basic usage of the tool, the RubyBreaker
|
71
|
+
Type Annotation Language, and the RubyBreaker Type System.</p>
|
72
|
+
|
73
|
+
<h2>Usage</h2>
|
74
|
+
|
75
|
+
<p>There are two ways to use RubyBreaker:</p>
|
76
|
+
|
77
|
+
<pre><code>$ rubybreaker prog.rb
|
78
|
+
</code></pre>
|
79
|
+
|
80
|
+
<p>Or, use it as a Ruby library and just run the program on Ruby.</p>
|
81
|
+
|
82
|
+
<pre><code>$ ruby prog.rb
|
83
|
+
</code></pre>
|
84
|
+
|
85
|
+
<p>Both methods require manual modification of the code, but the former will
|
86
|
+
generate the output into a separate <code>.rubybreaker</code> file whereas the latter
|
87
|
+
will display the output on the screen. The former will also automatically
|
88
|
+
import the <code>.rubybreaker</code> file for the user program of which the output is
|
89
|
+
appended at the end. Consequently, this output/input file will grow as more
|
90
|
+
analysis is done on the program.</p>
|
91
|
+
|
92
|
+
<p>For example, let us assume <code>prog.rb</code> as the following:</p>
|
93
|
+
|
94
|
+
<pre><code>require "rubybreaker"
|
95
|
+
class A
|
96
|
+
include RubyBreaker::Breakable
|
97
|
+
def foo(x)
|
98
|
+
x.to_s
|
99
|
+
end
|
100
|
+
end
|
101
|
+
class B
|
102
|
+
# include RubyBreaker::Breakable
|
103
|
+
def bar(y,z)
|
104
|
+
y.foo(z)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
RubyBreaker.monitor()
|
108
|
+
A.new.foo(1)
|
109
|
+
</code></pre>
|
110
|
+
|
111
|
+
<p>Do not worry about other parts of the code for now. This example is to show
|
112
|
+
how <code>foo</code> method is <em>typed</em> by RubyBreaker. After running <code>rubybreaker
|
113
|
+
prog.rb</code>, the following output will be generated and saved into
|
114
|
+
<code>prog.rubybreaker</code>.</p>
|
115
|
+
|
116
|
+
<pre><code>require "rubybreaker"
|
117
|
+
class A
|
118
|
+
include RubyBreaker::Broken
|
119
|
+
typesig("foo(fixnum[to_s]) -> string")
|
120
|
+
end
|
121
|
+
</code></pre>
|
122
|
+
|
123
|
+
<p>Now, assume that the last line of <code>prog.rb</code> is changed to
|
124
|
+
<code>B.new.bar(A.new,1)</code> and the <code>include</code> command in class <code>B</code> is uncommented.
|
125
|
+
The subsequent analysis will generate the following result:</p>
|
126
|
+
|
127
|
+
<pre><code># This is auto-generated by RubyBreaker
|
128
|
+
require "rubybreaker"
|
129
|
+
class A
|
130
|
+
include RubyBreaker::Broken
|
131
|
+
typesig("foo(fixnum[to_s]) -> string")
|
132
|
+
end
|
133
|
+
class B
|
134
|
+
include RubyBreaker::Broken
|
135
|
+
typesig("bar(a[foo], fixnum[to_s]) -> string")
|
136
|
+
end
|
137
|
+
</code></pre>
|
138
|
+
|
139
|
+
<p>RubyBreaker is designed to gather type information based on the actual
|
140
|
+
execution of a program. This means the program should be equipped with
|
141
|
+
test suites that cover a reasonable number of program paths for accurate
|
142
|
+
results. Additionally, RubyBreaker assumes that test runs are correct
|
143
|
+
and the program behaves correctly (for the test runs) as intended by
|
144
|
+
the programmer. This assumption is not a strong requirement, but is
|
145
|
+
necessary to obtain precise type information.</p>
|
146
|
+
|
147
|
+
<p>In order to use RubyBreaker, there needs two kinds of manual code changes.
|
148
|
+
First, the user must indicate which modules are subject to analysis and
|
149
|
+
which modules can be used for the analysis. Next, the user has to indicate
|
150
|
+
where the entry point of the program is. Alternatively, he has to make a
|
151
|
+
small change to the test cases to use RubyBreaker's testing framework.</p>
|
152
|
+
|
153
|
+
<h3>Breakable and Broken</h3>
|
154
|
+
|
155
|
+
<p>In order to indicate modules and classes that already have type information
|
156
|
+
or to designate those that need to be auto-documented, the user must be
|
157
|
+
familiar with the two most important modules of RubyBreaker--<code>Breakable</code> and
|
158
|
+
<code>Broken</code>. The former refers to a module (or a class) that needs dynamic
|
159
|
+
instrumentation and monitoring for getting type information. The latter
|
160
|
+
refers to a module that have type information already documented in type
|
161
|
+
signature form.</p>
|
162
|
+
|
163
|
+
<p>For example, consider the following Ruby code:</p>
|
164
|
+
|
165
|
+
<pre><code>require "rubybreaker"
|
166
|
+
class A
|
167
|
+
include RubyBreaker::Breakable
|
168
|
+
def foo(x)
|
169
|
+
x.to_s
|
170
|
+
end
|
171
|
+
end
|
172
|
+
</code></pre>
|
173
|
+
|
174
|
+
<p>By including <code>Breakable</code>, class <code>A</code> is subject to dynamic instrumentation
|
175
|
+
and monitoring. On the other hand, the following class is a <code>Broken</code> module.
|
176
|
+
(Yes, like a crazy wild horse that has been <em>broken</em>!)</p>
|
177
|
+
|
178
|
+
<pre><code>require "rubybreaker"
|
179
|
+
class B
|
180
|
+
include RubyBreaker::Broken
|
181
|
+
typesig("bar(fixnum[to_s]) -> string")
|
182
|
+
def foo(x)
|
183
|
+
x.to_s
|
184
|
+
end
|
185
|
+
end
|
186
|
+
</code></pre>
|
187
|
+
|
188
|
+
<p>This tells RubyBreaker that class <code>B</code> has type information in place, and
|
189
|
+
therefore, it will use the information for analyzing <code>Breakable</code> modules
|
190
|
+
elsewhere (if applicable). In this example, a method <code>foo</code> has a type
|
191
|
+
signature <code>bar(fixnum[to_s]) -> string</code>, which means it takes an object that
|
192
|
+
has <code>Fixnum</code>'s <code>to_s</code> method and returns a string. More detail on the type
|
193
|
+
annotation language will be explained in later section.</p>
|
194
|
+
|
195
|
+
<p>Currently, both <code>Breakable</code> and <code>Broken</code> only support instance methods.
|
196
|
+
Furthermore, class and module methods can neither be monitored nor used for
|
197
|
+
analysis. It is important to keep in mind that <code>Broken</code> module always wins.
|
198
|
+
In other words, if a module is declared as both <code>Broken</code> and <code>Breakable</code>, it
|
199
|
+
is treated as <code>Broken</code>.</p>
|
200
|
+
|
201
|
+
<h3>Program Entry Point</h3>
|
202
|
+
|
203
|
+
<p>In Ruby, as soon as a file is <code>require</code>d, the execution of that file begins.
|
204
|
+
For RubyBreaker, however, it is not trivial to find the actual starting
|
205
|
+
point of the program because there <em>has</em> to be a clear point in time at
|
206
|
+
which monitoring of <code>Breakable</code> modules begins. <em>This is necessary as
|
207
|
+
attempting to instrument and monitor at the same time will cause an infinite
|
208
|
+
loop!</em></p>
|
209
|
+
|
210
|
+
<p>Indicating the program entry point is simply done by inserting the following
|
211
|
+
line at the code (assuming "<code>require 'rubybreaker'</code>" is already placed at
|
212
|
+
the top of the file):</p>
|
213
|
+
|
214
|
+
<pre><code>RubyBreaker.monitor()
|
215
|
+
</code></pre>
|
216
|
+
|
217
|
+
<p>It basically tells RubyBreaker to start monitoring. What really happens at
|
218
|
+
this point is that all <code>Breakable</code> modules are dynamically instrumented so
|
219
|
+
that they are ready to be monitored. Any execution after this point will
|
220
|
+
run the instrumented code (for <code>Breakable</code> modules) which will gather type
|
221
|
+
information for methods.</p>
|
222
|
+
|
223
|
+
<p>Although this seems simple and easy, this is not the recommended way for
|
224
|
+
analyzing a program. Why? Because RubyBreaker has a built-in testing
|
225
|
+
framework that (supposedly :)) works seemlessly with the existing tests of
|
226
|
+
the program.</p>
|
227
|
+
|
228
|
+
<h3>Using RubyBreaker Testing Framework</h3>
|
229
|
+
|
230
|
+
<p>Instead of manually inserting the entry point indicator into the program,
|
231
|
+
the user can take advantage of the Ruby Unit Test framework. This is the
|
232
|
+
recommended way of using RubyBreaker, especially for a long term program
|
233
|
+
maintainability. But no worries! This method is as simple as the previous
|
234
|
+
one.</p>
|
235
|
+
|
236
|
+
<pre><code>require "rubybreaker"
|
237
|
+
require "test/unit"
|
238
|
+
class TestClassA < Test::Unit::TestCase
|
239
|
+
include RubyBreaker::TestCase
|
240
|
+
# ...tests!...
|
241
|
+
end
|
242
|
+
</code></pre>
|
243
|
+
|
244
|
+
<p>That's it!</p>
|
245
|
+
|
246
|
+
<p>Currently, RubyBreaker only supports the standard unit test framework.
|
247
|
+
Other testing frameworks such as RSpec and Cucumber are not supported at the
|
248
|
+
moment (but will be in future/hopefully).</p>
|
249
|
+
|
250
|
+
<h2>Type Annotation</h2>
|
251
|
+
|
252
|
+
<p>The annotation language used in RubyBreaker resembles the method
|
253
|
+
documentation used by Ruby Standard Library Doc. Each type signature
|
254
|
+
defines a method type using the name, argument types, block type, and return
|
255
|
+
type. But, let us consider a simple case where there is one argument type
|
256
|
+
and a return type.</p>
|
257
|
+
|
258
|
+
<pre><code>class A
|
259
|
+
...
|
260
|
+
typesig("foo(fixnum) -> string")
|
261
|
+
end
|
262
|
+
</code></pre>
|
263
|
+
|
264
|
+
<p>In RubyBreaker, a type signature is recognized by the meta-class level
|
265
|
+
method <code>typesig</code> which takes a string as an argument. This string is the
|
266
|
+
actual type signature written in the Ruby Type Annotation Language. This
|
267
|
+
language is designed to reflect the common documentation practice used by
|
268
|
+
RubyDoc. It starts with the name of the method. In the above example, <code>foo</code>
|
269
|
+
is currently being given a type. The rest of the signature takes a typical
|
270
|
+
method type symbol, <code>(x) -> y</code> where <code>x</code> is the argument type and <code>y</code> is the
|
271
|
+
return type. In the example shown above, the method takes a <code>Fixnum</code> object
|
272
|
+
and returns a <code>String</code> object. Note that these types are in lowercase,
|
273
|
+
indicating they are objects and not modules or classes themselves.</p>
|
274
|
+
|
275
|
+
<p>There are several types that represent an object: nominal, duck, fusion,
|
276
|
+
nil, 'any', and block. Each type signature itself represents a method type
|
277
|
+
or a method list type (explained below).</p>
|
278
|
+
|
279
|
+
<h3>Nominal Type</h3>
|
280
|
+
|
281
|
+
<p>This is the simplest and most intuitive way to represent an object. For
|
282
|
+
instance, <code>fixnum</code> is an object of type <code>Fixnum</code>. Use lower-case letters and
|
283
|
+
underscores instead of <em>camelized</em> name. <code>MyClass</code>, for example would be
|
284
|
+
<code>my_class</code> in RubyBreaker type signatures. There is no particular
|
285
|
+
reason for this convention other than it is the common practice used in
|
286
|
+
RubyDoc.</p>
|
287
|
+
|
288
|
+
<h3>Self Type</h3>
|
289
|
+
|
290
|
+
<p>This type is similar to the nominal type but is referring to the current
|
291
|
+
object--that is, the receiver of the method being typed. RubyBreaker will
|
292
|
+
auto-document the return type as a self type if the return value is the same
|
293
|
+
as the receiver of that call. It is also recommended to use this type over
|
294
|
+
a nominal type (if the return value is <code>self</code>) since it depicts more
|
295
|
+
precise return type.</p>
|
296
|
+
|
297
|
+
<h3>Duck Type</h3>
|
298
|
+
|
299
|
+
<p>This type is inspired by the Ruby Language's duck typing, <em>"if it
|
300
|
+
walks like a duck and quacks like a duck, it must be a duck."</em> Using this
|
301
|
+
type, an object can be represented simply by a list of method names. For
|
302
|
+
example <code>[walks, quacks]</code> is an object that has <code>walks</code> and <code>quacks</code>
|
303
|
+
methods. Note that these method names do <em>not</em> reveal any type
|
304
|
+
information for themselves.</p>
|
305
|
+
|
306
|
+
<h3>Fusion Type</h3>
|
307
|
+
|
308
|
+
<p>Duck type is very flexible but can be too lenient when trying to restrict
|
309
|
+
the type of an object. RubyBreaker provides a type called <em>the fusion type</em>
|
310
|
+
which lists method names but with respect to a nominal type. For
|
311
|
+
example, <code>fixnum[to_f, to_s]</code> represents an object that has methods <code>to_f</code>
|
312
|
+
and <code>to_s</code> whose types are same as those of <code>Fixnum</code>. This is more
|
313
|
+
restrictive (precise) than <code>[to_f, to_s]</code> because the two methods must have
|
314
|
+
the same types as <code>to_f</code> and <code>to_s</code> methods, respectively, in <code>Fixnum</code>.</p>
|
315
|
+
|
316
|
+
<h3>Nil Type</h3>
|
317
|
+
|
318
|
+
<p>A nil type represents a value of nil and is denoted by <code>nil</code>.</p>
|
319
|
+
|
320
|
+
<h3>Any Type</h3>
|
321
|
+
|
322
|
+
<p>RubyBreaker also provides a way to represent an object that is compatible with
|
323
|
+
any type. This type is denoted by <code>?</code>. Use caution with this type because
|
324
|
+
it should be only used for an object that requires an arbitrary yet most
|
325
|
+
specific type--that is, <code>?</code> is a subtype of any other type, but any
|
326
|
+
other type is not a subtype of <code>?</code>. This becomes a bit complicated for
|
327
|
+
method or block argument types because of their contra-variance
|
328
|
+
characteristic. Please kefer to the section <em>Subtyping</em>.</p>
|
329
|
+
|
330
|
+
<h3>Block Type</h3>
|
331
|
+
|
332
|
+
<p>One of the Ruby's prominent features is the block argument. It allows
|
333
|
+
the caller to pass in a piece of code to be executed inside the callee. This
|
334
|
+
code block can be executed by the Ruby construct, <code>yield</code>, or by directly
|
335
|
+
calling the <code>call</code> method of the block object. In RubyBreaker, this type can
|
336
|
+
be respresented by curly brackets. For instance, <code>{|fixnum,string| ->
|
337
|
+
string}</code> represents a block that takes two arguments--one <code>Fixnum</code> and one
|
338
|
+
<code>String</code>--and returns a <code>String</code>.</p>
|
339
|
+
|
340
|
+
<p>RubyBreaker does supports nested blocks as Ruby 1.9 finally allows them.
|
341
|
+
However, <em>keep in mind</em> that RubyBreaker <em>cannot</em> automatically document the
|
342
|
+
block types due to <code>yield</code> being a language construct rather than a method,
|
343
|
+
which means it cannot be captured by meta-programming!</p>
|
344
|
+
|
345
|
+
<h3>Optional Argument Type and Variable-Length Argument Type</h3>
|
346
|
+
|
347
|
+
<p>Another useful features of Ruby are the optional argument type and the
|
348
|
+
variable-length argument type. The former represents an argument that has a
|
349
|
+
default value (and therefore does not have to be provided). The latter
|
350
|
+
represents zero or more arguments of the same type. These are denoted by
|
351
|
+
suffices, <code>?</code> and <code>*</code>, respectively.</p>
|
352
|
+
|
353
|
+
<h3>Method Type and Method List Types</h3>
|
354
|
+
|
355
|
+
<p>Method type is similar to the block type, but it represents an actual method
|
356
|
+
and not a block object. It is the "root" type that the type annotation
|
357
|
+
language supports, along with method list types. Method <em>list</em> type is a
|
358
|
+
collection of method types to represent more than one type information for
|
359
|
+
the given method. Why would this type be needed? Consider the following Ruby
|
360
|
+
code:</p>
|
361
|
+
|
362
|
+
<pre><code>def foo(x)
|
363
|
+
case x
|
364
|
+
when Fixnum
|
365
|
+
1
|
366
|
+
when String
|
367
|
+
"1"
|
368
|
+
end
|
369
|
+
end
|
370
|
+
</code></pre>
|
371
|
+
|
372
|
+
<p>There is no way to document the type of <code>foo</code> without using a method list
|
373
|
+
type. Let's try to give a method type to <code>foo</code> without a method list. The
|
374
|
+
closest we can come up with would be <code>foo(fixnum or string) -> fixnum and
|
375
|
+
string</code>. But RubyBreaker does not have the "and" type in the type annotation
|
376
|
+
language because it gives me an headache! (By the way, it needs to be an
|
377
|
+
"and" type because the caller must handle both <code>Fixnum</code> and <code>String</code> return
|
378
|
+
values.)</p>
|
379
|
+
|
380
|
+
<p>It is a dilemma because Ruby programmers actually enjoy using this kind of
|
381
|
+
dynamic type checks in their code. To alleviate this headache, RubyBreaker
|
382
|
+
supports the method list type to represent different scenarios depending on
|
383
|
+
the argument types. Thus, the <code>foo</code> method shown above can be given the
|
384
|
+
following method list type:</p>
|
385
|
+
|
386
|
+
<pre><code>typesig("foo(fixnum) -> fixnum")
|
387
|
+
typesig("foo(string) -> string")
|
388
|
+
</code></pre>
|
389
|
+
|
390
|
+
<p>These two type signatures simply tell RubyBreaker that <code>foo</code> has two method
|
391
|
+
types--one for a <code>Fixnum</code> argument and another for a <code>String</code> argument.
|
392
|
+
Depending on the argument type, the return type is determined. In this
|
393
|
+
example, a <code>Fixnum</code> is returned when the argument is also a <code>Fixnum</code> and a
|
394
|
+
<code>String</code> is returned when the argument is also a <code>String</code>. When
|
395
|
+
automatically documenting such a type, RubyBreaker looks for the (subtyping)
|
396
|
+
compatibility between the return types and "promote" the method type to a
|
397
|
+
method list type by spliting the type signature into two (or more in
|
398
|
+
subsequent "promotions").</p>
|
399
|
+
|
400
|
+
<h2>Type System</h2>
|
401
|
+
|
402
|
+
<p>RubyBreaker comes with its own type system that is used to document type
|
403
|
+
information. This section describes how RubyBreaker determines which type(s)
|
404
|
+
to document. <em>More documentation coming soon...</em></p>
|
405
|
+
|
406
|
+
<h3>Subtyping</h3>
|
407
|
+
|
408
|
+
<p><em>Documentation coming soon...</em></p>
|
409
|
+
|
410
|
+
<h3>Subtyping vs. Subclassing</h3>
|
411
|
+
|
412
|
+
<p><em>Documentation coming soon...</em></p>
|
413
|
+
|
414
|
+
<h3>Pluggable Type System (Advanced)</h3>
|
415
|
+
|
416
|
+
<p>Yes, RubyBreaker was designed with the replaceable type system in mind. In
|
417
|
+
other words, anyone can write his own type system and plug it into
|
418
|
+
RubyBreaker.</p>
|
419
|
+
|
420
|
+
<p><em>Documentation coming soon...</em></p>
|
421
|
+
|
422
|
+
<hr />
|
423
|
+
|
424
|
+
<h1>Acknowledgment</h1>
|
425
|
+
|
426
|
+
<p>The term, "Fusion Type," is first coined by Professor Michael W. Hicks at
|
427
|
+
University of Maryland and represents an object using a structural type with
|
428
|
+
respect to a nominal type.</p>
|
429
|
+
|
430
|
+
<hr />
|
431
|
+
|
432
|
+
<h1>Copyright</h1>
|
433
|
+
|
434
|
+
<p>Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved.</p>
|
435
|
+
|
436
|
+
</div>
|
437
|
+
</center>
|
438
|
+
</body>
|
439
|
+
</html>
|
@@ -0,0 +1,53 @@
|
|
1
|
+
body {
|
2
|
+
background-color: #aa0000;
|
3
|
+
/* font-family: Verdana, Arial, "sans-serif"; */
|
4
|
+
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
|
5
|
+
width: 100%;
|
6
|
+
text-align: center;
|
7
|
+
padding:0px;
|
8
|
+
margin: 0px;
|
9
|
+
font-size:0.9em;
|
10
|
+
line-height:150%;
|
11
|
+
color: #2f2f2f;
|
12
|
+
}
|
13
|
+
|
14
|
+
/* Gradient transparent - color - transparent */
|
15
|
+
hr {
|
16
|
+
border: 0;
|
17
|
+
height: 2px;
|
18
|
+
background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
|
19
|
+
background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
|
20
|
+
background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
|
21
|
+
background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
|
22
|
+
margin: 40px 0px 40px 0px;
|
23
|
+
}
|
24
|
+
|
25
|
+
h1,
|
26
|
+
h2,
|
27
|
+
h3,
|
28
|
+
h4 {
|
29
|
+
margin: 40px 0px 20px 0px;
|
30
|
+
color: #990000;
|
31
|
+
}
|
32
|
+
|
33
|
+
code {
|
34
|
+
/* color: #5c5c5c; */
|
35
|
+
font-family: "Lucida Console", "Courier New", Monospace;
|
36
|
+
font-weight: bold;
|
37
|
+
}
|
38
|
+
|
39
|
+
div#content {
|
40
|
+
background-color: white;
|
41
|
+
width: 660px;
|
42
|
+
text-align: left;
|
43
|
+
padding: 20px 80px 40px 80px;
|
44
|
+
margin: 0px;
|
45
|
+
-moz-box-shadow: 0 0 30px 5px #333;
|
46
|
+
-webkit-box-shadow: 0 0 30px 5px #333;
|
47
|
+
}
|
48
|
+
|
49
|
+
div#logo {
|
50
|
+
padding-bottom: 20px;
|
51
|
+
text-align:center;
|
52
|
+
}
|
53
|
+
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubybreaker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jong-hoon (David) An
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: treetop
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: RubyBreaker is a dynamic type documentation tool for Ruby.
|
31
|
+
email: rubybreaker@gmail.com
|
32
|
+
executables:
|
33
|
+
- rubybreaker
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/rubybreaker/context.rb
|
38
|
+
- lib/rubybreaker/debug.rb
|
39
|
+
- lib/rubybreaker/error.rb
|
40
|
+
- lib/rubybreaker/rubylib/core.rb
|
41
|
+
- lib/rubybreaker/rubylib.rb
|
42
|
+
- lib/rubybreaker/runtime/inspector.rb
|
43
|
+
- lib/rubybreaker/runtime/monitor.rb
|
44
|
+
- lib/rubybreaker/runtime/object_wrapper.rb
|
45
|
+
- lib/rubybreaker/runtime/overrides.rb
|
46
|
+
- lib/rubybreaker/runtime/pluggable.rb
|
47
|
+
- lib/rubybreaker/runtime/type_placeholder.rb
|
48
|
+
- lib/rubybreaker/runtime/type_system.rb
|
49
|
+
- lib/rubybreaker/runtime/typesig_parser.rb
|
50
|
+
- lib/rubybreaker/runtime.rb
|
51
|
+
- lib/rubybreaker/test/testcase.rb
|
52
|
+
- lib/rubybreaker/test.rb
|
53
|
+
- lib/rubybreaker/type/type.rb
|
54
|
+
- lib/rubybreaker/type/type_comparer.rb
|
55
|
+
- lib/rubybreaker/type/type_grammar.treetop
|
56
|
+
- lib/rubybreaker/type/type_unparser.rb
|
57
|
+
- lib/rubybreaker/type.rb
|
58
|
+
- lib/rubybreaker/typing/rubytype.rb
|
59
|
+
- lib/rubybreaker/typing/subtyping.rb
|
60
|
+
- lib/rubybreaker/typing.rb
|
61
|
+
- lib/rubybreaker/util.rb
|
62
|
+
- lib/rubybreaker.rb
|
63
|
+
- bin/gen_stub_rubylib
|
64
|
+
- bin/rubybreaker
|
65
|
+
- AUTHORS
|
66
|
+
- LICENSE
|
67
|
+
- Rakefile
|
68
|
+
- README.md
|
69
|
+
- TODO
|
70
|
+
- test/integrated/tc_method_missing.rb
|
71
|
+
- test/integrated/tc_simple1.rb
|
72
|
+
- test/runtime/tc_obj_wrapper.rb
|
73
|
+
- test/runtime/tc_typesig_parser.rb
|
74
|
+
- test/ts_integrated.rb
|
75
|
+
- test/ts_runtime.rb
|
76
|
+
- test/ts_type.rb
|
77
|
+
- test/ts_typing.rb
|
78
|
+
- test/type/tc_comparer.rb
|
79
|
+
- test/type/tc_parser.rb
|
80
|
+
- test/type/tc_unparser.rb
|
81
|
+
- test/typing/tc_rubytype.rb
|
82
|
+
- test/typing/tc_typing.rb
|
83
|
+
- webpage/footer.html
|
84
|
+
- webpage/generated_toc.js
|
85
|
+
- webpage/header.html
|
86
|
+
- webpage/images/logo.png
|
87
|
+
- webpage/index.html
|
88
|
+
- webpage/rubybreaker.css
|
89
|
+
homepage:
|
90
|
+
licenses:
|
91
|
+
- BSD
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options:
|
94
|
+
- -x
|
95
|
+
- lib/rubybreaker/rubylib/*.rb
|
96
|
+
- -x
|
97
|
+
- lib/rubybreaker/type/type_grammar.rb
|
98
|
+
- lib
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 1.8.23
|
116
|
+
signing_key:
|
117
|
+
specification_version: 3
|
118
|
+
summary: Break Ruby types
|
119
|
+
test_files: []
|