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
@@ -0,0 +1,55 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "The not keyword" do
4
+ it "negates a `true' value" do
5
+ (not true).should be_false
6
+ (not 'true').should be_false
7
+ end
8
+
9
+ it "negates a `false' value" do
10
+ (not false).should be_true
11
+ (not nil).should be_true
12
+ end
13
+
14
+ it "accepts an argument" do
15
+ lambda do
16
+ not(true)
17
+ end.should_not raise_error(SyntaxError)
18
+ end
19
+
20
+ it "returns false if the argument is true" do
21
+ (not(true)).should be_false
22
+ end
23
+
24
+ it "returns true if the argument is false" do
25
+ (not(false)).should be_true
26
+ end
27
+
28
+ it "returns true if the argument is nil" do
29
+ (not(nil)).should be_true
30
+ end
31
+ end
32
+
33
+ # language_version __FILE__, "not"
34
+
35
+ describe "The `!' keyword" do
36
+ it "negates a `true' value" do
37
+ (!true).should be_false
38
+ (!'true').should be_false
39
+ end
40
+
41
+ it "negates a `false' value" do
42
+ (!false).should be_true
43
+ (!nil).should be_true
44
+ end
45
+
46
+ it "turns a truthful object into `true'" do
47
+ (!!true).should be_true
48
+ (!!'true').should be_true
49
+ end
50
+
51
+ it "turns a not truthful object into `false'" do
52
+ (!!false).should be_false
53
+ (!!nil).should be_false
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Ruby numbers in various ways" do
4
+
5
+ it "the standard way" do
6
+ 435.should == 435
7
+ end
8
+
9
+ it "with underscore separations" do
10
+ 4_35.should == 435
11
+ end
12
+
13
+ it "with some decimals" do
14
+ 4.35.should == 4.35
15
+ end
16
+
17
+ it "with decimals but no integer part should be a SyntaxError" do
18
+ lambda { eval(".75") }.should raise_error(SyntaxError)
19
+ lambda { eval("-.75") }.should raise_error(SyntaxError)
20
+ end
21
+
22
+ # TODO : find a better description
23
+ it "using the e expression" do
24
+ 1.2e-3.should == 0.0012
25
+ end
26
+
27
+ pending "the hexdecimal notation" do
28
+ 0xffff.should == 65535
29
+ end
30
+
31
+ pending "the binary notation" do
32
+ # 0b01011.should == 11
33
+ end
34
+
35
+ pending "octal representation" do
36
+ 0377.should == 255
37
+ end
38
+
39
+ ruby_version_is '' ... '1.9' do
40
+ it "character to numeric shortcut" do
41
+ ?z.should == 122
42
+ end
43
+
44
+ it "character with control character to numeric shortcut" do
45
+ # Control-Z
46
+ #?\C-z.should == 26
47
+
48
+ # Meta-Z
49
+ #?\M-z.should == 250
50
+
51
+ # Meta-Control-Z
52
+ #?\M-\C-z.should == 154
53
+ end
54
+ end
55
+
56
+ end
@@ -1,3 +1,5 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
1
3
  describe "The || operator" do
2
4
  it "evaluates to true if any of its operands are true" do
3
5
  if false || true || nil
@@ -6,7 +8,7 @@ describe "The || operator" do
6
8
  x.should == true
7
9
  end
8
10
 
9
- it "evaluates to false if all of its operands are false" do
11
+ it "evaluated to false if all of its operands are false" do
10
12
  if false || nil
11
13
  x = true
12
14
  end
@@ -30,6 +32,19 @@ describe "The || operator" do
30
32
  (false || ()).should be_nil
31
33
  (() || ()).should be_nil
32
34
  end
35
+
36
+ it "has a higher precedence than 'break' in 'break true || false'" do
37
+ # see also 'break true or false' below
38
+ lambda { break false || true }.call.should be_true
39
+ end
40
+
41
+ it "has a higher precedence than 'next' in 'next true || false'" do
42
+ lambda { next false || true }.call.should be_true
43
+ end
44
+
45
+ it "has a higher precedence than 'return' in 'return true || false'" do
46
+ lambda { return false || true }.call.should be_true
47
+ end
33
48
  end
34
49
 
35
50
  describe "The or operator" do
@@ -47,7 +62,7 @@ describe "The or operator" do
47
62
  end
48
63
 
49
64
  it "has a lower precedence than the || operator" do
50
- x = y= nil
65
+ x,y = nil
51
66
  x = true || false or y = 1
52
67
  y.should == nil
53
68
  end
@@ -59,4 +74,17 @@ describe "The or operator" do
59
74
  (false or ()).should be_nil
60
75
  (() or ()).should be_nil
61
76
  end
62
- end
77
+
78
+ it "has a lower precedence than 'break' in 'break true or false'" do
79
+ # see also 'break true || false' above
80
+ lambda { eval "break true or false" }.should raise_error(SyntaxError, /void value expression/)
81
+ end
82
+
83
+ pending "has a lower precedence than 'next' in 'next true or false'" do
84
+ lambda { eval "next true or false" }.should raise_error(SyntaxError, /void value expression/)
85
+ end
86
+
87
+ it "has a lower precedence than 'return' in 'return true or false'" do
88
+ lambda { eval "return true or false" }.should raise_error(SyntaxError, /void value expression/)
89
+ end
90
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "A method call" do
4
+ before :each do
5
+ @obj = Object.new
6
+ def @obj.foo0(&a)
7
+ [a ? a.call : nil]
8
+ end
9
+ def @obj.foo1(a, &b)
10
+ [a, b ? b.call : nil]
11
+ end
12
+ def @obj.foo2(a, b, &c)
13
+ [a, b, c ? c.call : nil]
14
+ end
15
+ def @obj.foo3(a, b, c, &d)
16
+ [a, b, c, d ? d.call : nil]
17
+ end
18
+ def @obj.foo4(a, b, c, d, &e)
19
+ [a, b, c, d, e ? e.call : nil]
20
+ end
21
+ end
22
+
23
+ it "evaluates the receiver first" do
24
+ (obj = @obj).foo1(obj = nil).should == [nil, nil]
25
+ (obj = @obj).foo2(obj = nil, obj = nil).should == [nil, nil, nil]
26
+ (obj = @obj).foo3(obj = nil, obj = nil, obj = nil).should == [nil, nil, nil, nil]
27
+ (obj = @obj).foo4(obj = nil, obj = nil, obj = nil, obj = nil).should == [nil, nil, nil, nil, nil]
28
+ end
29
+
30
+ pending "evaluates arguments after receiver" do
31
+ a = 0
32
+ # (a += 1; @obj).foo1(a).should == [1, nil]
33
+ # (a += 1; @obj).foo2(a, a).should == [2, 2, nil]
34
+ # (a += 1; @obj).foo3(a, a, a).should == [3, 3, 3, nil]
35
+ # (a += 1; @obj).foo4(a, a, a, a).should == [4, 4, 4, 4, nil]
36
+ a.should == 4
37
+ end
38
+
39
+ it "evaluates arguments left-to-right" do
40
+ a = 0
41
+ @obj.foo1(a += 1).should == [1, nil]
42
+ @obj.foo2(a += 1, a += 1).should == [2, 3, nil]
43
+ @obj.foo3(a += 1, a += 1, a += 1).should == [4, 5, 6, nil]
44
+ @obj.foo4(a += 1, a += 1, a += 1, a += 1).should == [7, 8, 9, 10, nil]
45
+ a.should == 10
46
+ end
47
+
48
+ pending do
49
+ ruby_bug "redmine #1034", "1.8" do
50
+ pending "evaluates block pass after arguments" do
51
+ a = 0
52
+ p = proc {true}
53
+ # @obj.foo1(a += 1, &(a += 1; p)).should == [1, true]
54
+ # @obj.foo2(a += 1, a += 1, &(a += 1; p)).should == [3, 4, true]
55
+ # @obj.foo3(a += 1, a += 1, a += 1, &(a += 1; p)).should == [6, 7, 8, true]
56
+ # @obj.foo4(a += 1, a += 1, a += 1, a += 1, &(a += 1; p)).should == [10, 11, 12, 13, true]
57
+ a.should == 14
58
+ end
59
+
60
+ pending "evaluates block pass after receiver" do
61
+ p1 = proc {true}
62
+ p2 = proc {false}
63
+ p1.should_not == p2
64
+
65
+ p = p1
66
+ # (p = p2; @obj).foo0(&p).should == [false]
67
+ p = p1
68
+ # (p = p2; @obj).foo1(1, &p).should == [1, false]
69
+ p = p1
70
+ # (p = p2; @obj).foo2(1, 1, &p).should == [1, 1, false]
71
+ p = p1
72
+ # (p = p2; @obj).foo3(1, 1, 1, &p).should == [1, 1, 1, false]
73
+ p = p1
74
+ # (p = p2; @obj).foo4(1, 1, 1, 1, &p).should == [1, 1, 1, 1, false]
75
+ p = p1
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,483 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ # Specifying the behavior of operators in combination could
4
+ # lead to combinatorial explosion. A better way seems to be
5
+ # to use a technique from formal proofs that involve a set of
6
+ # equivalent statements. Suppose you have statements A, B, C.
7
+ # If they are claimed to be equivalent, this can be shown by
8
+ # proving that A implies B, B implies C, and C implies A.
9
+ # (Actually any closed circuit of implications.)
10
+ #
11
+ # Here, we can use a similar technique where we show starting
12
+ # at the top that each level of operator has precedence over
13
+ # the level below (as well as showing associativity within
14
+ # the precedence level).
15
+
16
+
17
+ # Excerpted from 'Programming Ruby: The Pragmatic Programmer's Guide'
18
+ # Second Edition by Dave Thomas, Chad Fowler, and Andy Hunt, page 324
19
+
20
+ # Table 22.4. Ruby operators (high to low precedence)
21
+ # Method Operator Description
22
+ # -----------------------------------------------------------------------
23
+ # :: .
24
+ # x* [ ] [ ]= Element reference, element set
25
+ # x ** Exponentiation
26
+ # x ! ~ + - Not, complement, unary plus and minus
27
+ # (method names for the last two are +@ and -@)
28
+ # x * / % Multiply, divide, and modulo
29
+ # x + - Plus and minus
30
+ # x >> << Right and left shift
31
+ # x & “And” (bitwise for integers)
32
+ # x ^ | Exclusive “or” and regular “or” (bitwise for integers)
33
+ # x <= < > >= Comparison operators
34
+ # x <=> == === != =~ !~ Equality and pattern match operators (!=
35
+ # and !~ may not be defined as methods)
36
+ # && Logical “and”
37
+ # || Logical “or”
38
+ # .. ... Range (inclusive and exclusive)
39
+ # ? : Ternary if-then-else
40
+ # = %= /= -= += |= &= Assignment
41
+ # >>= <<= *= &&= ||= **=
42
+ # defined? Check if symbol defined
43
+ # not Logical negation
44
+ # or and Logical composition
45
+ # if unless while until Expression modifiers
46
+ # begin/end Block expression
47
+ # -----------------------------------------------------------------------
48
+
49
+ # * Operators marked with 'x' in the Method column are implemented as methods
50
+ # and can be overridden (except != and !~ as noted). (But see the specs
51
+ # below for implementations that define != and !~ as methods.)
52
+
53
+ # ** These are not included in the excerpted table but are shown here for
54
+ # completeness.
55
+
56
+
57
+ # -----------------------------------------------------------------------
58
+ # It seems that this table is not correct as of MRI 1.8.6
59
+ # The correct table derived from MRI's parse.y is as follows:
60
+ #
61
+ # Operator Assoc Description
62
+ #---------------------------------------------------------------
63
+ # ! ~ + > Not, complement, unary plus
64
+ # ** > Exponentiation
65
+ # - > Unary minus
66
+ # * / % < Multiply, divide, and modulo
67
+ # + - < Plus and minus
68
+ # >> << < Right and left shift
69
+ # & < “And” (bitwise for integers)
70
+ # ^ | < Exclusive “or” and regular “or” (bitwise for integers)
71
+ # <= < > >= < Comparison operators
72
+ # <=> == === != =~ !~ no Equality and pattern match operators (!=
73
+ # and !~ may not be defined as methods)
74
+ # && < Logical “and”
75
+ # || < Logical “or”
76
+ # .. ... no Range (inclusive and exclusive)
77
+ # ? : > Ternary if-then-else
78
+ # rescue < Rescue modifier
79
+ # = %= /= -= += |= &= > Assignment
80
+ # >>= <<= *= &&= ||= **=
81
+ # defined? no Check if symbol defined
82
+ # not > Logical negation
83
+ # or and < Logical composition
84
+ # if unless while until no Expression modifiers
85
+ # -----------------------------------------------------------------------
86
+ #
87
+ # [] and []= seem to fall out of here, as well as begin/end
88
+ #
89
+
90
+ # TODO: Resolve these two tables with actual specs. As the comment at the
91
+ # top suggests, these specs need to be reorganized into a single describe
92
+ # block for each operator. The describe block should include an example
93
+ # for associativity (if relevant), an example for any short circuit behavior
94
+ # (e.g. &&, ||, etc.) and an example block for each operator over which the
95
+ # instant operator has immediately higher precedence.
96
+
97
+ describe "Operators" do
98
+ it "! ~ + is right-associative" do
99
+ (!!true).should == true
100
+ (~~0).should == 0
101
+ (++2).should == 2
102
+ end
103
+
104
+ ruby_version_is "" ... "1.9" do
105
+ it "! ~ + have a higher precedence than **" do
106
+ class FalseClass; def **(a); 1000; end; end
107
+ (!0**2).should == 1000
108
+ class FalseClass; undef_method :**; end
109
+
110
+ class UnaryPlusTest; def +@; 50; end; end
111
+ a = UnaryPlusTest.new
112
+ (+a**2).should == 2500
113
+
114
+ (~0**2).should == 1
115
+ end
116
+ end
117
+
118
+ it "** is right-associative" do
119
+ (2**2**3).should == 256
120
+ end
121
+
122
+ it "** has higher precedence than unary minus" do
123
+ (-2**2).should == -4
124
+ end
125
+
126
+ it "unary minus is right-associative" do
127
+ (--2).should == 2
128
+ end
129
+
130
+ pending "unary minus has higher precedence than * / %" do
131
+ class UnaryMinusTest; def -@; 50; end; end
132
+ b = UnaryMinusTest.new
133
+
134
+ (-b * 5).should == 250
135
+ (-b / 5).should == 10
136
+ (-b % 7).should == 1
137
+ end
138
+
139
+ pending "* / % are left-associative" do
140
+ (2*1/2).should == (2*1)/2
141
+ # Guard against the Mathn library
142
+ # TODO: Make these specs not rely on specific behaviour / result values
143
+ # by using mocks.
144
+ conflicts_with :Prime do
145
+ (2*1/2).should_not == 2*(1/2)
146
+ end
147
+
148
+ (10/7/5).should == (10/7)/5
149
+ (10/7/5).should_not == 10/(7/5)
150
+
151
+ (101 % 55 % 7).should == (101 % 55) % 7
152
+ (101 % 55 % 7).should_not == 101 % (55 % 7)
153
+
154
+ (50*20/7%42).should == ((50*20)/7)%42
155
+ (50*20/7%42).should_not == 50*(20/(7%42))
156
+ end
157
+
158
+ it "* / % have higher precedence than + -" do
159
+ (2+2*2).should == 6
160
+ (1+10/5).should == 3
161
+ (2+10%5).should == 2
162
+
163
+ (2-2*2).should == -2
164
+ (1-10/5).should == -1
165
+ (10-10%4).should == 8
166
+ end
167
+
168
+ pending "+ - are left-associative" do
169
+ (2-3-4).should == -5
170
+ (4-3+2).should == 3
171
+
172
+ class BinaryPlusTest < String; alias_method :plus, :+; def +(a); plus(a) + "!"; end; end
173
+ s = BinaryPlusTest.new("a")
174
+
175
+ (s+s+s).should == (s+s)+s
176
+ (s+s+s).should_not == s+(s+s)
177
+ end
178
+
179
+ pending "+ - have higher precedence than >> <<" do
180
+ (2<<1+2).should == 16
181
+ (8>>1+2).should == 1
182
+ (4<<1-3).should == 1
183
+ (2>>1-3).should == 8
184
+ end
185
+
186
+ it ">> << are left-associative" do
187
+ (1 << 2 << 3).should == 32
188
+ (10 >> 1 >> 1).should == 2
189
+ (10 << 4 >> 1).should == 80
190
+ end
191
+
192
+ it ">> << have higher precedence than &" do
193
+ (4 & 2 << 1).should == 4
194
+ (2 & 4 >> 1).should == 2
195
+ end
196
+
197
+ pending "& is left-associative" do
198
+ class BitwiseAndTest; def &(a); a+1; end; end
199
+ c = BitwiseAndTest.new
200
+
201
+ (c & 5 & 2).should == (c & 5) & 2
202
+ (c & 5 & 2).should_not == c & (5 & 2)
203
+ end
204
+
205
+ it "& has higher precedence than ^ |" do
206
+ (8 ^ 16 & 16).should == 24
207
+ (8 | 16 & 16).should == 24
208
+ end
209
+
210
+ pending "^ | are left-associative" do
211
+ class OrAndXorTest; def ^(a); a+10; end; def |(a); a-10; end; end
212
+ d = OrAndXorTest.new
213
+
214
+ (d ^ 13 ^ 16).should == (d ^ 13) ^ 16
215
+ (d ^ 13 ^ 16).should_not == d ^ (13 ^ 16)
216
+
217
+ (d | 13 | 4).should == (d | 13) | 4
218
+ (d | 13 | 4).should_not == d | (13 | 4)
219
+ end
220
+
221
+ it "^ | have higher precedence than <= < > >=" do
222
+ (10 <= 7 ^ 7).should == false
223
+ (10 < 7 ^ 7).should == false
224
+ (10 > 7 ^ 7).should == true
225
+ (10 >= 7 ^ 7).should == true
226
+ (10 <= 7 | 7).should == false
227
+ (10 < 7 | 7).should == false
228
+ (10 > 7 | 7).should == true
229
+ (10 >= 7 | 7).should == true
230
+ end
231
+
232
+ pending "<= < > >= are left-associative" do
233
+ class ComparisonTest
234
+ def <=(a); 0; end;
235
+ def <(a); 0; end;
236
+ def >(a); 0; end;
237
+ def >=(a); 0; end;
238
+ end
239
+
240
+ e = ComparisonTest.new
241
+
242
+ (e <= 0 <= 1).should == (e <= 0) <= 1
243
+ (e <= 0 <= 1).should_not == e <= (0 <= 1)
244
+
245
+ (e < 0 < 1).should == (e < 0) < 1
246
+ (e < 0 < 1).should_not == e < (0 < 1)
247
+
248
+ (e >= 0 >= 1).should == (e >= 0) >= 1
249
+ (e >= 0 >= 1).should_not == e >= (0 >= 1)
250
+
251
+ (e > 0 > 1).should == (e > 0) > 1
252
+ (e > 0 > 1).should_not == e > (0 > 1)
253
+ end
254
+
255
+ ruby_version_is "" ... "1.9" do
256
+ it "<= < > >= have higher precedence than <=> == === != =~ !~" do
257
+ (1 <=> 5 < 1).should == nil
258
+ (1 <=> 5 <= 1).should == nil
259
+ (1 <=> 5 > 1).should == nil
260
+ (1 <=> 5 >= 1).should == nil
261
+
262
+ (1 == 5 < 1).should == false
263
+ (1 == 5 <= 1).should == false
264
+ (1 == 5 > 1).should == false
265
+ (1 == 5 >= 1).should == false
266
+
267
+ (1 === 5 < 1).should == false
268
+ (1 === 5 <= 1).should == false
269
+ (1 === 5 > 1).should == false
270
+ (1 === 5 >= 1).should == false
271
+
272
+ (1 != 5 < 1).should == true
273
+ (1 != 5 <= 1).should == true
274
+ (1 != 5 > 1).should == true
275
+ (1 != 5 >= 1).should == true
276
+
277
+ (1 =~ 5 < 1).should == false
278
+ (1 =~ 5 <= 1).should == false
279
+ (1 =~ 5 > 1).should == false
280
+ (1 =~ 5 >= 1).should == false
281
+
282
+ (1 !~ 5 < 1).should == true
283
+ (1 !~ 5 <= 1).should == true
284
+ (1 !~ 5 > 1).should == true
285
+ (1 !~ 5 >= 1).should == true
286
+ end
287
+ end
288
+
289
+ it "<=> == === != =~ !~ are non-associative" do
290
+ lambda { eval("1 <=> 2 <=> 3") }.should raise_error(SyntaxError)
291
+ lambda { eval("1 == 2 == 3") }.should raise_error(SyntaxError)
292
+ lambda { eval("1 === 2 === 3") }.should raise_error(SyntaxError)
293
+ lambda { eval("1 != 2 != 3") }.should raise_error(SyntaxError)
294
+ lambda { eval("1 =~ 2 =~ 3") }.should raise_error(SyntaxError)
295
+ lambda { eval("1 !~ 2 !~ 3") }.should raise_error(SyntaxError)
296
+ end
297
+
298
+ pending "<=> == === != =~ !~ have higher precedence than &&" do
299
+ (false && 2 <=> 3).should == false
300
+ (false && 3 == false).should == false
301
+ (false && 3 === false).should == false
302
+ (false && 3 != true).should == false
303
+
304
+ class FalseClass; def =~(o); o == false; end; end
305
+ (false && true =~ false).should == (false && (true =~ false))
306
+ (false && true =~ false).should_not == ((false && true) =~ false)
307
+ class FalseClass; undef_method :=~; end
308
+
309
+ (false && true !~ true).should == false
310
+ end
311
+
312
+ # XXX: figure out how to test it
313
+ # (a && b) && c equals to a && (b && c) for all a,b,c values I can imagine so far
314
+ pending "&& is left-associative"
315
+
316
+ it "&& has higher precedence than ||" do
317
+ (true || false && false).should == true
318
+ end
319
+
320
+ # XXX: figure out how to test it
321
+ pending "|| is left-associative"
322
+
323
+ it "|| has higher precedence than .. ..." do
324
+ (1..false||10).should == (1..10)
325
+ (1...false||10).should == (1...10)
326
+ end
327
+
328
+ it ".. ... are non-associative" do
329
+ lambda { eval("1..2..3") }.should raise_error(SyntaxError)
330
+ lambda { eval("1...2...3") }.should raise_error(SyntaxError)
331
+ end
332
+
333
+ # XXX: this is commented now due to a bug in compiler, which cannot
334
+ # distinguish between range and flip-flop operator so far. zenspider is
335
+ # currently working on a new lexer, which will be able to do that.
336
+ # As soon as it's done, these piece should be reenabled.
337
+ #
338
+ # it ".. ... have higher precedence than ? :" do
339
+ # (1..2 ? 3 : 4).should == 3
340
+ # (1...2 ? 3 : 4).should == 3
341
+ # end
342
+
343
+ it "? : is right-associative" do
344
+ (true ? 2 : 3 ? 4 : 5).should == 2
345
+ end
346
+
347
+ def oops; raise end
348
+
349
+ pending "? : has higher precedence than rescue" do
350
+
351
+ (true ? oops : 0 rescue 10).should == 10
352
+ end
353
+
354
+ # XXX: figure how to test it (problem similar to || associativity)
355
+ pending "rescue is left-associative"
356
+
357
+ pending "rescue has higher precedence than =" do
358
+ # a = oops rescue 10
359
+ a.should == 10
360
+
361
+ # rescue doesn't have the same sense for %= /= and friends
362
+ end
363
+
364
+ pending "= %= /= -= += |= &= >>= <<= *= &&= ||= **= are right-associative" do
365
+ # a = b = 10
366
+ # a.should == 10
367
+ # b.should == 10
368
+
369
+ # a = b = 10
370
+ # a %= b %= 3
371
+ # a.should == 0
372
+ # b.should == 1
373
+
374
+ # a = b = 10
375
+ # a /= b /= 2
376
+ # a.should == 2
377
+ # b.should == 5
378
+
379
+ # a = b = 10
380
+ # a -= b -= 2
381
+ # a.should == 2
382
+ # b.should == 8
383
+
384
+ # a = b = 10
385
+ # a += b += 2
386
+ # a.should == 22
387
+ # b.should == 12
388
+
389
+ # a,b = 32,64
390
+ # a |= b |= 2
391
+ # a.should == 98
392
+ # b.should == 66
393
+
394
+ # a,b = 25,13
395
+ # a &= b &= 7
396
+ # a.should == 1
397
+ # b.should == 5
398
+
399
+ # a,b=8,2
400
+ # a >>= b >>= 1
401
+ # a.should == 4
402
+ # b.should == 1
403
+
404
+ # a,b=8,2
405
+ # a <<= b <<= 1
406
+ # a.should == 128
407
+ # b.should == 4
408
+
409
+ # a,b=8,2
410
+ # a *= b *= 2
411
+ # a.should == 32
412
+ # b.should == 4
413
+
414
+ # a,b=10,20
415
+ # a &&= b &&= false
416
+ # a.should == false
417
+ # b.should == false
418
+
419
+ # a,b=nil,nil
420
+ # a ||= b ||= 10
421
+ # a.should == 10
422
+ # b.should == 10
423
+
424
+ # a,b=2,3
425
+ # a **= b **= 2
426
+ # a.should == 512
427
+ # b.should == 9
428
+ end
429
+
430
+ pending "= %= /= -= += |= &= >>= <<= *= &&= ||= **= have higher precedence than defined? operator" do
431
+ # (defined? a = 10).should == "assignment"
432
+ # (defined? a %= 10).should == "assignment"
433
+ # (defined? a /= 10).should == "assignment"
434
+ # (defined? a -= 10).should == "assignment"
435
+ # (defined? a += 10).should == "assignment"
436
+ # (defined? a |= 10).should == "assignment"
437
+ # (defined? a &= 10).should == "assignment"
438
+ # (defined? a >>= 10).should == "assignment"
439
+ # (defined? a <<= 10).should == "assignment"
440
+ # (defined? a *= 10).should == "assignment"
441
+ # (defined? a &&= 10).should == "assignment"
442
+ # (defined? a ||= 10).should == "assignment"
443
+ # (defined? a **= 10).should == "assignment"
444
+ end
445
+
446
+ # XXX: figure out how to test it
447
+ pending "defined? is non-associative"
448
+
449
+ it "defined? has higher precedence than not" do
450
+ # does it have sense?
451
+ (not defined? qqq).should == true
452
+ end
453
+
454
+ it "not is right-associative" do
455
+ (not not false).should == false
456
+ (not not 10).should == true
457
+ end
458
+
459
+ it "not has higher precedence than or/and" do
460
+ (not false and false).should == false
461
+ (not false or true).should == true
462
+ end
463
+
464
+ # XXX: figure out how to test it
465
+ pending "or/and are left-associative"
466
+
467
+ pending "or/and have higher precedence than if unless while until modifiers" do
468
+ (1 if 2 and 3).should == 1
469
+ (1 if 2 or 3).should == 1
470
+
471
+ (1 unless false and true).should == 1
472
+ (1 unless false or false).should == 1
473
+
474
+ (1 while true and false).should == nil # would hang upon error
475
+ (1 while false or false).should == nil
476
+
477
+ ((raise until true and false) rescue 10).should == 10
478
+ (1 until false or true).should == nil # would hang upon error
479
+ end
480
+
481
+ # XXX: it seems to me they are right-associative
482
+ pending "if unless while until are non-associative"
483
+ end