opal 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (796) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +8 -0
  5. data/CONTRIBUTING.md +46 -2
  6. data/Gemfile +17 -0
  7. data/README.md +13 -4
  8. data/Rakefile +22 -119
  9. data/bin/opal +11 -2
  10. data/bin/opal-repl +71 -0
  11. data/corelib/array.rb +554 -356
  12. data/corelib/basic_object.rb +22 -18
  13. data/corelib/boolean.rb +15 -6
  14. data/corelib/class.rb +12 -6
  15. data/corelib/comparable.rb +40 -9
  16. data/corelib/encoding.rb +164 -0
  17. data/corelib/enumerable.rb +532 -300
  18. data/corelib/enumerator.rb +31 -6
  19. data/corelib/error.rb +14 -3
  20. data/corelib/hash.rb +108 -97
  21. data/corelib/io.rb +30 -0
  22. data/corelib/kernel.rb +151 -82
  23. data/corelib/main.rb +7 -0
  24. data/corelib/match_data.rb +118 -0
  25. data/corelib/method.rb +58 -0
  26. data/corelib/module.rb +145 -77
  27. data/corelib/native.rb +144 -22
  28. data/corelib/nil_class.rb +2 -0
  29. data/corelib/numeric.rb +259 -61
  30. data/corelib/opal.rb +43 -28
  31. data/corelib/proc.rb +21 -9
  32. data/corelib/range.rb +42 -23
  33. data/corelib/regexp.rb +51 -9
  34. data/corelib/runtime.js +470 -129
  35. data/corelib/string.rb +170 -246
  36. data/corelib/struct.rb +13 -1
  37. data/corelib/time.rb +414 -43
  38. data/doc/compiler.md +42 -0
  39. data/doc/compiler_options.md +5 -0
  40. data/doc/examples/node_http_server.rb +49 -0
  41. data/doc/external_libraries.md +9 -0
  42. data/doc/generated_javascript.md +272 -0
  43. data/doc/home.md +17 -0
  44. data/doc/method_missing.md +58 -0
  45. data/doc/static_applications.md +60 -0
  46. data/doc/using_ruby_from_javascript.md +18 -0
  47. data/doc/using_sprockets.md +65 -0
  48. data/lib/opal.rb +18 -15
  49. data/lib/opal/builder.rb +26 -9
  50. data/lib/opal/cli.rb +143 -90
  51. data/lib/opal/cli_options.rb +19 -13
  52. data/lib/opal/compiler.rb +307 -0
  53. data/lib/opal/erb.rb +3 -3
  54. data/lib/opal/fragment.rb +34 -0
  55. data/lib/opal/nodes.rb +25 -0
  56. data/lib/opal/nodes/arglist.rb +56 -0
  57. data/lib/opal/nodes/array.rb +54 -0
  58. data/lib/opal/nodes/base.rb +150 -0
  59. data/lib/opal/nodes/base_scope.rb +11 -0
  60. data/lib/opal/nodes/call.rb +195 -0
  61. data/lib/opal/nodes/call_special.rb +153 -0
  62. data/lib/opal/nodes/case.rb +96 -0
  63. data/lib/opal/nodes/class.rb +43 -0
  64. data/lib/opal/nodes/constants.rb +91 -0
  65. data/lib/opal/nodes/def.rb +157 -0
  66. data/lib/opal/nodes/defined.rb +113 -0
  67. data/lib/opal/nodes/definitions.rb +182 -0
  68. data/lib/opal/nodes/hash.rb +67 -0
  69. data/lib/opal/nodes/helpers.rb +105 -0
  70. data/lib/opal/nodes/if.rb +60 -0
  71. data/lib/opal/nodes/iter.rb +118 -0
  72. data/lib/opal/nodes/literal.rb +193 -0
  73. data/lib/opal/nodes/logic.rb +211 -0
  74. data/lib/opal/nodes/masgn.rb +62 -0
  75. data/lib/opal/nodes/module.rb +46 -0
  76. data/lib/opal/nodes/rescue.rb +134 -0
  77. data/lib/opal/nodes/singleton_class.rb +26 -0
  78. data/lib/opal/nodes/super.rb +97 -0
  79. data/lib/opal/nodes/top.rb +63 -0
  80. data/lib/opal/nodes/variables.rb +155 -0
  81. data/lib/opal/nodes/while.rb +65 -0
  82. data/lib/opal/nodes/yield.rb +84 -0
  83. data/lib/opal/parser.rb +294 -2169
  84. data/lib/opal/parser/grammar.rb +5326 -0
  85. data/lib/opal/{grammar.y → parser/grammar.y} +180 -113
  86. data/lib/opal/parser/keywords.rb +64 -0
  87. data/lib/opal/{lexer.rb → parser/lexer.rb} +278 -327
  88. data/lib/opal/{lexer_scope.rb → parser/parser_scope.rb} +2 -5
  89. data/lib/opal/parser/sexp.rb +63 -0
  90. data/lib/opal/source_map.rb +6 -5
  91. data/lib/opal/target_scope.rb +15 -17
  92. data/lib/opal/version.rb +1 -1
  93. data/mri_spec/cli_spec.rb +67 -6
  94. data/opal.gemspec +4 -4
  95. data/spec/config.ru +2 -1
  96. data/spec/corelib/enumerable/all_break_spec.rb +5 -0
  97. data/spec/corelib/enumerable/any_break_spec.rb +5 -0
  98. data/spec/corelib/enumerable/collect_break_spec.rb +13 -0
  99. data/spec/corelib/enumerable/count_break_spec.rb +5 -0
  100. data/spec/corelib/enumerable/detect_break_spec.rb +5 -0
  101. data/spec/corelib/enumerable/drop_while_break_spec.rb +5 -0
  102. data/spec/corelib/enumerable/each_slice_break.rb +6 -0
  103. data/spec/corelib/enumerable/each_with_index_break_spec.rb +5 -0
  104. data/spec/corelib/enumerable/each_with_object_break_spec.rb +5 -0
  105. data/spec/corelib/enumerable/find_all_break_spec.rb +5 -0
  106. data/spec/corelib/enumerable/find_index_break_spec.rb +5 -0
  107. data/spec/corelib/enumerable/grep_break_spec.rb +5 -0
  108. data/spec/corelib/enumerable/max_break_spec.rb +5 -0
  109. data/spec/corelib/enumerable/max_by_break_spec.rb +5 -0
  110. data/spec/corelib/enumerable/min_break_spec.rb +5 -0
  111. data/spec/corelib/enumerable/min_by_break_spec.rb +5 -0
  112. data/spec/corelib/enumerable/none_break_spec.rb +5 -0
  113. data/spec/corelib/enumerable/one_break_spec.rb +5 -0
  114. data/spec/corelib/enumerable/reduce_break_spec.rb +5 -0
  115. data/spec/corelib/enumerable/take_while_break_spec.rb +5 -0
  116. data/spec/{rubyspec → corelib}/fixtures/class.rb +0 -0
  117. data/spec/{rubyspec → corelib}/fixtures/class_variables.rb +0 -0
  118. data/spec/{rubyspec → corelib}/fixtures/constants.rb +0 -0
  119. data/spec/{rubyspec/core → corelib}/kernel/Array_spec.rb +0 -0
  120. data/spec/{opal → corelib}/kernel/block_given_spec.rb +0 -0
  121. data/spec/{opal → corelib}/kernel/class_spec.rb +0 -0
  122. data/spec/{rubyspec/core → corelib}/kernel/define_singleton_method_spec.rb +0 -0
  123. data/spec/{rubyspec/core → corelib}/kernel/equal_value_spec.rb +0 -0
  124. data/spec/{opal → corelib}/kernel/extend_spec.rb +0 -0
  125. data/spec/{opal → corelib}/kernel/format_spec.rb +0 -0
  126. data/spec/{opal → corelib}/kernel/freeze_spec.rb +0 -0
  127. data/spec/{rubyspec/core → corelib}/kernel/instance_eval_spec.rb +0 -0
  128. data/spec/{opal → corelib}/kernel/instance_variable_defined_spec.rb +0 -0
  129. data/spec/{rubyspec/core → corelib}/kernel/instance_variable_get_spec.rb +0 -0
  130. data/spec/{rubyspec/core → corelib}/kernel/instance_variable_set_spec.rb +0 -0
  131. data/spec/{rubyspec/core → corelib}/kernel/loop_spec.rb +0 -0
  132. data/spec/{opal → corelib}/kernel/match_spec.rb +0 -0
  133. data/spec/{opal → corelib}/kernel/method_spec.rb +0 -0
  134. data/spec/{opal → corelib}/kernel/methods_spec.rb +0 -0
  135. data/spec/{opal → corelib}/kernel/nil_spec.rb +0 -0
  136. data/spec/{opal → corelib}/kernel/p_spec.rb +8 -6
  137. data/spec/{opal → corelib}/kernel/printf_spec.rb +4 -2
  138. data/spec/{opal → corelib}/kernel/proc_spec.rb +0 -0
  139. data/spec/{opal → corelib}/kernel/rand_spec.rb +0 -0
  140. data/spec/{opal → corelib}/kernel/respond_to_spec.rb +0 -0
  141. data/spec/{rubyspec/core → corelib}/kernel/send_spec.rb +0 -0
  142. data/spec/{opal → corelib}/kernel/sprintf_spec.rb +0 -0
  143. data/spec/corelib/kernel/warn_spec.rb +83 -0
  144. data/spec/{rubyspec → corelib}/language/block_spec.rb +17 -18
  145. data/spec/{rubyspec → corelib}/language/fixtures/array.rb +0 -0
  146. data/spec/{rubyspec → corelib}/language/fixtures/block.rb +0 -0
  147. data/spec/{rubyspec → corelib}/language/fixtures/break.rb +0 -0
  148. data/spec/{rubyspec → corelib}/language/fixtures/ensure.rb +0 -0
  149. data/spec/{rubyspec → corelib}/language/fixtures/literal_lambda.rb +0 -0
  150. data/spec/{rubyspec → corelib}/language/fixtures/metaclass.rb +0 -0
  151. data/spec/{rubyspec → corelib}/language/fixtures/module.rb +0 -0
  152. data/spec/{rubyspec → corelib}/language/fixtures/next.rb +0 -0
  153. data/spec/{rubyspec → corelib}/language/fixtures/return.rb +0 -0
  154. data/spec/{rubyspec → corelib}/language/fixtures/send.rb +1 -1
  155. data/spec/{rubyspec → corelib}/language/fixtures/send_1.9.rb +0 -0
  156. data/spec/{rubyspec → corelib}/language/fixtures/super.rb +0 -0
  157. data/spec/{rubyspec → corelib}/language/fixtures/variables.rb +0 -0
  158. data/spec/{rubyspec → corelib}/language/fixtures/yield.rb +0 -0
  159. data/spec/{rubyspec → corelib}/language/numbers_spec.rb +0 -2
  160. data/spec/{rubyspec → corelib}/language/predefined_spec.rb +0 -0
  161. data/spec/{rubyspec → corelib}/language/proc_spec.rb +0 -2
  162. data/spec/{rubyspec → corelib}/language/regexp_spec.rb +0 -0
  163. data/spec/{rubyspec → corelib}/language/send_spec.rb +6 -7
  164. data/spec/{rubyspec → corelib}/language/string_spec.rb +0 -0
  165. data/spec/{rubyspec → corelib}/language/symbol_spec.rb +0 -0
  166. data/spec/{rubyspec → corelib}/language/variables_spec.rb +1 -2
  167. data/spec/{rubyspec → corelib}/language/versions/array_1.9.rb +0 -0
  168. data/spec/{rubyspec → corelib}/language/versions/block_1.9.rb +0 -0
  169. data/spec/{rubyspec → corelib}/language/versions/break_1.9.rb +0 -0
  170. data/spec/{rubyspec → corelib}/language/versions/case_1.9.rb +0 -0
  171. data/spec/{rubyspec → corelib}/language/versions/hash_1.9.rb +0 -0
  172. data/spec/{rubyspec → corelib}/language/versions/literal_lambda_1.9.rb +0 -0
  173. data/spec/{rubyspec → corelib}/language/versions/not_1.9.rb +0 -0
  174. data/spec/{rubyspec → corelib}/language/versions/send_1.9.rb +0 -0
  175. data/spec/{rubyspec → corelib}/language/versions/symbol_1.9.rb +0 -0
  176. data/spec/{rubyspec → corelib}/language/versions/variables_1.9.rb +1 -1
  177. data/spec/corelib/module/alias_method_spec.rb +28 -0
  178. data/spec/{opal → corelib}/module/ancestors_spec.rb +0 -0
  179. data/spec/{opal → corelib}/module/append_features_spec.rb +0 -0
  180. data/spec/corelib/module/attr_accessor_spec.rb +26 -0
  181. data/spec/{rubyspec/core → corelib}/module/const_defined_spec.rb +1 -2
  182. data/spec/{rubyspec/core → corelib}/module/const_get_spec.rb +1 -2
  183. data/spec/{rubyspec/core → corelib}/module/const_missing_spec.rb +1 -2
  184. data/spec/{rubyspec/core → corelib}/module/const_set_spec.rb +1 -2
  185. data/spec/{opal → corelib}/module/constants_spec.rb +0 -0
  186. data/spec/{rubyspec/core → corelib}/module/fixtures/classes.rb +0 -0
  187. data/spec/{rubyspec/core → corelib}/module/method_defined_spec.rb +0 -1
  188. data/spec/{opal → corelib}/module/module_function_spec.rb +0 -2
  189. data/spec/corelib/module/name_spec.rb +52 -0
  190. data/spec/{rubyspec/core → corelib}/module/public_method_defined_spec.rb +0 -1
  191. data/spec/{rubyspec/core → corelib}/module/remove_const_spec.rb +0 -1
  192. data/spec/{rubyspec/core → corelib}/module/undef_method_spec.rb +0 -1
  193. data/spec/{opal → corelib}/native/alias_native_spec.rb +7 -0
  194. data/spec/{opal → corelib}/native/each_spec.rb +2 -5
  195. data/spec/{opal → corelib}/native/element_reference_spec.rb +0 -0
  196. data/spec/{rubyspec/core/hash/to_native_spec.rb → corelib/native/ext_spec.rb} +0 -0
  197. data/spec/corelib/native/initialize_spec.rb +17 -0
  198. data/spec/{opal → corelib}/native/method_missing_spec.rb +0 -0
  199. data/spec/corelib/native/new_spec.rb +6 -0
  200. data/spec/{rubyspec/core → corelib}/numeric/abs_spec.rb +0 -0
  201. data/spec/{rubyspec/core → corelib}/numeric/bit_and_spec.rb +0 -0
  202. data/spec/{rubyspec/core → corelib}/numeric/bit_or_spec.rb +0 -0
  203. data/spec/{rubyspec/core → corelib}/numeric/bit_xor_spec.rb +0 -0
  204. data/spec/{rubyspec/core → corelib}/numeric/ceil_spec.rb +0 -0
  205. data/spec/{rubyspec/core → corelib}/numeric/chr_spec.rb +0 -0
  206. data/spec/{rubyspec/core → corelib}/numeric/comparison_spec.rb +0 -0
  207. data/spec/{rubyspec/core → corelib}/numeric/complement_spec.rb +0 -0
  208. data/spec/{rubyspec/core → corelib}/numeric/divide_spec.rb +0 -0
  209. data/spec/{rubyspec/core → corelib}/numeric/downto_spec.rb +0 -0
  210. data/spec/{rubyspec/core → corelib}/numeric/eql_spec.rb +0 -0
  211. data/spec/{rubyspec/core → corelib}/numeric/equal_value_spec.rb +0 -0
  212. data/spec/{rubyspec/core → corelib}/numeric/even_spec.rb +0 -0
  213. data/spec/{rubyspec/core → corelib}/numeric/exponent_spec.rb +0 -0
  214. data/spec/{rubyspec/core → corelib}/numeric/floor_spec.rb +0 -0
  215. data/spec/{rubyspec/core → corelib}/numeric/gt_spec.rb +0 -0
  216. data/spec/{rubyspec/core → corelib}/numeric/gte_spec.rb +0 -0
  217. data/spec/{rubyspec/core → corelib}/numeric/integer_spec.rb +0 -0
  218. data/spec/{rubyspec/core → corelib}/numeric/left_shift_spec.rb +0 -0
  219. data/spec/{rubyspec/core → corelib}/numeric/lt_spec.rb +0 -0
  220. data/spec/{rubyspec/core → corelib}/numeric/lte_spec.rb +0 -0
  221. data/spec/{rubyspec/core → corelib}/numeric/magnitude_spec.rb +0 -0
  222. data/spec/{rubyspec/core → corelib}/numeric/minus_spec.rb +0 -0
  223. data/spec/{rubyspec/core → corelib}/numeric/modulo_spec.rb +0 -0
  224. data/spec/{rubyspec/core → corelib}/numeric/multiply_spec.rb +0 -0
  225. data/spec/{rubyspec/core → corelib}/numeric/next_spec.rb +0 -0
  226. data/spec/{rubyspec/core → corelib}/numeric/odd_spec.rb +0 -0
  227. data/spec/{rubyspec/core → corelib}/numeric/ord_spec.rb +0 -0
  228. data/spec/{rubyspec/core → corelib}/numeric/plus_spec.rb +0 -0
  229. data/spec/{rubyspec/core → corelib}/numeric/pred_spec.rb +0 -0
  230. data/spec/{rubyspec/core → corelib}/numeric/right_shift_spec.rb +0 -0
  231. data/spec/{rubyspec/core → corelib}/numeric/step_spec.rb +0 -3
  232. data/spec/{rubyspec/core → corelib}/numeric/succ_spec.rb +0 -0
  233. data/spec/{rubyspec/core → corelib}/numeric/times_spec.rb +0 -0
  234. data/spec/{rubyspec/core → corelib}/numeric/to_f_spec.rb +0 -0
  235. data/spec/{rubyspec/core → corelib}/numeric/to_i_spec.rb +0 -0
  236. data/spec/{rubyspec/core → corelib}/numeric/to_json_spec.rb +0 -0
  237. data/spec/corelib/numeric/to_s_spec.rb +26 -0
  238. data/spec/{rubyspec/core → corelib}/numeric/uminus_spec.rb +0 -0
  239. data/spec/{rubyspec/core → corelib}/numeric/upto_spec.rb +0 -0
  240. data/spec/{rubyspec/core → corelib}/numeric/zero_spec.rb +0 -0
  241. data/spec/{rubyspec/core → corelib}/proc/call_spec.rb +0 -0
  242. data/spec/{rubyspec/core → corelib}/proc/element_reference_spec.rb +0 -0
  243. data/spec/{opal → corelib}/proc/proc_tricks_spec.rb +0 -0
  244. data/spec/corelib/runtime/begin_spec.rb +39 -0
  245. data/spec/{opal → corelib}/runtime/block_send_spec.rb +0 -0
  246. data/spec/{opal/language → corelib/runtime}/block_spec.rb +10 -0
  247. data/spec/corelib/runtime/bridged_classes_spec.rb +64 -0
  248. data/spec/{opal → corelib/runtime}/constants_spec.rb +0 -0
  249. data/spec/{opal → corelib}/runtime/eval_spec.rb +0 -0
  250. data/spec/{opal → corelib}/runtime/main_methods_spec.rb +0 -0
  251. data/spec/{opal → corelib/runtime}/method_missing_spec.rb +0 -0
  252. data/spec/corelib/runtime/method_spec.rb +31 -0
  253. data/spec/corelib/runtime/paren_spec.rb +14 -0
  254. data/spec/{opal/language → corelib/runtime}/rescue_spec.rb +11 -0
  255. data/spec/{opal/language → corelib/runtime}/return_spec.rb +0 -0
  256. data/spec/{opal → corelib}/runtime/send_spec.rb +0 -0
  257. data/spec/{opal/language → corelib/runtime}/singleton_class_spec.rb +0 -0
  258. data/spec/{opal/language → corelib/runtime}/super_spec.rb +113 -0
  259. data/spec/{opal/language → corelib/runtime}/variables_spec.rb +0 -0
  260. data/spec/{opal → corelib}/source_map_spec.rb +3 -3
  261. data/spec/{rubyspec/core → corelib}/string/chop_spec.rb +0 -0
  262. data/spec/{rubyspec/core → corelib}/string/chr_spec.rb +0 -0
  263. data/spec/{rubyspec/core → corelib}/string/clone_spec.rb +0 -0
  264. data/spec/{rubyspec/core → corelib}/string/comparison_spec.rb +0 -0
  265. data/spec/{rubyspec/core → corelib}/string/dup_spec.rb +0 -0
  266. data/spec/{rubyspec/core → corelib}/string/element_reference_spec.rb +0 -1
  267. data/spec/{rubyspec/core → corelib}/string/fixtures/classes.rb +0 -0
  268. data/spec/{rubyspec/core → corelib}/string/format_spec.rb +0 -0
  269. data/spec/{opal → corelib}/string/freeze_spec.rb +0 -0
  270. data/spec/{rubyspec/core → corelib}/string/gsub_spec.rb +0 -0
  271. data/spec/{rubyspec/core → corelib}/string/lines_spec.rb +0 -0
  272. data/spec/{rubyspec/core → corelib}/string/ljust_spec.rb +0 -1
  273. data/spec/{rubyspec/core → corelib}/string/lstrip_spec.rb +0 -0
  274. data/spec/{rubyspec/core → corelib}/string/match_spec.rb +0 -0
  275. data/spec/{rubyspec/core → corelib}/string/next_spec.rb +0 -0
  276. data/spec/{rubyspec/core → corelib}/string/ord_spec.rb +0 -0
  277. data/spec/{rubyspec/core → corelib}/string/partition_spec.rb +0 -0
  278. data/spec/{rubyspec/core → corelib}/string/rindex_spec.rb +0 -0
  279. data/spec/{rubyspec/core → corelib}/string/rjust_spec.rb +0 -1
  280. data/spec/{rubyspec/core → corelib}/string/rstrip_spec.rb +0 -0
  281. data/spec/{rubyspec/core → corelib}/string/scan_spec.rb +0 -0
  282. data/spec/{rubyspec/core → corelib}/string/slice_spec.rb +1 -2
  283. data/spec/{rubyspec/core → corelib}/string/split_spec.rb +0 -0
  284. data/spec/{rubyspec/core → corelib}/string/strip_spec.rb +0 -0
  285. data/spec/{rubyspec/core → corelib}/string/sub_spec.rb +0 -0
  286. data/spec/{rubyspec/core → corelib}/string/succ_spec.rb +0 -0
  287. data/spec/{rubyspec/core → corelib}/string/sum_spec.rb +0 -0
  288. data/spec/{rubyspec/core → corelib}/string/to_f_spec.rb +0 -0
  289. data/spec/{rubyspec/core → corelib}/string/to_i_spec.rb +0 -0
  290. data/spec/{rubyspec/core → corelib}/string/tr_s_spec.rb +0 -0
  291. data/spec/{rubyspec/core → corelib}/string/tr_spec.rb +0 -0
  292. data/spec/filters/bugs/array.rb +236 -4
  293. data/spec/filters/bugs/basic_object.rb +4 -0
  294. data/spec/filters/bugs/class.rb +4 -0
  295. data/spec/filters/bugs/enumerable.rb +58 -0
  296. data/spec/filters/bugs/enumerator.rb +6 -0
  297. data/spec/filters/bugs/hash.rb +146 -0
  298. data/spec/filters/bugs/kernel.rb +10 -0
  299. data/spec/filters/bugs/language.rb +366 -0
  300. data/spec/filters/bugs/module.rb +14 -0
  301. data/spec/filters/bugs/regexp.rb +7 -0
  302. data/spec/filters/bugs/set.rb +7 -0
  303. data/spec/filters/bugs/{singleton/instance.rb → singleton.rb} +3 -1
  304. data/spec/filters/bugs/string.rb +37 -0
  305. data/spec/filters/bugs/stringscanner.rb +18 -0
  306. data/spec/filters/bugs/struct.rb +11 -0
  307. data/spec/filters/bugs/symbol.rb +5 -0
  308. data/spec/filters/bugs/time.rb +28 -0
  309. data/spec/filters/bugs/unknown.rb +11 -0
  310. data/spec/filters/unsupported/array_subclasses.rb +32 -0
  311. data/spec/filters/unsupported/encoding.rb +14 -0
  312. data/spec/filters/unsupported/float.rb +4 -0
  313. data/spec/filters/unsupported/frozen.rb +57 -0
  314. data/spec/filters/unsupported/hash_compare_by_identity.rb +16 -0
  315. data/spec/filters/unsupported/immutable_strings.rb +6 -0
  316. data/spec/filters/unsupported/mutable_strings.rb +49 -0
  317. data/spec/filters/unsupported/private_methods.rb +26 -0
  318. data/spec/filters/{mspec → unsupported}/ruby_exe.rb +0 -0
  319. data/spec/filters/unsupported/string_subclasses.rb +8 -0
  320. data/spec/filters/unsupported/tainted.rb +46 -0
  321. data/spec/filters/unsupported/time.rb +21 -0
  322. data/spec/filters/unsupported/trusted.rb +26 -0
  323. data/spec/opal/{parser → compiler}/irb_spec.rb +9 -9
  324. data/spec/{parser → opal/parser}/alias_spec.rb +0 -0
  325. data/spec/{parser → opal/parser}/and_spec.rb +0 -0
  326. data/spec/{parser → opal/parser}/array_spec.rb +0 -0
  327. data/spec/{parser → opal/parser}/attrasgn_spec.rb +0 -0
  328. data/spec/{parser → opal/parser}/begin_spec.rb +0 -0
  329. data/spec/{parser → opal/parser}/block_spec.rb +0 -0
  330. data/spec/{parser → opal/parser}/break_spec.rb +0 -0
  331. data/spec/{parser → opal/parser}/call_spec.rb +33 -8
  332. data/spec/{parser → opal/parser}/class_spec.rb +0 -0
  333. data/spec/{parser → opal/parser}/const_spec.rb +0 -0
  334. data/spec/{parser → opal/parser}/cvar_spec.rb +0 -0
  335. data/spec/{parser → opal/parser}/def_spec.rb +17 -17
  336. data/spec/{parser → opal/parser}/false_spec.rb +0 -0
  337. data/spec/{parser → opal/parser}/file_spec.rb +0 -0
  338. data/spec/{parser → opal/parser}/gvar_spec.rb +0 -0
  339. data/spec/{parser → opal/parser}/hash_spec.rb +0 -0
  340. data/spec/opal/parser/heredoc_spec.rb +30 -0
  341. data/spec/{parser → opal/parser}/iasgn_spec.rb +0 -0
  342. data/spec/{parser → opal/parser}/if_spec.rb +0 -0
  343. data/spec/{parser → opal/parser}/int_spec.rb +0 -0
  344. data/spec/opal/parser/iter_spec.rb +59 -0
  345. data/spec/{parser → opal/parser}/ivar_spec.rb +0 -0
  346. data/spec/opal/parser/lambda_spec.rb +64 -0
  347. data/spec/{parser → opal/parser}/lasgn_spec.rb +0 -0
  348. data/spec/{parser → opal/parser}/line_spec.rb +0 -0
  349. data/spec/{parser → opal/parser}/lvar_spec.rb +6 -6
  350. data/spec/{parser → opal/parser}/masgn_spec.rb +0 -0
  351. data/spec/{parser → opal/parser}/module_spec.rb +0 -0
  352. data/spec/{parser → opal/parser}/nil_spec.rb +0 -0
  353. data/spec/{parser → opal/parser}/not_spec.rb +0 -0
  354. data/spec/{parser → opal/parser}/nth_ref_spec.rb +0 -0
  355. data/spec/{parser → opal/parser}/op_asgn1_spec.rb +0 -0
  356. data/spec/{parser → opal/parser}/op_asgn2_spec.rb +0 -0
  357. data/spec/{parser → opal/parser}/or_spec.rb +0 -0
  358. data/spec/{parser → opal/parser}/parse_spec.rb +17 -17
  359. data/spec/{parser → opal/parser}/regexp_spec.rb +0 -0
  360. data/spec/{parser → opal/parser}/return_spec.rb +0 -0
  361. data/spec/{parser → opal/parser}/sclass_spec.rb +0 -0
  362. data/spec/{parser → opal/parser}/self_spec.rb +0 -0
  363. data/spec/{parser → opal/parser}/str_spec.rb +1 -12
  364. data/spec/{parser → opal/parser}/string_spec.rb +0 -0
  365. data/spec/opal/parser/super_spec.rb +20 -0
  366. data/spec/{parser → opal/parser}/true_spec.rb +0 -0
  367. data/spec/{parser → opal/parser}/undef_spec.rb +0 -0
  368. data/spec/{parser → opal/parser}/unless_spec.rb +0 -0
  369. data/spec/{parser → opal/parser}/while_spec.rb +0 -0
  370. data/spec/{parser → opal/parser}/xstr_spec.rb +2 -2
  371. data/spec/{parser → opal/parser}/yield_spec.rb +0 -0
  372. data/spec/ospec/main.rb.erb +1 -13
  373. data/spec/ospec/mspec_fixes.rb +87 -0
  374. data/spec/ospec/runner.rb +188 -0
  375. data/spec/rubyspecs +351 -0
  376. data/spec/spec_helper.rb +8 -198
  377. data/spec/{opal → stdlib}/erb/erb_spec.rb +3 -3
  378. data/spec/{opal → stdlib}/erb/inline_block.opalerb +0 -0
  379. data/spec/{opal → stdlib}/erb/quoted.opalerb +0 -0
  380. data/spec/{opal → stdlib}/erb/simple.opalerb +0 -0
  381. data/spec/stdlib/json/ext_spec.rb +48 -0
  382. data/spec/{opal → stdlib}/json/parse_spec.rb +0 -0
  383. data/spec/stdlib/template/paths_spec.rb +10 -0
  384. data/stdlib/delegate.rb +29 -0
  385. data/stdlib/dir.rb +5 -0
  386. data/stdlib/file.rb +7 -0
  387. data/stdlib/json.rb +82 -27
  388. data/stdlib/opal-parser.rb +46 -0
  389. data/stdlib/opal-source-maps.js.erb +1 -1
  390. data/stdlib/pathname.rb +31 -0
  391. data/stdlib/{racc.rb → racc/parser.rb} +0 -0
  392. data/stdlib/securerandom.rb +12 -0
  393. data/stdlib/set.rb +89 -0
  394. data/stdlib/stringio.rb +12 -4
  395. data/stdlib/strscan.rb +19 -0
  396. data/stdlib/template.rb +4 -0
  397. data/stdlib/thread.rb +20 -0
  398. data/tasks/mspec.rake +147 -0
  399. metadata +650 -1266
  400. data/lib/opal/core_ext.rb +0 -5
  401. data/lib/opal/grammar.rb +0 -5137
  402. data/lib/opal/grammar_helpers.rb +0 -364
  403. data/lib/opal/require_parser.rb +0 -77
  404. data/spec/filters/bugs/alias.rb +0 -6
  405. data/spec/filters/bugs/ancestors.rb +0 -4
  406. data/spec/filters/bugs/array/combination.rb +0 -11
  407. data/spec/filters/bugs/array/count.rb +0 -3
  408. data/spec/filters/bugs/array/delete_if.rb +0 -3
  409. data/spec/filters/bugs/array/drop.rb +0 -3
  410. data/spec/filters/bugs/array/drop_while.rb +0 -5
  411. data/spec/filters/bugs/array/eql.rb +0 -3
  412. data/spec/filters/bugs/array/flatten.rb +0 -9
  413. data/spec/filters/bugs/array/minus.rb +0 -5
  414. data/spec/filters/bugs/array/multipliy.rb +0 -9
  415. data/spec/filters/bugs/array/new.rb +0 -3
  416. data/spec/filters/bugs/array/pop.rb +0 -6
  417. data/spec/filters/bugs/array/rassoc.rb +0 -4
  418. data/spec/filters/bugs/array/rindex.rb +0 -6
  419. data/spec/filters/bugs/array/select.rb +0 -3
  420. data/spec/filters/bugs/array/shift.rb +0 -7
  421. data/spec/filters/bugs/array/shuffle.rb +0 -11
  422. data/spec/filters/bugs/array/slice.rb +0 -7
  423. data/spec/filters/bugs/array/take.rb +0 -3
  424. data/spec/filters/bugs/array/to_a.rb +0 -3
  425. data/spec/filters/bugs/array/try_convert.rb +0 -7
  426. data/spec/filters/bugs/array/uniq.rb +0 -10
  427. data/spec/filters/bugs/array/zip.rb +0 -4
  428. data/spec/filters/bugs/array_delete.rb +0 -4
  429. data/spec/filters/bugs/array_fetch.rb +0 -3
  430. data/spec/filters/bugs/array_first.rb +0 -3
  431. data/spec/filters/bugs/array_flatten.rb +0 -14
  432. data/spec/filters/bugs/array_intersection.rb +0 -5
  433. data/spec/filters/bugs/array_join.rb +0 -6
  434. data/spec/filters/bugs/break.rb +0 -10
  435. data/spec/filters/bugs/case.rb +0 -4
  436. data/spec/filters/bugs/coerce_integer.rb +0 -9
  437. data/spec/filters/bugs/enumerable_sort_by.rb +0 -3
  438. data/spec/filters/bugs/kernel/instance_variables.rb +0 -3
  439. data/spec/filters/bugs/kernel/rand.rb +0 -4
  440. data/spec/filters/bugs/language/array.rb +0 -3
  441. data/spec/filters/bugs/language/block.rb +0 -6
  442. data/spec/filters/bugs/language/break.rb +0 -3
  443. data/spec/filters/bugs/language/class.rb +0 -12
  444. data/spec/filters/bugs/language/class_variables.rb +0 -12
  445. data/spec/filters/bugs/language/def.rb +0 -27
  446. data/spec/filters/bugs/language/defined.rb +0 -3
  447. data/spec/filters/bugs/language/ensure.rb +0 -4
  448. data/spec/filters/bugs/language/execution.rb +0 -4
  449. data/spec/filters/bugs/language/for.rb +0 -18
  450. data/spec/filters/bugs/language/if.rb +0 -13
  451. data/spec/filters/bugs/language/loop.rb +0 -4
  452. data/spec/filters/bugs/language/metaclass.rb +0 -14
  453. data/spec/filters/bugs/language/module.rb +0 -6
  454. data/spec/filters/bugs/language/next.rb +0 -3
  455. data/spec/filters/bugs/language/or.rb +0 -3
  456. data/spec/filters/bugs/language/order.rb +0 -4
  457. data/spec/filters/bugs/language/precedence.rb +0 -10
  458. data/spec/filters/bugs/language/proc.rb +0 -24
  459. data/spec/filters/bugs/language/redo.rb +0 -5
  460. data/spec/filters/bugs/language/rescue.rb +0 -9
  461. data/spec/filters/bugs/language/retry.rb +0 -5
  462. data/spec/filters/bugs/language/send.rb +0 -10
  463. data/spec/filters/bugs/language/super.rb +0 -9
  464. data/spec/filters/bugs/language/until.rb +0 -8
  465. data/spec/filters/bugs/language/variables.rb +0 -37
  466. data/spec/filters/bugs/language/while.rb +0 -6
  467. data/spec/filters/bugs/language/yield.rb +0 -5
  468. data/spec/filters/bugs/module/class_variables.rb +0 -6
  469. data/spec/filters/bugs/module/method_defined.rb +0 -6
  470. data/spec/filters/bugs/public_methods.rb +0 -4
  471. data/spec/filters/bugs/return.rb +0 -7
  472. data/spec/filters/bugs/source_map.rb +0 -3
  473. data/spec/filters/bugs/string/center.rb +0 -4
  474. data/spec/filters/bugs/string/lines.rb +0 -3
  475. data/spec/filters/mspec/mocks.rb +0 -3
  476. data/spec/filters/mspec/should_receive.rb +0 -5
  477. data/spec/filters/parser/block_args.rb +0 -51
  478. data/spec/mspec/guards/block_device.rb +0 -0
  479. data/spec/mspec/guards/endian.rb +0 -0
  480. data/spec/mspec/helpers/environment.rb +0 -0
  481. data/spec/mspec/helpers/language_version.rb +0 -0
  482. data/spec/mspec/helpers/tmp.rb +0 -0
  483. data/spec/opal/array/element_reference_spec.rb +0 -206
  484. data/spec/opal/array/equal_value_spec.rb +0 -19
  485. data/spec/opal/array/fill_spec.rb +0 -26
  486. data/spec/opal/array/reduce_spec.rb +0 -31
  487. data/spec/opal/array/to_json_spec.rb +0 -9
  488. data/spec/opal/basic_object/send_spec.rb +0 -28
  489. data/spec/opal/boolean/singleton_class_spec.rb +0 -9
  490. data/spec/opal/boolean/to_json_spec.rb +0 -11
  491. data/spec/opal/browser/local_storage_spec.rb +0 -55
  492. data/spec/opal/class/constants_spec.rb +0 -7
  493. data/spec/opal/class/extend_spec.rb +0 -47
  494. data/spec/opal/class/instance_methods_spec.rb +0 -13
  495. data/spec/opal/class/last_value_spec.rb +0 -67
  496. data/spec/opal/class/proc_methods_spec.rb +0 -23
  497. data/spec/opal/class/singleton_methods_spec.rb +0 -41
  498. data/spec/opal/hash/allocate_spec.rb +0 -16
  499. data/spec/opal/hash/new_spec.rb +0 -10
  500. data/spec/opal/hash/to_s_spec.rb +0 -9
  501. data/spec/opal/kernel/to_json_spec.rb +0 -7
  502. data/spec/opal/module/alias_method_spec.rb +0 -10
  503. data/spec/opal/module/attr_accessor_spec.rb +0 -8
  504. data/spec/opal/native/new_spec.rb +0 -19
  505. data/spec/opal/native/nil_spec.rb +0 -14
  506. data/spec/opal/nil/to_json_spec.rb +0 -7
  507. data/spec/opal/numeric/equal_spec.rb +0 -9
  508. data/spec/opal/runtime2/call_spec.rb +0 -16
  509. data/spec/opal/runtime2/class_hierarchy_spec.rb +0 -21
  510. data/spec/opal/runtime2/defined_spec.rb +0 -11
  511. data/spec/opal/runtime2/super_spec.rb +0 -16
  512. data/spec/opal/string/to_json_spec.rb +0 -8
  513. data/spec/parser/iter_spec.rb +0 -59
  514. data/spec/parser/lambda_spec.rb +0 -64
  515. data/spec/parser/parser_spec.rb +0 -41
  516. data/spec/parser/strscan/check_spec.rb +0 -13
  517. data/spec/parser/strscan/get_byte_spec.rb +0 -29
  518. data/spec/parser/strscan/scan_spec.rb +0 -33
  519. data/spec/parser/strscan/skip_spec.rb +0 -40
  520. data/spec/parser/super_spec.rb +0 -20
  521. data/spec/rubyspec/core/array/allocate_spec.rb +0 -19
  522. data/spec/rubyspec/core/array/append_spec.rb +0 -43
  523. data/spec/rubyspec/core/array/array_spec.rb +0 -7
  524. data/spec/rubyspec/core/array/assoc_spec.rb +0 -40
  525. data/spec/rubyspec/core/array/at_spec.rb +0 -56
  526. data/spec/rubyspec/core/array/choice_spec.rb +0 -20
  527. data/spec/rubyspec/core/array/clear_spec.rb +0 -61
  528. data/spec/rubyspec/core/array/clone_spec.rb +0 -15
  529. data/spec/rubyspec/core/array/collect_spec.rb +0 -53
  530. data/spec/rubyspec/core/array/combination_spec.rb +0 -55
  531. data/spec/rubyspec/core/array/compact_spec.rb +0 -111
  532. data/spec/rubyspec/core/array/comparison_spec.rb +0 -16
  533. data/spec/rubyspec/core/array/concat_spec.rb +0 -19
  534. data/spec/rubyspec/core/array/constructor_spec.rb +0 -24
  535. data/spec/rubyspec/core/array/count_spec.rb +0 -17
  536. data/spec/rubyspec/core/array/delete_at_spec.rb +0 -71
  537. data/spec/rubyspec/core/array/delete_if_spec.rb +0 -71
  538. data/spec/rubyspec/core/array/delete_spec.rb +0 -104
  539. data/spec/rubyspec/core/array/drop_spec.rb +0 -29
  540. data/spec/rubyspec/core/array/drop_while_spec.rb +0 -17
  541. data/spec/rubyspec/core/array/dup_spec.rb +0 -15
  542. data/spec/rubyspec/core/array/each_index_spec.rb +0 -40
  543. data/spec/rubyspec/core/array/each_spec.rb +0 -30
  544. data/spec/rubyspec/core/array/empty_spec.rb +0 -10
  545. data/spec/rubyspec/core/array/eql_spec.rb +0 -14
  546. data/spec/rubyspec/core/array/fetch_spec.rb +0 -52
  547. data/spec/rubyspec/core/array/find_index_spec.rb +0 -8
  548. data/spec/rubyspec/core/array/first_spec.rb +0 -89
  549. data/spec/rubyspec/core/array/fixtures/classes.rb +0 -538
  550. data/spec/rubyspec/core/array/flatten_spec.rb +0 -232
  551. data/spec/rubyspec/core/array/frozen_spec.rb +0 -32
  552. data/spec/rubyspec/core/array/include_spec.rb +0 -33
  553. data/spec/rubyspec/core/array/index_spec.rb +0 -6
  554. data/spec/rubyspec/core/array/insert_spec.rb +0 -90
  555. data/spec/rubyspec/core/array/inspect_spec.rb +0 -7
  556. data/spec/rubyspec/core/array/intersection_spec.rb +0 -78
  557. data/spec/rubyspec/core/array/join_spec.rb +0 -34
  558. data/spec/rubyspec/core/array/keep_if_spec.rb +0 -12
  559. data/spec/rubyspec/core/array/last_spec.rb +0 -88
  560. data/spec/rubyspec/core/array/length_spec.rb +0 -7
  561. data/spec/rubyspec/core/array/map_spec.rb +0 -11
  562. data/spec/rubyspec/core/array/max_spec.rb +0 -32
  563. data/spec/rubyspec/core/array/min_spec.rb +0 -32
  564. data/spec/rubyspec/core/array/minus_spec.rb +0 -89
  565. data/spec/rubyspec/core/array/multiply_spec.rb +0 -143
  566. data/spec/rubyspec/core/array/new_spec.rb +0 -137
  567. data/spec/rubyspec/core/array/ntimes_spec.rb +0 -26
  568. data/spec/rubyspec/core/array/plus_spec.rb +0 -64
  569. data/spec/rubyspec/core/array/pop_spec.rb +0 -196
  570. data/spec/rubyspec/core/array/push_spec.rb +0 -44
  571. data/spec/rubyspec/core/array/rassoc_spec.rb +0 -38
  572. data/spec/rubyspec/core/array/reject_spec.rb +0 -134
  573. data/spec/rubyspec/core/array/replace_spec.rb +0 -7
  574. data/spec/rubyspec/core/array/reverse_each_spec.rb +0 -37
  575. data/spec/rubyspec/core/array/reverse_spec.rb +0 -58
  576. data/spec/rubyspec/core/array/rindex_spec.rb +0 -71
  577. data/spec/rubyspec/core/array/select_spec.rb +0 -36
  578. data/spec/rubyspec/core/array/shared/collect.rb +0 -7
  579. data/spec/rubyspec/core/array/shared/enumeratorize.rb +0 -12
  580. data/spec/rubyspec/core/array/shared/eql.rb +0 -95
  581. data/spec/rubyspec/core/array/shared/index.rb +0 -37
  582. data/spec/rubyspec/core/array/shared/inspect.rb +0 -3
  583. data/spec/rubyspec/core/array/shared/join.rb +0 -7
  584. data/spec/rubyspec/core/array/shared/keep_if.rb +0 -3
  585. data/spec/rubyspec/core/array/shared/length.rb +0 -3
  586. data/spec/rubyspec/core/array/shared/replace.rb +0 -3
  587. data/spec/rubyspec/core/array/shared/slice.rb +0 -3
  588. data/spec/rubyspec/core/array/shift_spec.rb +0 -160
  589. data/spec/rubyspec/core/array/shuffle_spec.rb +0 -87
  590. data/spec/rubyspec/core/array/size_spec.rb +0 -7
  591. data/spec/rubyspec/core/array/slice_spec.rb +0 -166
  592. data/spec/rubyspec/core/array/sort_spec.rb +0 -271
  593. data/spec/rubyspec/core/array/take_spec.rb +0 -29
  594. data/spec/rubyspec/core/array/take_while_spec.rb +0 -17
  595. data/spec/rubyspec/core/array/to_a_spec.rb +0 -24
  596. data/spec/rubyspec/core/array/to_ary_spec.rb +0 -20
  597. data/spec/rubyspec/core/array/try_convert_spec.rb +0 -52
  598. data/spec/rubyspec/core/array/uniq_spec.rb +0 -167
  599. data/spec/rubyspec/core/array/unshift_spec.rb +0 -64
  600. data/spec/rubyspec/core/array/zip_spec.rb +0 -55
  601. data/spec/rubyspec/core/class/fixtures/classes.rb +0 -9
  602. data/spec/rubyspec/core/class/new_spec.rb +0 -113
  603. data/spec/rubyspec/core/enumerable/all_spec.rb +0 -130
  604. data/spec/rubyspec/core/enumerable/any_spec.rb +0 -150
  605. data/spec/rubyspec/core/enumerable/collect_spec.rb +0 -39
  606. data/spec/rubyspec/core/enumerable/count_spec.rb +0 -45
  607. data/spec/rubyspec/core/enumerable/detect_spec.rb +0 -48
  608. data/spec/rubyspec/core/enumerable/drop_spec.rb +0 -20
  609. data/spec/rubyspec/core/enumerable/drop_while_spec.rb +0 -18
  610. data/spec/rubyspec/core/enumerable/each_slice_spec.rb +0 -25
  611. data/spec/rubyspec/core/enumerable/each_with_index_spec.rb +0 -14
  612. data/spec/rubyspec/core/enumerable/each_with_object_spec.rb +0 -20
  613. data/spec/rubyspec/core/enumerable/entries_spec.rb +0 -9
  614. data/spec/rubyspec/core/enumerable/find_all_spec.rb +0 -16
  615. data/spec/rubyspec/core/enumerable/find_index_spec.rb +0 -44
  616. data/spec/rubyspec/core/enumerable/find_spec.rb +0 -56
  617. data/spec/rubyspec/core/enumerable/first_spec.rb +0 -43
  618. data/spec/rubyspec/core/enumerable/fixtures/classes.rb +0 -240
  619. data/spec/rubyspec/core/enumerable/grep_spec.rb +0 -24
  620. data/spec/rubyspec/core/enumerable/group_by_spec.rb +0 -16
  621. data/spec/rubyspec/core/enumerable/none_spec.rb +0 -68
  622. data/spec/rubyspec/core/enumerable/select_spec.rb +0 -16
  623. data/spec/rubyspec/core/enumerable/sort_by_spec.rb +0 -31
  624. data/spec/rubyspec/core/enumerable/take_spec.rb +0 -43
  625. data/spec/rubyspec/core/enumerable/to_a_spec.rb +0 -9
  626. data/spec/rubyspec/core/enumerator/each_spec.rb +0 -11
  627. data/spec/rubyspec/core/enumerator/new_spec.rb +0 -17
  628. data/spec/rubyspec/core/enumerator/next_spec.rb +0 -25
  629. data/spec/rubyspec/core/enumerator/rewind_spec.rb +0 -28
  630. data/spec/rubyspec/core/false/and_spec.rb +0 -11
  631. data/spec/rubyspec/core/false/inspect_spec.rb +0 -7
  632. data/spec/rubyspec/core/false/or_spec.rb +0 -11
  633. data/spec/rubyspec/core/false/to_s_spec.rb +0 -7
  634. data/spec/rubyspec/core/false/xor_spec.rb +0 -11
  635. data/spec/rubyspec/core/hash/allocate_spec.rb +0 -13
  636. data/spec/rubyspec/core/hash/assoc_spec.rb +0 -25
  637. data/spec/rubyspec/core/hash/clear_spec.rb +0 -19
  638. data/spec/rubyspec/core/hash/clone_spec.rb +0 -10
  639. data/spec/rubyspec/core/hash/constructor_spec.rb +0 -13
  640. data/spec/rubyspec/core/hash/default_proc_spec.rb +0 -20
  641. data/spec/rubyspec/core/hash/default_spec.rb +0 -17
  642. data/spec/rubyspec/core/hash/delete_if_spec.rb +0 -13
  643. data/spec/rubyspec/core/hash/delete_spec.rb +0 -11
  644. data/spec/rubyspec/core/hash/dup_spec.rb +0 -10
  645. data/spec/rubyspec/core/hash/each_key_spec.rb +0 -15
  646. data/spec/rubyspec/core/hash/each_pair_spec.rb +0 -30
  647. data/spec/rubyspec/core/hash/each_spec.rb +0 -36
  648. data/spec/rubyspec/core/hash/each_value_spec.rb +0 -15
  649. data/spec/rubyspec/core/hash/element_reference_spec.rb +0 -41
  650. data/spec/rubyspec/core/hash/element_set_spec.rb +0 -7
  651. data/spec/rubyspec/core/hash/empty_spec.rb +0 -10
  652. data/spec/rubyspec/core/hash/fetch_spec.rb +0 -24
  653. data/spec/rubyspec/core/hash/flatten_spec.rb +0 -46
  654. data/spec/rubyspec/core/hash/has_key_spec.rb +0 -24
  655. data/spec/rubyspec/core/hash/has_value_spec.rb +0 -12
  656. data/spec/rubyspec/core/hash/include_spec.rb +0 -24
  657. data/spec/rubyspec/core/hash/index_spec.rb +0 -13
  658. data/spec/rubyspec/core/hash/indexes_spec.rb +0 -9
  659. data/spec/rubyspec/core/hash/indices_spec.rb +0 -9
  660. data/spec/rubyspec/core/hash/invert_spec.rb +0 -12
  661. data/spec/rubyspec/core/hash/keep_if_spec.rb +0 -18
  662. data/spec/rubyspec/core/hash/key_spec.rb +0 -24
  663. data/spec/rubyspec/core/hash/keys_spec.rb +0 -10
  664. data/spec/rubyspec/core/hash/length_spec.rb +0 -10
  665. data/spec/rubyspec/core/hash/member_spec.rb +0 -24
  666. data/spec/rubyspec/core/hash/merge_spec.rb +0 -37
  667. data/spec/rubyspec/core/hash/new_spec.rb +0 -19
  668. data/spec/rubyspec/core/hash/rassoc_spec.rb +0 -34
  669. data/spec/rubyspec/core/hash/reject_spec.rb +0 -18
  670. data/spec/rubyspec/core/hash/replace_spec.rb +0 -7
  671. data/spec/rubyspec/core/hash/select_spec.rb +0 -52
  672. data/spec/rubyspec/core/hash/shift_spec.rb +0 -19
  673. data/spec/rubyspec/core/hash/size_spec.rb +0 -10
  674. data/spec/rubyspec/core/hash/to_a_spec.rb +0 -13
  675. data/spec/rubyspec/core/hash/to_json_spec.rb +0 -11
  676. data/spec/rubyspec/core/hash/update_spec.rb +0 -17
  677. data/spec/rubyspec/core/hash/value_spec.rb +0 -12
  678. data/spec/rubyspec/core/hash/values_at_spec.rb +0 -9
  679. data/spec/rubyspec/core/hash/values_spec.rb +0 -7
  680. data/spec/rubyspec/core/kernel/eql_spec.rb +0 -15
  681. data/spec/rubyspec/core/kernel/equal_spec.rb +0 -12
  682. data/spec/rubyspec/core/kernel/tap_spec.rb +0 -10
  683. data/spec/rubyspec/core/kernel/to_s_spec.rb +0 -5
  684. data/spec/rubyspec/core/matchdata/to_a_spec.rb +0 -5
  685. data/spec/rubyspec/core/nil/and_spec.rb +0 -11
  686. data/spec/rubyspec/core/nil/dup_spec.rb +0 -7
  687. data/spec/rubyspec/core/nil/inspect_spec.rb +0 -7
  688. data/spec/rubyspec/core/nil/nil_spec.rb +0 -7
  689. data/spec/rubyspec/core/nil/or_spec.rb +0 -11
  690. data/spec/rubyspec/core/nil/to_a_spec.rb +0 -7
  691. data/spec/rubyspec/core/nil/to_f_spec.rb +0 -11
  692. data/spec/rubyspec/core/nil/to_h_spec.rb +0 -10
  693. data/spec/rubyspec/core/nil/to_i_spec.rb +0 -11
  694. data/spec/rubyspec/core/nil/to_s_spec.rb +0 -7
  695. data/spec/rubyspec/core/nil/xor_spec.rb +0 -11
  696. data/spec/rubyspec/core/numeric/to_s_spec.rb +0 -8
  697. data/spec/rubyspec/core/range/begin_spec.rb +0 -9
  698. data/spec/rubyspec/core/range/case_compare_spec.rb +0 -15
  699. data/spec/rubyspec/core/range/end_spec.rb +0 -9
  700. data/spec/rubyspec/core/regexp/match_spec.rb +0 -95
  701. data/spec/rubyspec/core/string/capitalize_spec.rb +0 -10
  702. data/spec/rubyspec/core/string/casecmp_spec.rb +0 -16
  703. data/spec/rubyspec/core/string/center_spec.rb +0 -49
  704. data/spec/rubyspec/core/string/chomp_spec.rb +0 -48
  705. data/spec/rubyspec/core/string/downcase_spec.rb +0 -6
  706. data/spec/rubyspec/core/string/empty_spec.rb +0 -7
  707. data/spec/rubyspec/core/string/end_with_spec.rb +0 -16
  708. data/spec/rubyspec/core/string/include_spec.rb +0 -6
  709. data/spec/rubyspec/core/string/index_spec.rb +0 -405
  710. data/spec/rubyspec/core/string/intern_spec.rb +0 -9
  711. data/spec/rubyspec/core/string/length_spec.rb +0 -9
  712. data/spec/rubyspec/core/string/reverse_spec.rb +0 -7
  713. data/spec/rubyspec/core/string/size_spec.rb +0 -9
  714. data/spec/rubyspec/core/string/start_with_spec.rb +0 -12
  715. data/spec/rubyspec/core/string/swapcase_spec.rb +0 -13
  716. data/spec/rubyspec/core/string/to_a_spec.rb +0 -9
  717. data/spec/rubyspec/core/string/to_s_spec.rb +0 -6
  718. data/spec/rubyspec/core/string/to_str_spec.rb +0 -6
  719. data/spec/rubyspec/core/string/to_sym_spec.rb +0 -9
  720. data/spec/rubyspec/core/string/upcase_spec.rb +0 -6
  721. data/spec/rubyspec/core/struct/fixtures/classes.rb +0 -26
  722. data/spec/rubyspec/core/struct/initialize_spec.rb +0 -11
  723. data/spec/rubyspec/core/struct/new_spec.rb +0 -24
  724. data/spec/rubyspec/core/symbol/to_proc_spec.rb +0 -12
  725. data/spec/rubyspec/core/time/at_spec.rb +0 -7
  726. data/spec/rubyspec/core/time/day_spec.rb +0 -5
  727. data/spec/rubyspec/core/time/friday_spec.rb +0 -9
  728. data/spec/rubyspec/core/time/hour_spec.rb +0 -5
  729. data/spec/rubyspec/core/time/min_spec.rb +0 -5
  730. data/spec/rubyspec/core/time/monday_spec.rb +0 -9
  731. data/spec/rubyspec/core/time/month_spec.rb +0 -5
  732. data/spec/rubyspec/core/time/now_spec.rb +0 -5
  733. data/spec/rubyspec/core/time/saturday_spec.rb +0 -9
  734. data/spec/rubyspec/core/true/and_spec.rb +0 -11
  735. data/spec/rubyspec/core/true/inspect_spec.rb +0 -7
  736. data/spec/rubyspec/core/true/or_spec.rb +0 -11
  737. data/spec/rubyspec/core/true/to_s_spec.rb +0 -7
  738. data/spec/rubyspec/core/true/xor_spec.rb +0 -11
  739. data/spec/rubyspec/language/alias_spec.rb +0 -160
  740. data/spec/rubyspec/language/and_spec.rb +0 -66
  741. data/spec/rubyspec/language/array_spec.rb +0 -117
  742. data/spec/rubyspec/language/break_spec.rb +0 -332
  743. data/spec/rubyspec/language/case_spec.rb +0 -310
  744. data/spec/rubyspec/language/class_spec.rb +0 -190
  745. data/spec/rubyspec/language/class_variable_spec.rb +0 -56
  746. data/spec/rubyspec/language/def_spec.rb +0 -551
  747. data/spec/rubyspec/language/defined_spec.rb +0 -107
  748. data/spec/rubyspec/language/ensure_spec.rb +0 -104
  749. data/spec/rubyspec/language/execution_spec.rb +0 -15
  750. data/spec/rubyspec/language/for_spec.rb +0 -192
  751. data/spec/rubyspec/language/hash_spec.rb +0 -65
  752. data/spec/rubyspec/language/if_spec.rb +0 -356
  753. data/spec/rubyspec/language/literal_lambda_spec.rb +0 -1
  754. data/spec/rubyspec/language/loop_spec.rb +0 -67
  755. data/spec/rubyspec/language/metaclass_spec.rb +0 -159
  756. data/spec/rubyspec/language/module_spec.rb +0 -56
  757. data/spec/rubyspec/language/next_spec.rb +0 -469
  758. data/spec/rubyspec/language/not_spec.rb +0 -55
  759. data/spec/rubyspec/language/or_spec.rb +0 -90
  760. data/spec/rubyspec/language/order_spec.rb +0 -77
  761. data/spec/rubyspec/language/precedence_spec.rb +0 -483
  762. data/spec/rubyspec/language/redo_spec.rb +0 -65
  763. data/spec/rubyspec/language/rescue_spec.rb +0 -121
  764. data/spec/rubyspec/language/retry_spec.rb +0 -56
  765. data/spec/rubyspec/language/return_spec.rb +0 -281
  766. data/spec/rubyspec/language/singleton_class_spec.rb +0 -32
  767. data/spec/rubyspec/language/super_spec.rb +0 -284
  768. data/spec/rubyspec/language/undef_spec.rb +0 -16
  769. data/spec/rubyspec/language/unless_spec.rb +0 -45
  770. data/spec/rubyspec/language/until_spec.rb +0 -234
  771. data/spec/rubyspec/language/while_spec.rb +0 -238
  772. data/spec/rubyspec/language/yield_spec.rb +0 -128
  773. data/spec/rubyspec/library/date/new_spec.rb +0 -10
  774. data/spec/rubyspec/library/date/to_s_spec.rb +0 -7
  775. data/spec/rubyspec/library/date/today_spec.rb +0 -7
  776. data/spec/rubyspec/library/erb/util/html_escape_spec.rb +0 -10
  777. data/spec/rubyspec/library/observer/add_observer_spec.rb +0 -31
  778. data/spec/rubyspec/library/observer/count_observers_spec.rb +0 -33
  779. data/spec/rubyspec/library/observer/delete_observer_spec.rb +0 -19
  780. data/spec/rubyspec/library/observer/delete_observers_spec.rb +0 -19
  781. data/spec/rubyspec/library/observer/fixtures/classes.rb +0 -25
  782. data/spec/rubyspec/library/observer/notify_observers_spec.rb +0 -31
  783. data/spec/rubyspec/library/rbconfig/config_spec.rb +0 -47
  784. data/spec/rubyspec/library/singleton/clone_spec.rb +0 -8
  785. data/spec/rubyspec/library/singleton/dup_spec.rb +0 -8
  786. data/spec/rubyspec/library/singleton/fixtures/classes.rb +0 -18
  787. data/spec/rubyspec/library/singleton/instance_spec.rb +0 -30
  788. data/spec/rubyspec/library/stringscanner/element_reference_spec.rb +0 -29
  789. data/spec/rubyspec/library/stringscanner/pos_spec.rb +0 -20
  790. data/spec/rubyspec/spec_helper.rb +0 -96
  791. data/stdlib/fileutils.rb +0 -0
  792. data/stdlib/iconv.rb +0 -0
  793. data/stdlib/opal-browser/local_storage.rb +0 -27
  794. data/stdlib/opal-browser/script_loader.rb +0 -35
  795. data/stdlib/opal-parser.js.erb +0 -13
  796. data/stdlib/yaml.rb +0 -0
@@ -0,0 +1,65 @@
1
+ require 'opal/nodes/base'
2
+
3
+ module Opal
4
+ module Nodes
5
+ class WhileNode < Base
6
+ handle :while
7
+
8
+ children :test, :body
9
+
10
+ def compile
11
+ with_temp do |redo_var|
12
+ test_code = js_truthy(test)
13
+
14
+ compiler.in_while do
15
+ while_loop[:closure] = true if wrap_in_closure?
16
+ while_loop[:redo_var] = redo_var
17
+
18
+ body_code = stmt(body)
19
+
20
+ if uses_redo?
21
+ push "#{redo_var} = false; #{while_open}#{redo_var} || "
22
+ push test_code
23
+ push while_close
24
+ else
25
+ push while_open, test_code, while_close
26
+ end
27
+
28
+ push "#{redo_var} = false;" if uses_redo?
29
+ line body_code, "}"
30
+ end
31
+ end
32
+
33
+ wrap '(function() {', '; return nil; })()' if wrap_in_closure?
34
+ end
35
+
36
+ def while_open
37
+ "while ("
38
+ end
39
+
40
+ def while_close
41
+ ") {"
42
+ end
43
+
44
+ def uses_redo?
45
+ while_loop[:use_redo]
46
+ end
47
+
48
+ def wrap_in_closure?
49
+ expr? or recv?
50
+ end
51
+ end
52
+
53
+ class UntilNode < WhileNode
54
+ handle :until
55
+
56
+ def while_open
57
+ "while (!("
58
+ end
59
+
60
+ def while_close
61
+ ")) {"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,84 @@
1
+ require 'opal/nodes/base'
2
+
3
+ module Opal
4
+ module Nodes
5
+ class BaseYieldNode < Base
6
+ def compile_call(children, level)
7
+ scope.uses_block!
8
+
9
+ if yields_single_arg?(children)
10
+ push expr(children.first)
11
+ wrap "$opal.$yield1(#{block_name}, ", ')'
12
+ else
13
+ push expr(s(:arglist, *children))
14
+
15
+ if uses_splat?(children)
16
+ wrap "$opal.$yieldX(#{block_name}, ", ')'
17
+ else
18
+ wrap "$opal.$yieldX(#{block_name}, [", '])'
19
+ end
20
+ end
21
+ end
22
+
23
+ def block_name
24
+ scope.block_name || '$yield'
25
+ end
26
+
27
+ def yields_single_arg?(children)
28
+ !uses_splat?(children) and children.size == 1
29
+ end
30
+
31
+ def uses_splat?(children)
32
+ children.any? { |child| child.type == :splat }
33
+ end
34
+ end
35
+
36
+ class YieldNode < BaseYieldNode
37
+ handle :yield
38
+
39
+ def compile
40
+ compile_call(children, @level)
41
+
42
+ if stmt?
43
+ wrap 'if (', ' === $breaker) return $breaker.$v'
44
+ else
45
+ with_temp do |tmp|
46
+ wrap "(((#{tmp} = ", ") === $breaker) ? $breaker.$v : #{tmp})"
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ # special opal yield assign, for `a = yield(arg1, arg2)` to assign
54
+ # to a temp value to make yield expr into stmt.
55
+ #
56
+ # level will always be stmt as its the reason for this to exist
57
+ #
58
+ # s(:yasgn, :a, s(:yield, arg1, arg2))
59
+ class YasgnNode < BaseYieldNode
60
+ handle :yasgn
61
+
62
+ children :var_name, :yield_args
63
+
64
+ def compile
65
+ compile_call(s(*yield_args[1..-1]), :stmt)
66
+ wrap "if ((#{var_name} = ", ") === $breaker) return $breaker.$v"
67
+ end
68
+ end
69
+
70
+ # Created by `#returns()` for when a yield statement should return
71
+ # it's value (its last in a block etc).
72
+ class ReturnableYieldNode < BaseYieldNode
73
+ handle :returnable_yield
74
+
75
+ def compile
76
+ compile_call children, @level
77
+
78
+ with_temp do |tmp|
79
+ wrap "return #{tmp} = ", ", #{tmp} === $breaker ? #{tmp} : #{tmp}"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,2298 +1,423 @@
1
- require 'opal/lexer'
2
- require 'opal/grammar'
3
- require 'opal/target_scope'
4
- require 'opal/version'
1
+ require 'opal/parser/sexp'
2
+ require 'opal/parser/lexer'
3
+ require 'opal/parser/grammar'
4
+ require 'opal/parser/parser_scope'
5
5
 
6
6
  module Opal
7
- class Parser
7
+ class Parser < Racc::Parser
8
8
 
9
- # A fragment holds a string of generated javascript that will be written
10
- # to the destination. It also keeps hold of the original sexp from which
11
- # it was generated. Using this sexp, when writing fragments in order, a
12
- # mapping can be created of the original location => target location,
13
- # aka, source-maps!
14
- class Fragment
15
- # String of javascript this fragment holds
16
- attr_reader :code
9
+ attr_reader :lexer, :file, :scope
17
10
 
18
- def initialize(code, sexp = nil)
19
- @code = code.to_s
20
- @sexp = sexp
21
- end
22
-
23
- # In debug mode we may wish to include the original line as a comment
24
- def to_code
25
- if @sexp
26
- "/*:#{@sexp.line}*/#{@code}"
27
- else
28
- @code
29
- end
30
- end
31
-
32
- # inspect the contents of this fragment, f("fooo")
33
- def inspect
34
- "f(#{@code.inspect})"
35
- end
36
-
37
- def line
38
- @sexp.line if @sexp
39
- end
40
- end
41
-
42
- # Generated code gets indented with two spaces on each scope
43
- INDENT = ' '
44
-
45
- # Expressions are handled at diffferent levels. Some sexps
46
- # need to know the js expression they are generating into.
47
- LEVEL = [:stmt, :stmt_closure, :list, :expr, :recv]
48
-
49
- # All compare method nodes - used to optimize performance of
50
- # math comparisons
51
- COMPARE = %w[< > <= >=]
52
-
53
- # Reserved javascript keywords - we cannot create variables with the
54
- # same name
55
- RESERVED = %w(
56
- break case catch continue debugger default delete do else finally for
57
- function if in instanceof new return switch this throw try typeof var let
58
- void while with class enum export extends import super true false native
59
- const static
60
- )
61
-
62
- # Statements which should not have ';' added to them.
63
- STATEMENTS = [:xstr, :dxstr]
64
-
65
- # Final generated javascript for this parser
66
- attr_reader :result
67
-
68
- # generated fragments as an array
69
- attr_reader :fragments
70
-
71
- # Parse some ruby code to a string.
72
- #
73
- # Opal::Parser.new.parse("1 + 2")
74
- # # => "(function() {....})()"
75
- def parse(source, options = {})
76
- @sexp = Grammar.new.parse(source, options[:file])
77
- @line = 1
78
- @indent = ''
79
- @unique = 0
80
-
81
- @helpers = {
82
- :breaker => true,
83
- :slice => true
84
- }
85
-
86
- # options
87
- @file = options[:file] || '(file)'
88
- @source_file = options[:source_file] || @file
89
- @method_missing = (options[:method_missing] != false)
90
- @arity_check = options[:arity_check]
91
- @const_missing = (options[:const_missing] != false)
92
- @irb_vars = (options[:irb] == true)
93
-
94
- @method_calls = {}
95
-
96
- @fragments = self.top(@sexp).flatten
97
-
98
- @fragments.unshift f(version_comment)
99
-
100
- @result = @fragments.map(&:code).join('')
101
- end
102
-
103
- # Always at top of generated file to show current opal version
104
- def version_comment
105
- "/* Generated by Opal #{Opal::VERSION} */\n"
106
- end
107
-
108
- def source_map
109
- Opal::SourceMap.new(@fragments, '(file)')
110
- end
111
-
112
- def extract_parser_options(content)
113
- result = {}
114
-
115
- if /^#\ opal\:(.*)/ =~ content
116
- $~[1].split(',').map(&:strip).each do |opt|
117
- next if opt == ""
118
- opt = opt.gsub('-', '_')
119
-
120
- if opt =~ /no_/
121
- result[opt.sub(/no_/, '').to_sym] = false
122
- else
123
- result[opt.to_sym] = true
124
- end
125
- end
126
- end
127
-
128
- result
129
- end
130
-
131
- # This is called when a parsing/processing error occurs. This
132
- # method simply appends the filename and curent line number onto
133
- # the message and raises it.
134
- #
135
- # parser.error "bad variable name"
136
- # # => raise "bad variable name :foo.rb:26"
137
- #
138
- # @param [String] msg error message to raise
139
- def error(msg)
140
- raise SyntaxError, "#{msg} :#{@file}:#{@line}"
141
- end
142
-
143
- # This is called when a parsing/processing warning occurs. This
144
- # method simply appends the filename and curent line number onto
145
- # the message and issues a warning.
146
- #
147
- # @param [String] msg warning message to raise
148
- def warning(msg)
149
- warn "#{msg} :#{@file}:#{@line}"
150
- end
151
-
152
- # Instances of `Scope` can use this to determine the current
153
- # scope indent. The indent is used to keep generated code easily
154
- # readable.
155
- #
156
- # @return [String]
157
- def parser_indent
158
- @indent
159
- end
160
-
161
- # Create a new sexp using the given parts. Even though this just
162
- # returns an array, it must be used incase the internal structure
163
- # of sexps does change.
164
- #
165
- # s(:str, "hello there")
166
- # # => [:str, "hello there"]
167
- #
168
- # @result [Array]
169
- def s(*parts)
170
- sexp = Array.new(parts)
171
- sexp.line = @line
172
- sexp
173
- end
174
-
175
- # @param [String] code the string of code
176
- # @return [Fragment]
177
- def f(code, sexp = nil)
178
- Fragment.new(code, sexp)
179
- end
180
-
181
- alias_method :fragment, :f
182
-
183
- # Converts a ruby method name into its javascript equivalent for
184
- # a method/function call. All ruby method names get prefixed with
185
- # a '$', and if the name is a valid javascript identifier, it will
186
- # have a '.' prefix (for dot-calling), otherwise it will be
187
- # wrapped in brackets to use reference notation calling.
188
- #
189
- # mid_to_jsid('foo') # => ".$foo"
190
- # mid_to_jsid('class') # => ".$class"
191
- # mid_to_jsid('==') # => "['$==']"
192
- # mid_to_jsid('name=') # => "['$name=']"
193
- #
194
- # @param [String] mid ruby method id
195
- # @return [String]
196
- def mid_to_jsid(mid)
197
- if /\=|\+|\-|\*|\/|\!|\?|\<|\>|\&|\||\^|\%|\~|\[/ =~ mid.to_s
198
- "['$#{mid}']"
199
- else
200
- '.$' + mid
201
- end
202
- end
203
-
204
- # Converts a ruby lvar/arg name to a js identifier. Not all ruby names
205
- # are valid in javascript. A $ suffix is added to non-valid names.
206
- def lvar_to_js(var)
207
- var = "#{var}$" if RESERVED.include? var.to_s
208
- var.to_sym
209
- end
210
-
211
- # Used to generate a unique id name per file. These are used
212
- # mainly to name method bodies for methods that use blocks.
213
- #
214
- # @return [String]
215
- def unique_temp
216
- "TMP_#{@unique += 1}"
217
- end
218
-
219
- # Generate the code for the top level sexp, i.e. the root sexp
220
- # for a file. This is used directly by `#parse`. It pushes a
221
- # ":top" scope onto the stack and handles the passed in sexp.
222
- # The result is a string of javascript representing the sexp.
223
- #
224
- # @param [Array] sexp the sexp to process
225
- # @return [String]
226
- def top(sexp, options = {})
227
- code, vars = nil, nil
228
-
229
- # empty file = nil as our top sexp
230
- sexp = s(:nil) unless sexp
231
-
232
- in_scope(:top) do
233
- indent {
234
- scope = s(:scope, sexp)
235
- scope.line = sexp.line
236
-
237
- code = process(scope, :stmt)
238
- code = [code] unless code.is_a? Array
239
- code.unshift f(@indent, sexp)
240
- }
241
-
242
- @scope.add_temp "self = $opal.top"
243
- @scope.add_temp "$scope = $opal"
244
- @scope.add_temp "nil = $opal.nil"
245
- @scope.add_temp "def = $opal.Object._proto" if @scope.defines_defn
246
- @helpers.keys.each { |h| @scope.add_temp "$#{h} = $opal.#{h}" }
247
-
248
- vars = [f(INDENT, sexp), @scope.to_vars, f("\n", sexp)]
249
-
250
- if @irb_vars
251
- code.unshift f("if (!$opal.irb_vars) { $opal.irb_vars = {}; }\n", sexp)
252
- end
253
- end
254
-
255
- if @method_missing
256
- stubs = f("\n#{INDENT}$opal.add_stubs([" + @method_calls.keys.map { |k| "'$#{k}'" }.join(", ") + "]);\n", sexp)
257
- else
258
- stubs = []
259
- end
260
-
261
- [f("(function($opal) {\n", sexp), vars, stubs, code, f("\n})(Opal);\n", sexp)]
262
- end
263
-
264
- # Every time the parser enters a new scope, this is called with
265
- # the scope type as an argument. Valid types are `:top` for the
266
- # top level/file scope; `:class`, `:module` and `:sclass` for the
267
- # obvious ruby classes/modules; `:def` and `:iter` for methods
268
- # and blocks respectively.
269
- #
270
- # This method just pushes a new instance of `Opal::Scope` onto the
271
- # stack, sets the new scope as the `@scope` variable, and yields
272
- # the given block. Once the block returns, the old scope is put
273
- # back on top of the stack.
274
- #
275
- # in_scope(:class) do
276
- # # generate class body in here
277
- # body = "..."
278
- # end
279
- #
280
- # # use body result..
281
- #
282
- # @param [Symbol] type the type of scope
283
- # @return [nil]
284
- def in_scope(type)
285
- return unless block_given?
286
-
287
- parent = @scope
288
- @scope = TargetScope.new(type, self).tap { |s| s.parent = parent }
289
- yield @scope
290
-
291
- @scope = parent
292
- end
293
-
294
- # To keep code blocks nicely indented, this will yield a block after
295
- # adding an extra layer of indent, and then returning the resulting
296
- # code after reverting the indent.
297
- #
298
- # indented_code = indent do
299
- # "foo"
300
- # end
301
- #
302
- # @result [String]
303
- def indent(&block)
304
- indent = @indent
305
- @indent += INDENT
306
- @space = "\n#@indent"
307
- res = yield
308
- @indent = indent
309
- @space = "\n#@indent"
310
- res
311
- end
312
-
313
- # Temporary varibales will be needed from time to time in the
314
- # generated code, and this method will assign (or reuse) on
315
- # while the block is yielding, and queue it back up once it is
316
- # finished. Variables are queued once finished with to save the
317
- # numbers of variables needed at runtime.
318
- #
319
- # with_temp do |tmp|
320
- # "tmp = 'value';"
321
- # end
322
- #
323
- # @return [String] generated code withing block
324
- def with_temp(&block)
325
- tmp = @scope.new_temp
326
- res = yield tmp
327
- @scope.queue_temp tmp
328
- res
329
- end
330
-
331
- # Used when we enter a while statement. This pushes onto the current
332
- # scope's while stack so we know how to handle break, next etc.
333
- #
334
- # Usage:
335
- #
336
- # in_while do
337
- # # generate while body here.
338
- # end
339
- def in_while
340
- return unless block_given?
341
- @while_loop = @scope.push_while
342
- result = yield
343
- @scope.pop_while
344
-
345
- result
346
- end
347
-
348
- def in_case
349
- return unless block_given?
350
- old = @case_stmt
351
- @case_stmt = {}
352
- yield
353
- @case_stmt = old
354
- end
355
-
356
- # Returns true if the parser is curently handling a while sexp,
357
- # false otherwise.
358
- #
359
- # @return [Boolean]
360
- def in_while?
361
- @scope.in_while?
362
- end
363
-
364
- # Processes a given sexp. This will send a method to the receiver
365
- # of the format "process_<sexp_name>". Any sexp handler should
366
- # return a string of content.
367
- #
368
- # For example, calling `process` with `s(:sym, 42)` will call the
369
- # method `#process_lit`. If a method with that name cannot be
370
- # found, then an error is raised.
371
- #
372
- # process(s(:int, 42), :stmt)
373
- # # => "42"
374
- #
375
- # @param [Array] sexp the sexp to process
376
- # @param [Symbol] level the level to process (see `LEVEL`)
377
- # @return [String]
378
- def process(sexp, level = :expr)
379
- type = sexp.shift
380
- meth = "process_#{type}"
381
- raise "Unsupported sexp: #{type}" unless respond_to? meth
382
-
383
- @line = sexp.line
384
-
385
- __send__(meth, sexp, level)
386
- end
387
-
388
- # The last sexps in method bodies, for example, need to be returned
389
- # in the compiled javascript. Due to syntax differences between
390
- # javascript any ruby, some sexps need to be handled specially. For
391
- # example, `if` statemented cannot be returned in javascript, so
392
- # instead the "truthy" and "falsy" parts of the if statement both
393
- # need to be returned instead.
394
- #
395
- # Sexps that need to be returned are passed to this method, and the
396
- # alterned/new sexps are returned and should be used instead. Most
397
- # sexps can just be added into a s(:return) sexp, so that is the
398
- # default action if no special case is required.
399
- #
400
- # sexp = s(:str, "hey")
401
- # parser.returns(sexp)
402
- # # => s(:js_return, s(:str, "hey"))
403
- #
404
- # `s(:js_return)` is just a special sexp used to return the result
405
- # of processing its arguments.
406
- #
407
- # @param [Array] sexp the sexp to alter
408
- # @return [Array] altered sexp
409
- def returns(sexp)
410
- return returns s(:nil) unless sexp
411
-
412
- case sexp.first
413
- when :break, :next
414
- sexp
415
- when :yield
416
- sexp[0] = :returnable_yield
417
- sexp
418
- when :scope
419
- sexp[1] = returns sexp[1]
420
- sexp
421
- when :block
422
- if sexp.length > 1
423
- sexp[-1] = returns sexp[-1]
424
- else
425
- sexp << returns(s(:nil))
426
- end
427
- sexp
428
- when :when
429
- sexp[2] = returns(sexp[2])
430
- sexp
431
- when :rescue
432
- sexp[1] = returns sexp[1]
433
-
434
- if sexp[2] and sexp[2][0] == :resbody and sexp[2][2]
435
- sexp[2][2] = returns sexp[2][2]
436
- end
437
- sexp
438
- when :ensure
439
- sexp[1] = returns sexp[1]
440
- sexp
441
- when :while
442
- # sexp[2] = returns(sexp[2])
443
- sexp
444
- when :return
445
- sexp
446
- when :xstr
447
- sexp[1] = "return #{sexp[1]};" unless /return|;/ =~ sexp[1]
448
- sexp
449
- when :dxstr
450
- sexp[1] = "return #{sexp[1]}" unless /return|;|\n/ =~ sexp[1]
451
- sexp
452
- when :if
453
- sexp[2] = returns(sexp[2] || s(:nil))
454
- sexp[3] = returns(sexp[3] || s(:nil))
455
- sexp
456
- else
457
- s(:js_return, sexp).tap { |s|
458
- s.line = sexp.line
459
- }
460
- end
461
- end
462
-
463
- # Returns true if the given sexp is an expression. All expressions
464
- # will get ';' appended to their result, except for the statement
465
- # sexps. See `STATEMENTS` for a list of sexp names that are
466
- # statements.
467
- #
468
- # @param [Array] sexp the sexp to check
469
- # @return [Boolean]
470
- def expression?(sexp)
471
- !STATEMENTS.include?(sexp.first)
472
- end
473
-
474
- # More than one expression in a row will be grouped by the grammar
475
- # into a block sexp. A block sexp just holds any number of other
476
- # sexps.
477
- #
478
- # s(:block, s(:str, "hey"), s(:int, 42))
479
- #
480
- # A block can actually be empty. As opal requires real values to
481
- # be returned (to appease javascript values), a nil sexp
482
- # s(:nil) will be generated if the block is empty.
483
- #
484
- # @return [String]
485
- def process_block(sexp, level)
486
- return process s(:nil) if sexp.empty?
487
-
488
- result = []
489
- join = (@scope.class_scope? ? "\n\n#@indent" : "\n#@indent")
490
-
491
- sexp.each do |stmt|
492
- result << f(join, sexp) unless result.empty?
493
-
494
- # find any inline yield statements
495
- if yasgn = find_inline_yield(stmt)
496
- result << process(yasgn, level) << f(";", yasgn)
497
- end
498
-
499
- expr = expression?(stmt) and LEVEL.index(level) < LEVEL.index(:list)
500
-
501
- result << process(stmt, level)
502
- result << f(";", stmt) if expr
503
- end
504
-
505
- result
506
- end
507
-
508
- # When a block sexp gets generated, any inline yields (i.e. yield
509
- # statements that are not direct members of the block) need to be
510
- # generated as a top level member. This is because if a yield
511
- # is returned by a break statement, then the method must return.
512
- #
513
- # As inline expressions in javascript cannot return, the block
514
- # must be rewritten.
515
- #
516
- # For example, a yield inside an array:
517
- #
518
- # [1, 2, 3, yield(4)]
519
- #
520
- # Must be rewitten into:
521
- #
522
- # tmp = yield 4
523
- # [1, 2, 3, tmp]
524
- #
525
- # This rewriting happens on sexps directly.
526
- #
527
- # @param [Sexp] stmt sexps to (maybe) rewrite
528
- # @return [Sexp]
529
- def find_inline_yield(stmt)
530
- found = nil
531
- case stmt.first
532
- when :js_return
533
- if found = find_inline_yield(stmt[1])
534
- found = found[2]
535
- end
536
- when :array
537
- stmt[1..-1].each_with_index do |el, idx|
538
- if el.first == :yield
539
- found = el
540
- stmt[idx+1] = s(:js_tmp, '$yielded')
541
- end
542
- end
543
- when :call
544
- arglist = stmt[3]
545
- arglist[1..-1].each_with_index do |el, idx|
546
- if el.first == :yield
547
- found = el
548
- arglist[idx+1] = s(:js_tmp, '$yielded')
549
- end
550
- end
551
- end
552
-
553
- if found
554
- @scope.add_temp '$yielded' unless @scope.has_temp? '$yielded'
555
- s(:yasgn, '$yielded', found)
556
- end
557
- end
558
-
559
- def process_scope(sexp, level)
560
- stmt = sexp[0] || s(:nil)
561
- stmt = returns stmt unless @scope.class_scope?
562
-
563
- process stmt, :stmt
564
- end
565
-
566
- # s(:js_return, sexp)
567
- def process_js_return(sexp, level)
568
- [f("return ", sexp), process(sexp[0])]
569
- end
570
-
571
- # s(:js_tmp, str)
572
- def process_js_tmp(sexp, level)
573
- f(sexp[0].to_s, sexp)
574
- end
575
-
576
- def js_block_given(sexp, level)
577
- @scope.uses_block!
578
- if @scope.block_name
579
- f("(#{@scope.block_name} !== nil)", sexp)
580
- elsif scope = @scope.find_parent_def and scope.block_name
581
- f("(#{scope.block_name} !== nil)", sexp)
582
- else
583
- f("false", sexp)
584
- end
585
- end
586
-
587
- def handle_block_given(sexp, reverse = false)
588
- @scope.uses_block!
589
- name = @scope.block_name
590
-
591
- f((reverse ? "#{ name } === nil" : "#{ name } !== nil"), sexp)
592
- end
593
-
594
- def process_sym(sexp, level)
595
- f(sexp[0].to_s.inspect, sexp)
596
- end
597
-
598
- # Process integers. Wrap in parens if a receiver of method call
599
- def process_int(sexp, level)
600
- f((level == :recv ? "(#{sexp[0]})" : sexp[0].to_s), sexp)
601
- end
602
-
603
- # Floats generated just like integers
604
- alias_method :process_float, :process_int
605
-
606
- # Regexp literals. Convert to empty js regexp if empty (not compatible)
607
- def process_regexp(sexp, level)
608
- val = sexp[0]
609
- f((val == // ? /^/.inspect : val.inspect), sexp)
610
- end
611
-
612
- # Dynamic regexps with interpolation
613
- # s(:dregx, parts...) => new Regexp("...")
614
- def process_dregx(sexp, level)
615
- result = []
616
-
617
- sexp.each do |part|
618
- result << f(" + ", sexp) unless result.empty?
619
-
620
- if String === part
621
- result << f(part.inspect, sexp)
622
- elsif part[0] == :str
623
- result << process(part)
624
- else
625
- result << process(part[1])
626
- end
627
- end
628
-
629
- [f("(new RegExp(", sexp), result, f("))", sexp)]
630
- end
631
-
632
- # Exclusive range, uses opal __range helper.
633
- # s(:dot3, start, end) => __range(start, end, false)
634
- def process_dot2(sexp, level)
635
- @helpers[:range] = true
636
-
637
- [f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", false)", sexp)]
638
- end
639
-
640
- # Inclusive range, uses __range helper
641
- # s(:dot3, start, end) => __range(start, end, true)
642
- def process_dot3(sexp, level)
643
- @helpers[:range] = true
644
-
645
- [f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", true)", sexp)]
646
- end
647
-
648
- # Simple strings, no interpolation.
649
- # s(:str, "string") => "string"
650
- def process_str(sexp, level)
651
- f sexp[0].inspect, sexp
652
- end
653
-
654
- # defined?(x) => various
655
- def process_defined(sexp, level)
656
- part = sexp[0]
657
- case part[0]
658
- when :self
659
- f("'self'", sexp)
660
- when :nil
661
- f("'nil'", sexp)
662
- when :true
663
- f("'true'", sexp)
664
- when :false
665
- f("'false'", sexp)
666
- when :call
667
- mid = mid_to_jsid part[2].to_s
668
- recv = part[1] ? process(part[1]) : f(current_self, sexp)
669
- [f("(", sexp), recv, f("#{mid} ? 'method' : nil)", sexp)]
670
- when :xstr, :dxstr
671
- [f("(typeof(", sexp), process(part), f(") !== 'undefined')", sexp)]
672
- when :const
673
- f("($scope.#{part[1].to_s} != null)", sexp)
674
- when :cvar
675
- f("($opal.cvars[#{part[1].to_s.inspect}] != null ? 'class-variable' : nil)", sexp)
676
- when :colon2
677
- f("false", sexp)
678
- when :colon3
679
- f("($opal.Object._scope.#{sexp[0][1]} == null ? nil : 'constant')", sexp)
680
- when :ivar
681
- ivar_name = part[1].to_s[1..-1]
682
- with_temp do |t|
683
- f("((#{t} = #{current_self}[#{ivar_name.inspect}], #{t} != null && #{t} !== nil) ? 'instance-variable' : nil)", sexp)
684
- end
685
- when :lvar
686
- f("local-variable", sexp)
687
- else
688
- raise "bad defined? part: #{part[0]}"
689
- end
690
- end
691
-
692
- # not keyword or '!' operand
693
- # s(:not, value) => (tmp = value, (tmp === nil || tmp === false))
694
- def process_not(sexp, level)
695
- with_temp do |tmp|
696
- expr = sexp[0]
697
- [f("(#{tmp} = ", sexp), process(expr), f(", (#{tmp} === nil || #{tmp} === false))", sexp)]
698
- end
699
- end
700
-
701
- # A block pass '&foo' syntax
702
- # s(:block_pass, value) => value.$to_proc()
703
- def process_block_pass(exp, level)
704
- process s(:call, exp[0], :to_proc, s(:arglist))
705
- end
706
-
707
- # A block/iter with embeded call. Compiles into function
708
- # s(:iter, call, block_args [, body) => (function() { ... })
709
- def process_iter(sexp, level)
710
- call, args, body = sexp
711
-
712
- body ||= s(:nil)
713
- body = returns body
714
- code = []
715
- params = nil
716
- scope_name = nil
717
- identity = nil
718
- to_vars = nil
719
-
720
- args = nil if Fixnum === args # argh
721
- args ||= s(:masgn, s(:array))
722
- args = args.first == :lasgn ? s(:array, args) : args[1]
723
-
724
- # opt args are last, if present, and are a [:block]
725
- if args.last.is_a?(Array) and args.last[0] == :block
726
- opt_args = args.pop
727
- opt_args.shift
728
- end
729
-
730
- if args.last.is_a?(Array) and args.last[0] == :block_pass
731
- block_arg = args.pop
732
- block_arg = block_arg[1][1].to_sym
733
- end
734
-
735
- if args.last.is_a?(Array) and args.last[0] == :splat
736
- splat = args.last[1][1]
737
- args.pop
738
- len = args.length
739
- end
740
-
741
- indent do
742
- in_scope(:iter) do
743
- identity = @scope.identify!
744
- @scope.add_temp "#{current_self} = #{identity}._s || this"
745
-
746
- args[1..-1].each do |arg|
747
- arg = arg[1]
748
- arg = "#{arg}$" if RESERVED.include? arg.to_s
749
-
750
- if opt_args and current_opt = opt_args.find { |s| s[1] == arg.to_sym }
751
- code << [f("if (#{arg} == null) #{arg} = ", sexp), process(current_opt[2]), f(";\n", sexp)]
752
- else
753
- code << f("if (#{arg} == null) #{arg} = nil;\n", sexp)
754
- end
755
- end
756
-
757
- params = js_block_args(args[1..-1])
758
-
759
- if splat
760
- @scope.add_arg splat
761
- params << splat
762
- code << f("#{splat} = $slice.call(arguments, #{len - 1});", sexp)
763
- end
764
-
765
- if block_arg
766
- @scope.block_name = block_arg
767
- @scope.add_temp block_arg
768
- scope_name = @scope.identify!
769
-
770
- blk = []
771
- blk << f("\n#@indent#{block_arg} = #{scope_name}._p || nil, #{scope_name}.p = null;\n#@indent", sexp)
772
-
773
- code.unshift blk
774
- end
775
-
776
- code << f("\n#@indent", sexp)
777
- code << process(body, :stmt)
778
-
779
- if @scope.defines_defn
780
- @scope.add_temp "def = ((#{current_self}._isClass) ? #{current_self}._proto : #{current_self})"
781
- end
782
-
783
- to_vars = [f("\n#@indent", sexp), @scope.to_vars, f("\n#@indent", sexp)]
784
- end
785
- end
786
-
787
- itercode = [f("function(#{params.join ', '}) {\n", sexp), to_vars, code, f("\n#@indent}", sexp)]
788
-
789
- itercode.unshift f("(#{identity} = ", sexp)
790
- itercode << f(", #{identity}._s = #{current_self}, #{identity})", sexp)
791
-
792
- call << itercode
793
- process call, level
794
- end
795
-
796
- # Maps block args into array of jsid. Adds $ suffix to invalid js
797
- # identifiers.
798
- #
799
- # s(:args, parts...) => ["a", "b", "break$"]
800
- def js_block_args(sexp)
801
- sexp.map do |arg|
802
- @scope.add_arg lvar_to_js(arg[1])
803
- end
804
- end
805
-
806
- ##
807
- # recv.mid = rhs
808
- #
809
- # s(recv, :mid=, s(:arglist, rhs))
810
- def process_attrasgn(exp, level)
811
- recv, mid, arglist = exp
812
- process s(:call, recv, mid, arglist), level
813
- end
814
-
815
- # s(:call, recv, :mid, s(:arglist))
816
- # s(:call, nil, :mid, s(:arglist))
817
- def process_call(sexp, level)
818
- recv, meth, arglist, iter = sexp
819
- mid = mid_to_jsid meth.to_s
820
-
821
- @method_calls[meth.to_sym] = true
822
-
823
- # we are trying to access a lvar in irb mode
824
- if @irb_vars and @scope.top? and arglist == s(:arglist) and recv == nil
825
- return with_temp { |t|
826
- lvar = meth.intern
827
- lvar = "#{lvar}$" if RESERVED.include? lvar
828
- call = s(:call, s(:self), meth.intern, s(:arglist))
829
- [f("((#{t} = $opal.irb_vars.#{lvar}) == null ? ", sexp), process(call), f(" : #{t})", sexp)]
830
- }
831
- end
832
-
833
- case meth
834
- when :block_given?
835
- return js_block_given(sexp, level)
836
- end
837
-
838
- splat = arglist[1..-1].any? { |a| a.first == :splat }
839
-
840
- if Array === arglist.last and arglist.last.first == :block_pass
841
- block = process(arglist.pop)
842
- elsif iter
843
- block = iter
844
- end
845
-
846
- recv ||= s(:self)
847
-
848
- if block
849
- tmpfunc = @scope.new_temp
850
- end
851
-
852
- tmprecv = @scope.new_temp if splat || tmpfunc
853
- args = ""
854
-
855
- recv_code = process recv, :recv
856
-
857
- call_recv = s(:js_tmp, tmprecv || recv_code)
858
- arglist.insert 1, call_recv if tmpfunc and !splat
859
- args = process arglist
860
-
861
- dispatch = if tmprecv
862
- [f("(#{tmprecv} = "), recv_code, f(")#{mid}")]
863
- else
864
- [recv_code, f(mid)]
865
- end
866
-
867
- if tmpfunc
868
- dispatch.unshift f("(#{tmpfunc} = ")
869
- dispatch << f(", #{tmpfunc}._p = ")
870
- dispatch << block
871
- dispatch << f(", #{tmpfunc})")
872
- end
873
-
874
- result = if splat
875
- [dispatch, f(".apply("), (tmprecv ? f(tmprecv) : recv_code),
876
- f(", "), args, f(")")]
877
- elsif tmpfunc
878
- [dispatch, f(".call("), args, f(")")]
879
- else
880
- [dispatch, f("("), args, f(")")]
881
- end
882
-
883
- @scope.queue_temp tmpfunc if tmpfunc
884
- result
885
- end
886
-
887
- # s(:arglist, [arg [, arg ..]])
888
- def process_arglist(sexp, level)
889
- code, work = [], []
890
-
891
- sexp.each do |current|
892
- splat = current.first == :splat
893
- arg = process current
894
-
895
- if splat
896
- if work.empty?
897
- if code.empty?
898
- code << f("[].concat(", sexp)
899
- code << arg
900
- code << f(")")
901
- else
902
- code += ".concat(#{arg})"
903
- end
904
- else
905
- if code.empty?
906
- code << [f("["), work, f("]")]
907
- else
908
- code << [f(".concat(["), work, f("])")]
909
- end
910
-
911
- code << [f(".concat("), arg, f(")")]
912
- end
913
-
914
- work = []
915
- else
916
- work << f(", ") unless work.empty?
917
- work << arg
918
- end
919
- end
920
-
921
- unless work.empty?
922
- join = work
923
-
924
- if code.empty?
925
- code = join
926
- else
927
- code << f(".concat(") << join << f(")")
928
- end
929
- end
930
-
931
- code
932
- end
933
-
934
- # s(:splat, sexp)
935
- def process_splat(sexp, level)
936
- if sexp.first == [:nil]
937
- [f("[]")]
938
- elsif sexp.first.first == :sym
939
- [f("["), process(sexp[0]), f("]")]
940
- else
941
- process sexp.first, :recv
942
- end
943
- end
944
-
945
- # s(:class, cid, super, body)
946
- def process_class(sexp, level)
947
- cid, sup, body = sexp
948
-
949
- body[1] = s(:nil) unless body[1]
950
-
951
- code = []
952
- @helpers[:klass] = true
953
-
954
- if Symbol === cid or String === cid
955
- base = process s(:self)
956
- name = cid.to_s
957
- elsif cid[0] == :colon2
958
- base = process(cid[1])
959
- name = cid[2].to_s
960
- elsif cid[0] == :colon3
961
- base = process(s(:js_tmp, '$opal.Object'))
962
- name = cid[1].to_s
963
- else
964
- raise "Bad receiver in class"
965
- end
966
-
967
- sup = sup ? process(sup) : process(s(:js_tmp, 'null'))
968
-
969
- indent do
970
- in_scope(:class) do
971
- @scope.name = name
972
- @scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
973
-
974
- if Array === body.last
975
- # A single statement will need a block
976
- needs_block = body.last.first != :block
977
- body.last.first == :block
978
- last_body_statement = needs_block ? body.last : body.last.last
979
-
980
- if last_body_statement and Array === last_body_statement
981
- if [:defn, :defs].include? last_body_statement.first
982
- body[-1] = s(:block, body[-1]) if needs_block
983
- body.last << s(:nil)
984
- end
985
- end
986
- end
987
-
988
- body = process(returns(body), :stmt)
989
- code << f("\n")
990
- code << @scope.to_donate_methods
991
-
992
- code << f(@indent)
993
- code << @scope.to_vars
994
- code << f("\n\n#@indent")
995
- code << body
996
- end
997
- end
998
-
999
- spacer = "\n#{@indent}#{INDENT}"
1000
- cls = "function #{name}() {};"
1001
- boot = "#{name} = $klass($base, $super, #{name.inspect}, #{name});"
1002
-
1003
- [f("(function($base, $super){#{spacer}#{cls}#{spacer}#{boot}\n", sexp),
1004
- code, f("\n#@indent})", sexp), f("(", sexp), base, f(", ", sexp), sup, f(")", sexp)]
1005
- end
1006
-
1007
- # Singleton class syntax. Runs body in context of singleton_class.
1008
- # s(:sclass, recv, body) => (function() { ... }).call(recv.$singleton_class())
1009
- def process_sclass(sexp, level)
1010
- recv, body, code = sexp[0], sexp[1], []
1011
-
1012
- in_scope(:sclass) do
1013
- @scope.add_temp "$scope = #{current_self}._scope"
1014
- @scope.add_temp "def = #{current_self}._proto"
1015
-
1016
- code << @scope.to_vars << process(body, :stmt)
1017
- end
1018
-
1019
- [f("(function(){"), code, f("}).call("), process(recv, :recv), f(".$singleton_class())")]
1020
- end
1021
-
1022
- # s(:module, cid, body)
1023
- def process_module(sexp, level)
1024
- cid, body = sexp
1025
- code = []
1026
- @helpers[:module] = true
1027
-
1028
- if Symbol === cid or String === cid
1029
- base = process(s(:self))
1030
- name = cid.to_s
1031
- elsif cid[0] == :colon2
1032
- base = process(cid[1])
1033
- name = cid[2].to_s
1034
- elsif cid[0] == :colon3
1035
- base = f('$opal.Object', sexp)
1036
- name = cid[1].to_s
1037
- else
1038
- raise "Bad receiver in class"
1039
- end
1040
-
1041
- indent do
1042
- in_scope(:module) do
1043
- @scope.name = name
1044
- @scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
1045
- body = process body, :stmt
1046
-
1047
- code << f(@indent)
1048
- code << @scope.to_vars
1049
- code << f("\n\n#@indent")
1050
- code << body
1051
- code << f("\n#@ident")
1052
- code << @scope.to_donate_methods
1053
- end
1054
- end
1055
-
1056
- spacer = "\n#{@indent}#{INDENT}"
1057
- cls = "function #{name}() {};"
1058
- boot = "#{name} = $module($base, #{name.inspect}, #{name});"
1059
-
1060
- code.unshift f("(function($base){#{spacer}#{cls}#{spacer}#{boot}\n", sexp)
1061
- code << f("\n#@indent})(")
1062
- code << base
1063
- code << f(")")
1064
-
1065
- code
1066
- end
1067
-
1068
- # undef :foo
1069
- # => delete MyClass.prototype.$foo
1070
- # FIXME: we should be setting method to a stub method here
1071
- def process_undef(sexp, level)
1072
- f("delete #{ @scope.proto }#{ mid_to_jsid sexp[0][1].to_s }", sexp)
1073
- end
1074
-
1075
- # s(:defn, mid, s(:args), s(:scope))
1076
- def process_defn(sexp, level)
1077
- mid, args, stmts = sexp
1078
-
1079
- js_def nil, mid, args, stmts, sexp.line, sexp.end_line, sexp
1080
- end
1081
-
1082
- # s(:defs, recv, mid, s(:args), s(:scope))
1083
- def process_defs(sexp, level)
1084
- recv, mid, args, stmts = sexp
1085
-
1086
- js_def recv, mid, args, stmts, sexp.line, sexp.end_line, sexp
1087
- end
1088
-
1089
- def js_def(recvr, mid, args, stmts, line, end_line, sexp)
1090
- jsid = mid_to_jsid mid.to_s
1091
-
1092
- if recvr
1093
- @scope.defines_defs = true
1094
- smethod = true if @scope.class_scope? && recvr.first == :self
1095
- recv = process(recvr)
1096
- else
1097
- @scope.defines_defn = true
1098
- recv = current_self
1099
- end
1100
-
1101
- code = []
1102
- params = nil
1103
- scope_name = nil
1104
- uses_super = nil
1105
- uses_splat = nil
1106
-
1107
- # opt args if last arg is sexp
1108
- opt = args.pop if Array === args.last
1109
-
1110
- argc = args.length - 1
1111
-
1112
- # block name &block
1113
- if args.last.to_s.start_with? '&'
1114
- block_name = args.pop.to_s[1..-1].to_sym
1115
- argc -= 1
1116
- end
1117
-
1118
- # splat args *splat
1119
- if args.last.to_s.start_with? '*'
1120
- uses_splat = true
1121
- if args.last == :*
1122
- argc -= 1
1123
- else
1124
- splat = args[-1].to_s[1..-1].to_sym
1125
- args[-1] = splat
1126
- argc -= 1
1127
- end
1128
- end
1129
-
1130
- if @arity_check
1131
- arity_code = arity_check(args, opt, uses_splat, block_name, mid) + "\n#{INDENT}"
1132
- end
1133
-
1134
- indent do
1135
- in_scope(:def) do
1136
- @scope.mid = mid
1137
- @scope.defs = true if recvr
1138
-
1139
- if block_name
1140
- @scope.uses_block!
1141
- @scope.add_arg block_name
1142
- end
1143
-
1144
- yielder = block_name || '$yield'
1145
- @scope.block_name = yielder
1146
-
1147
- params = process args
1148
- stmt_code = [f("\n#@indent"), process(stmts, :stmt)]
1149
-
1150
- opt[1..-1].each do |o|
1151
- next if o[2][2] == :undefined
1152
- code << f("if (#{o[1]} == null) {\n#{@indent + INDENT}", o)
1153
- code << process(o)
1154
- code << f("\n#{@indent}}", o)
1155
- end if opt
1156
-
1157
- code << f("#{splat} = $slice.call(arguments, #{argc});", sexp) if splat
1158
-
1159
- scope_name = @scope.identity
1160
-
1161
- if @scope.uses_block?
1162
- @scope.add_temp "$iter = #{scope_name}._p"
1163
- @scope.add_temp "#{yielder} = $iter || nil"
1164
-
1165
- code.unshift f("#{scope_name}._p = null;", sexp)
1166
- end
1167
-
1168
- code.push(*stmt_code)
1169
-
1170
- uses_super = @scope.uses_super
1171
-
1172
- code = [f("#{arity_code}#@indent", sexp), @scope.to_vars, code]
1173
-
1174
- if @scope.uses_zuper
1175
- code.unshift f("var $zuper = $slice.call(arguments, 0);", sexp)
1176
- end
1177
-
1178
- if @scope.catch_return
1179
- code.unshift f("try {\n", sexp)
1180
- code.push f("\n} catch($returner) { if ($returner === $opal.returner) { return $returner.$v; } throw $returner; }", sexp)
1181
- end
1182
- end
1183
- end
1184
-
1185
- result = [f("#{"#{scope_name} = " if scope_name}function(", sexp)]
1186
- result.push(*params)
1187
- result << f(") {\n", sexp)
1188
- result.push(*code)
1189
- result << f("\n#@indent}", sexp)
1190
-
1191
- if recvr
1192
- if smethod
1193
- [f("#{@scope.name}.constructor.prototype['$#{mid}'] = ", sexp), result]
1194
- else
1195
- [recv, f("#{jsid} = ", sexp), result]
1196
- end
1197
- elsif @scope.class? and @scope.name == 'Object'
1198
- [f("#{current_self}._defn('$#{mid}', ", sexp), result, f(")", sexp)]
1199
- elsif @scope.class_scope?
1200
- @scope.methods << "$#{mid}"
1201
- if uses_super
1202
- @scope.add_temp uses_super
1203
- uses_super = "#{uses_super} = #{@scope.proto}#{jsid};\n#@indent"
1204
- end
1205
-
1206
- [f("#{uses_super}#{@scope.proto}#{jsid} = ", sexp), result]
1207
- else # :top, :iter
1208
- [f("def#{jsid} = ", sexp), result]
1209
- end
1210
- end
1211
-
1212
- ##
1213
- # Returns code used in debug mode to check arity of method call
1214
- def arity_check(args, opt, splat, block_name, mid)
1215
- meth = mid.to_s.inspect
1216
-
1217
- arity = args.size - 1
1218
- arity -= (opt.size - 1) if opt
1219
- arity -= 1 if splat
1220
- arity = -arity - 1 if opt or splat
1221
-
1222
- # $arity will point to our received arguments count
1223
- aritycode = "var $arity = arguments.length;"
1224
-
1225
- if arity < 0 # splat or opt args
1226
- aritycode + "if ($arity < #{-(arity + 1)}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
1227
- else
1228
- aritycode + "if ($arity !== #{arity}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
1229
- end
1230
- end
1231
-
1232
- def process_args(exp, level)
1233
- args = []
1234
-
1235
- exp.each do |a|
1236
- a = a.to_sym
1237
- next if a.to_s == '*'
1238
- a = lvar_to_js a
1239
- @scope.add_arg a
1240
- args << a
1241
- end
1242
-
1243
- f(args.join(', '), exp)
1244
- end
1245
-
1246
- # s(:self) # => this
1247
- def process_self(sexp, level)
1248
- f(current_self, sexp)
1249
- end
1250
-
1251
- # Returns the current value for 'self'. This will be native
1252
- # 'this' for methods and blocks, and the class name for class
1253
- # and module bodies.
1254
- # s(:self) => self or this or class name
1255
- def current_self
1256
- if @scope.class_scope?
1257
- @scope.name
1258
- elsif @scope.top? or @scope.iter?
1259
- 'self'
1260
- else # defn, defs
1261
- 'this'
1262
- end
1263
- end
1264
-
1265
- # true literal
1266
- # s(:true) => true
1267
- def process_true(sexp, level)
1268
- f "true", sexp
1269
- end
1270
-
1271
- # false literal
1272
- # s(:false) => false
1273
- def process_false(sexp, level)
1274
- f "false", sexp
1275
- end
1276
-
1277
- # nil literal
1278
- # s(:nil) => nil
1279
- def process_nil(sexp, level)
1280
- f "nil", sexp
1281
- end
1282
-
1283
- # s(:array [, sexp [, sexp]]) => [...]
1284
- def process_array(sexp, level)
1285
- return [f("[]", sexp)] if sexp.empty?
1286
-
1287
- code, work = [], []
1288
-
1289
- sexp.each do |current|
1290
- splat = current.first == :splat
1291
- part = process current
1292
-
1293
- if splat
1294
- if work.empty?
1295
- if code.empty?
1296
- code << f("[].concat(", sexp) << part << f(")", sexp)
1297
- else
1298
- code << f(".concat(", sexp) << part << f(")", sexp)
1299
- end
1300
- else
1301
- if code.empty?
1302
- code << f("[", sexp) << work << f("]", sexp)
1303
- else
1304
- code << f(".concat([", sexp) << work << f("])", sexp)
1305
- end
1306
-
1307
- code << f(".concat(", sexp) << part << f(")", sexp)
1308
- end
1309
- work = []
1310
- else
1311
- work << f(", ", current) unless work.empty?
1312
- work << part
1313
- end
1314
- end
1315
-
1316
- unless work.empty?
1317
- join = [f("[", sexp), work, f("]", sexp)]
1318
-
1319
- if code.empty?
1320
- code = join
1321
- else
1322
- code.push([f(".concat(", sexp), join, f(")", sexp)])
1323
- end
1324
- end
11
+ def parse(source, file = '(string)')
12
+ @lexer = Lexer.new(source, file)
13
+ @file = file
14
+ @scopes = []
1325
15
 
1326
- code
16
+ self.parse_to_sexp
1327
17
  end
1328
18
 
1329
- # s(:hash, key1, val1, key2, val2...)
1330
- def process_hash(sexp, level)
1331
- keys = []
1332
- vals = []
1333
-
1334
- sexp.each_with_index do |obj, idx|
1335
- if idx.even?
1336
- keys << obj
1337
- else
1338
- vals << obj
1339
- end
1340
- end
1341
-
1342
- if keys.all? { |k| [:sym, :str].include? k[0] }
1343
- hash_obj = {}
1344
- hash_keys = []
1345
- keys.size.times do |i|
1346
- k = keys[i][1].to_s.inspect
1347
- hash_keys << k unless hash_obj.include? k
1348
- hash_obj[k] = process(vals[i])
1349
- end
1350
-
1351
- result = []
1352
- @helpers[:hash2] = true
1353
-
1354
- hash_keys.each do |k|
1355
- result << f(", ", sexp) unless result.empty?
1356
- result << f("#{k}: ", sexp)
1357
- result << hash_obj[k]
1358
- end
1359
-
1360
- [f("$hash2([#{hash_keys.join ', '}], {", sexp), result, f("})", sexp)]
1361
- else
1362
- @helpers[:hash] = true
1363
- result = []
1364
-
1365
- sexp.each do |p|
1366
- result << f(", ", p) unless result.empty?
1367
- result << process(p)
1368
- end
19
+ def parse_to_sexp
20
+ push_scope
21
+ result = do_parse
22
+ pop_scope
1369
23
 
1370
- [f("$hash(", sexp), result, f(")", sexp)]
1371
- end
24
+ result
1372
25
  end
1373
26
 
1374
- # s(:while, exp, block, true)
1375
- def process_while(sexp, level)
1376
- expr, stmt = sexp
1377
- redo_var = @scope.new_temp
1378
- code = []
1379
-
1380
- stmt_level = if level == :expr or level == :recv
1381
- :stmt_closure
1382
- else
1383
- :stmt
1384
- end
1385
-
1386
- code << js_truthy(expr) << f("){", sexp)
1387
- pre = "while ("
1388
-
1389
- in_while do
1390
- @while_loop[:closure] = true if stmt_level == :stmt_closure
1391
- @while_loop[:redo_var] = redo_var
1392
- body = process(stmt, :stmt)
1393
-
1394
- if @while_loop[:use_redo]
1395
- pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
1396
- code << f("#{redo_var}=false;", sexp)
1397
- end
1398
-
1399
- code << body
1400
- end
1401
-
1402
- code << f("}", sexp)
1403
- code.unshift f(pre, sexp)
1404
- @scope.queue_temp redo_var
1405
-
1406
- if stmt_level == :stmt_closure
1407
- code.unshift f("(function() {", sexp)
1408
- code.push f("; return nil; }).call(#{current_self})", sexp)
1409
- end
1410
-
1411
- code
27
+ def next_token
28
+ @lexer.next_token
1412
29
  end
1413
30
 
1414
- def process_until(exp, level)
1415
- expr, stmt = exp
1416
- redo_var = @scope.new_temp
1417
- stmt_level = if level == :expr or level == :recv
1418
- :stmt_closure
1419
- else
1420
- :stmt
1421
- end
1422
-
1423
- code = []
1424
- pre = "while (!("
1425
- code << js_truthy(expr) << f(")) {", exp)
1426
-
1427
- in_while do
1428
- @while_loop[:closure] = true if stmt_level == :stmt_closure
1429
- @while_loop[:redo_var] = redo_var
1430
- body = process(stmt, :stmt)
1431
-
1432
- if @while_loop[:use_redo]
1433
- pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
1434
- code << f("#{redo_var}=false;", exp)
1435
- end
1436
-
1437
- code << body
1438
- end
1439
-
1440
- code << f("}", exp)
1441
- code.unshift f(pre, exp)
1442
- @scope.queue_temp redo_var
1443
-
1444
- if stmt_level == :stmt_closure
1445
- code.unshift f("(function() {", exp)
1446
- code << f("; return nil; }).call(#{current_self})", exp)
1447
- end
1448
-
1449
- code
31
+ def s(*parts)
32
+ sexp = Sexp.new(parts)
33
+ sexp.line = @lexer.line
34
+ sexp
1450
35
  end
1451
36
 
1452
- # alias foo bar
1453
- #
1454
- # s(:alias, s(:sym, :foo), s(:sym, :bar))
1455
- def process_alias(exp, level)
1456
- new = mid_to_jsid exp[0][1].to_s
1457
- old = mid_to_jsid exp[1][1].to_s
1458
-
1459
- if [:class, :module].include? @scope.type
1460
- @scope.methods << "$#{exp[0][1].to_s}"
1461
- f("%s%s = %s%s" % [@scope.proto, new, @scope.proto, old], exp)
1462
- else
1463
- current = current_self
1464
- f("%s._proto%s = %s._proto%s" % [current, new, current, old], exp)
1465
- end
37
+ def push_scope(type = nil)
38
+ top = @scopes.last
39
+ scope = ParserScope.new type
40
+ scope.parent = top
41
+ @scopes << scope
42
+ @scope = scope
1466
43
  end
1467
44
 
1468
- def process_masgn(sexp, level)
1469
- lhs, rhs = sexp
1470
- tmp = @scope.new_temp
1471
- len = 0
1472
- code = []
1473
-
1474
- if rhs[0] == :array
1475
- len = rhs.length - 1 # we are guaranteed an array of this length
1476
- code << f("#{tmp} = ", sexp) << process(rhs)
1477
- elsif rhs[0] == :to_ary
1478
- code << f("((#{tmp} = ", sexp) << process(rhs[1])
1479
- code << f(")._isArray ? #{tmp} : (#{tmp} = [#{tmp}]))", sexp)
1480
- elsif rhs[0] == :splat
1481
- code << f("(#{tmp} = ", sexp) << process(rhs[1])
1482
- code << f(")['$to_a'] ? (#{tmp} = #{tmp}['$to_a']()) : (#{tmp})._isArray ? #{tmp} : (#{tmp} = [#{tmp}])", sexp)
1483
- else
1484
- raise "Unsupported mlhs type"
1485
- end
1486
-
1487
- lhs[1..-1].each_with_index do |l, idx|
1488
- code << f(", ", sexp) unless code.empty?
1489
-
1490
- if l.first == :splat
1491
- if s = l[1]
1492
- s << s(:js_tmp, "$slice.call(#{tmp}, #{idx})")
1493
- code << process(s)
1494
- end
1495
- else
1496
- if idx >= len
1497
- assign = s(:js_tmp, "(#{tmp}[#{idx}] == null ? nil : #{tmp}[#{idx}])")
1498
- else
1499
- assign = s(:js_tmp, "#{tmp}[#{idx}]")
1500
- end
1501
-
1502
- if l[0] == :lasgn or l[0] == :iasgn or l[0] == :lvar
1503
- l << assign
1504
- elsif l[0] == :call
1505
- l[2] = "#{l[2]}=".to_sym
1506
- l.last << assign
1507
- elsif l[0] == :attrasgn
1508
- l.last << assign
1509
- else
1510
- raise "bad lhs for masgn: #{l.inspect}"
1511
- end
1512
-
1513
- code << process(l)
1514
- end
1515
- end
1516
-
1517
- @scope.queue_temp tmp
1518
- code
45
+ def pop_scope
46
+ @scopes.pop
47
+ @scope = @scopes.last
1519
48
  end
1520
49
 
1521
- def process_svalue(sexp, level)
1522
- process sexp[0], level
50
+ def on_error(t, val, vstack)
51
+ raise "parse error on value #{val.inspect} (#{token_to_str(t) || '?'}) :#{@file}:#{lexer.line}"
1523
52
  end
1524
53
 
1525
- # s(:lasgn, :lvar, rhs)
1526
- def process_lasgn(sexp, level)
1527
- lvar = sexp[0]
1528
- rhs = sexp[1]
1529
- lvar = "#{lvar}$".to_sym if RESERVED.include? lvar.to_s
1530
-
1531
- if @irb_vars and @scope.top?
1532
- [f("$opal.irb_vars.#{lvar} = ", sexp), process(rhs)]
1533
- else
1534
- @scope.add_local lvar
1535
- rhs = process(rhs)
1536
- result = [f(lvar, sexp), f(" = ", sexp), rhs]
1537
-
1538
- if level == :recv
1539
- result.unshift f("(", sexp)
1540
- result.push f(")", sexp)
1541
- end
1542
-
1543
- result
1544
- end
54
+ def new_block(stmt = nil)
55
+ s = s(:block)
56
+ s << stmt if stmt
57
+ s
1545
58
  end
1546
59
 
1547
- # s(:lvar, :lvar)
1548
- def process_lvar(sexp, level)
1549
- lvar = sexp[0].to_s
1550
- lvar = "#{lvar}$" if RESERVED.include? lvar
1551
-
1552
- if @irb_vars and @scope.top?
1553
- with_temp { |t| f("((#{t} = $opal.irb_vars.#{lvar}) == null ? nil : #{t})", sexp) }
60
+ def new_compstmt(block)
61
+ if block.size == 1
62
+ nil
63
+ elsif block.size == 2
64
+ block[1]
1554
65
  else
1555
- f(lvar, sexp)
66
+ block.line = block[1].line
67
+ block
1556
68
  end
1557
69
  end
1558
70
 
1559
- # s(:iasgn, :ivar, rhs)
1560
- def process_iasgn(exp, level)
1561
- ivar, rhs = exp
1562
- ivar = ivar.to_s[1..-1]
1563
- lhs = RESERVED.include?(ivar) ? "#{current_self}['#{ivar}']" : "#{current_self}.#{ivar}"
1564
- [f(lhs, exp), f(" = ", exp), process(rhs)]
1565
- end
1566
-
1567
- # s(:ivar, :ivar)
1568
- def process_ivar(exp, level)
1569
- ivar = exp[0].to_s[1..-1]
1570
- part = RESERVED.include?(ivar) ? "['#{ivar}']" : ".#{ivar}"
1571
- @scope.add_ivar part
1572
- f("#{current_self}#{part}", exp)
1573
- end
1574
-
1575
- # s(:gvar, gvar)
1576
- def process_gvar(sexp, level)
1577
- gvar = sexp[0].to_s[1..-1]
1578
- @helpers['gvars'] = true
1579
- f("$gvars[#{gvar.inspect}]", sexp)
1580
- end
71
+ def new_body(compstmt, res, els, ens)
72
+ s = compstmt || s(:block)
73
+ s.line = compstmt.line if compstmt
1581
74
 
1582
- def process_nth_ref(sexp, level)
1583
- f("nil", sexp)
1584
- end
75
+ if res
76
+ s = s(:rescue, s)
77
+ res.each { |r| s << r }
78
+ s << els if els
79
+ end
1585
80
 
1586
- # s(:gasgn, :gvar, rhs)
1587
- def process_gasgn(sexp, level)
1588
- gvar = sexp[0].to_s[1..-1]
1589
- rhs = sexp[1]
1590
- @helpers['gvars'] = true
1591
- [f("$gvars[#{gvar.to_s.inspect}] = ", sexp), process(rhs)]
81
+ ens ? s(:ensure, s, ens) : s
1592
82
  end
1593
83
 
1594
- # s(:const, :const)
1595
- def process_const(sexp, level)
1596
- cname = sexp[0].to_s
1597
-
1598
- if @const_missing
1599
- with_temp do |t|
1600
- f("((#{t} = $scope.#{cname}) == null ? $opal.cm(#{cname.inspect}) : #{t})", sexp)
1601
- end
1602
- else
1603
- f("$scope.#{cname}", sexp)
1604
- end
84
+ def new_def(line, recv, name, args, body)
85
+ body = s(:block, body) if body.type != :block
86
+ scope = s(:scope, body)
87
+ body << s(:nil) if body.size == 1
88
+ scope.line = body.line
89
+ args.line = line
90
+ s = s(:def, recv, name.to_sym, args, scope)
91
+ s.line = line
92
+ s.end_line = @lexer.line
93
+ s
1605
94
  end
1606
95
 
1607
- # s(:cdecl, :const, rhs)
1608
- def process_cdecl(sexp, level)
1609
- const, rhs = sexp
1610
- [f("$scope.#{const} = ", sexp), process(rhs)]
96
+ def new_class(path, sup, body)
97
+ scope = s(:scope)
98
+ scope << body unless body.size == 1
99
+ scope.line = body.line
100
+ s = s(:class, path, sup, scope)
101
+ s
1611
102
  end
1612
103
 
1613
- # s(:casgn, s(:const, ::A), :B, val)
1614
- # A::B = 100
1615
- def process_casgn(sexp, level)
1616
- lhs, const, rhs = sexp
1617
- [process(lhs), f("._scope.#{const} = ", sexp), process(rhs)]
104
+ def new_sclass(expr, body)
105
+ scope = s(:scope)
106
+ scope << body #unless body.size == 1
107
+ scope.line = body.line
108
+ s = s(:sclass, expr, scope)
109
+ s
1618
110
  end
1619
111
 
1620
- # s(:return [val])
1621
- def process_return(sexp, level)
1622
- val = process(sexp[0] || s(:nil))
1623
-
1624
- if @scope.iter? and parent_def = @scope.find_parent_def
1625
- parent_def.catch_return = true
1626
- [f("$opal.$return(", sexp), val, f(")", sexp)]
1627
-
1628
- elsif level == :expr and @scope.def?
1629
- @scope.catch_return = true
1630
- [f("$opal.$return(", sexp), val, f(")", sexp)]
1631
-
1632
- elsif level == :stmt
1633
- [f("return ", sexp), val]
1634
-
1635
- else
1636
- raise SyntaxError, "void value expression: cannot return as an expression"
1637
- end
112
+ def new_module(path, body)
113
+ scope = s(:scope)
114
+ scope << body unless body.size == 1
115
+ scope.line = body.line
116
+ s = s(:module, path, scope)
117
+ s
1638
118
  end
1639
119
 
1640
- # s(:xstr, content)
1641
- def process_xstr(sexp, level)
1642
- code = sexp.first.to_s
1643
- code += ";" if level == :stmt and !code.include?(';')
1644
-
1645
- result = f(code, sexp)
1646
-
1647
- level == :recv ? [f("(", sexp), result, f(")", sexp)] : result
120
+ def new_iter(args, body)
121
+ s = s(:iter, args)
122
+ s << body if body
123
+ s.end_line = @lexer.line
124
+ s
1648
125
  end
1649
126
 
1650
- # s(:dxstr, parts...)
1651
- def process_dxstr(sexp, level)
1652
- result = []
1653
- needs_sc = false
1654
-
1655
- sexp.each do |p|
1656
- if String === p
1657
- result << f(p.to_s, sexp)
1658
- needs_sc = true if level == :stmt and !p.to_s.include?(';')
1659
- elsif p.first == :evstr
1660
- result.push(*process(p.last, :stmt))
1661
- elsif p.first == :str
1662
- result << f(p.last.to_s, p)
1663
- needs_sc = true if level == :stmt and !p.last.to_s.include?(';')
1664
- else
1665
- raise "Bad dxstr part"
1666
- end
1667
- end
1668
-
1669
- result << f(";", sexp) if needs_sc
1670
-
1671
- if level == :recv
1672
- [f("(", sexp), result, f(")", sexp)]
1673
- else
1674
- result
1675
- end
127
+ def new_if(expr, stmt, tail)
128
+ s = s(:if, expr, stmt, tail)
129
+ s.line = expr.line
130
+ s.end_line = @lexer.line
131
+ s
1676
132
  end
1677
133
 
1678
- # s(:dstr, parts..)
1679
- def process_dstr(sexp, level)
1680
- result = []
134
+ def new_args(norm, opt, rest, block)
135
+ res = s(:args)
1681
136
 
1682
- sexp.each do |p|
1683
- result << f(" + ", sexp) unless result.empty?
1684
- if String === p
1685
- result << f(p.inspect, sexp)
1686
- elsif p.first == :evstr
1687
- result << f("(", p)
1688
- result << process(p.last)
1689
- result << f(")", p)
1690
- elsif p.first == :str
1691
- result << f(p.last.inspect, p)
1692
- else
1693
- raise "Bad dstr part"
137
+ if norm
138
+ norm.each do |arg|
139
+ scope.add_local arg
140
+ res << arg
1694
141
  end
1695
142
  end
1696
143
 
1697
- if level == :recv
1698
- [f("(", sexp), result, f(")", sexp)]
1699
- else
1700
- result
1701
- end
1702
- end
1703
-
1704
- def process_dsym(sexp, level)
1705
- result = []
1706
-
1707
- sexp.each do |p|
1708
- result << f(" + ", sexp) unless result.empty?
1709
-
1710
- if String === p
1711
- result << f(p.inspect, sexp)
1712
- elsif p.first == :evstr
1713
- result << process(s(:call, p.last, :to_s, s(:arglist)))
1714
- elsif p.first == :str
1715
- result << f(p.last.inspect, sexp)
1716
- else
1717
- raise "Bad dsym part"
144
+ if opt
145
+ opt[1..-1].each do |_opt|
146
+ res << _opt[1]
1718
147
  end
1719
148
  end
1720
149
 
1721
- [f("(", sexp), result, f(")", sexp)]
1722
- end
1723
-
1724
- # s(:if, test, truthy, falsy)
1725
- def process_if(sexp, level)
1726
- test, truthy, falsy = sexp
1727
- returnable = (level == :expr or level == :recv)
1728
-
1729
- if returnable
1730
- truthy = returns(truthy || s(:nil))
1731
- falsy = returns(falsy || s(:nil))
1732
- end
1733
-
1734
- # optimize unless (we don't want else unless we need to)
1735
- if falsy and !truthy
1736
- truthy = falsy
1737
- falsy = nil
1738
- check = js_falsy test
1739
- else
1740
- check = js_truthy test
150
+ if rest
151
+ res << rest
152
+ rest_str = rest.to_s[1..-1]
153
+ scope.add_local rest_str.to_sym unless rest_str.empty?
1741
154
  end
1742
155
 
1743
- result = [f("if (", sexp), check, f(") {\n", sexp)]
1744
-
1745
- indent { result.push(f(@indent, sexp), process(truthy, :stmt)) } if truthy
1746
-
1747
- outdent = @indent
1748
- indent { result.push(f("\n#{outdent}} else {\n#@indent", sexp), process(falsy, :stmt)) } if falsy
1749
-
1750
- result << f("\n#@indent}", sexp)
1751
-
1752
- if returnable
1753
- result.unshift f("(function() { ", sexp)
1754
- result.push f("; return nil; }).call(#{current_self})", sexp)
156
+ if block
157
+ res << block
158
+ scope.add_local block.to_s[1..-1].to_sym
1755
159
  end
1756
160
 
1757
- result
1758
- end
161
+ res << opt if opt
1759
162
 
1760
- def js_truthy_optimize(sexp)
1761
- if sexp.first == :call
1762
- mid = sexp[2]
1763
- if mid == :block_given?
1764
- return process sexp
1765
- elsif COMPARE.include? mid.to_s
1766
- return process sexp
1767
- elsif mid == :"=="
1768
- return process sexp
1769
- end
1770
- elsif [:lvar, :self].include? sexp.first
1771
- [process(sexp.dup), f(" !== false && ", sexp), process(sexp.dup), f(" !== nil", sexp)]
1772
- end
163
+ res
1773
164
  end
1774
165
 
1775
- def js_truthy(sexp)
1776
- if optimized = js_truthy_optimize(sexp)
1777
- return optimized
1778
- end
166
+ def new_block_args(norm, opt, rest, block)
167
+ res = s(:array)
1779
168
 
1780
- with_temp do |tmp|
1781
- [f("(#{tmp} = ", sexp), process(sexp), f(") !== false && #{tmp} !== nil", sexp)]
169
+ if norm
170
+ norm.each do |arg|
171
+ if arg.is_a? Symbol
172
+ scope.add_local arg
173
+ res << s(:lasgn, arg)
174
+ else
175
+ res << arg
176
+ end
177
+ end
1782
178
  end
1783
- end
1784
179
 
1785
- def js_falsy(sexp)
1786
- if sexp.first == :call
1787
- mid = sexp[2]
1788
- if mid == :block_given?
1789
- return handle_block_given(sexp, true)
180
+ if opt
181
+ opt[1..-1].each do |_opt|
182
+ res << s(:lasgn, _opt[1])
1790
183
  end
1791
184
  end
1792
185
 
1793
- with_temp do |tmp|
1794
- result = []
1795
- result << f("(#{tmp} = ", sexp)
1796
- result << process(sexp)
1797
- result << f(") === false || #{tmp} === nil", sexp)
1798
- result
186
+ if rest
187
+ r = rest.to_s[1..-1].to_sym
188
+ res << s(:splat, s(:lasgn, r))
189
+ scope.add_local r
1799
190
  end
1800
- end
1801
-
1802
- # s(:and, lhs, rhs)
1803
- def process_and(sexp, level)
1804
- lhs, rhs = sexp
1805
- t = nil
1806
- tmp = @scope.new_temp
1807
191
 
1808
- if t = js_truthy_optimize(lhs)
1809
- result = []
1810
- result << f("((#{tmp} = ", sexp) << t
1811
- result << f(") ? ", sexp) << process(rhs)
1812
- result << f(" : #{tmp})", sexp)
1813
- @scope.queue_temp tmp
1814
-
1815
- return result
192
+ if block
193
+ b = block.to_s[1..-1].to_sym
194
+ res << s(:block_pass, s(:lasgn, b))
195
+ scope.add_local b
1816
196
  end
1817
197
 
1818
- @scope.queue_temp tmp
1819
-
1820
- [f("(#{tmp} = ", sexp), process(lhs), f(", #{tmp} !== false && #{tmp} !== nil ? ", sexp), process(rhs), f(" : #{tmp})", sexp)]
1821
-
1822
- end
1823
-
1824
- # s(:or, lhs, rhs)
1825
- def process_or(sexp, level)
1826
- lhs, rhs = sexp
198
+ res << opt if opt
1827
199
 
1828
- with_temp do |tmp|
1829
- lhs = process lhs
1830
- rhs = process rhs
1831
- [f("(((#{tmp} = ", sexp), lhs, f(") !== false && #{tmp} !== nil) ? #{tmp} : ", sexp), rhs, f(")", sexp)]
1832
- end
1833
- end
200
+ args = res.size == 2 && norm ? res[1] : s(:masgn, res)
1834
201
 
1835
- # s(:yield, arg1, arg2)
1836
- def process_yield(sexp, level)
1837
- call = handle_yield_call sexp, level
1838
-
1839
- if level == :stmt
1840
- [f("if (", sexp), call, f(" === $breaker) return $breaker.$v")]
202
+ if args.type == :array
203
+ s(:masgn, args)
1841
204
  else
1842
- with_temp do |tmp|
1843
- [f("(((#{tmp} = ", sexp), call, f(") === $breaker) ? $breaker.$v : #{tmp})", sexp)]
1844
- end
1845
- end
1846
- end
1847
-
1848
- # special opal yield assign, for `a = yield(arg1, arg2)` to assign
1849
- # to a temp value to make yield expr into stmt.
1850
- #
1851
- # level will always be stmt as its the reason for this to exist
1852
- #
1853
- # s(:yasgn, :a, s(:yield, arg1, arg2))
1854
- def process_yasgn(sexp, level)
1855
- call = handle_yield_call s(*sexp[1][1..-1]), :stmt
1856
-
1857
- [f("if ((#{sexp[0]} = ", sexp), call, f(") === $breaker) return $breaker.$v", sexp)]
1858
- end
1859
-
1860
- # Created by `#returns()` for when a yield statement should return
1861
- # it's value (its last in a block etc).
1862
- def process_returnable_yield(sexp, level)
1863
- call = handle_yield_call sexp, level
1864
-
1865
- with_temp do |tmp|
1866
- [f("return #{tmp} = ", sexp), call,
1867
- f(", #{tmp} === $breaker ? #{tmp} : #{tmp}")]
205
+ args
1868
206
  end
1869
207
  end
1870
208
 
1871
- def handle_yield_call(sexp, level)
1872
- @scope.uses_block!
1873
-
1874
- splat = sexp.any? { |s| s.first == :splat }
209
+ def new_call(recv, meth, args = nil)
210
+ call = s(:call, recv, meth)
211
+ args = s(:arglist) unless args
212
+ args.type = :arglist if args.type == :array
213
+ call << args
1875
214
 
1876
- if !splat and sexp.size == 1
1877
- return [f("$opal.$yield1(#{@scope.block_name || '$yield'}, "), process(sexp[0]), f(")")]
215
+ if recv
216
+ call.line = recv.line
217
+ elsif args[1]
218
+ call.line = args[1].line
1878
219
  end
1879
220
 
1880
- args = process_arglist sexp, level
1881
- y = @scope.block_name || '$yield'
1882
-
1883
- if splat
1884
- [f("$opal.$yieldX(#{y}, ", sexp), args, f(")")]
221
+ # fix arglist spilling over into next line if no args
222
+ if args.length == 1
223
+ args.line = call.line
1885
224
  else
1886
- [f("$opal.$yieldX(#{y}, [", sexp), args, f("])")]
225
+ args.line = args[1].line
1887
226
  end
1888
- end
1889
227
 
1890
- def process_break(sexp, level)
1891
- val = sexp.empty? ? f('nil', sexp) : process(sexp[0])
1892
- if in_while?
1893
- @while_loop[:closure] ? [f("return ", sexp), val, f("", sexp)] : f("break;", sexp)
1894
- elsif @scope.iter?
1895
- error "break must be used as a statement" unless level == :stmt
1896
- [f("return ($breaker.$v = ", sexp), val, f(", $breaker)", sexp)]
1897
- else
1898
- error "void value expression: cannot use break outside of iter/while"
1899
- end
228
+ call
1900
229
  end
1901
230
 
1902
- # s(:case, expr, when1, when2, ..)
1903
- def process_case(exp, level)
1904
- pre, code = [], []
1905
-
1906
- # are we inside a statement_closure
1907
- returnable = level != :stmt
1908
- done_else = false
1909
-
1910
- in_case do
1911
- if cond = exp[0]
1912
- @case_stmt[:cond] = true
1913
- @scope.add_local "$case"
1914
- expr = process cond
1915
- pre << f("$case = ", exp) << expr << f(";", exp)
1916
- end
1917
-
1918
- exp[1..-1].each do |wen|
1919
- if wen and wen.first == :when
1920
- returns(wen) if returnable
1921
- wen = process(wen, :stmt)
1922
- code << f("else ", exp) unless code.empty?
1923
- code << wen
1924
- elsif wen # s(:else)
1925
- done_else = true
1926
- wen = returns(wen) if returnable
1927
- code << f("else {", exp) << process(wen, :stmt) << f("}", exp)
1928
- end
1929
- end
1930
- end
1931
-
1932
- code << f("else { return nil }", exp) if returnable and !done_else
1933
-
1934
- code.unshift pre
1935
-
1936
- if returnable
1937
- code.unshift f("(function() { ", exp)
1938
- code << f(" }).call(#{current_self})", exp)
1939
- end
1940
-
1941
- code
231
+ def add_block_pass(arglist, block)
232
+ arglist << block if block
233
+ arglist
1942
234
  end
1943
235
 
1944
- # when foo
1945
- # bar
1946
- #
1947
- # s(:when, s(:array, foo), bar)
1948
- def process_when(exp, level)
1949
- arg = exp[0][1..-1]
1950
- body = exp[1] || s(:nil)
1951
- body = process body, level
1952
-
1953
- test = []
1954
- arg.each do |a|
1955
- test << f(" || ") unless test.empty?
1956
-
1957
- if a.first == :splat # when inside another when means a splat of values
1958
- call = f("$splt[i]['$===']($case)", a)
1959
-
1960
- splt = [f("(function($splt) { for(var i = 0; i < $splt.length; i++) {", exp)]
1961
- splt << f("if (") << call << f(") { return true; }", exp)
1962
- splt << f("} return false; }).call(#{current_self}, ", exp)
1963
- splt << process(a[1]) << f(")")
236
+ def new_op_asgn(op, lhs, rhs)
237
+ case op
238
+ when :"||"
239
+ result = s(:op_asgn_or, new_gettable(lhs))
240
+ result << (lhs << rhs)
241
+ when :"&&"
242
+ result = s(:op_asgn_and, new_gettable(lhs))
243
+ result << (lhs << rhs)
244
+ else
245
+ result = lhs
246
+ result << new_call(new_gettable(lhs), op, s(:arglist, rhs))
1964
247
 
1965
- test << splt
1966
- else
1967
- if @case_stmt[:cond]
1968
- call = s(:call, a, :===, s(:arglist, s(:js_tmp, "$case")))
1969
- test << process(call)
1970
- else
1971
- test << js_truthy(a)
1972
- end
1973
- end
1974
248
  end
1975
249
 
1976
- [f("if ("), test, f(") {#@space"), body, f("#@space}")]
1977
- end
1978
-
1979
- # lhs =~ rhs
1980
- #
1981
- # s(:match3, lhs, rhs) # => s(:call, lhs, :=~, s(:arglist, rhs))
1982
- def process_match3(sexp, level)
1983
- process s(:call, sexp[0], :=~, s(:arglist, sexp[1])), level
250
+ result.line = lhs.line
251
+ result
1984
252
  end
1985
253
 
1986
- # @@class_variable
1987
- #
1988
- # s(:cvar, name)
1989
- def process_cvar(exp, level)
1990
- with_temp do |tmp|
1991
- f("((#{tmp} = $opal.cvars['#{exp[0]}']) == null ? nil : #{tmp})", exp)
254
+ def new_assign(lhs, rhs)
255
+ case lhs.type
256
+ when :iasgn, :cdecl, :lasgn, :gasgn, :cvdecl, :nth_ref
257
+ lhs << rhs
258
+ lhs
259
+ when :call, :attrasgn
260
+ lhs.last << rhs
261
+ lhs
262
+ when :colon2
263
+ lhs << rhs
264
+ lhs.type = :casgn
265
+ lhs
266
+ when :colon3
267
+ lhs << rhs
268
+ lhs.type = :casgn3
269
+ lhs
270
+ else
271
+ raise "Bad lhs for new_assign: #{lhs.type}"
1992
272
  end
1993
273
  end
1994
274
 
1995
- # @@name = rhs
1996
- #
1997
- # s(:cvasgn, :@@name, rhs)
1998
- def process_cvasgn(exp, level)
1999
- "($opal.cvars['#{exp[0]}'] = #{process exp[1]})"
2000
- end
2001
-
2002
- # s(:cvdecl, :@@foo, value) # => ($opal.cvars['@@foo'] = value)
2003
- def process_cvdecl(exp, level)
2004
- [f("($opal.cvars['#{exp[0]}'] = ", exp), process(exp[1]), f(")", exp)]
2005
- end
2006
-
2007
- # BASE::NAME
2008
- #
2009
- # s(:colon2, base, :NAME)
2010
- def process_colon2(sexp, level)
2011
- base, cname = sexp
2012
- result = []
2013
-
2014
- if @const_missing
2015
- with_temp do |t|
2016
- base = process base
2017
-
2018
- result << f("((#{t} = (", sexp) << base << f(")._scope).", sexp)
2019
- result << f("#{cname} == null ? #{t}.cm('#{cname}') : #{t}.#{cname})", sexp)
2020
- end
275
+ def new_assignable(ref)
276
+ case ref.type
277
+ when :ivar
278
+ ref.type = :iasgn
279
+ when :const
280
+ ref.type = :cdecl
281
+ when :identifier
282
+ scope.add_local ref[1] unless scope.has_local? ref[1]
283
+ ref.type = :lasgn
284
+ when :gvar
285
+ ref.type = :gasgn
286
+ when :cvar
287
+ ref.type = :cvdecl
2021
288
  else
2022
- result << f("(", sexp) << process(base) << f(")._scope.#{cname}", sexp)
289
+ raise "Bad new_assignable type: #{ref.type}"
2023
290
  end
2024
291
 
2025
- result
2026
- end
2027
-
2028
- # s(:colon3, :CONST_NAME) # => $opal.Object._scope.CONST_NAME
2029
- def process_colon3(exp, level)
2030
- with_temp do |t|
2031
- f("((#{t} = $opal.Object._scope.#{exp[0]}) == null ? $opal.cm('#{exp[0]}') : #{t})", exp)
2032
- end
292
+ ref
2033
293
  end
2034
294
 
2035
- # super a, b, c
2036
- #
2037
- # s(:super, arg1, arg2, ...)
2038
- def process_super(sexp, level)
2039
- args = []
2040
- sexp.each do |part|
2041
- args << f(", ", sexp) unless args.empty?
2042
- args << process(part)
2043
- end
2044
-
2045
- js_super [f("[", sexp), args, f("]", sexp)], false, sexp
2046
- end
295
+ def new_gettable(ref)
296
+ res = case ref.type
297
+ when :lasgn
298
+ s(:lvar, ref[1])
299
+ when :iasgn
300
+ s(:ivar, ref[1])
301
+ when :gasgn
302
+ s(:gvar, ref[1])
303
+ when :cvdecl
304
+ s(:cvar, ref[1])
305
+ else
306
+ raise "Bad new_gettable ref: #{ref.type}"
307
+ end
2047
308
 
2048
- # super
2049
- #
2050
- # s(:zsuper)
2051
- def process_zsuper(exp, level)
2052
- if @scope.def?
2053
- @scope.uses_zuper = true
2054
- js_super f("$zuper", exp), true, exp
2055
- else
2056
- js_super f("$slice.call(arguments)", exp), true, exp
2057
- end
309
+ res.line = ref.line
310
+ res
2058
311
  end
2059
312
 
2060
- def js_super args, pass_block, sexp
2061
- if @scope.def_in_class?
2062
- @scope.uses_block!
2063
- mid = @scope.mid.to_s
2064
-
2065
- if @scope.uses_super
2066
- sid = @scope.uses_super
2067
- else
2068
- sid = @scope.uses_super = "super_#{unique_temp}"
2069
- end
2070
-
2071
- if pass_block
2072
- @scope.uses_block!
2073
- [f("(#{sid}._p = $iter, #{sid}.apply(#{current_self}, ", sexp), args, f("))", sexp)]
2074
- else
2075
- [f("#{sid}.apply(#{current_self}, ", sexp), args, f(")", sexp)]
2076
- end
2077
-
2078
-
2079
- elsif @scope.type == :def
2080
- @scope.uses_block!
2081
- @scope.identify!
2082
- cls_name = @scope.parent.name || "#{current_self}._klass._proto"
2083
- jsid = mid_to_jsid @scope.mid.to_s
2084
-
2085
- if pass_block
2086
- @scope.uses_block!
2087
- iter = "$iter"
2088
- else
2089
- iter = "null"
2090
- end
2091
-
2092
- if @scope.defs
2093
- [f("$opal.dispatch_super(this, #{@scope.mid.to_s.inspect},", sexp), args, f(", #{iter}, #{cls_name})", sexp)]
313
+ def new_var_ref(ref)
314
+ case ref.type
315
+ when :self, :nil, :true, :false, :line, :file
316
+ ref
317
+ when :const
318
+ ref
319
+ when :ivar, :gvar, :cvar
320
+ ref
321
+ when :int
322
+ # this is when we passed __LINE__ which is converted into :int
323
+ ref
324
+ when :str
325
+ # returns for __FILE__ as it is converted into str
326
+ ref
327
+ when :identifier
328
+ if scope.has_local? ref[1]
329
+ s(:lvar, ref[1])
2094
330
  else
2095
- [f("$opal.dispatch_super(#{current_self}, #{@scope.mid.to_s.inspect}, ", sexp), args, f(", #{iter})", sexp)]
331
+ s(:call, nil, ref[1], s(:arglist))
2096
332
  end
2097
-
2098
- elsif @scope.type == :iter
2099
- chain, defn, mid = @scope.get_super_chain
2100
- trys = chain.map { |c| "#{c}._sup" }.join ' || '
2101
- [f("(#{trys} || #{current_self}._klass._super._proto[#{mid}]).apply(#{current_self}, ", sexp), args, f(")", sexp)]
2102
333
  else
2103
- raise "Cannot call super() from outside a method block"
334
+ raise "Bad var_ref type: #{ref.type}"
2104
335
  end
2105
336
  end
2106
337
 
2107
- # a ||= rhs
2108
- #
2109
- # s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, rhs))
2110
- def process_op_asgn_or(exp, level)
2111
- process s(:or, exp[0], exp[1])
2112
- end
2113
-
2114
- # a &&= rhs
2115
- #
2116
- # s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, rhs))
2117
- def process_op_asgn_and(sexp, level)
2118
- process s(:and, sexp[0], sexp[1])
2119
- end
2120
-
2121
- # lhs[args] ||= rhs
2122
- #
2123
- # s(:op_asgn1, lhs, args, :||, rhs)
2124
- def process_op_asgn1(sexp, level)
2125
- lhs, arglist, op, rhs = sexp
2126
-
2127
- with_temp do |a| # args
2128
- with_temp do |r| # recv
2129
- args = process arglist[1]
2130
- recv = process lhs
2131
-
2132
- aref = s(:call, s(:js_tmp, r), :[], s(:arglist, s(:js_tmp, a)))
2133
- aset = s(:call, s(:js_tmp, r), :[]=, s(:arglist, s(:js_tmp, a), rhs))
2134
- orop = s(:or, aref, aset)
338
+ def new_super(args)
339
+ args = (args || s(:arglist))
2135
340
 
2136
- result = []
2137
- result << f("(#{a} = ", sexp) << args << f(", #{r} = ", sexp)
2138
- result << recv << f(", ", sexp) << process(orop)
2139
- result << f(")", sexp)
2140
- result
2141
- end
341
+ if args.type == :array
342
+ args.type = :arglist
2142
343
  end
2143
- end
2144
-
2145
- # lhs.b += rhs
2146
- #
2147
- # s(:op_asgn2, lhs, :b=, :+, rhs)
2148
- def process_op_asgn2(sexp, level)
2149
- lhs = process sexp[0]
2150
- mid = sexp[1].to_s[0..-2]
2151
- op = sexp[2]
2152
- rhs = sexp[3]
2153
-
2154
- if op.to_s == "||"
2155
- with_temp do |temp|
2156
- getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
2157
- asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
2158
- orop = s(:or, getr, asgn)
2159
344
 
2160
- [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(orop), f(")", sexp)]
2161
- end
2162
- elsif op.to_s == '&&'
2163
- with_temp do |temp|
2164
- getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
2165
- asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
2166
- andop = s(:and, getr, asgn)
2167
-
2168
- [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(andop), f(")", sexp)]
2169
- end
2170
- else
2171
- with_temp do |temp|
2172
- getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
2173
- oper = s(:call, getr, op, s(:arglist, rhs))
2174
- asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, oper))
2175
-
2176
- [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(asgn), f(")", sexp)]
2177
- end
2178
- end
345
+ s(:super, args)
2179
346
  end
2180
347
 
2181
- # s(:ensure, body, ensure)
2182
- def process_ensure(exp, level)
2183
- begn = exp[0]
2184
- if level == :recv || level == :expr
2185
- retn = true
2186
- begn = returns begn
2187
- end
2188
-
2189
- result = []
2190
- body = process begn, level
2191
- ensr = exp[1] || s(:nil)
2192
- ensr = process ensr, level
2193
-
2194
- body = [f("try {\n", exp), body, f("}", exp)]
2195
-
2196
- result << body << f("#{@space}finally {#@space", exp) << ensr << f("}", exp)
2197
-
2198
- if retn
2199
- [f("(function() { ", exp), result, f("; }).call(#{current_self})", exp)]
2200
- else
2201
- result
2202
- end
348
+ def new_yield(args)
349
+ args = (args || s(:arglist))[1..-1]
350
+ s(:yield, *args)
2203
351
  end
2204
352
 
2205
- def process_rescue(exp, level)
2206
- body = exp.first.first == :resbody ? s(:nil) : exp[0]
2207
- body = indent { process body, level }
2208
- handled_else = false
2209
-
2210
- parts = []
2211
- exp[1..-1].each do |a|
2212
- handled_else = true unless a.first == :resbody
2213
- part = indent { process a, level }
2214
-
2215
- unless parts.empty?
2216
- parts << f("else ", exp)
2217
- end
2218
-
2219
- parts << part
2220
- end
2221
- # if no rescue statement captures our error, we should rethrow
2222
- parts << indent { f("else { throw $err; }", exp) } unless handled_else
2223
-
2224
- code = []
2225
- code << f("try {#@space#{INDENT}", exp)
2226
- code << body
2227
- code << f("#@space} catch ($err) {#@space", exp)
2228
- code << parts
2229
- code << f("#@space}", exp)
2230
-
2231
- if level == :expr
2232
- code.unshift f("(function() { ", exp)
2233
- code << f(" }).call(#{current_self})", exp)
353
+ def new_xstr(str)
354
+ return s(:xstr, '') unless str
355
+ case str.type
356
+ when :str then str.type = :xstr
357
+ when :dstr then str.type = :dxstr
358
+ when :evstr then str = s(:dxstr, '', str)
2234
359
  end
2235
360
 
2236
- code
361
+ str
2237
362
  end
2238
363
 
2239
- def process_resbody(exp, level)
2240
- args = exp[0]
2241
- body = exp[1]
2242
-
2243
- body = process(body || s(:nil), level)
2244
- types = args[1..-1]
2245
- types.pop if types.last and types.last.first != :const
2246
-
2247
- err = []
2248
- types.each do |t|
2249
- err << f(", ", exp) unless err.empty?
2250
- call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
2251
- a = process call
2252
- err << a
2253
- end
2254
- err << f("true", exp) if err.empty?
2255
-
2256
- if Array === args.last and [:lasgn, :iasgn].include? args.last.first
2257
- val = args.last
2258
- val[2] = s(:js_tmp, "$err")
2259
- val = [process(val) , f(";", exp)]
364
+ def new_dsym(str)
365
+ return s(:nil) unless str
366
+ case str.type
367
+ when :str
368
+ str.type = :sym
369
+ str[1] = str[1].to_sym
370
+ when :dstr
371
+ str.type = :dsym
2260
372
  end
2261
373
 
2262
- val = [] unless val
2263
-
2264
- [f("if (", exp), err, f("){#@space", exp), val, body, f("}", exp)]
2265
- end
2266
-
2267
- # FIXME: Hack.. grammar should remove top level begin.
2268
- def process_begin(exp, level)
2269
- process exp[0], level
374
+ str
2270
375
  end
2271
376
 
2272
- def process_next(exp, level)
2273
- if in_while?
2274
- f("continue;", exp)
377
+ def new_str(str)
378
+ # cover empty strings
379
+ return s(:str, "") unless str
380
+ # catch s(:str, "", other_str)
381
+ if str.size == 3 and str[1] == "" and str.type == :str
382
+ return str[2]
383
+ # catch s(:str, "content", more_content)
384
+ elsif str.type == :str && str.size > 3
385
+ str.type = :dstr
386
+ str
387
+ # top level evstr should be a dstr
388
+ elsif str.type == :evstr
389
+ s(:dstr, "", str)
2275
390
  else
2276
- result = []
2277
- result << f("return ", exp)
2278
-
2279
- result << (exp.empty? ? f('nil', exp) : process(exp[0]))
2280
- result << f(";", exp)
391
+ str
392
+ end
393
+ end
2281
394
 
2282
- result
395
+ def new_regexp(reg, ending)
396
+ return s(:regexp, //) unless reg
397
+ case reg.type
398
+ when :str
399
+ s(:regexp, Regexp.new(reg[1], ending))
400
+ when :evstr
401
+ s(:dregx, "", reg)
402
+ when :dstr
403
+ reg.type = :dregx
404
+ reg
2283
405
  end
2284
406
  end
2285
407
 
2286
- # s(:redo) # => $redo_var = true
2287
- # Only currently supported inside while loops. Simply sets the redo variable
2288
- # for the loop to true.
2289
- def process_redo(exp, level)
2290
- if in_while?
2291
- @while_loop[:use_redo] = true
2292
- f("#{@while_loop[:redo_var]} = true", exp)
408
+ def str_append(str, str2)
409
+ return str2 unless str
410
+ return str unless str2
411
+
412
+ if str.type == :evstr
413
+ str = s(:dstr, "", str)
414
+ elsif str.type == :str
415
+ str = s(:dstr, str[1])
2293
416
  else
2294
- f("REDO()", exp)
417
+ #puts str.type
2295
418
  end
419
+ str << str2
420
+ str
2296
421
  end
2297
422
  end
2298
423
  end