rubybreaker 0.0.1 → 0.0.2
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/NEWS +48 -0
- data/README.md +56 -20
- data/Rakefile +9 -34
- data/TODO +10 -10
- data/VERSION +1 -0
- data/bin/gen_stub_rubylib +35 -36
- data/bin/rubybreaker +1 -4
- data/lib/rubybreaker/debug.rb +8 -4
- data/lib/rubybreaker/rubylib/core.rb +738 -571
- data/lib/rubybreaker/runtime/inspector.rb +16 -7
- data/lib/rubybreaker/runtime/monitor.rb +14 -18
- data/lib/rubybreaker/runtime/object_wrapper.rb +9 -3
- data/lib/rubybreaker/runtime/overrides.rb +51 -8
- data/lib/rubybreaker/runtime/pluggable.rb +1 -3
- data/lib/rubybreaker/runtime/type_placeholder.rb +2 -6
- data/lib/rubybreaker/runtime/type_system.rb +53 -17
- data/lib/rubybreaker/runtime/typesig_parser.rb +1 -0
- data/lib/rubybreaker/runtime/util.rb +18 -0
- data/lib/rubybreaker/runtime.rb +42 -15
- data/lib/rubybreaker/type/type_comparer.rb +10 -10
- data/lib/rubybreaker/type/type_grammar.treetop +30 -21
- data/lib/rubybreaker/type/type_unparser.rb +2 -2
- data/lib/rubybreaker/typing/subtyping.rb +21 -21
- data/lib/rubybreaker/util.rb +11 -1
- data/lib/rubybreaker.rb +75 -54
- data/test/integrated/tc_class_methods.rb +35 -0
- data/test/integrated/tc_inherit_broken.rb +29 -0
- data/test/integrated/tc_method_missing.rb +1 -1
- data/test/runtime/tc_obj_wrapper.rb +104 -4
- data/test/ts_integrated.rb +2 -0
- data/test/type/tc_comparer.rb +96 -96
- data/test/type/tc_parser.rb +18 -0
- data/test/type/tc_unparser.rb +16 -0
- data/test/typing/tc_typing.rb +20 -20
- data/webpage/footer.html +1 -1
- data/webpage/header.html +7 -7
- data/webpage/index.html +65 -28
- data/webpage/rdoc/RubyBreaker/Breakable.html +280 -0
- data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +304 -0
- data/webpage/rdoc/RubyBreaker/Broken.html +308 -0
- data/webpage/rdoc/RubyBreaker/Context.html +421 -0
- data/webpage/rdoc/RubyBreaker/Debug.html +411 -0
- data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +263 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +263 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +214 -0
- data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +212 -0
- data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +212 -0
- data/webpage/rdoc/RubyBreaker/Errors/UserError.html +264 -0
- data/webpage/rdoc/RubyBreaker/Errors.html +209 -0
- data/webpage/rdoc/RubyBreaker/Kernel.html +259 -0
- data/webpage/rdoc/RubyBreaker/Main.html +560 -0
- data/webpage/rdoc/RubyBreaker/ObjectPosition.html +334 -0
- data/webpage/rdoc/RubyBreaker/Position.html +463 -0
- data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +308 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +380 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +324 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +354 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +379 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +382 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +400 -0
- data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +411 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +305 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypePlaceholder.html +280 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +283 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +630 -0
- data/webpage/rdoc/RubyBreaker/Runtime.html +255 -0
- data/webpage/rdoc/RubyBreaker/TestCase.html +332 -0
- data/webpage/rdoc/RubyBreaker/TypeComparer.html +304 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +260 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +310 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +320 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +323 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +260 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +329 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +409 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs.html +212 -0
- data/webpage/rdoc/RubyBreaker/TypeUnparser.html +273 -0
- data/webpage/rdoc/RubyBreaker/Typing.html +305 -0
- data/webpage/rdoc/RubyBreaker/Utilities.html +294 -0
- data/webpage/rdoc/RubyBreaker.html +337 -0
- data/webpage/rdoc/created.rid +26 -0
- data/webpage/rdoc/images/add.png +0 -0
- data/webpage/rdoc/images/brick.png +0 -0
- data/webpage/rdoc/images/brick_link.png +0 -0
- data/webpage/rdoc/images/bug.png +0 -0
- data/webpage/rdoc/images/bullet_black.png +0 -0
- data/webpage/rdoc/images/bullet_toggle_minus.png +0 -0
- data/webpage/rdoc/images/bullet_toggle_plus.png +0 -0
- data/webpage/rdoc/images/date.png +0 -0
- data/webpage/rdoc/images/delete.png +0 -0
- data/webpage/rdoc/images/find.png +0 -0
- data/webpage/rdoc/images/loadingAnimation.gif +0 -0
- data/webpage/rdoc/images/macFFBgHack.png +0 -0
- data/webpage/rdoc/images/package.png +0 -0
- data/webpage/rdoc/images/page_green.png +0 -0
- data/webpage/rdoc/images/page_white_text.png +0 -0
- data/webpage/rdoc/images/page_white_width.png +0 -0
- data/webpage/rdoc/images/plugin.png +0 -0
- data/webpage/rdoc/images/ruby.png +0 -0
- data/webpage/rdoc/images/tag_blue.png +0 -0
- data/webpage/rdoc/images/tag_green.png +0 -0
- data/webpage/rdoc/images/transparent.png +0 -0
- data/webpage/rdoc/images/wrench.png +0 -0
- data/webpage/rdoc/images/wrench_orange.png +0 -0
- data/webpage/rdoc/images/zoom.png +0 -0
- data/webpage/rdoc/index.html +165 -0
- data/webpage/rdoc/js/darkfish.js +153 -0
- data/webpage/rdoc/js/jquery.js +18 -0
- data/webpage/rdoc/js/navigation.js +142 -0
- data/webpage/rdoc/js/search.js +94 -0
- data/webpage/rdoc/js/search_index.js +1 -0
- data/webpage/rdoc/js/searcher.js +228 -0
- data/webpage/rdoc/rdoc.css +543 -0
- data/webpage/rdoc/table_of_contents.html +376 -0
- data/webpage/rubybreaker.css +31 -31
- metadata +93 -6
data/test/type/tc_comparer.rb
CHANGED
|
@@ -63,13 +63,13 @@ class ComparerTest < Test::Unit::TestCase
|
|
|
63
63
|
assert(!t7.eql?(t11), msg(t7, t11, true))
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
def test_self
|
|
67
|
+
t1 = SelfType.new()
|
|
68
|
+
t2 = SelfType.new()
|
|
69
|
+
t3 = NominalType.new(Fixnum)
|
|
70
|
+
assert(t1.eql?(t2), msg(t1, t2))
|
|
71
|
+
assert(!t1.eql?(t3), msg(t1, t3, true))
|
|
72
|
+
end
|
|
73
73
|
|
|
74
74
|
def test_duck
|
|
75
75
|
t1 = DuckType.new([:foo, :bar])
|
|
@@ -84,45 +84,45 @@ class ComparerTest < Test::Unit::TestCase
|
|
|
84
84
|
def test_fusion
|
|
85
85
|
t1 = FusionType.new(NominalType.new(Fixnum), [:to_s, :to_f])
|
|
86
86
|
t2 = FusionType.new(NominalType.new(Fixnum), [:to_f, :to_s])
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
t3 = FusionType.new(NominalType.new(String), [:to_s, :to_f])
|
|
88
|
+
t4 = DuckType.new([:to_s, :to_f])
|
|
89
|
+
t5 = NominalType.new(Fixnum)
|
|
90
|
+
assert(t1.eql?(t2), msg(t1, t2))
|
|
91
|
+
assert(!t1.eql?(t3), msg(t1, t3, true))
|
|
92
|
+
assert(!t1.eql?(t4), msg(t1, t4, true))
|
|
93
|
+
assert(!t1.eql?(t5), msg(t1, t5, true))
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
def test_block_no_arg
|
|
97
|
+
t1 = NominalType.new(String)
|
|
98
|
+
t2 = NominalType.new(String)
|
|
99
|
+
t3 = NominalType.new(Fixnum)
|
|
100
|
+
t4 = BlockType.new([],nil,t1)
|
|
101
|
+
t5 = BlockType.new([],nil,t2)
|
|
102
|
+
t6 = BlockType.new([],nil,t3)
|
|
103
|
+
assert(t4.eql?(t5), msg(t4, t5))
|
|
104
|
+
assert(!t4.eql?(t6), msg(t4, t6, true))
|
|
105
|
+
end
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
107
|
+
def test_block_one_arg
|
|
108
|
+
t1 = NominalType.new(String)
|
|
109
|
+
t2 = NominalType.new(String)
|
|
110
|
+
t3 = NominalType.new(Fixnum)
|
|
111
|
+
t4 = BlockType.new([t1],nil,t3)
|
|
112
|
+
t5 = BlockType.new([t2],nil,t3)
|
|
113
|
+
t6 = BlockType.new([],nil,t3)
|
|
114
|
+
assert(t4.eql?(t5), msg(t4, t5))
|
|
115
|
+
assert(!t4.eql?(t6), msg(t4, t6, true))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_block_more_args
|
|
119
|
+
t1 = NominalType.new(String)
|
|
120
|
+
t2 = NominalType.new(String)
|
|
121
|
+
t3 = NominalType.new(Fixnum)
|
|
122
|
+
t4 = OptionalType.new(NominalType.new(Object))
|
|
123
|
+
t5 = VarLengthType.new(NominalType.new(String))
|
|
124
|
+
t6 = NominalType.new(BasicObject)
|
|
125
|
+
t7 = BlockType.new([t1,t4,t5],nil,t3)
|
|
126
126
|
t8 = BlockType.new([t2,t4,t5],nil,t3)
|
|
127
127
|
t9 = BlockType.new([t1,t5,t4],nil,t3)
|
|
128
128
|
t10 = BlockType.new([t1,t4],nil,t3)
|
|
@@ -133,56 +133,56 @@ class ComparerTest < Test::Unit::TestCase
|
|
|
133
133
|
assert(!t7.eql?(t10), msg(t7, t10, true))
|
|
134
134
|
assert(!t7.eql?(t11), msg(t7, t11, true))
|
|
135
135
|
assert(!t7.eql?(t12), msg(t7, t12, true))
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_method_no_arg
|
|
139
|
+
t1 = NominalType.new(String)
|
|
140
|
+
t2 = NominalType.new(String)
|
|
141
|
+
t3 = NominalType.new(Fixnum)
|
|
142
|
+
t4 = MethodType.new(:foo,[],nil,t1)
|
|
143
|
+
t5 = MethodType.new(:foo,[],nil,t2)
|
|
144
|
+
t6 = MethodType.new(:bar,[],nil,t2)
|
|
145
|
+
t7 = MethodType.new(:foo,[],nil,t3)
|
|
146
|
+
assert(t4.eql?(t5), msg(t4, t5))
|
|
147
|
+
assert(!t4.eql?(t6), msg(t4, t6, true))
|
|
148
|
+
assert(!t4.eql?(t7), msg(t4, t7, true))
|
|
149
|
+
end
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
151
|
+
def test_method_one_arg
|
|
152
|
+
t1 = NominalType.new(String)
|
|
153
|
+
t2 = NominalType.new(String)
|
|
154
|
+
t3 = NominalType.new(Fixnum)
|
|
155
|
+
t4 = MethodType.new(:foo, [t1],nil,t3)
|
|
156
|
+
t5 = MethodType.new(:foo, [t2],nil,t3)
|
|
157
|
+
t6 = MethodType.new(:foo, [],nil,t3)
|
|
158
|
+
assert(t4.eql?(t5), msg(t4, t5))
|
|
159
|
+
assert(!t4.eql?(t6), msg(t4, t6, true))
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_method_one_arg_with_blk
|
|
163
|
+
t1 = NominalType.new(String)
|
|
164
|
+
t2 = NominalType.new(String)
|
|
165
|
+
t3 = NominalType.new(Fixnum)
|
|
166
|
+
t4 = BlockType.new([t1],nil,t3)
|
|
167
|
+
t5 = BlockType.new([t2],nil,t3)
|
|
168
|
+
t6 = BlockType.new([],nil,t3)
|
|
169
169
|
t7 = MethodType.new(:foo, [t1], t4, t3)
|
|
170
170
|
t8 = MethodType.new(:foo, [t2], t5, t3)
|
|
171
171
|
t9 = MethodType.new(:bar, [t1], t4, t3)
|
|
172
172
|
t10 = MethodType.new(:foo, [t1], t6, t3)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
173
|
+
assert(t7.eql?(t8), msg(t7, t8))
|
|
174
|
+
assert(!t7.eql?(t9), msg(t7, t9, true))
|
|
175
|
+
assert(!t7.eql?(t10), msg(t7, t10, true))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def test_method_more_args
|
|
179
|
+
t1 = NominalType.new(String)
|
|
180
|
+
t2 = NominalType.new(String)
|
|
181
|
+
t3 = NominalType.new(Fixnum)
|
|
182
|
+
t4 = OptionalType.new(NominalType.new(Object))
|
|
183
|
+
t5 = VarLengthType.new(NominalType.new(String))
|
|
184
|
+
t6 = NominalType.new(BasicObject)
|
|
185
|
+
t7 = MethodType.new(:foo, [t1,t4,t5],nil,t3)
|
|
186
186
|
t8 = MethodType.new(:foo, [t2,t4,t5],nil,t3)
|
|
187
187
|
t9 = MethodType.new(:foo, [t1,t5,t4],nil,t3)
|
|
188
188
|
t10 = MethodType.new(:foo, [t1,t4],nil,t3)
|
|
@@ -193,16 +193,16 @@ class ComparerTest < Test::Unit::TestCase
|
|
|
193
193
|
assert(!t7.eql?(t10), msg(t7, t10, true))
|
|
194
194
|
assert(!t7.eql?(t11), msg(t7, t11, true))
|
|
195
195
|
assert(!t7.eql?(t12), msg(t7, t12, true))
|
|
196
|
-
|
|
196
|
+
end
|
|
197
197
|
|
|
198
198
|
def test_method_lists
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
199
|
+
t1 = NominalType.new(String)
|
|
200
|
+
t2 = NominalType.new(String)
|
|
201
|
+
t3 = NominalType.new(Fixnum)
|
|
202
|
+
t4 = MethodType.new(:foo,[],nil,t1)
|
|
203
|
+
t5 = MethodType.new(:foo,[],nil,t2)
|
|
204
|
+
t6 = MethodType.new(:bar,[],nil,t2)
|
|
205
|
+
t7 = MethodType.new(:foo,[],nil,t3)
|
|
206
206
|
t8 = MethodListType.new([t4,t6])
|
|
207
207
|
t9 = MethodListType.new([t5,t7])
|
|
208
208
|
assert(!t8.eql?(t9), msg(t8, t9, true))
|
data/test/type/tc_parser.rb
CHANGED
|
@@ -211,6 +211,24 @@ class GrammarTest < Test::Unit::TestCase
|
|
|
211
211
|
assert_equal("foo() -> nil", str)
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
+
def test_multi_line_1
|
|
215
|
+
type = @parser.parse("foo(fixnum[to_s,to_i]) ->
|
|
216
|
+
fixnum").value
|
|
217
|
+
str = TypeUnparser.unparse(type)
|
|
218
|
+
#puts str
|
|
219
|
+
assert_equal("foo(fixnum[to_i, to_s]) -> fixnum",str)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def test_multi_line_2
|
|
223
|
+
type = @parser.parse("foo(fixnum[to_s,
|
|
224
|
+
to_i])
|
|
225
|
+
->
|
|
226
|
+
fixnum").value
|
|
227
|
+
str = TypeUnparser.unparse(type)
|
|
228
|
+
#puts str
|
|
229
|
+
assert_equal("foo(fixnum[to_i, to_s]) -> fixnum",str)
|
|
230
|
+
end
|
|
231
|
+
|
|
214
232
|
def test_parse_fail_no_methname
|
|
215
233
|
type = @parser.parse("() -> nil")
|
|
216
234
|
assert_equal(nil, type, "Type signature without a method name")
|
data/test/type/tc_unparser.rb
CHANGED
|
@@ -68,6 +68,22 @@ class UnparserTest < Test::Unit::TestCase
|
|
|
68
68
|
assert_equal("a*",str2)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
def test_star_duck_type()
|
|
72
|
+
t1 = DuckType.new([:foo, :bar])
|
|
73
|
+
t2 = VarLengthType.new(t1)
|
|
74
|
+
str2 = TypeUnparser.unparse(t2)
|
|
75
|
+
# puts str1
|
|
76
|
+
assert_equal("[bar, foo]*",str2)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_star_fusion_type()
|
|
80
|
+
t1 = FusionType.new(NominalType.new(A), [:foo, :bar])
|
|
81
|
+
t2 = VarLengthType.new(t1)
|
|
82
|
+
str2 = TypeUnparser.unparse(t2)
|
|
83
|
+
# puts str1
|
|
84
|
+
assert_equal("a[bar, foo]*",str2)
|
|
85
|
+
end
|
|
86
|
+
|
|
71
87
|
def test_star_or_type()
|
|
72
88
|
t1 = NominalType.new(A)
|
|
73
89
|
t2 = NominalType.new(B)
|
data/test/typing/tc_typing.rb
CHANGED
|
@@ -59,26 +59,26 @@ class TypingTest < Test::Unit::TestCase
|
|
|
59
59
|
assert(!t4.subtype_of?(t1), msg(t4,t1,true))
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
62
|
+
def test_self()
|
|
63
|
+
SelfType.set_self(Fixnum)
|
|
64
|
+
t1 = SelfType.new()
|
|
65
|
+
t2 = SelfType.new()
|
|
66
|
+
SelfType.set_self(String)
|
|
67
|
+
t3 = SelfType.new()
|
|
68
|
+
t4 = NominalType.new(Numeric)
|
|
69
|
+
t5 = NominalType.new(String)
|
|
70
|
+
t6 = DuckType.new([:to_s])
|
|
71
|
+
assert(t1.subtype_of?(t2), msg(t1,t2))
|
|
72
|
+
assert(t2.subtype_of?(t1), msg(t2,t1))
|
|
73
|
+
assert(t1.subtype_of?(t3), msg(t1, t3))
|
|
74
|
+
assert(t3.subtype_of?(t1), msg(t3, t1))
|
|
75
|
+
assert(t1.subtype_of?(t4), msg(t1, t4))
|
|
76
|
+
assert(!t4.subtype_of?(t1), msg(t4, t1, true))
|
|
77
|
+
assert(!t1.subtype_of?(t5), msg(t1, t5, true))
|
|
78
|
+
assert(!t5.subtype_of?(t1), msg(t5, t1, true))
|
|
79
|
+
assert(t1.subtype_of?(t6), msg(t1, t5))
|
|
80
|
+
assert(!t6.subtype_of?(t1), msg(t5, t1, true))
|
|
81
|
+
end
|
|
82
82
|
|
|
83
83
|
def test_duck_types_id()
|
|
84
84
|
t1 = DuckType.new([:foo,:baz])
|
data/webpage/footer.html
CHANGED
data/webpage/header.html
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
<head>
|
|
3
3
|
<title>RubyBreaker</title>
|
|
4
4
|
<LINK REL=StyleSheet HREF="rubybreaker.css" TYPE="text/css">
|
|
5
|
-
|
|
5
|
+
<script type="text/javascript" src="generated_toc.js"> </script>
|
|
6
6
|
</head>
|
|
7
7
|
<body onLoad="createTOC()">
|
|
8
8
|
<center>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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>
|
data/webpage/index.html
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
<head>
|
|
3
3
|
<title>RubyBreaker</title>
|
|
4
4
|
<LINK REL=StyleSheet HREF="rubybreaker.css" TYPE="text/css">
|
|
5
|
-
|
|
5
|
+
<script type="text/javascript" src="generated_toc.js"> </script>
|
|
6
6
|
</head>
|
|
7
7
|
<body onLoad="createTOC()">
|
|
8
8
|
<center>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
15
|
<hr />
|
|
16
16
|
|
|
17
17
|
<h1>Introduction</h1>
|
|
@@ -32,6 +32,11 @@ document their code more rigorously and effectively. Currently, manual
|
|
|
32
32
|
modification of the user program is required to run RubyBreaker, but this is
|
|
33
33
|
kept minimal.</p>
|
|
34
34
|
|
|
35
|
+
<p>To contribute to the project, visit RubyBreaker's
|
|
36
|
+
<a href="http://github.com/rockalizer/rubybreaker">GitHub page</a> and
|
|
37
|
+
<a href="http://rubygems.org/gems/rubybreaker">RubyGems page</a>. RubyBreaker RDoc can
|
|
38
|
+
be found in <a href="rdoc/index.html">here</a>.</p>
|
|
39
|
+
|
|
35
40
|
<h2>Limitations</h2>
|
|
36
41
|
|
|
37
42
|
<ul>
|
|
@@ -192,11 +197,34 @@ signature <code>bar(fixnum[to_s]) -> string</code>, which means it takes an o
|
|
|
192
197
|
has <code>Fixnum</code>'s <code>to_s</code> method and returns a string. More detail on the type
|
|
193
198
|
annotation language will be explained in later section.</p>
|
|
194
199
|
|
|
195
|
-
<p>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
is
|
|
200
|
+
<p>It is possible to include either <code>Breakable</code> or <code>Broken</code> in an eigen-class
|
|
201
|
+
to document class methods. To make this easier, RubyBreaker will
|
|
202
|
+
automatically support auto-documentation and manual documentation of class
|
|
203
|
+
methods if the original module is declared as <code>Breakable</code> or <code>Broken</code>,
|
|
204
|
+
respectively--that is, up to immediate eigen class level of a "nominal"
|
|
205
|
+
module. The following example shows how class methods can be
|
|
206
|
+
auto-documented and manually documented, respectively.</p>
|
|
207
|
+
|
|
208
|
+
<pre><code>require "rubybreaker"
|
|
209
|
+
class A
|
|
210
|
+
include RubyBreaker::Breakable
|
|
211
|
+
class << self
|
|
212
|
+
def foo(x); x.to_s end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
class B
|
|
216
|
+
include RubyBreaker::Broken
|
|
217
|
+
class << self
|
|
218
|
+
typesig("foo(fixnum[to_s]) -> string")
|
|
219
|
+
def foo(x); x.to_s end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
</code></pre>
|
|
223
|
+
|
|
224
|
+
<p>Keep in mind that <code>Broken</code> module always wins against <code>Breakable</code>. In other
|
|
225
|
+
words, if a module is declared as both <code>Broken</code> and <code>Breakable</code>, it is
|
|
226
|
+
treated as <code>Broken</code>. Future versions of RubyBreaker will support a hybrid of
|
|
227
|
+
the two modules, but it remains as a limitation in the current version.</p>
|
|
200
228
|
|
|
201
229
|
<h3>Program Entry Point</h3>
|
|
202
230
|
|
|
@@ -325,7 +353,7 @@ it should be only used for an object that requires an arbitrary yet most
|
|
|
325
353
|
specific type--that is, <code>?</code> is a subtype of any other type, but any
|
|
326
354
|
other type is not a subtype of <code>?</code>. This becomes a bit complicated for
|
|
327
355
|
method or block argument types because of their contra-variance
|
|
328
|
-
characteristic. Please
|
|
356
|
+
characteristic. Please refer to the section <em>Subtyping</em>.</p>
|
|
329
357
|
|
|
330
358
|
<h3>Block Type</h3>
|
|
331
359
|
|
|
@@ -399,25 +427,34 @@ subsequent "promotions").</p>
|
|
|
399
427
|
|
|
400
428
|
<h2>Type System</h2>
|
|
401
429
|
|
|
402
|
-
<p>RubyBreaker comes with its own type system
|
|
403
|
-
information.
|
|
404
|
-
to
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
430
|
+
<p>RubyBreaker comes with its own type system to auto-document the type
|
|
431
|
+
information. Each method in a <code>Breakable</code> module is dynamically instrumented
|
|
432
|
+
to be monitored during runtime. This monitoring code observes the types of
|
|
433
|
+
the arguments, block, and return value of each method. Once this information
|
|
434
|
+
is gathered, RubyBreaker will compare it to the information gathered so far.
|
|
435
|
+
If these two types are "compatiable", RubyBreaker will choose more general
|
|
436
|
+
type of the two. Otherwise, RubyBreaker will use the method list type to
|
|
437
|
+
accommodate two "incompatible" types.</p>
|
|
438
|
+
|
|
439
|
+
<h3>Subtyping and Subclassing</h3>
|
|
440
|
+
|
|
441
|
+
<p>RubyBreaker uses subtyping to choose one from the two "compatible" types.
|
|
442
|
+
Two types are "compatible" if one is subtype of another. This means that the
|
|
443
|
+
<em>subtype</em> can be represented using the <em>supertype</em> instead. This is why
|
|
444
|
+
RubyBrekaer chooses the latter to document both types. RubyBreaker relies on
|
|
445
|
+
subclassing of Ruby to determine a subtyping relationship between two types.
|
|
446
|
+
For example, <code>Fixnum</code> is considered to be subtype of <code>Numeric</code> since the
|
|
447
|
+
former is subclass of the latter. (Strictly speaking, <code>Fixnum</code> is not really
|
|
448
|
+
subtype of <code>Numeric</code> because some methods are overriden in <code>Fixnum</code> with
|
|
449
|
+
method types that are not subtype of the counterparts in <code>Numeric</code>. But,
|
|
450
|
+
RubyBreaker is lenient and considers them compatible--that is, <code>Numeric</code> can
|
|
451
|
+
represent any <code>Fixnum</code>.</p>
|
|
413
452
|
|
|
414
453
|
<h3>Pluggable Type System (Advanced)</h3>
|
|
415
454
|
|
|
416
455
|
<p>Yes, RubyBreaker was designed with the replaceable type system in mind. In
|
|
417
456
|
other words, anyone can write his own type system and plug it into
|
|
418
|
-
RubyBreaker
|
|
419
|
-
|
|
420
|
-
<p><em>Documentation coming soon...</em></p>
|
|
457
|
+
RubyBreaker. <em>Technical documentation coming soon...</em></p>
|
|
421
458
|
|
|
422
459
|
<hr />
|
|
423
460
|
|
|
@@ -433,7 +470,7 @@ respect to a nominal type.</p>
|
|
|
433
470
|
|
|
434
471
|
<p>Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved.</p>
|
|
435
472
|
|
|
436
|
-
|
|
473
|
+
</div>
|
|
437
474
|
</center>
|
|
438
475
|
</body>
|
|
439
476
|
</html>
|