opal 0.3.41 → 0.3.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (285) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +3 -0
  3. data/CHANGELOG.md +14 -1
  4. data/Gemfile +2 -5
  5. data/Rakefile +41 -3
  6. data/bin/opal +33 -0
  7. data/lib/opal.rb +2 -12
  8. data/lib/opal/core_ext.rb +5 -0
  9. data/lib/opal/grammar.rb +2207 -2138
  10. data/lib/opal/grammar.y +21 -0
  11. data/lib/opal/grammar_helpers.rb +360 -0
  12. data/lib/opal/lexer.rb +55 -401
  13. data/lib/opal/lexer_scope.rb +28 -0
  14. data/lib/opal/parser.rb +155 -171
  15. data/lib/opal/target_scope.rb +257 -0
  16. data/lib/opal/version.rb +1 -1
  17. data/opal.gemspec +6 -2
  18. data/opal/opal-parser.js.erb +3 -2
  19. data/opal/opal.rb +20 -18
  20. data/opal/opal/array.rb +21 -12
  21. data/opal/opal/basic_object.rb +2 -1
  22. data/opal/opal/boolean.rb +3 -0
  23. data/opal/opal/browser_loader.js +57 -0
  24. data/opal/opal/class.rb +51 -13
  25. data/opal/opal/date.rb +1 -20
  26. data/opal/opal/enumerable.rb +66 -33
  27. data/opal/opal/error.rb +2 -0
  28. data/opal/opal/hash.rb +1 -1
  29. data/opal/opal/kernel.rb +14 -3
  30. data/opal/opal/nil_class.rb +4 -0
  31. data/opal/opal/proc.rb +9 -1
  32. data/opal/opal/racc.rb +2 -2
  33. data/opal/opal/regexp.rb +1 -1
  34. data/opal/opal/runtime.js +14 -4
  35. data/opal/opal/string.rb +21 -4
  36. data/opal/opal/time.rb +27 -0
  37. data/spec/core/array/allocate_spec.rb +7 -1
  38. data/spec/core/array/append_spec.rb +18 -3
  39. data/spec/core/array/array_spec.rb +7 -0
  40. data/spec/core/array/assoc_spec.rb +23 -8
  41. data/spec/core/array/at_spec.rb +23 -3
  42. data/spec/core/array/choice_spec.rb +20 -0
  43. data/spec/core/array/clear_spec.rb +45 -4
  44. data/spec/core/array/combination_spec.rb +55 -0
  45. data/spec/core/array/compact_spec.rb +72 -1
  46. data/spec/core/array/constructor_spec.rb +13 -2
  47. data/spec/core/array/count_spec.rb +15 -7
  48. data/spec/core/array/delete_at_spec.rb +44 -1
  49. data/spec/core/array/delete_if_spec.rb +52 -2
  50. data/spec/core/array/delete_spec.rb +83 -2
  51. data/spec/core/array/drop_spec.rb +24 -16
  52. data/spec/core/array/drop_while_spec.rb +17 -0
  53. data/spec/core/array/each_index_spec.rb +11 -1
  54. data/spec/core/array/each_spec.rb +20 -2
  55. data/spec/core/array/empty_spec.rb +4 -1
  56. data/spec/core/array/eql_spec.rb +14 -0
  57. data/spec/core/array/fetch_spec.rb +31 -2
  58. data/spec/core/array/find_index_spec.rb +8 -0
  59. data/spec/core/array/first_spec.rb +45 -8
  60. data/spec/core/array/fixtures/classes.rb +538 -0
  61. data/spec/core/array/flatten_spec.rb +200 -7
  62. data/spec/core/array/frozen_spec.rb +32 -0
  63. data/spec/core/array/include_spec.rb +16 -1
  64. data/spec/core/array/index_spec.rb +5 -25
  65. data/spec/core/array/insert_spec.rb +37 -3
  66. data/spec/core/array/inspect_spec.rb +6 -12
  67. data/spec/core/array/intersection_spec.rb +55 -4
  68. data/spec/core/array/join_spec.rb +29 -4
  69. data/spec/core/array/keep_if_spec.rb +13 -6
  70. data/spec/core/array/last_spec.rb +35 -1
  71. data/spec/core/array/length_spec.rb +7 -4
  72. data/spec/core/array/map_spec.rb +9 -47
  73. data/spec/core/array/minus_spec.rb +68 -4
  74. data/spec/core/array/multiply_spec.rb +138 -6
  75. data/spec/core/array/new_spec.rb +92 -3
  76. data/spec/core/array/ntimes_spec.rb +26 -0
  77. data/spec/core/array/plus_spec.rb +48 -2
  78. data/spec/core/array/pop_spec.rb +159 -39
  79. data/spec/core/array/push_spec.rb +29 -1
  80. data/spec/core/array/rassoc_spec.rb +31 -2
  81. data/spec/core/array/reject_spec.rb +89 -2
  82. data/spec/core/array/replace_spec.rb +7 -29
  83. data/spec/core/array/reverse_each_spec.rb +25 -1
  84. data/spec/core/array/reverse_spec.rb +53 -1
  85. data/spec/core/array/rindex_spec.rb +55 -5
  86. data/spec/core/array/select_spec.rb +35 -8
  87. data/spec/core/array/shared/collect.rb +0 -0
  88. data/spec/core/array/shared/enumeratorize.rb +12 -0
  89. data/spec/core/array/shared/eql.rb +95 -0
  90. data/spec/core/array/shared/index.rb +37 -0
  91. data/spec/core/array/shared/inspect.rb +3 -0
  92. data/spec/core/array/shared/join.rb +7 -0
  93. data/spec/core/array/shared/keep_if.rb +0 -0
  94. data/spec/core/array/shared/length.rb +0 -0
  95. data/spec/core/array/shared/replace.rb +0 -0
  96. data/spec/core/array/shared/slice.rb +0 -0
  97. data/spec/core/array/shift_spec.rb +132 -23
  98. data/spec/core/array/shuffle_spec.rb +82 -6
  99. data/spec/core/array/size_spec.rb +7 -4
  100. data/spec/core/array/slice_spec.rb +132 -1
  101. data/spec/core/array/sort_spec.rb +263 -14
  102. data/spec/core/array/take_spec.rb +24 -16
  103. data/spec/core/array/take_while_spec.rb +14 -10
  104. data/spec/core/array/to_a_spec.rb +18 -1
  105. data/spec/core/array/to_ary_spec.rb +15 -1
  106. data/spec/core/array/try_convert_spec.rb +39 -2
  107. data/spec/core/array/uniq_spec.rb +148 -3
  108. data/spec/core/array/unshift_spec.rb +36 -1
  109. data/spec/core/array/zip_spec.rb +36 -1
  110. data/spec/core/class/new_spec.rb +8 -6
  111. data/spec/core/enumerable/all_spec.rb +37 -9
  112. data/spec/core/enumerable/any_spec.rb +45 -7
  113. data/spec/core/enumerable/collect_spec.rb +4 -1
  114. data/spec/core/enumerable/count_spec.rb +4 -1
  115. data/spec/core/enumerable/detect_spec.rb +2 -2
  116. data/spec/core/enumerable/drop_spec.rb +4 -1
  117. data/spec/core/enumerable/drop_while_spec.rb +4 -1
  118. data/spec/core/enumerable/each_slice_spec.rb +2 -1
  119. data/spec/core/enumerable/each_with_index_spec.rb +4 -1
  120. data/spec/core/enumerable/each_with_object_spec.rb +4 -1
  121. data/spec/core/enumerable/entries_spec.rb +4 -1
  122. data/spec/core/enumerable/find_all_spec.rb +4 -1
  123. data/spec/core/enumerable/find_index_spec.rb +4 -1
  124. data/spec/core/enumerable/find_spec.rb +5 -2
  125. data/spec/core/enumerable/first_spec.rb +4 -1
  126. data/spec/core/enumerable/fixtures/classes.rb +198 -2
  127. data/spec/core/enumerable/grep_spec.rb +4 -1
  128. data/spec/core/enumerable/take_spec.rb +4 -1
  129. data/spec/core/enumerable/to_a_spec.rb +4 -1
  130. data/spec/core/false/and_spec.rb +11 -0
  131. data/spec/core/false/inspect_spec.rb +7 -0
  132. data/spec/core/false/or_spec.rb +11 -0
  133. data/spec/core/false/to_s_spec.rb +7 -0
  134. data/spec/core/false/xor_spec.rb +11 -0
  135. data/spec/core/kernel/rand_spec.rb +5 -5
  136. data/spec/core/module/const_get_spec.rb +4 -4
  137. data/spec/core/module/fixtures/classes.rb +434 -0
  138. data/spec/core/module/method_defined_spec.rb +49 -0
  139. data/spec/core/module/module_function_spec.rb +28 -0
  140. data/spec/core/nil/and_spec.rb +3 -1
  141. data/spec/core/nil/dup_spec.rb +7 -0
  142. data/spec/core/nil/inspect_spec.rb +3 -1
  143. data/spec/core/nil/nil_spec.rb +3 -1
  144. data/spec/core/nil/or_spec.rb +4 -2
  145. data/spec/core/nil/to_a_spec.rb +3 -1
  146. data/spec/core/nil/to_f_spec.rb +3 -1
  147. data/spec/core/nil/to_i_spec.rb +3 -1
  148. data/spec/core/nil/to_s_spec.rb +3 -1
  149. data/spec/core/nil/xor_spec.rb +4 -2
  150. data/spec/core/string/element_reference_spec.rb +14 -1
  151. data/spec/core/string/fixtures/classes.rb +0 -0
  152. data/spec/core/true/and_spec.rb +11 -0
  153. data/spec/core/true/inspect_spec.rb +7 -0
  154. data/spec/core/true/or_spec.rb +11 -0
  155. data/spec/core/true/to_s_spec.rb +7 -0
  156. data/spec/core/true/xor_spec.rb +11 -0
  157. data/spec/{core → core_ext}/array/element_reference_spec.rb +0 -0
  158. data/spec/{core → core_ext}/array/equal_value_spec.rb +0 -0
  159. data/spec/{core → core_ext}/array/fill_spec.rb +0 -0
  160. data/spec/{core → core_ext}/array/reduce_spec.rb +0 -0
  161. data/spec/core_ext/basic_object/send_spec.rb +3 -3
  162. data/spec/{core → core_ext}/boolean/singleton_class_spec.rb +0 -0
  163. data/spec/{core → core_ext}/boolean/to_json_spec.rb +0 -0
  164. data/spec/core_ext/class/_inherited_spec.rb +3 -3
  165. data/spec/core_ext/class/proc_methods_spec.rb +2 -2
  166. data/spec/core_ext/class/singleton_methods_spec.rb +8 -8
  167. data/spec/core_ext/method_missing_spec.rb +3 -3
  168. data/spec/core_ext/native/method_missing_spec.rb +3 -2
  169. data/spec/core_ext/native/to_native_spec.rb +3 -2
  170. data/spec/{core → core_ext}/nil/to_json_spec.rb +0 -0
  171. data/spec/date.rb +0 -0
  172. data/spec/fileutils.rb +0 -0
  173. data/spec/filters/ancestors.rb +4 -0
  174. data/spec/filters/array_delete.rb +3 -0
  175. data/spec/filters/array_fetch.rb +3 -0
  176. data/spec/filters/array_first.rb +3 -0
  177. data/spec/filters/array_flatten.rb +14 -0
  178. data/spec/filters/array_intersection.rb +5 -0
  179. data/spec/filters/array_join.rb +6 -0
  180. data/spec/filters/array_subclasses.rb +4 -0
  181. data/spec/filters/block_args.rb +3 -0
  182. data/spec/filters/coerce_integer.rb +9 -0
  183. data/spec/filters/frozen.rb +4 -0
  184. data/spec/filters/mocks.rb +3 -0
  185. data/spec/filters/should_receive.rb +4 -0
  186. data/spec/filters/tainted.rb +7 -0
  187. data/spec/fixtures/class.rb +124 -0
  188. data/spec/fixtures/class_variables.rb +0 -0
  189. data/spec/fixtures/constants.rb +0 -0
  190. data/spec/grammar/alias_spec.rb +1 -1
  191. data/spec/grammar/def_spec.rb +1 -0
  192. data/spec/grammar/lvar_spec.rb +1 -2
  193. data/spec/grammar/nth_ref_spec.rb +13 -0
  194. data/spec/grammar/sclass_spec.rb +6 -7
  195. data/spec/grammar/str_spec.rb +4 -4
  196. data/spec/grammar/string_spec.rb +8 -0
  197. data/spec/grammar/xstr_spec.rb +4 -4
  198. data/spec/iconv.rb +0 -0
  199. data/spec/language/alias_spec.rb +140 -3
  200. data/spec/language/and_spec.rb +14 -7
  201. data/spec/language/array_spec.rb +57 -5
  202. data/spec/language/block_spec.rb +466 -49
  203. data/spec/language/break_spec.rb +294 -44
  204. data/spec/language/case_spec.rb +151 -3
  205. data/spec/language/class_spec.rb +196 -0
  206. data/spec/language/class_variable_spec.rb +56 -0
  207. data/spec/language/def_spec.rb +507 -4
  208. data/spec/language/defined_spec.rb +19 -7
  209. data/spec/language/ensure_spec.rb +26 -39
  210. data/spec/language/execution_spec.rb +15 -0
  211. data/spec/language/fixtures/array.rb +11 -0
  212. data/spec/language/fixtures/block.rb +57 -0
  213. data/spec/language/fixtures/break.rb +240 -0
  214. data/spec/language/fixtures/ensure.rb +72 -0
  215. data/spec/language/fixtures/literal_lambda.rb +7 -0
  216. data/spec/language/fixtures/metaclass.rb +33 -0
  217. data/spec/language/fixtures/module.rb +24 -0
  218. data/spec/language/fixtures/next.rb +78 -12
  219. data/spec/language/fixtures/return.rb +118 -0
  220. data/spec/language/fixtures/send.rb +110 -0
  221. data/spec/language/fixtures/send_1.9.rb +22 -0
  222. data/spec/language/fixtures/super.rb +308 -0
  223. data/spec/language/fixtures/variables.rb +58 -0
  224. data/spec/language/fixtures/yield.rb +5 -0
  225. data/spec/language/for_spec.rb +192 -0
  226. data/spec/language/hash_spec.rb +29 -5
  227. data/spec/language/if_spec.rb +90 -9
  228. data/spec/language/literal_lambda_spec.rb +1 -47
  229. data/spec/language/loop_spec.rb +39 -2
  230. data/spec/language/metaclass_spec.rb +151 -5
  231. data/spec/language/module_spec.rb +56 -0
  232. data/spec/language/next_spec.rb +370 -12
  233. data/spec/language/not_spec.rb +55 -0
  234. data/spec/language/numbers_spec.rb +56 -0
  235. data/spec/language/or_spec.rb +31 -3
  236. data/spec/language/order_spec.rb +79 -0
  237. data/spec/language/precedence_spec.rb +483 -0
  238. data/spec/language/proc_spec.rb +249 -21
  239. data/spec/language/redo_spec.rb +67 -0
  240. data/spec/language/rescue_spec.rb +121 -0
  241. data/spec/language/retry_spec.rb +56 -0
  242. data/spec/language/return_spec.rb +281 -0
  243. data/spec/language/send_spec.rb +141 -48
  244. data/spec/language/singleton_class_spec.rb +1 -1
  245. data/spec/language/string_spec.rb +11 -0
  246. data/spec/language/super_spec.rb +213 -133
  247. data/spec/language/symbol_spec.rb +2 -1
  248. data/spec/language/undef_spec.rb +3 -1
  249. data/spec/language/unless_spec.rb +6 -2
  250. data/spec/language/until_spec.rb +102 -3
  251. data/spec/language/variables_spec.rb +1212 -16
  252. data/spec/language/versions/array_1.9.rb +39 -0
  253. data/spec/language/versions/case_1.9.rb +20 -0
  254. data/spec/language/versions/hash_1.9.rb +18 -0
  255. data/spec/language/versions/literal_lambda_1.9.rb +143 -0
  256. data/spec/language/versions/not_1.9.rb +22 -0
  257. data/spec/language/versions/send_1.9.rb +241 -0
  258. data/spec/language/versions/symbol_1.9.rb +15 -0
  259. data/spec/language/versions/variables_1.9.rb +8 -0
  260. data/spec/language/while_spec.rb +70 -5
  261. data/spec/language/yield_spec.rb +32 -6
  262. data/spec/mspec/guards/block_device.rb +0 -0
  263. data/spec/mspec/guards/endian.rb +0 -0
  264. data/spec/mspec/helpers/environment.rb +0 -0
  265. data/spec/mspec/helpers/language_version.rb +0 -0
  266. data/spec/mspec/helpers/tmp.rb +0 -0
  267. data/spec/ospec/filter.rb +32 -0
  268. data/spec/ospec/main.rb.erb +18 -0
  269. data/spec/ospec/phantom.rb +97 -0
  270. data/spec/ospec/runner.rb +95 -0
  271. data/spec/ospec/sprockets.js +40 -0
  272. data/spec/pp.rb +3 -0
  273. data/spec/rbconfig.rb +5 -0
  274. data/spec/spec_helper.rb +53 -26
  275. data/spec/yaml.rb +0 -0
  276. metadata +275 -31
  277. data/config.ru +0 -8
  278. data/lib/opal/processor.rb +0 -47
  279. data/lib/opal/scope.rb +0 -236
  280. data/lib/opal/server.rb +0 -94
  281. data/spec/core/boolean/and_spec.rb +0 -17
  282. data/spec/core/boolean/inspect_spec.rb +0 -9
  283. data/spec/core/boolean/or_spec.rb +0 -17
  284. data/spec/core/boolean/to_s_spec.rb +0 -9
  285. data/spec/core/boolean/xor_spec.rb +0 -17
@@ -1,3 +1,5 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
1
3
  class UndefSpecClass
2
4
  def meth(other);other;end
3
5
  end
@@ -11,4 +13,4 @@ describe "The undef keyword" do
11
13
  end
12
14
  lambda { obj.meth 5 }.should raise_error(NoMethodError)
13
15
  end
14
- end
16
+ end
@@ -1,3 +1,5 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
1
3
  describe "The unless expression" do
2
4
  it "evaluates the unless body when the expression is false" do
3
5
  unless false
@@ -25,7 +27,7 @@ describe "The unless expression" do
25
27
  end.should == 'bar'
26
28
  end
27
29
 
28
- it "takes and optional then after the expression" do
30
+ it "takes an optional then after the expression" do
29
31
  unless false then
30
32
  'baz'
31
33
  end.should == 'baz'
@@ -38,4 +40,6 @@ describe "The unless expression" do
38
40
  it "allows expression and body to be on one line (using 'then')" do
39
41
  unless false then 'foo'; else 'bar'; end.should == 'foo'
40
42
  end
41
- end
43
+ end
44
+
45
+ # language_version __FILE__, "unless"
@@ -1,3 +1,14 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ # until bool-expr [do]
4
+ # body
5
+ # end
6
+ #
7
+ # begin
8
+ # body
9
+ # end until bool-expr
10
+ #
11
+ # expr until bool-expr
1
12
  describe "The until expression" do
2
13
  it "runs while the expression is false" do
3
14
  i = 0
@@ -91,6 +102,18 @@ describe "The until expression" do
91
102
  end
92
103
  a.should == [1, 2, 4]
93
104
  end
105
+
106
+ pending "restarts the current iteration without reevaluating condition with redo" do
107
+ a = []
108
+ i = 0
109
+ j = 0
110
+ until (i+=1)>=3
111
+ a << i
112
+ j+=1
113
+ redo if j<3
114
+ end
115
+ a.should == [1, 1, 1, 2]
116
+ end
94
117
  end
95
118
 
96
119
  describe "The until modifier" do
@@ -104,10 +127,10 @@ describe "The until modifier" do
104
127
  a = []
105
128
  i = 0
106
129
  a << i until (i+=1) >= 3
107
- a.should == [1,2]
130
+ a.should == [1, 2]
108
131
  end
109
132
 
110
- it "does not run the preceding statement if the condition is true" do
133
+ it "does not run preceding statement if the condition is true" do
111
134
  i = 0
112
135
  i += 1 until true
113
136
  i.should == 0
@@ -132,4 +155,80 @@ describe "The until modifier" do
132
155
  ((i+=1) == 3 ? next : j+=i) until i > 10
133
156
  j.should == 63
134
157
  end
135
- end
158
+
159
+ pending "restarts the current iteration without reevaluating condition with redo" do
160
+ i = 0
161
+ j = 0
162
+ (i+=1) == 4 ? redo : j+=i until (i+=1) > 10
163
+ j.should == 34
164
+ end
165
+ end
166
+
167
+ describe "The until modifier with begin .. end block" do
168
+ pending "runs block while the expression is false" do
169
+ i = 0
170
+ begin
171
+ i += 1
172
+ end until i > 9
173
+
174
+ i.should == 10
175
+ end
176
+
177
+ pending "stops running block if interrupted by break" do
178
+ i = 0
179
+ begin
180
+ i += 1
181
+ break if i > 5
182
+ end until i > 9
183
+
184
+ i.should == 6
185
+ end
186
+
187
+ pending "returns value passed to break if interrupted by break" do
188
+ (begin; break 123; end until false).should == 123
189
+ end
190
+
191
+ pending "returns nil if interrupted by break with no arguments" do
192
+ (begin; break; end until false).should == nil
193
+ end
194
+
195
+ pending "runs block at least once (even if the expression is true)" do
196
+ i = 0
197
+ begin
198
+ i += 1
199
+ end until true
200
+
201
+ i.should == 1
202
+ end
203
+
204
+ pending "evaluates condition after block execution" do
205
+ a = []
206
+ i = 0
207
+ begin
208
+ a << i
209
+ end until (i+=1)>=5
210
+ a.should == [0, 1, 2, 3, 4]
211
+ end
212
+
213
+ pending "skips to end of body with next" do
214
+ a = []
215
+ i = 0
216
+ begin
217
+ next if i==3
218
+ a << i
219
+ end until (i+=1)>=5
220
+ a.should == [0, 1, 2, 4]
221
+ end
222
+
223
+ pending "restart the current iteration without reevaluting condition with redo" do
224
+ a = []
225
+ i = 0
226
+ j = 0
227
+ begin
228
+ a << i
229
+ j+=1
230
+ redo if j<3
231
+ end until (i+=1)>=3
232
+ a.should == [0, 0, 0, 1, 2]
233
+ end
234
+ end
@@ -1,3 +1,8 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require File.expand_path('../fixtures/variables', __FILE__)
3
+
4
+ # TODO: partition these specs into distinct cases based on the
5
+ # real parsed forms, not the superficial code forms.
1
6
  describe "Basic assignment" do
2
7
  it "allows the rhs to be assigned to the lhs" do
3
8
  a = nil
@@ -9,19 +14,86 @@ describe "Basic assignment" do
9
14
  a.should be_nil
10
15
  end
11
16
 
12
- it "assigns [] to lhs when rhs is an empty splat expression" do
13
- a = *()
14
- a.should == []
17
+ ruby_version_is "" ... "1.9" do
18
+ it "assigns nil to lhs when rhs is an empty splat expression" do
19
+ a = *()
20
+ a.should be_nil
21
+ end
22
+ end
23
+
24
+ ruby_version_is "1.9" do
25
+ it "assigns [] to lhs when rhs is an empty splat expression" do
26
+ a = *()
27
+ a.should == []
28
+ end
29
+ end
30
+
31
+ ruby_version_is "" ... "1.9" do
32
+ it "allows the assignment of the rhs to the lhs using the rhs splat operator" do
33
+ a = *nil; a.should == nil
34
+ a = *1; a.should == 1
35
+ a = *[]; a.should == nil
36
+ a = *[1]; a.should == 1
37
+ a = *[nil]; a.should == nil
38
+ a = *[[]]; a.should == []
39
+ a = *[1,2]; a.should == [1,2]
40
+ end
15
41
  end
16
42
 
17
- it "allows the assignment of the rhs to the lhs using the rhs splat operator" do
18
- a = *nil; a.should == []
19
- a = *1; a.should == [1]
20
- a = *[]; a.should == []
21
- a = *[1]; a.should == [1]
22
- a = *[nil]; a.should == [nil]
23
- a = *[[]]; a.should == [[]]
24
- a = *[1,2]; a.should == [1,2]
43
+ ruby_version_is "1.9" do
44
+ it "allows the assignment of the rhs to the lhs using the rhs splat operator" do
45
+ a = *nil; a.should == []
46
+ a = *1; a.should == [1]
47
+ a = *[]; a.should == []
48
+ a = *[1]; a.should == [1]
49
+ a = *[nil]; a.should == [nil]
50
+ a = *[[]]; a.should == [[]]
51
+ a = *[1,2]; a.should == [1,2]
52
+ end
53
+ end
54
+
55
+ ruby_version_is "" ... "1.9" do
56
+ it "allows the assignment of the rhs to the lhs using the lhs splat operator" do
57
+ # * = 1,2 # Valid syntax, but pretty useless! Nothing to test
58
+ *a = nil; a.should == [nil]
59
+ *a = 1; a.should == [1]
60
+ *a = []; a.should == [[]]
61
+ *a = [1]; a.should == [[1]]
62
+ *a = [1,2]; a.should == [[1,2]]
63
+ end
64
+ end
65
+
66
+ ruby_version_is "1.9" do
67
+ pending "allows the assignment of the rhs to the lhs using the lhs splat operator" do
68
+ # * = 1,2 # Valid syntax, but pretty useless! Nothing to test
69
+ *a = nil; a.should == [nil]
70
+ *a = 1; a.should == [1]
71
+ *a = []; a.should == []
72
+ *a = [1]; a.should == [1]
73
+ *a = [1,2]; a.should == [1,2]
74
+ end
75
+ end
76
+
77
+ ruby_version_is "" ... "1.9" do
78
+ it "allows the assignment of rhs to the lhs using the lhs and rhs splat operators simultaneously" do
79
+ *a = *nil; a.should == [nil]
80
+ *a = *1; a.should == [1]
81
+ *a = *[]; a.should == []
82
+ *a = *[1]; a.should == [1]
83
+ *a = *[nil]; a.should == [nil]
84
+ *a = *[1,2]; a.should == [1,2]
85
+ end
86
+ end
87
+
88
+ ruby_version_is "1.9" do
89
+ pending "allows the assignment of rhs to the lhs using the lhs and rhs splat operators simultaneously" do
90
+ *a = *nil; a.should == []
91
+ *a = *1; a.should == [1]
92
+ *a = *[]; a.should == []
93
+ *a = *[1]; a.should == [1]
94
+ *a = *[nil]; a.should == [nil]
95
+ *a = *[1,2]; a.should == [1,2]
96
+ end
25
97
  end
26
98
 
27
99
  it "sets unavailable values to nil" do
@@ -42,7 +114,7 @@ describe "Basic assignment" do
42
114
  c.should == []
43
115
  end
44
116
 
45
- it "allows multiple values to be assigned" do
117
+ pending "allows multiple values to be assigned" do
46
118
  a,b,*c = nil; [a,b,c].should == [nil, nil, []]
47
119
  a,b,*c = 1; [a,b,c].should == [1, nil, []]
48
120
  a,b,*c = []; [a,b,c].should == [nil, nil, []]
@@ -52,12 +124,29 @@ describe "Basic assignment" do
52
124
  a,b,*c = [1,2]; [a,b,c].should == [1,2,[]]
53
125
 
54
126
  a,b,*c = *nil; [a,b,c].should == [nil, nil, []]
127
+ a,b,*c = *1; [a,b,c].should == [1, nil, []]
55
128
  a,b,*c = *[]; [a,b,c].should == [nil, nil, []]
129
+ a,b,*c = *[1]; [a,b,c].should == [1, nil, []]
56
130
  a,b,*c = *[nil]; [a,b,c].should == [nil, nil, []]
57
131
  a,b,*c = *[[]]; [a,b,c].should == [[], nil, []]
58
132
  a,b,*c = *[1,2]; [a,b,c].should == [1,2,[]]
59
133
  end
60
134
 
135
+ pending "calls to_a on the given argument when using a splat" do
136
+ a,b = *VariablesSpecs::ArrayLike.new([1,2]); [a,b].should == [1,2]
137
+ end
138
+
139
+ it "supports the {|r,| } form of block assignment" do
140
+ f = lambda {|r,| r.should == []}
141
+ f.call([], *[])
142
+
143
+ f = lambda{|x,| x}
144
+ f.call(42).should == 42
145
+ f.call([42]).should == [42]
146
+ f.call([[42]]).should == [[42]]
147
+ f.call([42,55]).should == [42,55]
148
+ end
149
+
61
150
  it "allows assignment through lambda" do
62
151
  f = lambda {|r,*l| r.should == []; l.should == [1]}
63
152
  f.call([], *[1])
@@ -86,6 +175,13 @@ describe "Basic assignment" do
86
175
  end
87
176
 
88
177
  describe "Assignment using expansion" do
178
+ ruby_version_is "" ... "1.9" do
179
+ it "succeeds without conversion" do
180
+ *x = (1..7).to_a
181
+ x.should == [[1, 2, 3, 4, 5, 6, 7]]
182
+ end
183
+ end
184
+
89
185
  ruby_version_is "1.9" do
90
186
  it "succeeds without conversion" do
91
187
  *x = (1..7).to_a
@@ -94,13 +190,164 @@ describe "Assignment using expansion" do
94
190
  end
95
191
  end
96
192
 
193
+ describe "Basic multiple assignment" do
194
+ describe "with a single RHS value" do
195
+ pending "does not call #to_ary on an Array instance" do
196
+ x = [1, 2]
197
+ x.should_not_receive(:to_ary)
198
+
199
+ a, b = x
200
+ a.should == 1
201
+ b.should == 2
202
+ end
203
+
204
+ pending "does not call #to_a on an Array instance" do
205
+ x = [1, 2]
206
+ x.should_not_receive(:to_a)
207
+
208
+ a, b = x
209
+ a.should == 1
210
+ b.should == 2
211
+ end
212
+
213
+ pending "does not call #to_ary on an Array subclass instance" do
214
+ x = VariablesSpecs::ArraySubclass.new [1, 2]
215
+ x.should_not_receive(:to_ary)
216
+
217
+ a, b = x
218
+ a.should == 1
219
+ b.should == 2
220
+ end
221
+
222
+ pending "does not call #to_a on an Array subclass instance" do
223
+ x = VariablesSpecs::ArraySubclass.new [1, 2]
224
+ x.should_not_receive(:to_a)
225
+
226
+ a, b = x
227
+ a.should == 1
228
+ b.should == 2
229
+ end
230
+
231
+ pending "calls #to_ary on an object" do
232
+ x = mock("single rhs value for masgn")
233
+ x.should_receive(:to_ary).and_return([1, 2])
234
+
235
+ a, b = x
236
+ a.should == 1
237
+ b.should == 2
238
+ end
239
+
240
+ pending "does not call #to_a on an object if #to_ary is not defined" do
241
+ x = mock("single rhs value for masgn")
242
+ x.should_not_receive(:to_a)
243
+
244
+ a, b = x
245
+ a.should == x
246
+ b.should be_nil
247
+ end
248
+
249
+ it "does not call #to_a on a String" do
250
+ x = "one\ntwo"
251
+
252
+ a, b = x
253
+ a.should == x
254
+ b.should be_nil
255
+ end
256
+ end
257
+
258
+ describe "with a splatted single RHS value" do
259
+ pending "does not call #to_ary on an Array instance" do
260
+ x = [1, 2]
261
+ x.should_not_receive(:to_ary)
262
+
263
+ a, b = *x
264
+ a.should == 1
265
+ b.should == 2
266
+ end
267
+
268
+ pending "does not call #to_a on an Array instance" do
269
+ x = [1, 2]
270
+ x.should_not_receive(:to_a)
271
+
272
+ a, b = *x
273
+ a.should == 1
274
+ b.should == 2
275
+ end
276
+
277
+ pending "does not call #to_ary on an Array subclass instance" do
278
+ x = VariablesSpecs::ArraySubclass.new [1, 2]
279
+ x.should_not_receive(:to_ary)
280
+
281
+ a, b = *x
282
+ a.should == 1
283
+ b.should == 2
284
+ end
285
+
286
+ pending "does not call #to_a on an Array subclass instance" do
287
+ x = VariablesSpecs::ArraySubclass.new [1, 2]
288
+ x.should_not_receive(:to_a)
289
+
290
+ a, b = *x
291
+ a.should == 1
292
+ b.should == 2
293
+ end
294
+
295
+ pending "calls #to_a on an object if #to_ary is not defined" do
296
+ x = mock("single splatted rhs value for masgn")
297
+ x.should_receive(:to_a).and_return([1, 2])
298
+
299
+ a, b = *x
300
+ a.should == 1
301
+ b.should == 2
302
+ end
303
+
304
+ ruby_version_is ""..."1.9" do
305
+ it "calls #to_ary on an object" do
306
+ x = mock("single splatted rhs value for masgn")
307
+ x.should_receive(:to_ary).and_return([1, 2])
308
+
309
+ a, b = *x
310
+ a.should == 1
311
+ b.should == 2
312
+ end
313
+
314
+ it "calls #to_a on a String" do
315
+ x = "one\ntwo"
316
+
317
+ a, b = *x
318
+ a.should == "one\n"
319
+ b.should == "two"
320
+ end
321
+ end
322
+
323
+ ruby_version_is "1.9" do
324
+ pending "does not call #to_ary on an object" do
325
+ x = mock("single splatted rhs value for masgn")
326
+ x.should_not_receive(:to_ary)
327
+
328
+ a, b = *x
329
+ a.should == x
330
+ b.should be_nil
331
+ end
332
+
333
+ pending "does not call #to_a on a String" do
334
+ x = "one\ntwo"
335
+
336
+ a, b = *x
337
+ a.should == x
338
+ b.should be_nil
339
+ end
340
+ end
341
+ end
342
+ end
343
+
97
344
  describe "Assigning multiple values" do
98
- it "allows parallel assignment" do
345
+ pending "allows parallel assignment" do
99
346
  a, b = 1, 2
100
347
  a.should == 1
101
348
  b.should == 2
102
349
 
103
- a, = 1,2
350
+ # a, = 1,2
104
351
  a.should == 1
105
352
  end
106
353
 
@@ -111,6 +358,67 @@ describe "Assigning multiple values" do
111
358
  b.should == 1
112
359
  end
113
360
 
361
+ pending do
362
+ not_compliant_on :rubinius do
363
+ pending "returns the rhs values used for assignment as an array" do
364
+ # x = begin; a, b, c = 1, 2, 3; end
365
+ x.should == [1,2,3]
366
+ end
367
+ end
368
+ end
369
+
370
+ ruby_version_is "" ... "1.9" do
371
+ it "wraps a single value in an Array" do
372
+ *a = 1
373
+ a.should == [1]
374
+
375
+ b = [1]
376
+ *a = b
377
+ a.should == [b]
378
+ end
379
+ end
380
+
381
+ ruby_version_is "1.9" do
382
+ it "wraps a single value in an Array if it's not already one" do
383
+ *a = 1
384
+ a.should == [1]
385
+
386
+ b = [1]
387
+ *a = b
388
+ a.should == b
389
+ end
390
+ end
391
+
392
+ it "evaluates rhs left-to-right" do
393
+ a = VariablesSpecs::ParAsgn.new
394
+ d, e ,f = a.inc, a.inc, a.inc
395
+ d.should == 1
396
+ e.should == 2
397
+ f.should == 3
398
+ end
399
+
400
+ pending "supports parallel assignment to lhs args via object.method=" do
401
+ a = VariablesSpecs::ParAsgn.new
402
+ a.x, b = 1, 2
403
+
404
+ a.x.should == 1
405
+ b.should == 2
406
+
407
+ c = VariablesSpecs::ParAsgn.new
408
+ c.x, a.x = a.x, b
409
+
410
+ c.x.should == 1
411
+ a.x.should == 2
412
+ end
413
+
414
+ pending "supports parallel assignment to lhs args using []=" do
415
+ a = [1,2,3]
416
+ a[3], b = 4,5
417
+
418
+ a.should == [1,2,3,4]
419
+ b.should == 5
420
+ end
421
+
114
422
  it "bundles remaining values to an array when using the splat operator" do
115
423
  a, *b = 1, 2, 3
116
424
  a.should == 1
@@ -128,6 +436,659 @@ describe "Assigning multiple values" do
128
436
  a, = *[1]
129
437
  a.should == 1
130
438
  end
439
+
440
+ ruby_version_is ""..."1.9" do
441
+ it "calls #to_ary on rhs arg if rhs has only a single arg" do
442
+ x = VariablesSpecs::ParAsgn.new
443
+ a,b,c = x
444
+ a.should == 1
445
+ b.should == 2
446
+ c.should == 3
447
+
448
+ a,b,c = x,5
449
+ a.should == x
450
+ b.should == 5
451
+ c.should == nil
452
+
453
+ a,b,c = 5,x
454
+ a.should == 5
455
+ b.should == x
456
+ c.should == nil
457
+
458
+ a,b,*c = x,5
459
+ a.should == x
460
+ b.should == 5
461
+ c.should == []
462
+
463
+ # a,(b,c) = 5,x
464
+ a.should == 5
465
+ b.should == 1
466
+ c.should == 2
467
+
468
+ # a,(b,*c) = 5,x
469
+ a.should == 5
470
+ b.should == 1
471
+ c.should == [2,3,4]
472
+
473
+ # a,(b,(*c)) = 5,x
474
+ a.should == 5
475
+ b.should == 1
476
+ c.should == [2]
477
+
478
+ # a,(b,(*c),(*d)) = 5,x
479
+ a.should == 5
480
+ b.should == 1
481
+ c.should == [2]
482
+ d.should == [3]
483
+
484
+ # a,(b,(*c),(d,*e)) = 5,x
485
+ a.should == 5
486
+ b.should == 1
487
+ c.should == [2]
488
+ d.should == 3
489
+ e.should == []
490
+ end
491
+ end
492
+
493
+ ruby_version_is "1.9" do
494
+ pending "calls #to_ary on RHS arg if the corresponding LHS var is a splat" do
495
+ x = VariablesSpecs::ParAsgn.new
496
+
497
+ # a,(*b),c = 5,x
498
+ a.should == 5
499
+ b.should == x.to_ary
500
+ c.should == nil
501
+ end
502
+ end
503
+
504
+ ruby_version_is ""..."1.9" do
505
+ it "doen't call #to_ary on RHS arg when the corresponding LHS var is a splat" do
506
+ x = VariablesSpecs::ParAsgn.new
507
+
508
+ # a,(*b),c = 5,x
509
+ a.should == 5
510
+ b.should == [x]
511
+ c.should == nil
512
+ end
513
+ end
514
+
515
+ pending "allows complex parallel assignment" do
516
+ # a, (b, c), d = 1, [2, 3], 4
517
+ a.should == 1
518
+ b.should == 2
519
+ c.should == 3
520
+ d.should == 4
521
+
522
+ # x, (y, z) = 1, 2, 3
523
+ [x,y,z].should == [1,2,nil]
524
+ # x, (y, z) = 1, [2,3]
525
+ [x,y,z].should == [1,2,3]
526
+ # x, (y, z) = 1, [2]
527
+ [x,y,z].should == [1,2,nil]
528
+
529
+ # a,(b,c,*d),(e,f),*g = 0,[1,2,3,4],[5,6],7,8
530
+ a.should == 0
531
+ b.should == 1
532
+ c.should == 2
533
+ d.should == [3,4]
534
+ e.should == 5
535
+ f.should == 6
536
+ g.should == [7,8]
537
+
538
+ x = VariablesSpecs::ParAsgn.new
539
+ # a,(b,c,*d),(e,f),*g = 0,x,[5,6],7,8
540
+ a.should == 0
541
+ b.should == 1
542
+ c.should == 2
543
+ d.should == [3,4]
544
+ e.should == 5
545
+ f.should == 6
546
+ g.should == [7,8]
547
+ end
548
+
549
+ pending "allows a lhs arg to be used in another lhs args parallel assignment" do
550
+ c = [4,5,6]
551
+ a,b,c[a] = 1,2,3
552
+ a.should == 1
553
+ b.should == 2
554
+ c.should == [4,3,6]
555
+
556
+ c[a],b,a = 7,8,9
557
+ a.should == 9
558
+ b.should == 8
559
+ c.should == [4,7,6]
560
+ end
561
+ end
562
+
563
+ describe "Conditional assignment" do
564
+ it "assigns the lhs if previously unassigned" do
565
+ a=[]
566
+ a[0] ||= "bar"
567
+ a[0].should == "bar"
568
+
569
+ h={}
570
+ h["foo"] ||= "bar"
571
+ h["foo"].should == "bar"
572
+
573
+ h["foo".to_sym] ||= "bar"
574
+ h["foo".to_sym].should == "bar"
575
+
576
+ aa = 5
577
+ aa ||= 25
578
+ aa.should == 5
579
+
580
+ bb ||= 25
581
+ bb.should == 25
582
+
583
+ cc &&=33
584
+ cc.should == nil
585
+
586
+ cc = 5
587
+ cc &&=44
588
+ cc.should == 44
589
+ end
590
+
591
+ it "checks for class variable definition before fetching its value" do
592
+ class VariableSpecCVarSpec
593
+ @@cvarspec ||= 5
594
+ @@cvarspec.should == 5
595
+ end
596
+ end
597
+ end
598
+
599
+ describe "Unconditional operator assignment 'var op= expr'" do
600
+ it "is equivalent to 'var = var op expr'" do
601
+ x = 13
602
+ (x += 5).should == 18
603
+ x.should == 18
604
+
605
+ x = 17
606
+ (x -= 11).should == 6
607
+ x.should == 6
608
+
609
+ x = 2
610
+ (x *= 5).should == 10
611
+ x.should == 10
612
+
613
+ x = 36
614
+ (x /= 9).should == 4
615
+ x.should == 4
616
+
617
+ x = 23
618
+ (x %= 5).should == 3
619
+ x.should == 3
620
+ (x %= 3).should == 0
621
+ x.should == 0
622
+
623
+ x = 2
624
+ (x **= 3).should == 8
625
+ x.should == 8
626
+
627
+ x = 4
628
+ (x |= 3).should == 7
629
+ x.should == 7
630
+ (x |= 4).should == 7
631
+ x.should == 7
632
+
633
+ x = 6
634
+ (x &= 3).should == 2
635
+ x.should == 2
636
+ (x &= 4).should == 0
637
+ x.should == 0
638
+
639
+ # XOR
640
+ x = 2
641
+ (x ^= 3).should == 1
642
+ x.should == 1
643
+ (x ^= 4).should == 5
644
+ x.should == 5
645
+
646
+ # Bit-shift left
647
+ x = 17
648
+ (x <<= 3).should == 136
649
+ x.should == 136
650
+
651
+ # Bit-shift right
652
+ x = 5
653
+ (x >>= 1).should == 2
654
+ x.should == 2
655
+ end
656
+ end
657
+
658
+ describe "Conditional operator assignment 'var op= expr'" do
659
+ it "assigns the lhs if its truthiness is false for ||, true for &&" do
660
+ x = nil
661
+ (x ||= 17).should == 17
662
+ x.should == 17
663
+ (x ||= 2).should == 17
664
+ x.should == 17
665
+
666
+ x = false
667
+ (x &&= true).should == false
668
+ x.should == false
669
+ (x &&= false).should == false
670
+ x.should == false
671
+ x = true
672
+ (x &&= true).should == true
673
+ x.should == true
674
+ (x &&= false).should == false
675
+ x.should == false
676
+ end
677
+
678
+ pending "may not assign at all, depending on the truthiness of lhs" do
679
+ Object.new.instance_eval do
680
+ @falsey = false
681
+ @truthy = true
682
+ freeze
683
+ # lambda{ @truthy ||= 42 }.should_not raise_error
684
+ # lambda{ @falsey &&= 42 }.should_not raise_error
685
+ end
686
+ end
687
+
688
+ pending "uses short-circuit arg evaluation" do
689
+ x = 8
690
+ y = VariablesSpecs::OpAsgn.new
691
+ (x ||= y.do_side_effect).should == 8
692
+ y.side_effect.should == nil
693
+
694
+ x = nil
695
+ (x &&= y.do_side_effect).should == nil
696
+ y.side_effect.should == nil
697
+
698
+ y.a = 5
699
+ (x ||= y.do_side_effect).should == 5
700
+ y.side_effect.should == true
701
+ end
702
+ end
703
+
704
+ describe "Unconditional operator assignment 'obj.meth op= expr'" do
705
+ it "is equivalent to 'obj.meth = obj.meth op expr'" do
706
+ @x = VariablesSpecs::OpAsgn.new
707
+ @x.a = 13
708
+ (@x.a += 5).should == 18
709
+ @x.a.should == 18
710
+
711
+ @x.a = 17
712
+ (@x.a -= 11).should == 6
713
+ @x.a.should == 6
714
+
715
+ @x.a = 2
716
+ (@x.a *= 5).should == 10
717
+ @x.a.should == 10
718
+
719
+ @x.a = 36
720
+ (@x.a /= 9).should == 4
721
+ @x.a.should == 4
722
+
723
+ @x.a = 23
724
+ (@x.a %= 5).should == 3
725
+ @x.a.should == 3
726
+ (@x.a %= 3).should == 0
727
+ @x.a.should == 0
728
+
729
+ @x.a = 2
730
+ (@x.a **= 3).should == 8
731
+ @x.a.should == 8
732
+
733
+ @x.a = 4
734
+ (@x.a |= 3).should == 7
735
+ @x.a.should == 7
736
+ (@x.a |= 4).should == 7
737
+ @x.a.should == 7
738
+
739
+ @x.a = 6
740
+ (@x.a &= 3).should == 2
741
+ @x.a.should == 2
742
+ (@x.a &= 4).should == 0
743
+ @x.a.should == 0
744
+
745
+ # XOR
746
+ @x.a = 2
747
+ (@x.a ^= 3).should == 1
748
+ @x.a.should == 1
749
+ (@x.a ^= 4).should == 5
750
+ @x.a.should == 5
751
+
752
+ @x.a = 17
753
+ (@x.a <<= 3).should == 136
754
+ @x.a.should == 136
755
+
756
+ @x.a = 5
757
+ (@x.a >>= 1).should == 2
758
+ @x.a.should == 2
759
+ end
760
+ end
761
+
762
+ describe "Conditional operator assignment 'obj.meth op= expr'" do
763
+ it "is equivalent to 'obj.meth op obj.meth = expr'" do
764
+ @x = VariablesSpecs::OpAsgn.new
765
+ @x.a = nil
766
+ (@x.a ||= 17).should == 17
767
+ @x.a.should == 17
768
+ (@x.a ||= 2).should == 17
769
+ @x.a.should == 17
770
+
771
+ @x.a = false
772
+ (@x.a &&= true).should == false
773
+ @x.a.should == false
774
+ (@x.a &&= false).should == false
775
+ @x.a.should == false
776
+ @x.a = true
777
+ (@x.a &&= true).should == true
778
+ @x.a.should == true
779
+ (@x.a &&= false).should == false
780
+ @x.a.should == false
781
+ end
782
+
783
+ pending "may not assign at all, depending on the truthiness of lhs" do
784
+ m = mock("object")
785
+ m.should_receive(:foo).and_return(:truthy)
786
+ m.should_not_receive(:foo=)
787
+ # m.foo ||= 42
788
+
789
+ m.should_receive(:bar).and_return(false)
790
+ m.should_not_receive(:bar=)
791
+ # m.bar &&= 42
792
+ end
793
+
794
+ pending "uses short-circuit arg evaluation" do
795
+ x = 8
796
+ y = VariablesSpecs::OpAsgn.new
797
+ (x ||= y.do_side_effect).should == 8
798
+ y.side_effect.should == nil
799
+
800
+ x = nil
801
+ (x &&= y.do_side_effect).should == nil
802
+ y.side_effect.should == nil
803
+
804
+ y.a = 5
805
+ (x ||= y.do_side_effect).should == 5
806
+ y.side_effect.should == true
807
+ end
808
+ end
809
+
810
+ describe "Operator assignment 'obj.meth op= expr'" do
811
+ pending "evaluates lhs one time" do
812
+ x = VariablesSpecs::OpAsgn.new
813
+ x.a = 5
814
+ (x.do_more_side_effects.a += 5).should == 15
815
+ x.a.should == 15
816
+
817
+ x.a = 5
818
+ (x.do_more_side_effects.a -= 4).should == 6
819
+ x.a.should == 6
820
+
821
+ x.a = 2
822
+ (x.do_more_side_effects.a *= 5).should == 35
823
+ x.a.should == 35
824
+
825
+ x.a = 31
826
+ (x.do_more_side_effects.a /= 9).should == 4
827
+ x.a.should == 4
828
+
829
+ x.a = 18
830
+ (x.do_more_side_effects.a %= 5).should == 3
831
+ x.a.should == 3
832
+
833
+ x.a = 0
834
+ (x.do_more_side_effects.a **= 3).should == 125
835
+ x.a.should == 125
836
+
837
+ x.a = -1
838
+ (x.do_more_side_effects.a |= 3).should == 7
839
+ x.a.should == 7
840
+
841
+ x.a = 1
842
+ (x.do_more_side_effects.a &= 3).should == 2
843
+ x.a.should == 2
844
+
845
+ # XOR
846
+ x.a = -3
847
+ (x.do_more_side_effects.a ^= 3).should == 1
848
+ x.a.should == 1
849
+
850
+ x.a = 12
851
+ (x.do_more_side_effects.a <<= 3).should == 136
852
+ x.a.should == 136
853
+
854
+ x.a = 0
855
+ (x.do_more_side_effects.a >>= 1).should == 2
856
+ x.a.should == 2
857
+
858
+ x.a = nil
859
+ x.b = 0
860
+ # (x.do_bool_side_effects.a ||= 17).should == 17
861
+ # x.a.should == 17
862
+ # x.b.should == 1
863
+
864
+ x.a = false
865
+ x.b = 0
866
+ # # (x.do_bool_side_effects.a &&= true).should == false
867
+ # x.a.should == false
868
+ # x.b.should == 1
869
+ # (x.do_bool_side_effects.a &&= false).should == false
870
+ # x.a.should == false
871
+ # x.b.should == 2
872
+ # x.a = true
873
+ # x.b = 0
874
+ # (x.do_bool_side_effects.a &&= true).should == true
875
+ # x.a.should == true
876
+ # x.b.should == 1
877
+ # (x.do_bool_side_effects.a &&= false).should == false
878
+ # x.a.should == false
879
+ # x.b.should == 2
880
+ end
881
+ end
882
+
883
+ describe "Unconditional operator assignment 'obj[idx] op= expr'" do
884
+ pending "is equivalent to 'obj[idx] = obj[idx] op expr'" do
885
+ # x = [2,13,7]
886
+ # (x[1] += 5).should == 18
887
+ # x.should == [2,18,7]
888
+
889
+ # x = [17,6]
890
+ # (x[0] -= 11).should == 6
891
+ # x.should == [6,6]
892
+
893
+ # x = [nil,2,28]
894
+ # (x[2] *= 2).should == 56
895
+ # x.should == [nil,2,56]
896
+
897
+ # x = [3,9,36]
898
+ # (x[2] /= x[1]).should == 4
899
+ # x.should == [3,9,4]
900
+
901
+ # x = [23,4]
902
+ # (x[0] %= 5).should == 3
903
+ # x.should == [3,4]
904
+ # (x[0] %= 3).should == 0
905
+ # x.should == [0,4]
906
+
907
+ # x = [1,2,3]
908
+ # (x[1] **= 3).should == 8
909
+ # x.should == [1,8,3]
910
+
911
+ # x = [4,5,nil]
912
+ # (x[0] |= 3).should == 7
913
+ # x.should == [7,5,nil]
914
+ # (x[0] |= 4).should == 7
915
+ # x.should == [7,5,nil]
916
+
917
+ # x = [3,6,9]
918
+ # (x[1] &= 3).should == 2
919
+ # x.should == [3,2,9]
920
+ # (x[1] &= 4).should == 0
921
+ # x.should == [3,0,9]
922
+
923
+ # # XOR
924
+ # x = [0,1,2]
925
+ # (x[2] ^= 3).should == 1
926
+ # x.should == [0,1,1]
927
+ # (x[2] ^= 4).should == 5
928
+ # x.should == [0,1,5]
929
+
930
+ # x = [17]
931
+ # (x[0] <<= 3).should == 136
932
+ # x.should == [136]
933
+
934
+ # x = [nil,5,8]
935
+ # (x[1] >>= 1).should == 2
936
+ # x.should == [nil,2,8]
937
+ end
938
+ end
939
+
940
+ describe "Conditional operator assignment 'obj[idx] op= expr'" do
941
+ pending "is equivalent to 'obj[idx] op obj[idx] = expr'" do
942
+ # x = [1,nil,12]
943
+ # (x[1] ||= 17).should == 17
944
+ # x.should == [1,17,12]
945
+ # (x[1] ||= 2).should == 17
946
+ # x.should == [1,17,12]
947
+
948
+ # x = [true, false, false]
949
+ # (x[1] &&= true).should == false
950
+ # x.should == [true, false, false]
951
+ # (x[1] &&= false).should == false
952
+ # x.should == [true, false, false]
953
+ # (x[0] &&= true).should == true
954
+ # x.should == [true, false, false]
955
+ # (x[0] &&= false).should == false
956
+ # x.should == [false, false, false]
957
+ end
958
+
959
+ pending "may not assign at all, depending on the truthiness of lhs" do
960
+ # m = mock("object")
961
+ # m.should_receive(:[]).and_return(:truthy)
962
+ # m.should_not_receive(:[]=)
963
+ # m[:foo] ||= 42
964
+
965
+ # m = mock("object")
966
+ # m.should_receive(:[]).and_return(false)
967
+ # m.should_not_receive(:[]=)
968
+ # m[:bar] &&= 42
969
+ end
970
+
971
+ pending "uses short-circuit arg evaluation" do
972
+ # x = 8
973
+ # y = VariablesSpecs::OpAsgn.new
974
+ # (x ||= y.do_side_effect).should == 8
975
+ # y.side_effect.should == nil
976
+
977
+ # x = nil
978
+ # (x &&= y.do_side_effect).should == nil
979
+ # y.side_effect.should == nil
980
+
981
+ # y.a = 5
982
+ # (x ||= y.do_side_effect).should == 5
983
+ # y.side_effect.should == true
984
+ end
985
+ end
986
+
987
+ describe "Operator assignment 'obj[idx] op= expr'" do
988
+ class ArrayWithDefaultIndex < Array
989
+ def [](index=nil)
990
+ super(index || 0)
991
+ end
992
+
993
+ def []=(first_arg, second_arg=nil)
994
+ if second_arg
995
+ index = fist_arg
996
+ value = second_arg
997
+ else
998
+ index = 0
999
+ value = first_arg
1000
+ end
1001
+
1002
+ super(index, value)
1003
+ end
1004
+ end
1005
+
1006
+ pending "handles empty index (idx) arguments" do
1007
+ # array = ArrayWithDefaultIndex.new
1008
+ # array << 1
1009
+ # (array[] += 5).should == 6
1010
+ end
1011
+
1012
+ pending "handles complex index (idx) arguments" do
1013
+ # x = [1,2,3,4]
1014
+ # (x[0,2] += [5]).should == [1,2,5]
1015
+ # x.should == [1,2,5,3,4]
1016
+ # (x[0,2] += [3,4]).should == [1,2,3,4]
1017
+ # x.should == [1,2,3,4,5,3,4]
1018
+
1019
+ # (x[2..3] += [8]).should == [3,4,8]
1020
+ # x.should == [1,2,3,4,8,5,3,4]
1021
+
1022
+ # y = VariablesSpecs::OpAsgn.new
1023
+ # y.a = 1
1024
+ # (x[y.do_side_effect] *= 2).should == 4
1025
+ # x.should == [1,4,3,4,8,5,3,4]
1026
+
1027
+ # h = {'key1' => 23, 'key2' => 'val'}
1028
+ # (h['key1'] %= 5).should == 3
1029
+ # (h['key2'] += 'ue').should == 'value'
1030
+ # h.should == {'key1' => 3, 'key2' => 'value'}
1031
+ end
1032
+
1033
+ pending "handles empty splat index (idx) arguments" do
1034
+ # array = ArrayWithDefaultIndex.new
1035
+ # array << 5
1036
+ # splat_index = []
1037
+
1038
+ # (array[*splat_index] += 5).should == 10
1039
+ # array.should== [10]
1040
+ end
1041
+
1042
+ pending "handles single splat index (idx) arguments" do
1043
+ # array = [1,2,3,4]
1044
+ # splat_index = [0]
1045
+
1046
+ # (array[*splat_index] += 5).should == 6
1047
+ # array.should == [6,2,3,4]
1048
+ end
1049
+
1050
+ pending "handles multiple splat index (idx) arguments" do
1051
+ # array = [1,2,3,4]
1052
+ # splat_index = [0,2]
1053
+
1054
+ # (array[*splat_index] += [5]).should == [1,2,5]
1055
+ # array.should == [1,2,5,3,4]
1056
+ end
1057
+
1058
+ pending "handles splat index (idx) arguments with normal arguments" do
1059
+ # array = [1,2,3,4]
1060
+ # splat_index = [2]
1061
+
1062
+ # (array[0, *splat_index] += [5]).should == [1,2,5]
1063
+ # array.should == [1,2,5,3,4]
1064
+ end
1065
+
1066
+ # This example fails on 1.9 because of bug #2050
1067
+ pending "returns result of rhs not result of []=" do
1068
+ # a = VariablesSpecs::Hashalike.new
1069
+
1070
+ # (a[123] = 2).should == 2
1071
+ # (a[123] += 2).should == 125
1072
+ # (a[123] -= 2).should == 121
1073
+ # (a[123] *= 2).should == 246
1074
+ # # Guard against the Mathn library
1075
+ # # TODO: Make these specs not rely on specific behaviour / result values
1076
+ # # by using mocks.
1077
+ # conflicts_with :Prime do
1078
+ # (a[123] /= 2).should == 61
1079
+ # end
1080
+ # (a[123] %= 2).should == 1
1081
+ # (a[123] **= 2).should == 15129
1082
+ # (a[123] |= 2).should == 123
1083
+ # (a[123] &= 2).should == 2
1084
+ # (a[123] ^= 2).should == 121
1085
+ # (a[123] <<= 2).should == 492
1086
+ # (a[123] >>= 2).should == 30
1087
+ # (a[123] ||= 2).should == 123
1088
+ # (a[nil] ||= 2).should == 2
1089
+ # (a[123] &&= 2).should == 2
1090
+ # (a[nil] &&= 2).should == nil
1091
+ end
131
1092
  end
132
1093
 
133
1094
  describe "Single assignment" do
@@ -147,7 +1108,7 @@ describe "Single assignment" do
147
1108
  end
148
1109
 
149
1110
  it "If rhs has multiple arguments, lhs becomes an Array of them" do
150
- a = [1, 2, 3]
1111
+ a = 1, 2, 3
151
1112
  a.should == [1, 2, 3]
152
1113
 
153
1114
  a = 1, (), 3
@@ -176,4 +1137,239 @@ describe "Multiple assignment without grouping or splatting" do
176
1137
  a.should == 1
177
1138
  b.should == 2
178
1139
  end
179
- end
1140
+
1141
+ it "The assignments are done in parallel so that lhs and rhs are independent of eachother without copying" do
1142
+ o_of_a, o_of_b = mock('a'), mock('b')
1143
+ a, b = o_of_a, o_of_b
1144
+ a, b = b, a
1145
+ a.should equal(o_of_b)
1146
+ b.should equal(o_of_a)
1147
+ end
1148
+ end
1149
+
1150
+ describe "Multiple assignments with splats" do
1151
+ ruby_version_is ""..."1.9" do
1152
+ it "* on the lhs has to be applied to the last parameter" do
1153
+ lambda { eval 'a, *b, c = 1, 2, 3' }.should raise_error(SyntaxError)
1154
+ end
1155
+ end
1156
+
1157
+ it "* on the lhs collects all parameters from its position onwards as an Array or an empty Array" do
1158
+ a, *b = 1, 2
1159
+ c, *d = 1
1160
+ e, *f = 1, 2, 3
1161
+ g, *h = 1, [2, 3]
1162
+ *i = 1, [2,3]
1163
+ *k = 1,2,3
1164
+
1165
+ a.should == 1
1166
+ b.should == [2]
1167
+ c.should == 1
1168
+ d.should == []
1169
+ e.should == 1
1170
+ f.should == [2, 3]
1171
+ g.should == 1
1172
+ h.should == [[2, 3]]
1173
+ i.should == [1, [2, 3]]
1174
+ k.should == [1,2,3]
1175
+ end
1176
+
1177
+ ruby_version_is ""..."1.9" do
1178
+ it "* on the LHS returns the Array on the RHS enclosed in an Array" do
1179
+ *j = [1,2,3]
1180
+ j.should == [[1,2,3]]
1181
+ end
1182
+ end
1183
+
1184
+ ruby_version_is "1.9" do
1185
+ it "* on the LHS returns the Array on the RHS without enclosing it in an Array" do
1186
+ *j = [1,2,3]
1187
+ j.should == [1,2,3]
1188
+ end
1189
+ end
1190
+ end
1191
+
1192
+ describe "Multiple assignments with grouping" do
1193
+ pending "A group on the lhs is considered one position and treats its corresponding rhs position like an Array" do
1194
+ # a, (b, c), d = 1, 2, 3, 4
1195
+ # e, (f, g), h = 1, [2, 3, 4], 5
1196
+ # i, (j, k), l = 1, 2, 3
1197
+ a.should == 1
1198
+ b.should == 2
1199
+ c.should == nil
1200
+ d.should == 3
1201
+ e.should == 1
1202
+ f.should == 2
1203
+ g.should == 3
1204
+ h.should == 5
1205
+ i.should == 1
1206
+ j.should == 2
1207
+ k.should == nil
1208
+ l.should == 3
1209
+ end
1210
+
1211
+ pending "supports multiple levels of nested groupings" do
1212
+ # a,(b,(c,d)) = 1,[2,[3,4]]
1213
+ a.should == 1
1214
+ b.should == 2
1215
+ c.should == 3
1216
+ d.should == 4
1217
+
1218
+ # a,(b,(c,d)) = [1,[2,[3,4]]]
1219
+ a.should == 1
1220
+ b.should == 2
1221
+ c.should == 3
1222
+ d.should == 4
1223
+
1224
+ x = [1,[2,[3,4]]]
1225
+ # a,(b,(c,d)) = x
1226
+ a.should == 1
1227
+ b.should == 2
1228
+ c.should == 3
1229
+ d.should == 4
1230
+ end
1231
+
1232
+ pending "rhs cannot use parameter grouping, it is a syntax error" do
1233
+ lambda { eval '(a, b) = (1, 2)' }.should raise_error(SyntaxError)
1234
+ end
1235
+ end
1236
+
1237
+ # TODO: merge the following two describe blocks and partition the specs
1238
+ # into distinct cases.
1239
+ describe "Multiple assignment" do
1240
+ pending do
1241
+ not_compliant_on :rubinius do
1242
+ it "has the proper return value" do
1243
+ # (a,b,*c = *[5,6,7,8,9,10]).should == [5,6,7,8,9,10]
1244
+ # (d,e = VariablesSpecs.reverse_foo(4,3)).should == [3,4]
1245
+ # (f,g,h = VariablesSpecs.reverse_foo(6,7)).should == [7,6]
1246
+ # (i,*j = *[5,6,7]).should == [5,6,7]
1247
+ # (k,*l = [5,6,7]).should == [5,6,7]
1248
+ a.should == 5
1249
+ b.should == 6
1250
+ c.should == [7,8,9,10]
1251
+ d.should == 3
1252
+ e.should == 4
1253
+ f.should == 7
1254
+ g.should == 6
1255
+ h.should == nil
1256
+ i.should == 5
1257
+ j.should == [6,7]
1258
+ k.should == 5
1259
+ l.should == [6,7]
1260
+ end
1261
+ end
1262
+ end
1263
+
1264
+ # TODO: write Rubinius versions
1265
+ end
1266
+
1267
+ # For now, masgn is deliberately non-compliant with MRI wrt the return val from an masgn.
1268
+ # Rubinius returns true as the result of the assignment, but MRI returns an array
1269
+ # containing all the elements on the rhs. As this result is never used, the cost
1270
+ # of creating and then discarding this array is avoided
1271
+ describe "Multiple assignment, array-style" do
1272
+ pending do
1273
+ not_compliant_on :rubinius do
1274
+ it "returns an array of all rhs values" do
1275
+ (a,b = 5,6,7).should == [5,6,7]
1276
+ a.should == 5
1277
+ b.should == 6
1278
+
1279
+ (c,d,*e = 99,8).should == [99,8]
1280
+ c.should == 99
1281
+ d.should == 8
1282
+ e.should == []
1283
+
1284
+ (f,g,h = 99,8).should == [99,8]
1285
+ f.should == 99
1286
+ g.should == 8
1287
+ h.should == nil
1288
+ end
1289
+ end
1290
+
1291
+ deviates_on :rubinius do
1292
+ it "returns true" do
1293
+ (a,b = 5,6,7).should == true
1294
+ a.should == 5
1295
+ b.should == 6
1296
+
1297
+ (c,d,*e = 99,8).should == true
1298
+ c.should == 99
1299
+ d.should == 8
1300
+ e.should == []
1301
+
1302
+ (f,g,h = 99,8).should == true
1303
+ f.should == 99
1304
+ g.should == 8
1305
+ h.should == nil
1306
+ end
1307
+ end
1308
+ end
1309
+ end
1310
+
1311
+ describe "Scope of variables" do
1312
+ pending "instance variables not overwritten by local variable in each block" do
1313
+
1314
+ class ScopeVariables
1315
+ attr_accessor :v
1316
+
1317
+ def initialize
1318
+ @v = ['a', 'b', 'c']
1319
+ end
1320
+
1321
+ def check_access
1322
+ v.should == ['a', 'b', 'c']
1323
+ self.v.should == ['a', 'b', 'c']
1324
+ end
1325
+
1326
+ def check_local_variable
1327
+ v = nil
1328
+ self.v.should == ['a', 'b', 'c']
1329
+ end
1330
+
1331
+ def check_each_block
1332
+ self.v.each { |v|
1333
+ # Don't actually do anything
1334
+ }
1335
+ self.v.should == ['a', 'b', 'c']
1336
+ v.should == ['a', 'b', 'c']
1337
+ self.v.object_id.should == v.object_id
1338
+ end
1339
+ end # Class ScopeVariables
1340
+
1341
+ instance = ScopeVariables.new()
1342
+ instance.check_access
1343
+ instance.check_local_variable
1344
+ instance.check_each_block
1345
+ end
1346
+ end
1347
+
1348
+ describe "A local variable in a #define_method scope" do
1349
+ pending do
1350
+ ruby_bug '#1322', '1.8.7.228' do
1351
+ it "shares the lexical scope containing the call to #define_method" do
1352
+ # We need a new scope to reproduce this bug.
1353
+ handle = mock("handle for containing scope method")
1354
+
1355
+ def handle.produce_bug
1356
+ local = 1
1357
+
1358
+ klass = Class.new
1359
+ klass.send :define_method, :set_local do |arg|
1360
+ lambda { local = 2 }.call
1361
+ end
1362
+
1363
+ # We must call with at least one argument to reproduce the bug.
1364
+ klass.new.set_local(nil)
1365
+
1366
+ local
1367
+ end
1368
+
1369
+ handle.produce_bug.should == 2
1370
+ end
1371
+ end
1372
+ end
1373
+ end
1374
+
1375
+ # # language_version __FILE__, "variables"