fancy 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. data/README.md +38 -86
  2. data/bin/fdoc +2 -22
  3. data/bin/fspec +8 -3
  4. data/bin/ifancy +1 -1
  5. data/boot/fancy_ext.rb +1 -0
  6. data/boot/fancy_ext/array.rb +19 -0
  7. data/boot/fancy_ext/class.rb +2 -4
  8. data/boot/fancy_ext/module.rb +2 -0
  9. data/boot/fancy_ext/object.rb +0 -17
  10. data/boot/rbx-compiler/compiler/ast/method_def.rb +0 -4
  11. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +0 -7
  12. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  13. data/boot/rbx-compiler/parser/fancy_parser.c +1 -0
  14. data/doc/api/fancy.css +10 -1
  15. data/doc/api/fancy.jsonp +1 -1
  16. data/doc/api/fdoc.js +22 -9
  17. data/doc/api/octocat.png +0 -0
  18. data/doc/features.md +1 -2
  19. data/examples/actors.fy +1 -2
  20. data/examples/armstrong_numbers.fy +7 -3
  21. data/examples/blocks.fy +3 -3
  22. data/examples/distributing_proxy.fy +31 -0
  23. data/examples/future_sends.fy +15 -0
  24. data/examples/person.fy +1 -2
  25. data/lib/argv.fy +1 -7
  26. data/lib/array.fy +7 -11
  27. data/lib/block.fy +15 -0
  28. data/lib/boot.fy +4 -3
  29. data/lib/class.fy +354 -10
  30. data/lib/compiler.fy +1 -1
  31. data/lib/compiler/ast/assign.fy +4 -8
  32. data/lib/compiler/ast/async_send.fy +1 -2
  33. data/lib/compiler/ast/block.fy +5 -0
  34. data/lib/compiler/ast/class_def.fy +2 -1
  35. data/lib/compiler/ast/expression_list.fy +1 -2
  36. data/lib/compiler/ast/future_send.fy +1 -2
  37. data/lib/compiler/ast/identifier.fy +34 -17
  38. data/lib/compiler/ast/literals.fy +31 -19
  39. data/lib/compiler/ast/match.fy +5 -4
  40. data/lib/compiler/ast/message_send.fy +3 -5
  41. data/lib/compiler/ast/method_def.fy +0 -3
  42. data/lib/compiler/ast/range.fy +2 -4
  43. data/lib/compiler/ast/return.fy +2 -4
  44. data/lib/compiler/ast/script.fy +2 -4
  45. data/lib/compiler/ast/singleton_method_def.fy +0 -3
  46. data/lib/compiler/ast/string_interpolation.fy +2 -2
  47. data/lib/compiler/ast/super.fy +2 -4
  48. data/lib/compiler/ast/try_catch.fy +13 -9
  49. data/lib/compiler/ast/tuple_literal.fy +1 -2
  50. data/lib/compiler/compiler.fy +2 -2
  51. data/lib/compiler/stages.fy +3 -6
  52. data/lib/contracts.fy +89 -57
  53. data/lib/dynamic_slot_object.fy +21 -3
  54. data/lib/enumerable.fy +140 -4
  55. data/lib/enumerator.fy +1 -1
  56. data/lib/eval.fy +23 -9
  57. data/lib/exception.fy +16 -0
  58. data/lib/false_class.fy +36 -5
  59. data/lib/fancy_spec.fy +64 -34
  60. data/lib/fdoc.fy +85 -24
  61. data/lib/file.fy +19 -0
  62. data/lib/future.fy +4 -46
  63. data/lib/hash.fy +113 -0
  64. data/lib/integer.fy +25 -6
  65. data/lib/iteration.fy +3 -3
  66. data/lib/main.fy +5 -0
  67. data/lib/matchers.fy +79 -0
  68. data/lib/nil_class.fy +8 -0
  69. data/lib/object.fy +109 -18
  70. data/lib/option_parser.fy +118 -0
  71. data/lib/package/dependency.fy +4 -8
  72. data/lib/package/dependency_installer.fy +1 -1
  73. data/lib/package/handler.fy +6 -0
  74. data/lib/package/installer.fy +43 -16
  75. data/lib/package/list.fy +1 -2
  76. data/lib/package/specification.fy +5 -5
  77. data/lib/package/uninstaller.fy +9 -2
  78. data/lib/parser.fy +1 -3
  79. data/lib/parser/ext/ext.c +1 -0
  80. data/lib/parser/ext/lexer.lex +5 -0
  81. data/lib/parser/methods.fy +48 -46
  82. data/lib/proxies.fy +151 -0
  83. data/lib/rbx.fy +1 -0
  84. data/lib/rbx/actor.fy +16 -18
  85. data/lib/rbx/array.fy +18 -3
  86. data/lib/rbx/block.fy +1 -7
  87. data/lib/rbx/class.fy +54 -9
  88. data/lib/rbx/code_loader.fy +2 -5
  89. data/lib/rbx/compiled_method.fy +31 -0
  90. data/lib/rbx/debugger.fy +66 -0
  91. data/lib/rbx/directory.fy +8 -3
  92. data/lib/rbx/documentation.fy +1 -1
  93. data/lib/rbx/file.fy +22 -0
  94. data/lib/rbx/integer.fy +1 -1
  95. data/lib/rbx/match_data.fy +2 -1
  96. data/lib/rbx/method.fy +26 -0
  97. data/lib/rbx/object.fy +8 -3
  98. data/lib/rbx/regexp.fy +6 -3
  99. data/lib/rbx/string.fy +9 -1
  100. data/lib/rbx/stringio.fy +12 -0
  101. data/lib/rbx/symbol.fy +4 -0
  102. data/lib/stack.fy +1 -1
  103. data/lib/string.fy +34 -0
  104. data/lib/stringio.fy +1 -1
  105. data/lib/symbol.fy +6 -2
  106. data/lib/system.fy +15 -1
  107. data/lib/tuple.fy +5 -2
  108. data/lib/version.fy +1 -1
  109. data/ruby_lib/fdoc +2 -22
  110. data/tests/array.fy +3 -17
  111. data/tests/class.fy +312 -10
  112. data/tests/contracts.fy +51 -0
  113. data/tests/distributing_proxy.fy +28 -0
  114. data/tests/enumerable.fy +104 -1
  115. data/tests/exception.fy +35 -0
  116. data/tests/fixnum.fy +1 -1
  117. data/tests/hash.fy +81 -1
  118. data/tests/integer.fy +9 -0
  119. data/tests/matchers.fy +18 -0
  120. data/tests/method.fy +8 -14
  121. data/tests/object.fy +76 -2
  122. data/tests/option_parser.fy +80 -0
  123. data/tests/string.fy +21 -0
  124. data/tests/stringio.fy +1 -1
  125. data/tests/tuple.fy +1 -1
  126. metadata +21 -44
  127. data/examples/arithmetic.fy +0 -7
  128. data/examples/array.fy +0 -50
  129. data/examples/boolean.fy +0 -24
  130. data/examples/class.fy +0 -68
  131. data/examples/constant_access.fy +0 -15
  132. data/examples/default_args.fy +0 -20
  133. data/examples/define_methods.fy +0 -15
  134. data/examples/dynamic_output.fy +0 -15
  135. data/examples/empty_catch.fy +0 -4
  136. data/examples/exception.fy +0 -9
  137. data/examples/files.fy +0 -23
  138. data/examples/finally.fy +0 -5
  139. data/examples/future.fy +0 -30
  140. data/examples/future_composition.fy +0 -20
  141. data/examples/futures.fy +0 -9
  142. data/examples/game_of_life.fy +0 -148
  143. data/examples/html_generator.fy +0 -84
  144. data/examples/implicit_return.fy +0 -3
  145. data/examples/matchers.fy +0 -6
  146. data/examples/nested_try.fy +0 -9
  147. data/examples/numbers.fy +0 -12
  148. data/examples/rbx/and_or.fy +0 -7
  149. data/examples/rbx/blocks.fy +0 -22
  150. data/examples/rbx/classes.fy +0 -32
  151. data/examples/rbx/hello.fy +0 -8
  152. data/examples/rbx/include.fy +0 -12
  153. data/examples/rbx/inherit.fy +0 -11
  154. data/examples/rbx/methods.fy +0 -15
  155. data/examples/rbx/nested_classes.fy +0 -9
  156. data/examples/rbx/require.fy +0 -3
  157. data/examples/rbx/strings.fy +0 -5
  158. data/examples/require.fy +0 -7
  159. data/examples/return.fy +0 -13
  160. data/examples/singleton_methods.fy +0 -21
  161. data/examples/threads.fy +0 -18
  162. data/examples/tuple.fy +0 -8
  163. data/examples/webserver/webserver.fy +0 -15
  164. data/lib/proxy.fy +0 -86
  165. data/lib/thread_pool.fy +0 -102
@@ -0,0 +1,51 @@
1
+ FancySpec describe: Class Contracts with: {
2
+ it: "fails inclusion" when: {
3
+ {
4
+ class A {
5
+ include: Fancy Enumerable
6
+ }
7
+ } raises: Class Contracts InterfaceNotImplementedError
8
+ }
9
+
10
+ it: "doesn't fail inclusion" when: {
11
+ {
12
+ class A {
13
+ def each: block
14
+ include: Fancy Enumerable
15
+ }
16
+ } does_not raise: Class Contracts InterfaceNotImplementedError
17
+
18
+ {
19
+ class B {
20
+ provides_interface: 'each:
21
+ include: Fancy Enumerable
22
+ }
23
+ } does_not raise: Class Contracts InterfaceNotImplementedError
24
+ }
25
+
26
+ it: "returns the amount of not implemented interface methods" with: 'missing_methods_for_interface: when: {
27
+ class Interface {
28
+ expects_interface_on_inclusion: ['hello, 'world]
29
+ }
30
+ {
31
+ class C {
32
+ include: Interface
33
+ }
34
+ } raises: Class Contracts InterfaceNotImplementedError with: |e| {
35
+ e methods is: ['hello, 'world]
36
+ e interface is: Interface
37
+ e including_class is: C
38
+ }
39
+
40
+ {
41
+ class D {
42
+ def hello
43
+ include: Interface
44
+ }
45
+ } raises: Class Contracts InterfaceNotImplementedError with: |e| {
46
+ e methods is: ['world]
47
+ e interface is: Interface
48
+ e including_class is: D
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,28 @@
1
+ FancySpec describe: Proxies DistributingProxy with: {
2
+ it: "forwards messages to each element in turn" when: {
3
+ p = Proxies DistributingProxy new: [1,2,3]
4
+ p is: 1
5
+ p is: 2
6
+ p is: 3
7
+ # and again
8
+ p is: 1
9
+ p is: 2
10
+ p is: 3
11
+ # and once more
12
+ p class is: Fixnum
13
+ p inspect is: "2"
14
+ p to_s is: "3"
15
+ }
16
+
17
+ it: "waits appropriately if all elements are currently in use" when: {
18
+ p = Proxies DistributingProxy new: ["foo", "bar", "baz"]
19
+ results = []
20
+ threads = (1..10) map: |i| {
21
+ Thread new: {
22
+ results << (i, p * 2)
23
+ }
24
+ }
25
+ threads each: @{ join }
26
+ results size is: 10
27
+ }
28
+ }
@@ -44,11 +44,114 @@ FancySpec describe: Fancy Enumerable with: {
44
44
  [] to_s is: ""
45
45
 
46
46
  class MyCollection {
47
- include: Fancy Enumerable
48
47
  def each: block {
49
48
  (0..5) each: block
50
49
  }
50
+ include: Fancy Enumerable
51
51
  }
52
52
  MyCollection new to_s is: "012345"
53
53
  }
54
+
55
+ it: "returns the array in groups of 3" with: 'in_groups_of: when: {
56
+ ['a,'b,'c] in_groups_of: 1 . is: [['a],['b],['c]]
57
+ array = 1 upto: 10
58
+ array in_groups_of: 3 . is: [[1,2,3], [4,5,6], [7,8,9], [10]]
59
+
60
+ (20,30,40) in_groups_of: 2 . is: [[20,30], [40]]
61
+
62
+ [1,2,3] in_groups_of: -1 . is: []
63
+ [1,2,3] in_groups_of: 0 . is: []
64
+ [1,2,3] in_groups_of: 1 . is: [[1],[2],[3]]
65
+
66
+ [] in_groups_of: -1 . is: []
67
+ [] in_groups_of: 0 . is: []
68
+ [] in_groups_of: 1 . is: []
69
+ }
70
+
71
+ it: "indicates if it's sorted" with: 'sorted? when: {
72
+ [] sorted? is: true
73
+ [1] sorted? is: true
74
+ [1,2] sorted? is: true
75
+ [2,1] sorted? is: false
76
+
77
+ (1,2,3) sorted? is: true
78
+ (1,3,2) sorted? is: false
79
+
80
+ "" sorted? is: true
81
+ "a" sorted? is: true
82
+ "abc" sorted? is: true
83
+ "fabc" sorted? is: false
84
+ }
85
+
86
+ it: "splits a collection at an index" with: 'split_at: when: {
87
+ [] split_at: 0 . is: [[],[]]
88
+ [1] split_at: 0 . is: [[],[1]]
89
+ [1] split_at: 1 . is: [[1],[]]
90
+
91
+ (1,2,3) split_at: 1 . is: [[1], [2,3]]
92
+ (1,2,3) split_at: 2 . is: [[1,2], [3]]
93
+
94
+ "foo" split_at: 1 . is: [["f"], ["o", "o"]]
95
+ }
96
+
97
+ it: "splits a collection based on a predicate block" with: 'split_with: when: {
98
+ [] split_with: @{ true } . is: [[],[]]
99
+ [] split_with: @{ false } . is: [[],[]]
100
+ [1] split_with: @{ true } . is: [[1], []]
101
+ [1] split_with: @{ false } . is: [[], [1]]
102
+ [1,2,3] split_with: @{ < 2 } . is: [[1], [2,3]]
103
+ [1,2,3] split_with: @{ <= 2 } . is: [[1,2], [3]]
104
+
105
+ "" split_with: @{ true } . is: [[], []]
106
+ "a" split_with: @{ true } . is: [["a"], []]
107
+ "a" split_with: @{ false } . is: [[], ["a"]]
108
+ "abcde" split_with: @{ <= "c" } . is: [["a", "b", "c"], ["d", "e"]]
109
+ }
110
+
111
+ it: "takes elements from itself as long a block yields true" with: 'take_while: when: {
112
+ (1..15) take_while: |x| { x < 10 } . is: (1 upto: 9)
113
+ }
114
+
115
+ it: "drops elements from itself as long a block yields true" with: 'drop_while: when: {
116
+ (1..15) drop_while: |x| { x < 10 } . is: (10 upto: 15)
117
+ }
118
+
119
+ it: "returns the first n elements" with: 'first: when: {
120
+ (1,2,3) first: 0 . is: []
121
+ (1,2,3) first: 1 . is: [1]
122
+ (1,2,3) first: 2 . is: [1,2]
123
+ (1,2,3) first: 3 . is: [1,2,3]
124
+ (1,2,3) first: 4 . is: [1,2,3]
125
+ }
126
+
127
+ it: "returns the last n elements" with: 'last: when: {
128
+ (1,2,3) last: 0 . is: []
129
+ (1,2,3) last: 1 . is: [3]
130
+ (1,2,3) last: 2 . is: [2,3]
131
+ (1,2,3) last: 3 . is: [1,2,3]
132
+ (1,2,3) last: 4 . is: [1,2,3]
133
+ }
134
+
135
+ it: "returns the elements for which a pattern matches" with: 'grep: when: {
136
+ "hello world" grep: /[a-h]/ . is: ["h", "e", "d"]
137
+ ["hello", "world", 1, 2, 3] grep: String . is: ["hello", "world"]
138
+ (1,2,3,4,5) grep: @{ < 2 } . is: [1] # blocks can be used as patterns, too :)
139
+ (1,2,3) grep: String . is: []
140
+ (1,2,3,4) grep: (2..3) . is: [2, 3]
141
+ }
142
+
143
+ it: "returns the values of calling a block for all elements for which a pattern matches" with: 'grep:taking: when: {
144
+ "hello world" grep: /[a-h]/ taking: 'upcase . is: ["H", "E", "D"]
145
+ ["hello", "world", 1, 2, 3] grep: String taking: 'upcase . is: ["HELLO", "WORLD"]
146
+ (1,2,3,4,5) grep: @{ < 2 } taking: 'doubled . is: [2]
147
+ (1,2,3) grep: String taking: 'to_s . is: []
148
+ (1,2,3,4) grep: (2..3) taking: 'to_s . is: ["2", "3"]
149
+ }
150
+
151
+ it: "joins all elements by a block" with: 'join_by: when: {
152
+ (1,2,3) join_by: '+ . is: $ (1,2,3) sum
153
+ ("foo", "bar", "baz") join_by: '+ . is: "foobarbaz"
154
+ [NoMethodError, IOError, ZeroDivisionError] join_by: '>< . is: (NoMethodError >< IOError >< ZeroDivisionError)
155
+ [NoMethodError, IOError, ZeroDivisionError] join_by: '<> . is: (NoMethodError <> IOError <> ZeroDivisionError)
156
+ }
54
157
  }
@@ -129,4 +129,39 @@ FancySpec describe: StdError with: {
129
129
  e message is: msg
130
130
  }
131
131
  }
132
+
133
+ it: "always executes the finally block, even when raise_returning from within the try block" when: {
134
+ def do_something {
135
+ try {
136
+ return "Ok"
137
+ } finally {
138
+ @ran_finally? = true
139
+ }
140
+ }
141
+ @ran_finally? = false
142
+ do_something is: "Ok"
143
+ @ran_finally? is: true
144
+ }
145
+
146
+ it: "always executes the finally block, even when raising from within a catch block" when: {
147
+ def do_something {
148
+ try {
149
+ 10 / 0
150
+ } catch ZeroDivisionError => e {
151
+ IOError new: (e message) . raise!
152
+ } finally {
153
+ @ran_finally? = true
154
+ }
155
+ }
156
+ @ran_finally? = false
157
+ { do_something } raises: IOError
158
+ @ran_finally? is: true
159
+ }
160
+
161
+ it: "raises an exception" with: 'raise: when: {
162
+ { StandardError raise: "error" } raises: Exception with: @{ message is: "error" }
163
+ { StandardError raise: "error" } raises: StandardError with: @{ message is: "error" }
164
+ { ArgumentError raise: "error2" } raises: ArgumentError with: @{ message is: "error2" }
165
+ { IOError raise: "bar" } raises: IOError with: @{ message is: "bar" }
166
+ }
132
167
  }
@@ -118,7 +118,7 @@ FancySpec describe: Fixnum with: {
118
118
  sum is: ((10..19) sum)
119
119
  }
120
120
 
121
- it: "tries to run a code block self amount of times or fails" with: 'try_times: when: {
121
+ it: "tries to run a code block self amount of times or fails" with: 'times_try: when: {
122
122
  { -2 times_try: { 2 / 0 } } does_not raise: Exception
123
123
  { -1 times_try: { 2 / 0 } } does_not raise: Exception
124
124
  { 0 times_try: { 2 / 0 } } does_not raise: Exception
@@ -131,7 +131,7 @@ FancySpec describe: Hash with: {
131
131
  h includes?: nil . is: false
132
132
  }
133
133
 
134
- it: "returns an object with slots based on key-value pairs in Hash" for: 'to_object when: {
134
+ it: "returns an object with slots based on key-value pairs in Hash" with: 'to_object when: {
135
135
  <[]> to_object slots empty? is: true
136
136
  <['name => "Chris"]> to_object tap: @{
137
137
  slots is: ['name]
@@ -151,4 +151,84 @@ FancySpec describe: Hash with: {
151
151
  b is: "hello"
152
152
  }
153
153
  }
154
+
155
+ it: "returns a hash with all entries for which a block yields true" with: 'select_keys: when: {
156
+ <[]> select_keys: { true } . is: <[]>
157
+ <[]> select_keys: { false } . is: <[]>
158
+ <['hello => "world"]> select_keys: { true } . is: <['hello => "world"]>
159
+ <['hello => "world"]> select_keys: { false } . is: <[]>
160
+ <['hello => "world", "world" => 'hello]> select_keys: @{ is_a?: Symbol } . is: <['hello => "world"]>
161
+ <[5 => 1, 4 => 2, 3 => 3, 2 => 4, 1 => 5]> select_keys: @{ <= 3 } . is: <[1 => 5, 2 => 4, 3 => 3]>
162
+ }
163
+
164
+ it: "returns a hash with all entries for which a block yields false" with: 'reject_keys: when: {
165
+ <[]> reject_keys: { true } . is: <[]>
166
+ <[]> reject_keys: { false } . is: <[]>
167
+ <['hello => "world"]> reject_keys: { true } . is: <[]>
168
+ <['hello => "world"]> reject_keys: { false } . is: <['hello => "world"]>
169
+ <['hello => "world", "world" => 'hello]> reject_keys: @{ is_a?: Symbol } . is: <["world" => 'hello]>
170
+ <[5 => 1, 4 => 2, 3 => 3, 2 => 4, 1 => 5]> reject_keys: @{ <= 3 } . is: <[5 => 1, 4 => 2]>
171
+ }
172
+
173
+ class HashCallable {
174
+ read_write_slots: ('foo, 'bar)
175
+ }
176
+
177
+ it: "is callable, like a block" with: 'call: when: {
178
+ hc = HashCallable new
179
+
180
+ hc foo is: nil
181
+ hc bar is: nil
182
+
183
+ <['foo: => "bar", 'bar: => 123]> call: [hc] . is: hc
184
+
185
+ hc foo is: "bar"
186
+ hc bar is: 123
187
+
188
+ <['foo => "foobar", 'bar => 456]> call: [hc]
189
+
190
+ hc foo is: "foobar"
191
+ hc bar is: 456
192
+ }
193
+
194
+ it: "returns itself as a block" with: 'to_block when: {
195
+ hc = HashCallable new
196
+
197
+ hc foo is: nil
198
+ hc bar is: nil
199
+
200
+ <['foo: => "hello", 'bar: => "world"]> tap: |hash| {
201
+ block = hash to_block
202
+ block is_a?: Block . is: true
203
+ block arity is: 1
204
+ block call: [hc] . is: hc
205
+ }
206
+
207
+ hc foo is: "hello"
208
+ hc bar is: "world"
209
+
210
+ <['foo => 123, 'bar => 'baz]> to_block call: [hc]
211
+
212
+ hc foo is: 123
213
+ hc bar is: 'baz
214
+ }
215
+
216
+ it: "returns a nested Hash" with: 'to_hash_deep when: {
217
+ <[]> to_hash_deep is: <[]>
218
+ <['foo => "bar"]> to_hash_deep is: <['foo => "bar"]>
219
+ <['foo => {bar: "baz"}]> to_hash_deep is: <['foo => <['bar => "baz"]>]>
220
+ <[
221
+ 'foo => {
222
+ bar: {
223
+ baz: "quux"
224
+ }
225
+ }
226
+ ]> to_hash_deep is: <[
227
+ 'foo => <[
228
+ 'bar => <[
229
+ 'baz => "quux"
230
+ ]>
231
+ ]>
232
+ ]>
233
+ }
154
234
  }
@@ -0,0 +1,9 @@
1
+ FancySpec describe: Integer with: {
2
+ it: "returns its decimals as an array" with: 'decimals when: {
3
+ (0..9) each: |i| { i decimals is: [i] }
4
+ 10 decimals is: [1, 0]
5
+ 100 decimals is: [1, 0, 0]
6
+ 123 decimals is: [1, 2, 3]
7
+ 998811 decimals is: [9, 9, 8, 8, 1, 1]
8
+ }
9
+ }
@@ -0,0 +1,18 @@
1
+ FancySpec describe: Matchers with: {
2
+ it: "matches with any value defined matching" when: {
3
+ m = Matchers MatchAny new: 1 with: 2
4
+ m === 0 is: false
5
+ m === 1 is: true
6
+ m === 2 is: true
7
+ m === 3 is_not: true
8
+ }
9
+
10
+ it: "matches only with all values defined matching" when: {
11
+ m = Matchers MatchAll new: Integer with: Fixnum
12
+ m === -1 is: true
13
+ m === 0 is: true
14
+ m === 1 is: true
15
+ m === 2.1 is_not: true
16
+ m === 0.0 is_not: true
17
+ }
18
+ }
@@ -16,14 +16,10 @@ FancySpec describe: Method with: {
16
16
 
17
17
  it: "returns the amount of arguments a Method takes" with: 'arity when: {
18
18
  class Foo {
19
- def no_args {
20
- }
21
- def one_arg: yo {
22
- }
23
- def two: a args: b {
24
- }
25
- def three: a args: b ok: c {
26
- }
19
+ def no_args
20
+ def one_arg: yo
21
+ def two: a args: b
22
+ def three: a args: b ok: c
27
23
  }
28
24
 
29
25
  Foo instance_method: 'no_args . arity is: 0
@@ -86,13 +82,11 @@ FancySpec describe: Method with: {
86
82
  }
87
83
 
88
84
  class Foo {
89
- def bar {
90
- }
91
- def private_bar {
92
- }
85
+ def bar
86
+ def private_bar
93
87
  private: 'private_bar
94
- def protected_bar {
95
- }
88
+
89
+ def protected_bar
96
90
  protected: 'protected_bar
97
91
  }
98
92
 
@@ -215,6 +215,22 @@ FancySpec describe: Object with: {
215
215
  }
216
216
  }
217
217
 
218
+ it: "calls a given block with self if the block takes an argument" with: 'do: when: {
219
+ arr = []
220
+ arr do: @{
221
+ << 1
222
+ << 2
223
+ << 3
224
+ select!: 'even?
225
+ } . is: [2]
226
+
227
+ arr do: @{
228
+ is: [2] # same
229
+ }
230
+
231
+ 2 do: @{ inspect } . is: 2
232
+ }
233
+
218
234
  it: "calls a given block with the receiver before returning itself" with: 'tap: when: {
219
235
  10 + 2 tap: |x| {
220
236
  x is: 12
@@ -259,7 +275,7 @@ FancySpec describe: Object with: {
259
275
  o2 get_slot: 'slot2 == (o1 slot2) is: true
260
276
  }
261
277
 
262
- it: "returns itself when return is send as a message" with: 'return when: {
278
+ it: "returns itself when return is send as a message" when: {
263
279
  def foo: array {
264
280
  array each: @{ return }
265
281
  }
@@ -277,7 +293,7 @@ FancySpec describe: Object with: {
277
293
  v is: [1]
278
294
  }
279
295
 
280
- it: "provides temporarily mutable slots" with: 'with_mutable_slots: when: {
296
+ it: "provides temporarily mutable slots" with: 'with_mutable_slots:do: when: {
281
297
  class Student {
282
298
  read_slots: ('name, 'age, 'city)
283
299
  def initialize: block {
@@ -304,4 +320,62 @@ FancySpec describe: Object with: {
304
320
  p age is: 24
305
321
  p city is: "Osnabrück"
306
322
  }
323
+
324
+ it: "ignores all specified exception types" with: 'ignoring:do: when: {
325
+ {
326
+ [{ 2 / 0 }, { "foo" unknown_method_on_string! }] each: |b| {
327
+ ignoring: (ZeroDivisionError, NoMethodError) do: b
328
+ }
329
+ } does_not raise: Exception
330
+ }
331
+
332
+ it: "rebinds a singleton method within a block" with: 'rebind_method:with:within: when: {
333
+ s = "foo"
334
+ s rebind_method: 'hello with: { 42 } within: {
335
+ s hello is: 42
336
+ }
337
+
338
+ s rebind_method: 'hello with: 'to_s within: {
339
+ s hello is: "foo"
340
+ }
341
+
342
+ { s hello } raises: NoMethodError
343
+
344
+ def s bar {
345
+ "bar!"
346
+ }
347
+
348
+ s bar is: "bar!"
349
+
350
+ s rebind_method: 'bar with: { "new bar!" } within: {
351
+ s bar is: "new bar!"
352
+ }
353
+
354
+ s rebind_method: 'bar with: { "another bar!" } within: |x| { x bar } . is: "another bar!"
355
+
356
+ s bar is: "bar!"
357
+ }
358
+
359
+ it: "binds a dynvar correctly" with: 'let:be:in:ensuring: when: {
360
+ *var* is: nil
361
+ let: '*var* be: 'hello in: {
362
+ *var* is: 'hello
363
+ } ensuring: {
364
+ *var* is: 'hello
365
+ }
366
+ *var* is: nil
367
+
368
+ @val = nil
369
+ def check {
370
+ *var* is: @val
371
+ }
372
+
373
+ check
374
+ @val = "test"
375
+ let: '*var* be: @val in: {
376
+ check
377
+ }
378
+ @val = nil
379
+ check
380
+ }
307
381
  }