opal 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (303) hide show
  1. data/.rspec +3 -0
  2. data/.travis.yml +0 -4
  3. data/README.md +6 -0
  4. data/Rakefile +30 -6
  5. data/bin/opal +6 -82
  6. data/corelib/{opal/array.rb → array.rb} +40 -56
  7. data/corelib/{opal/basic_object.rb → basic_object.rb} +2 -2
  8. data/corelib/{opal/boolean.rb → boolean.rb} +0 -8
  9. data/corelib/class.rb +47 -0
  10. data/corelib/{opal/comparable.rb → comparable.rb} +0 -0
  11. data/corelib/{opal/enumerable.rb → enumerable.rb} +208 -141
  12. data/corelib/{opal/enumerator.rb → enumerator.rb} +3 -3
  13. data/corelib/{opal/error.rb → error.rb} +1 -0
  14. data/corelib/{opal/hash.rb → hash.rb} +67 -56
  15. data/corelib/io.rb +39 -0
  16. data/corelib/{opal/kernel.rb → kernel.rb} +35 -31
  17. data/corelib/{opal/class.rb → module.rb} +29 -57
  18. data/corelib/native.rb +148 -0
  19. data/corelib/{opal/nil_class.rb → nil_class.rb} +2 -10
  20. data/corelib/{opal/numeric.rb → numeric.rb} +39 -14
  21. data/corelib/opal.rb +42 -25
  22. data/corelib/{opal/proc.rb → proc.rb} +3 -3
  23. data/corelib/{opal/range.rb → range.rb} +5 -1
  24. data/corelib/{opal/regexp.rb → regexp.rb} +0 -0
  25. data/corelib/{opal/runtime.js → runtime.js} +96 -188
  26. data/corelib/{opal/string.rb → string.rb} +20 -15
  27. data/corelib/struct.rb +139 -0
  28. data/corelib/{opal/time.rb → time.rb} +0 -0
  29. data/lib/opal.rb +4 -0
  30. data/lib/opal/cli.rb +79 -32
  31. data/lib/opal/cli_options.rb +91 -0
  32. data/lib/opal/erb.rb +41 -8
  33. data/lib/opal/grammar.rb +24 -10
  34. data/lib/opal/grammar.y +15 -4
  35. data/lib/opal/grammar_helpers.rb +4 -0
  36. data/lib/opal/lexer.rb +214 -143
  37. data/lib/opal/parser.rb +596 -562
  38. data/lib/opal/require_parser.rb +1 -1
  39. data/lib/opal/source_map.rb +15 -30
  40. data/lib/opal/target_scope.rb +24 -5
  41. data/lib/opal/version.rb +1 -1
  42. data/mri_spec/cli_spec.rb +18 -0
  43. data/mri_spec/fixtures/opal_file.rb +2 -0
  44. data/mri_spec/spec_helper.rb +17 -0
  45. data/opal.gemspec +5 -2
  46. data/spec/{rubyspec/filters → filters}/bugs/alias.rb +0 -0
  47. data/spec/{rubyspec/filters → filters}/bugs/ancestors.rb +0 -0
  48. data/spec/{rubyspec/filters → filters}/bugs/array.rb +0 -0
  49. data/spec/filters/bugs/array/combination.rb +11 -0
  50. data/spec/filters/bugs/array/count.rb +3 -0
  51. data/spec/filters/bugs/array/delete_if.rb +3 -0
  52. data/spec/filters/bugs/array/drop.rb +3 -0
  53. data/spec/filters/bugs/array/drop_while.rb +5 -0
  54. data/spec/filters/bugs/array/eql.rb +3 -0
  55. data/spec/filters/bugs/array/flatten.rb +9 -0
  56. data/spec/filters/bugs/array/minus.rb +5 -0
  57. data/spec/filters/bugs/array/multipliy.rb +9 -0
  58. data/spec/filters/bugs/array/new.rb +3 -0
  59. data/spec/filters/bugs/array/pop.rb +6 -0
  60. data/spec/filters/bugs/array/rassoc.rb +4 -0
  61. data/spec/filters/bugs/array/rindex.rb +6 -0
  62. data/spec/filters/bugs/array/select.rb +3 -0
  63. data/spec/filters/bugs/array/shift.rb +7 -0
  64. data/spec/filters/bugs/array/shuffle.rb +11 -0
  65. data/spec/filters/bugs/array/slice.rb +7 -0
  66. data/spec/filters/bugs/array/take.rb +3 -0
  67. data/spec/filters/bugs/array/to_a.rb +3 -0
  68. data/spec/filters/bugs/array/try_convert.rb +7 -0
  69. data/spec/filters/bugs/array/uniq.rb +10 -0
  70. data/spec/filters/bugs/array/zip.rb +4 -0
  71. data/spec/{rubyspec/filters → filters}/bugs/array_delete.rb +1 -0
  72. data/spec/{rubyspec/filters → filters}/bugs/array_fetch.rb +0 -0
  73. data/spec/{rubyspec/filters → filters}/bugs/array_first.rb +0 -0
  74. data/spec/{rubyspec/filters → filters}/bugs/array_flatten.rb +0 -0
  75. data/spec/{rubyspec/filters → filters}/bugs/array_intersection.rb +0 -0
  76. data/spec/{rubyspec/filters → filters}/bugs/array_join.rb +0 -0
  77. data/spec/{rubyspec/filters → filters}/bugs/break.rb +0 -0
  78. data/spec/filters/bugs/case.rb +4 -0
  79. data/spec/{rubyspec/filters → filters}/bugs/coerce_integer.rb +0 -0
  80. data/spec/filters/bugs/enumerable_sort_by.rb +3 -0
  81. data/spec/{rubyspec/filters → filters}/bugs/kernel/instance_variables.rb +0 -0
  82. data/spec/filters/bugs/kernel/rand.rb +4 -0
  83. data/spec/filters/bugs/language/array.rb +3 -0
  84. data/spec/filters/bugs/language/block.rb +6 -0
  85. data/spec/filters/bugs/language/break.rb +3 -0
  86. data/spec/{rubyspec/filters → filters}/bugs/language/class.rb +3 -0
  87. data/spec/{rubyspec/filters → filters}/bugs/language/class_variables.rb +0 -0
  88. data/spec/filters/bugs/language/def.rb +27 -0
  89. data/spec/filters/bugs/language/defined.rb +3 -0
  90. data/spec/filters/bugs/language/ensure.rb +4 -0
  91. data/spec/filters/bugs/language/execution.rb +4 -0
  92. data/spec/filters/bugs/language/for.rb +18 -0
  93. data/spec/filters/bugs/language/if.rb +13 -0
  94. data/spec/filters/bugs/language/loop.rb +4 -0
  95. data/spec/filters/bugs/language/metaclass.rb +14 -0
  96. data/spec/filters/bugs/language/module.rb +6 -0
  97. data/spec/filters/bugs/language/next.rb +3 -0
  98. data/spec/filters/bugs/language/or.rb +3 -0
  99. data/spec/filters/bugs/language/order.rb +4 -0
  100. data/spec/filters/bugs/language/precedence.rb +10 -0
  101. data/spec/filters/bugs/language/proc.rb +24 -0
  102. data/spec/filters/bugs/language/redo.rb +5 -0
  103. data/spec/filters/bugs/language/rescue.rb +9 -0
  104. data/spec/filters/bugs/language/retry.rb +5 -0
  105. data/spec/filters/bugs/language/send.rb +10 -0
  106. data/spec/filters/bugs/language/super.rb +9 -0
  107. data/spec/filters/bugs/language/until.rb +8 -0
  108. data/spec/filters/bugs/language/variables.rb +37 -0
  109. data/spec/filters/bugs/language/while.rb +6 -0
  110. data/spec/filters/bugs/language/yield.rb +5 -0
  111. data/spec/{rubyspec/filters → filters}/bugs/module/class_variables.rb +0 -0
  112. data/spec/filters/bugs/module/method_defined.rb +6 -0
  113. data/spec/filters/bugs/parser.rb +10 -0
  114. data/spec/{rubyspec/filters → filters}/bugs/public_methods.rb +1 -0
  115. data/spec/filters/bugs/return.rb +7 -0
  116. data/spec/filters/bugs/singleton/instance.rb +4 -0
  117. data/spec/filters/bugs/source_map.rb +3 -0
  118. data/spec/filters/bugs/string/center.rb +4 -0
  119. data/spec/filters/bugs/string/lines.rb +3 -0
  120. data/spec/{rubyspec/filters → filters}/mspec/mocks.rb +0 -0
  121. data/spec/{rubyspec/filters → filters}/mspec/ruby_exe.rb +0 -0
  122. data/spec/{rubyspec/filters → filters}/mspec/should_receive.rb +0 -0
  123. data/spec/{rubyspec/filters → filters}/parser/block_args.rb +0 -0
  124. data/spec/{rubyspec/filters → filters}/unsupported/array_subclasses.rb +1 -0
  125. data/spec/filters/unsupported/frozen.rb +32 -0
  126. data/spec/filters/unsupported/immutable_strings.rb +3 -0
  127. data/spec/filters/unsupported/tainted.rb +17 -0
  128. data/spec/filters/unsupported/trusted.rb +15 -0
  129. data/spec/opal/class/constants_spec.rb +7 -0
  130. data/spec/opal/erb/erb_spec.rb +7 -1
  131. data/spec/opal/erb/inline_block.opalerb +3 -0
  132. data/spec/opal/hash/allocate_spec.rb +16 -0
  133. data/spec/opal/hash/new_spec.rb +10 -0
  134. data/spec/opal/hash/to_s_spec.rb +9 -0
  135. data/spec/opal/kernel/instance_variable_defined_spec.rb +15 -0
  136. data/spec/opal/kernel/rand_spec.rb +5 -5
  137. data/spec/opal/kernel/respond_to_spec.rb +14 -1
  138. data/spec/opal/language/block_spec.rb +13 -0
  139. data/spec/opal/language/rescue_spec.rb +27 -0
  140. data/spec/opal/language/return_spec.rb +38 -0
  141. data/spec/opal/language/singleton_class_spec.rb +13 -0
  142. data/spec/opal/language/super_spec.rb +99 -0
  143. data/spec/opal/language/variables_spec.rb +20 -0
  144. data/spec/opal/module/attr_accessor_spec.rb +8 -0
  145. data/spec/opal/module/constants_spec.rb +2 -2
  146. data/spec/opal/native/alias_native_spec.rb +18 -0
  147. data/spec/opal/native/each_spec.rb +14 -0
  148. data/spec/opal/native/element_reference_spec.rb +14 -0
  149. data/spec/opal/native/method_missing_spec.rb +39 -0
  150. data/spec/opal/native/new_spec.rb +19 -0
  151. data/spec/opal/native/nil_spec.rb +14 -0
  152. data/spec/opal/runtime2/class_hierarchy_spec.rb +2 -2
  153. data/spec/opal/source_map_spec.rb +3 -7
  154. data/spec/ospec/main.rb.erb +2 -5
  155. data/spec/parser/alias_spec.rb +4 -4
  156. data/spec/parser/and_spec.rb +2 -2
  157. data/spec/parser/array_spec.rb +6 -6
  158. data/spec/parser/attrasgn_spec.rb +8 -8
  159. data/spec/parser/begin_spec.rb +11 -11
  160. data/spec/parser/block_spec.rb +3 -3
  161. data/spec/parser/break_spec.rb +4 -4
  162. data/spec/parser/call_spec.rb +50 -48
  163. data/spec/parser/class_spec.rb +2 -2
  164. data/spec/parser/const_spec.rb +1 -1
  165. data/spec/parser/cvar_spec.rb +1 -1
  166. data/spec/parser/def_spec.rb +5 -5
  167. data/spec/parser/gvar_spec.rb +2 -2
  168. data/spec/parser/hash_spec.rb +4 -4
  169. data/spec/parser/iasgn_spec.rb +3 -3
  170. data/spec/parser/if_spec.rb +6 -6
  171. data/spec/parser/iter_spec.rb +6 -6
  172. data/spec/parser/lambda_spec.rb +5 -5
  173. data/spec/parser/lasgn_spec.rb +2 -2
  174. data/spec/parser/line_spec.rb +2 -2
  175. data/spec/parser/lvar_spec.rb +5 -5
  176. data/spec/parser/masgn_spec.rb +1 -1
  177. data/spec/parser/module_spec.rb +2 -2
  178. data/spec/parser/not_spec.rb +4 -4
  179. data/spec/parser/op_asgn1_spec.rb +2 -2
  180. data/spec/parser/op_asgn2_spec.rb +2 -2
  181. data/spec/parser/or_spec.rb +2 -2
  182. data/spec/parser/parse_spec.rb +66 -0
  183. data/spec/parser/parser_spec.rb +32 -38
  184. data/spec/parser/regexp_spec.rb +4 -4
  185. data/spec/parser/return_spec.rb +4 -4
  186. data/spec/parser/sclass_spec.rb +4 -4
  187. data/spec/parser/str_spec.rb +3 -3
  188. data/spec/parser/super_spec.rb +6 -6
  189. data/spec/parser/undef_spec.rb +3 -3
  190. data/spec/parser/unless_spec.rb +4 -4
  191. data/spec/parser/while_spec.rb +3 -3
  192. data/spec/parser/xstr_spec.rb +3 -3
  193. data/spec/parser/yield_spec.rb +6 -6
  194. data/spec/rubyspec/core/array/drop_spec.rb +1 -1
  195. data/spec/rubyspec/core/array/keep_if_spec.rb +1 -3
  196. data/spec/rubyspec/core/array/length_spec.rb +1 -3
  197. data/spec/rubyspec/core/array/map_spec.rb +2 -6
  198. data/spec/rubyspec/core/array/minus_spec.rb +3 -3
  199. data/spec/rubyspec/core/array/multiply_spec.rb +14 -16
  200. data/spec/rubyspec/core/array/new_spec.rb +3 -5
  201. data/spec/rubyspec/core/array/plus_spec.rb +2 -2
  202. data/spec/rubyspec/core/array/pop_spec.rb +4 -4
  203. data/spec/rubyspec/core/array/rassoc_spec.rb +2 -2
  204. data/spec/rubyspec/core/array/reject_spec.rb +2 -6
  205. data/spec/rubyspec/core/array/replace_spec.rb +1 -3
  206. data/spec/rubyspec/core/array/reverse_each_spec.rb +1 -3
  207. data/spec/rubyspec/core/array/reverse_spec.rb +4 -4
  208. data/spec/rubyspec/core/array/rindex_spec.rb +1 -1
  209. data/spec/rubyspec/core/array/select_spec.rb +3 -7
  210. data/spec/rubyspec/core/array/shared/collect.rb +7 -0
  211. data/spec/rubyspec/core/array/shared/index.rb +1 -1
  212. data/spec/rubyspec/core/array/shared/keep_if.rb +3 -0
  213. data/spec/rubyspec/core/array/shared/length.rb +3 -0
  214. data/spec/rubyspec/core/array/shared/replace.rb +3 -0
  215. data/spec/rubyspec/core/array/shared/slice.rb +3 -0
  216. data/spec/rubyspec/core/array/shuffle_spec.rb +1 -1
  217. data/spec/rubyspec/core/array/size_spec.rb +1 -3
  218. data/spec/rubyspec/core/array/slice_spec.rb +4 -6
  219. data/spec/rubyspec/core/array/sort_spec.rb +2 -2
  220. data/spec/rubyspec/core/array/to_a_spec.rb +1 -1
  221. data/spec/rubyspec/core/array/try_convert_spec.rb +7 -7
  222. data/spec/rubyspec/core/array/uniq_spec.rb +7 -7
  223. data/spec/rubyspec/core/array/zip_spec.rb +1 -1
  224. data/spec/rubyspec/core/enumerable/collect_spec.rb +24 -0
  225. data/spec/rubyspec/core/enumerable/count_spec.rb +35 -19
  226. data/spec/rubyspec/core/enumerable/find_spec.rb +5 -0
  227. data/spec/rubyspec/core/hash/each_pair_spec.rb +7 -7
  228. data/spec/rubyspec/core/hash/each_spec.rb +13 -7
  229. data/spec/rubyspec/core/module/method_defined_spec.rb +4 -4
  230. data/spec/rubyspec/core/module/public_method_defined_spec.rb +19 -0
  231. data/spec/rubyspec/core/module/remove_const_spec.rb +23 -0
  232. data/spec/rubyspec/core/numeric/step_spec.rb +14 -0
  233. data/spec/rubyspec/core/string/center_spec.rb +43 -65
  234. data/spec/rubyspec/core/string/lines_spec.rb +1 -1
  235. data/spec/rubyspec/core/string/ljust_spec.rb +25 -9
  236. data/spec/rubyspec/core/string/rjust_spec.rb +26 -10
  237. data/spec/rubyspec/core/struct/fixtures/classes.rb +26 -0
  238. data/spec/rubyspec/core/struct/initialize_spec.rb +11 -0
  239. data/spec/rubyspec/core/struct/new_spec.rb +24 -0
  240. data/spec/rubyspec/fixtures/constants.rb +7 -0
  241. data/spec/rubyspec/language/break_spec.rb +1 -1
  242. data/spec/rubyspec/language/case_spec.rb +30 -30
  243. data/spec/rubyspec/language/def_spec.rb +34 -34
  244. data/spec/rubyspec/language/defined_spec.rb +2 -2
  245. data/spec/rubyspec/language/ensure_spec.rb +2 -2
  246. data/spec/rubyspec/language/execution_spec.rb +2 -2
  247. data/spec/rubyspec/language/for_spec.rb +17 -17
  248. data/spec/rubyspec/language/hash_spec.rb +3 -3
  249. data/spec/rubyspec/language/if_spec.rb +11 -11
  250. data/spec/rubyspec/language/loop_spec.rb +3 -3
  251. data/spec/rubyspec/language/metaclass_spec.rb +14 -14
  252. data/spec/rubyspec/language/module_spec.rb +6 -6
  253. data/spec/rubyspec/language/next_spec.rb +5 -5
  254. data/spec/rubyspec/language/not_spec.rb +1 -1
  255. data/spec/rubyspec/language/or_spec.rb +1 -1
  256. data/spec/rubyspec/language/order_spec.rb +3 -5
  257. data/spec/rubyspec/language/precedence_spec.rb +19 -19
  258. data/spec/rubyspec/language/proc_spec.rb +29 -29
  259. data/spec/rubyspec/language/redo_spec.rb +3 -5
  260. data/spec/rubyspec/language/rescue_spec.rb +7 -7
  261. data/spec/rubyspec/language/retry_spec.rb +2 -2
  262. data/spec/rubyspec/language/return_spec.rb +12 -12
  263. data/spec/rubyspec/language/send_spec.rb +9 -9
  264. data/spec/rubyspec/language/singleton_class_spec.rb +3 -4
  265. data/spec/rubyspec/language/super_spec.rb +7 -11
  266. data/spec/rubyspec/language/until_spec.rb +10 -10
  267. data/spec/rubyspec/language/variables_spec.rb +59 -67
  268. data/spec/rubyspec/language/versions/array_1.9.rb +1 -1
  269. data/spec/rubyspec/language/versions/block_1.9.rb +0 -0
  270. data/spec/rubyspec/language/versions/break_1.9.rb +0 -0
  271. data/spec/rubyspec/language/versions/literal_lambda_1.9.rb +12 -12
  272. data/spec/rubyspec/language/versions/send_1.9.rb +23 -23
  273. data/spec/rubyspec/language/versions/symbol_1.9.rb +2 -2
  274. data/spec/rubyspec/language/versions/variables_1.9.rb +1 -1
  275. data/spec/rubyspec/language/while_spec.rb +4 -4
  276. data/spec/rubyspec/language/yield_spec.rb +3 -3
  277. data/spec/rubyspec/library/erb/util/html_escape_spec.rb +10 -0
  278. data/spec/rubyspec/library/singleton/clone_spec.rb +8 -0
  279. data/spec/rubyspec/library/singleton/dup_spec.rb +8 -0
  280. data/spec/rubyspec/library/singleton/fixtures/classes.rb +18 -0
  281. data/spec/rubyspec/library/singleton/instance_spec.rb +30 -0
  282. data/spec/spec_helper.rb +214 -0
  283. data/stdlib/buffer.rb +40 -0
  284. data/stdlib/buffer/array.rb +66 -0
  285. data/stdlib/buffer/view.rb +70 -0
  286. data/stdlib/erb.rb +11 -20
  287. data/stdlib/forwardable.rb +71 -0
  288. data/stdlib/json.rb +78 -0
  289. data/stdlib/ostruct.rb +69 -0
  290. data/stdlib/rbconfig.rb +1 -0
  291. data/stdlib/singleton.rb +40 -0
  292. data/stdlib/stringio.rb +173 -0
  293. data/stdlib/template.rb +44 -0
  294. metadata +285 -79
  295. data/corelib/opal/native.rb +0 -31
  296. data/spec/opal/class/bridge_class_spec.rb +0 -39
  297. data/spec/opal/native_spec.rb +0 -209
  298. data/spec/ospec/runner.rb +0 -223
  299. data/spec/rubyspec/filters/bugs/block_args.rb +0 -3
  300. data/spec/rubyspec/filters/bugs/case.rb +0 -8
  301. data/spec/rubyspec/filters/bugs/language/module.rb +0 -3
  302. data/spec/rubyspec/filters/unsupported/frozen.rb +0 -4
  303. data/spec/rubyspec/filters/unsupported/tainted.rb +0 -7
data/lib/opal/parser.rb CHANGED
@@ -6,15 +6,21 @@ require 'opal/version'
6
6
  module Opal
7
7
  class 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!
9
14
  class Fragment
10
-
15
+ # String of javascript this fragment holds
11
16
  attr_reader :code
12
17
 
13
18
  def initialize(code, sexp = nil)
14
- @code = code
19
+ @code = code.to_s
15
20
  @sexp = sexp
16
21
  end
17
22
 
23
+ # In debug mode we may wish to include the original line as a comment
18
24
  def to_code
19
25
  if @sexp
20
26
  "/*:#{@sexp.line}*/#{@code}"
@@ -23,8 +29,13 @@ module Opal
23
29
  end
24
30
  end
25
31
 
32
+ # inspect the contents of this fragment, f("fooo")
26
33
  def inspect
27
- "fragment(#{@code.inspect})"
34
+ "f(#{@code.inspect})"
35
+ end
36
+
37
+ def line
38
+ @sexp.line if @sexp
28
39
  end
29
40
  end
30
41
 
@@ -51,8 +62,16 @@ module Opal
51
62
  # Statements which should not have ';' added to them.
52
63
  STATEMENTS = [:xstr, :dxstr]
53
64
 
65
+ # Final generated javascript for this parser
54
66
  attr_reader :result
55
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() {....})()"
56
75
  def parse(source, options = {})
57
76
  @sexp = Grammar.new.parse(source, options[:file])
58
77
  @line = 1
@@ -68,29 +87,45 @@ module Opal
68
87
  @file = options[:file] || '(file)'
69
88
  @source_file = options[:source_file] || @file
70
89
  @method_missing = (options[:method_missing] != false)
71
- @optimized_operators = (options[:optimized_operators] != false)
72
90
  @arity_check = options[:arity_check]
73
91
  @const_missing = (options[:const_missing] != false)
74
92
  @irb_vars = (options[:irb] == true)
75
- @source_map = (options[:source_map_enabled] != false)
76
93
 
77
- fragments = self.top(@sexp).flatten
94
+ @method_calls = {}
78
95
 
79
- code = @source_map ? fragments.map(&:to_code).join('') : fragments.map(&:code).join('')
96
+ @fragments = self.top(@sexp).flatten
80
97
 
81
- @result = source_map_comment + version_comment + file_comment + code
98
+ @fragments.unshift f(version_comment)
99
+
100
+ @result = @fragments.map(&:code).join('')
82
101
  end
83
102
 
103
+ # Always at top of generated file to show current opal version
84
104
  def version_comment
85
105
  "/* Generated by Opal #{Opal::VERSION} */\n"
86
106
  end
87
107
 
88
- def source_map_comment
89
- @source_map ? "//@ sourceMappingURL=/__opal_source_maps__/#{@file}.js.map\n" : ''
108
+ def source_map
109
+ Opal::SourceMap.new(@fragments, '(file)')
90
110
  end
91
111
 
92
- def file_comment
93
- @source_map ? "/*-file:#{@source_file}-*/" : ''
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
94
129
  end
95
130
 
96
131
  # This is called when a parsing/processing error occurs. This
@@ -139,10 +174,12 @@ module Opal
139
174
 
140
175
  # @param [String] code the string of code
141
176
  # @return [Fragment]
142
- def fragment(code, sexp = nil)
177
+ def f(code, sexp = nil)
143
178
  Fragment.new(code, sexp)
144
179
  end
145
180
 
181
+ alias_method :fragment, :f
182
+
146
183
  # Converts a ruby method name into its javascript equivalent for
147
184
  # a method/function call. All ruby method names get prefixed with
148
185
  # a '$', and if the name is a valid javascript identifier, it will
@@ -164,6 +201,13 @@ module Opal
164
201
  end
165
202
  end
166
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
+
167
211
  # Used to generate a unique id name per file. These are used
168
212
  # mainly to name method bodies for methods that use blocks.
169
213
  #
@@ -192,24 +236,29 @@ module Opal
192
236
 
193
237
  code = process(scope, :stmt)
194
238
  code = [code] unless code.is_a? Array
195
- code.unshift fragment(@indent, sexp)
239
+ code.unshift f(@indent, sexp)
196
240
  }
197
241
 
198
- @scope.add_temp "self = __opal.top"
199
- @scope.add_temp "__scope = __opal"
200
- @scope.add_temp "$mm = __opal.mm"
201
- @scope.add_temp "nil = __opal.nil"
202
- @scope.add_temp "def = __opal.Object._proto" if @scope.defines_defn
203
- @helpers.keys.each { |h| @scope.add_temp "__#{h} = __opal.#{h}" }
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}" }
204
247
 
205
- vars = [fragment(INDENT, sexp), @scope.to_vars, fragment("\n", sexp)]
248
+ vars = [f(INDENT, sexp), @scope.to_vars, f("\n", sexp)]
206
249
 
207
250
  if @irb_vars
208
- code.unshift fragment("if (!Opal.irb_vars) { Opal.irb_vars = {}; }\n", sexp)
251
+ code.unshift f("if (!$opal.irb_vars) { $opal.irb_vars = {}; }\n", sexp)
209
252
  end
210
253
  end
211
254
 
212
- [fragment("(function(__opal) {\n", sexp), vars, code, fragment("\n})(Opal);\n", sexp)]
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)]
213
262
  end
214
263
 
215
264
  # Every time the parser enters a new scope, this is called with
@@ -296,6 +345,14 @@ module Opal
296
345
  result
297
346
  end
298
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
+
299
356
  # Returns true if the parser is curently handling a while sexp,
300
357
  # false otherwise.
301
358
  #
@@ -318,7 +375,7 @@ module Opal
318
375
  # @param [Array] sexp the sexp to process
319
376
  # @param [Symbol] level the level to process (see `LEVEL`)
320
377
  # @return [String]
321
- def process(sexp, level)
378
+ def process(sexp, level = :expr)
322
379
  type = sexp.shift
323
380
  meth = "process_#{type}"
324
381
  raise "Unsupported sexp: #{type}" unless respond_to? meth
@@ -373,6 +430,10 @@ module Opal
373
430
  sexp
374
431
  when :rescue
375
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
376
437
  sexp
377
438
  when :ensure
378
439
  sexp[1] = returns sexp[1]
@@ -422,30 +483,23 @@ module Opal
422
483
  #
423
484
  # @return [String]
424
485
  def process_block(sexp, level)
425
- result = []
426
- sexp << s(:nil) if sexp.empty?
486
+ return process s(:nil) if sexp.empty?
427
487
 
488
+ result = []
428
489
  join = (@scope.class_scope? ? "\n\n#@indent" : "\n#@indent")
429
490
 
430
- until sexp.empty?
431
- stmt = sexp.shift
432
-
433
- result << fragment(join, sexp) unless result.empty?
491
+ sexp.each do |stmt|
492
+ result << f(join, sexp) unless result.empty?
434
493
 
435
494
  # find any inline yield statements
436
495
  if yasgn = find_inline_yield(stmt)
437
- result << process(yasgn, level)
438
- result << fragment(";", yasgn)
496
+ result << process(yasgn, level) << f(";", yasgn)
439
497
  end
440
498
 
441
499
  expr = expression?(stmt) and LEVEL.index(level) < LEVEL.index(:list)
442
500
 
443
- code = process(stmt, level)
444
-
445
- result << code
446
- if expr
447
- result << fragment(";", stmt)
448
- end
501
+ result << process(stmt, level)
502
+ result << f(";", stmt) if expr
449
503
  end
450
504
 
451
505
  result
@@ -476,12 +530,14 @@ module Opal
476
530
  found = nil
477
531
  case stmt.first
478
532
  when :js_return
479
- found = find_inline_yield stmt[1]
533
+ if found = find_inline_yield(stmt[1])
534
+ found = found[2]
535
+ end
480
536
  when :array
481
537
  stmt[1..-1].each_with_index do |el, idx|
482
538
  if el.first == :yield
483
539
  found = el
484
- stmt[idx+1] = s(:js_tmp, '__yielded')
540
+ stmt[idx+1] = s(:js_tmp, '$yielded')
485
541
  end
486
542
  end
487
543
  when :call
@@ -489,72 +545,42 @@ module Opal
489
545
  arglist[1..-1].each_with_index do |el, idx|
490
546
  if el.first == :yield
491
547
  found = el
492
- arglist[idx+1] = s(:js_tmp, '__yielded')
548
+ arglist[idx+1] = s(:js_tmp, '$yielded')
493
549
  end
494
550
  end
495
551
  end
496
552
 
497
553
  if found
498
- @scope.add_temp '__yielded' unless @scope.has_temp? '__yielded'
499
- s(:yasgn, '__yielded', found)
554
+ @scope.add_temp '$yielded' unless @scope.has_temp? '$yielded'
555
+ s(:yasgn, '$yielded', found)
500
556
  end
501
557
  end
502
558
 
503
559
  def process_scope(sexp, level)
504
- stmt = sexp.shift
505
- if stmt
506
- unless @scope.class_scope?
507
- stmt = returns stmt
508
- end
560
+ stmt = sexp[0] || s(:nil)
561
+ stmt = returns stmt unless @scope.class_scope?
509
562
 
510
- process stmt, :stmt
511
- else
512
- fragment("nil", sexp)
513
- end
563
+ process stmt, :stmt
514
564
  end
515
565
 
516
566
  # s(:js_return, sexp)
517
567
  def process_js_return(sexp, level)
518
- [fragment("return ", sexp), process(sexp.shift, :expr)]
568
+ [f("return ", sexp), process(sexp[0])]
519
569
  end
520
570
 
521
571
  # s(:js_tmp, str)
522
572
  def process_js_tmp(sexp, level)
523
- fragment(sexp.shift.to_s, sexp)
524
- end
525
-
526
- def process_operator(sexp, level)
527
- meth, recv, arg = sexp
528
- mid = mid_to_jsid meth.to_s
529
- result = []
530
-
531
- if @optimized_operators
532
- with_temp do |a|
533
- with_temp do |b|
534
- l = process recv, :expr
535
- r = process arg, :expr
536
-
537
- result << fragment("(#{a} = ", sexp)
538
- result << l
539
- result << fragment(", #{b} = ", sexp)
540
- result << r
541
- result << fragment(", typeof(#{a}) === 'number' ? #{a} #{meth} #{b} ", sexp)
542
- result << fragment(": #{a}#{mid}(#{b}))", sexp)
543
- end
544
- end
545
- else
546
- "#{process recv, :recv}#{mid}(#{process arg, :expr})"
547
- end
548
-
549
- result
573
+ f(sexp[0].to_s, sexp)
550
574
  end
551
575
 
552
576
  def js_block_given(sexp, level)
553
577
  @scope.uses_block!
554
578
  if @scope.block_name
555
- fragment("(#{@scope.block_name} !== nil)", sexp)
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)
556
582
  else
557
- fragment("false", sexp)
583
+ f("false", sexp)
558
584
  end
559
585
  end
560
586
 
@@ -562,127 +588,124 @@ module Opal
562
588
  @scope.uses_block!
563
589
  name = @scope.block_name
564
590
 
565
- fragment((reverse ? "#{ name } === nil" : "#{ name } !== nil"), sexp)
591
+ f((reverse ? "#{ name } === nil" : "#{ name } !== nil"), sexp)
566
592
  end
567
593
 
568
594
  def process_sym(sexp, level)
569
- fragment(sexp[0].to_s.inspect, sexp)
595
+ f(sexp[0].to_s.inspect, sexp)
570
596
  end
571
597
 
598
+ # Process integers. Wrap in parens if a receiver of method call
572
599
  def process_int(sexp, level)
573
- handle_number sexp, level
600
+ f((level == :recv ? "(#{sexp[0]})" : sexp[0].to_s), sexp)
574
601
  end
575
602
 
576
- def process_float(sexp, level)
577
- handle_number sexp, level
578
- end
579
-
580
- def handle_number(sexp, level)
581
- if level == :recv
582
- fragment("(#{sexp[0]})", sexp)
583
- else
584
- fragment(sexp[0].to_s, sexp)
585
- end
586
- end
603
+ # Floats generated just like integers
604
+ alias_method :process_float, :process_int
587
605
 
606
+ # Regexp literals. Convert to empty js regexp if empty (not compatible)
588
607
  def process_regexp(sexp, level)
589
608
  val = sexp[0]
590
- fragment((val == // ? /^/.inspect : val.inspect), sexp)
609
+ f((val == // ? /^/.inspect : val.inspect), sexp)
591
610
  end
592
611
 
612
+ # Dynamic regexps with interpolation
613
+ # s(:dregx, parts...) => new Regexp("...")
593
614
  def process_dregx(sexp, level)
594
615
  result = []
595
616
 
596
617
  sexp.each do |part|
597
- result << fragment(" + ", sexp) unless result.empty?
618
+ result << f(" + ", sexp) unless result.empty?
598
619
 
599
620
  if String === part
600
- result << fragment(part.inspect, sexp)
621
+ result << f(part.inspect, sexp)
601
622
  elsif part[0] == :str
602
- result << process(part, :expr)
623
+ result << process(part)
603
624
  else
604
- result << process(part[1], :expr)
625
+ result << process(part[1])
605
626
  end
606
627
  end
607
628
 
608
- [fragment("(new RegExp(", sexp), result, fragment("))", sexp)]
629
+ [f("(new RegExp(", sexp), result, f("))", sexp)]
609
630
  end
610
631
 
632
+ # Exclusive range, uses opal __range helper.
633
+ # s(:dot3, start, end) => __range(start, end, false)
611
634
  def process_dot2(sexp, level)
612
- lhs = process sexp[0], :expr
613
- rhs = process sexp[1], :expr
614
635
  @helpers[:range] = true
615
636
 
616
- [fragment("__range(", sexp), lhs, fragment(", ", sexp), rhs, fragment(", false)", sexp)]
637
+ [f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", false)", sexp)]
617
638
  end
618
639
 
640
+ # Inclusive range, uses __range helper
641
+ # s(:dot3, start, end) => __range(start, end, true)
619
642
  def process_dot3(sexp, level)
620
- lhs = process sexp[0], :expr
621
- rhs = process sexp[1], :expr
622
643
  @helpers[:range] = true
623
644
 
624
- [fragment("__range(", sexp), lhs, fragment(", ", sexp), rhs, fragment(", true)", sexp)]
645
+ [f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", true)", sexp)]
625
646
  end
626
647
 
627
- # s(:str, "string")
648
+ # Simple strings, no interpolation.
649
+ # s(:str, "string") => "string"
628
650
  def process_str(sexp, level)
629
- str = sexp.shift
630
- if str == @file
631
- @uses_file = true
632
- fragment(@file.inspect, sexp)
633
- else
634
- fragment(str.inspect, sexp)
635
- end
651
+ f sexp[0].inspect, sexp
636
652
  end
637
653
 
654
+ # defined?(x) => various
638
655
  def process_defined(sexp, level)
639
656
  part = sexp[0]
640
657
  case part[0]
641
658
  when :self
642
- fragment("self".inspect, sexp)
659
+ f("'self'", sexp)
643
660
  when :nil
644
- fragment("nil".inspect, sexp)
661
+ f("'nil'", sexp)
645
662
  when :true
646
- fragment("true".inspect, sexp)
663
+ f("'true'", sexp)
647
664
  when :false
648
- fragment("false".inspect, sexp)
665
+ f("'false'", sexp)
649
666
  when :call
650
667
  mid = mid_to_jsid part[2].to_s
651
- recv = part[1] ? process(part[1], :expr) : fragment(current_self, sexp)
652
- [fragment("(", sexp), recv, fragment("#{mid} ? 'method' : nil)", sexp)]
653
- when :xstr
654
- [fragment("(typeof(", sexp), process(part, :expr), fragment(") !== 'undefined')", sexp)]
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)]
655
672
  when :const
656
- fragment("(__scope.#{part[1].to_s} != null)", sexp)
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)
657
676
  when :colon2
658
- fragment("false", sexp)
677
+ f("false", sexp)
659
678
  when :colon3
660
- fragment("(__opal.Object._scope.#{sexp[0][1]} == null ? nil : 'constant')", sexp)
679
+ f("($opal.Object._scope.#{sexp[0][1]} == null ? nil : 'constant')", sexp)
661
680
  when :ivar
662
681
  ivar_name = part[1].to_s[1..-1]
663
682
  with_temp do |t|
664
- fragment("((#{t} = #{current_self}[#{ivar_name.inspect}], #{t} != null && #{t} !== nil) ? 'instance-variable' : nil)", sexp)
683
+ f("((#{t} = #{current_self}[#{ivar_name.inspect}], #{t} != null && #{t} !== nil) ? 'instance-variable' : nil)", sexp)
665
684
  end
666
685
  when :lvar
667
- fragment("local-variable", sexp)
686
+ f("local-variable", sexp)
668
687
  else
669
688
  raise "bad defined? part: #{part[0]}"
670
689
  end
671
690
  end
672
691
 
673
- # s(:not, sexp)
692
+ # not keyword or '!' operand
693
+ # s(:not, value) => (tmp = value, (tmp === nil || tmp === false))
674
694
  def process_not(sexp, level)
675
695
  with_temp do |tmp|
676
- expr = sexp.shift
677
- [fragment("(#{tmp} = ", sexp), process(expr, :expr), fragment(", (#{tmp} === nil || #{tmp} === false))", sexp)]
696
+ expr = sexp[0]
697
+ [f("(#{tmp} = ", sexp), process(expr), f(", (#{tmp} === nil || #{tmp} === false))", sexp)]
678
698
  end
679
699
  end
680
700
 
701
+ # A block pass '&foo' syntax
702
+ # s(:block_pass, value) => value.$to_proc()
681
703
  def process_block_pass(exp, level)
682
- process(s(:call, exp.shift, :to_proc, s(:arglist)), :expr)
704
+ process s(:call, exp[0], :to_proc, s(:arglist))
683
705
  end
684
706
 
685
- # s(:iter, call, block_args [, body)
707
+ # A block/iter with embeded call. Compiles into function
708
+ # s(:iter, call, block_args [, body) => (function() { ... })
686
709
  def process_iter(sexp, level)
687
710
  call, args, body = sexp
688
711
 
@@ -698,6 +721,12 @@ module Opal
698
721
  args ||= s(:masgn, s(:array))
699
722
  args = args.first == :lasgn ? s(:array, args) : args[1]
700
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
+
701
730
  if args.last.is_a?(Array) and args.last[0] == :block_pass
702
731
  block_arg = args.pop
703
732
  block_arg = block_arg[1][1].to_sym
@@ -717,7 +746,12 @@ module Opal
717
746
  args[1..-1].each do |arg|
718
747
  arg = arg[1]
719
748
  arg = "#{arg}$" if RESERVED.include? arg.to_s
720
- code << fragment("if (#{arg} == null) #{arg} = nil;\n", sexp)
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
721
755
  end
722
756
 
723
757
  params = js_block_args(args[1..-1])
@@ -725,47 +759,47 @@ module Opal
725
759
  if splat
726
760
  @scope.add_arg splat
727
761
  params << splat
728
- code << fragment("#{splat} = __slice.call(arguments, #{len - 1});", sexp)
762
+ code << f("#{splat} = $slice.call(arguments, #{len - 1});", sexp)
729
763
  end
730
764
 
731
765
  if block_arg
732
766
  @scope.block_name = block_arg
733
767
  @scope.add_temp block_arg
734
- @scope.add_temp '__context'
735
768
  scope_name = @scope.identify!
736
769
 
737
770
  blk = []
738
- blk << fragment("\n#@indent#{block_arg} = #{scope_name}._p || nil, #{scope_name}.p = null;\n#@indent", sexp)
771
+ blk << f("\n#@indent#{block_arg} = #{scope_name}._p || nil, #{scope_name}.p = null;\n#@indent", sexp)
739
772
 
740
773
  code.unshift blk
741
774
  end
742
775
 
743
- code << fragment("\n#@indent", sexp)
776
+ code << f("\n#@indent", sexp)
744
777
  code << process(body, :stmt)
745
778
 
746
779
  if @scope.defines_defn
747
780
  @scope.add_temp "def = ((#{current_self}._isClass) ? #{current_self}._proto : #{current_self})"
748
781
  end
749
782
 
750
- to_vars = [fragment("\n#@indent", sexp), @scope.to_vars, fragment("\n#@indent", sexp)]
783
+ to_vars = [f("\n#@indent", sexp), @scope.to_vars, f("\n#@indent", sexp)]
751
784
  end
752
785
  end
753
786
 
754
- itercode = [fragment("function(#{params.join ', '}) {\n", sexp), to_vars, code, fragment("\n#@indent}", sexp)]
787
+ itercode = [f("function(#{params.join ', '}) {\n", sexp), to_vars, code, f("\n#@indent}", sexp)]
755
788
 
756
- itercode.unshift fragment("(#{identity} = ", sexp)
757
- itercode << fragment(", #{identity}._s = #{current_self}, #{identity})", sexp)
789
+ itercode.unshift f("(#{identity} = ", sexp)
790
+ itercode << f(", #{identity}._s = #{current_self}, #{identity})", sexp)
758
791
 
759
792
  call << itercode
760
793
  process call, level
761
794
  end
762
795
 
796
+ # Maps block args into array of jsid. Adds $ suffix to invalid js
797
+ # identifiers.
798
+ #
799
+ # s(:args, parts...) => ["a", "b", "break$"]
763
800
  def js_block_args(sexp)
764
801
  sexp.map do |arg|
765
- a = arg[1].to_sym
766
- a = "#{a}$".to_sym if RESERVED.include? a.to_s
767
- @scope.add_arg a
768
- a
802
+ @scope.add_arg lvar_to_js(arg[1])
769
803
  end
770
804
  end
771
805
 
@@ -778,60 +812,25 @@ module Opal
778
812
  process s(:call, recv, mid, arglist), level
779
813
  end
780
814
 
781
- # Used to generate optimized attr_reader, attr_writer and
782
- # attr_accessor methods. These are optimized to avoid the added
783
- # cost of converting the method id's into jsid's at runtime.
784
- #
785
- # This method will only be called if all the given ids are strings
786
- # or symbols. Any dynamic arguments will default to being called
787
- # using the Module#attr_* methods as expected.
788
- #
789
- # @param [Symbol] meth :attr_{reader,writer,accessor}
790
- # @param [Array<Sexp>] attrs array of s(:sym) or s(:str)
791
- # @return [String] precompiled attr methods
792
- def handle_attr_optimize(meth, attrs)
793
- out = []
794
-
795
- attrs.each do |attr|
796
- mid = attr[1]
797
- ivar = "@#{mid}".to_sym
798
-
799
- unless meth == :attr_writer
800
- out << fragment(", \n#@indent") unless out.empty?
801
- out << process(s(:defn, mid, s(:args), s(:scope, s(:ivar, ivar))), :stmt)
802
- end
803
-
804
- unless meth == :attr_reader
805
- out << fragment(", \n#@indent") unless out.empty?
806
- mid = "#{mid}=".to_sym
807
- out << process(s(:defn, mid, s(:args, :val), s(:scope,
808
- s(:iasgn, ivar, s(:lvar, :val)))), :stmt)
809
- end
810
- end
811
-
812
- out << fragment(", nil")
813
- out
814
- end
815
-
816
815
  # s(:call, recv, :mid, s(:arglist))
817
816
  # s(:call, nil, :mid, s(:arglist))
818
817
  def process_call(sexp, level)
819
818
  recv, meth, arglist, iter = sexp
820
819
  mid = mid_to_jsid meth.to_s
821
820
 
821
+ @method_calls[meth.to_sym] = true
822
+
822
823
  # we are trying to access a lvar in irb mode
823
824
  if @irb_vars and @scope.top? and arglist == s(:arglist) and recv == nil
824
825
  return with_temp { |t|
825
826
  lvar = meth.intern
826
827
  lvar = "#{lvar}$" if RESERVED.include? lvar
827
828
  call = s(:call, s(:self), meth.intern, s(:arglist))
828
- [fragment("((#{t} = Opal.irb_vars.#{lvar}) == null ? ", sexp), process(call, :expr), fragment(" : #{t})", sexp)]
829
+ [f("((#{t} = $opal.irb_vars.#{lvar}) == null ? ", sexp), process(call), f(" : #{t})", sexp)]
829
830
  }
830
831
  end
831
832
 
832
833
  case meth
833
- when :attr_reader, :attr_writer, :attr_accessor
834
- return handle_attr_optimize(meth, arglist[1..-1]) if @scope.class_scope?
835
834
  when :block_given?
836
835
  return js_block_given(sexp, level)
837
836
  end
@@ -839,7 +838,7 @@ module Opal
839
838
  splat = arglist[1..-1].any? { |a| a.first == :splat }
840
839
 
841
840
  if Array === arglist.last and arglist.last.first == :block_pass
842
- block = process(arglist.pop, :expr)
841
+ block = process(arglist.pop)
843
842
  elsif iter
844
843
  block = iter
845
844
  end
@@ -850,54 +849,35 @@ module Opal
850
849
  tmpfunc = @scope.new_temp
851
850
  end
852
851
 
853
- tmprecv = @scope.new_temp
852
+ tmprecv = @scope.new_temp if splat || tmpfunc
854
853
  args = ""
855
854
 
856
855
  recv_code = process recv, :recv
857
856
 
858
- if @method_missing
859
- call_recv = s(:js_tmp, tmprecv || recv_code)
860
- arglist.insert 1, call_recv unless splat
861
- args = process arglist, :expr
862
-
863
- dispatch = "((#{tmprecv} = #{recv_code})#{mid} || $mm('#{meth.to_s}'))"
864
- dispatch = [fragment("((#{tmprecv} = ", sexp), recv_code, fragment(")#{mid} || $mm('#{meth.to_s}'))", sexp)]
865
-
866
- if tmpfunc
867
- dispatch.unshift fragment("(#{tmpfunc} = ", sexp)
868
- dispatch << fragment(", #{tmpfunc}._p = ", sexp)
869
- dispatch << block
870
- dispatch << fragment(", #{tmpfunc})", sexp)
871
- end
857
+ call_recv = s(:js_tmp, tmprecv || recv_code)
858
+ arglist.insert 1, call_recv if tmpfunc and !splat
859
+ args = process arglist
872
860
 
873
- if splat
874
- dispatch << fragment(".apply(", sexp)
875
- dispatch << process(call_recv, :expr)
876
- dispatch << fragment(", ", sexp)
877
- dispatch << args
878
- dispatch << fragment(")", sexp)
879
- else
880
- dispatch << fragment(".call(", sexp)
881
- dispatch.push(*args)
882
- dispatch << fragment(")", sexp)
883
- end
884
-
885
- result = dispatch
861
+ dispatch = if tmprecv
862
+ [f("(#{tmprecv} = "), recv_code, f(")#{mid}")]
886
863
  else
887
- args = process arglist, :expr
864
+ [recv_code, f(mid)]
865
+ end
888
866
 
889
- dispatch = if tmprecv
890
- [fragment("(#{tmprecv} = ", sexp), recv_code, fragment(")#{mid}", sexp)]
891
- else
892
- [recv_code, fragment(mid, sexp)]
893
- end
867
+ if tmpfunc
868
+ dispatch.unshift f("(#{tmpfunc} = ")
869
+ dispatch << f(", #{tmpfunc}._p = ")
870
+ dispatch << block
871
+ dispatch << f(", #{tmpfunc})")
872
+ end
894
873
 
895
- result = if splat
896
- [dispatch, fragment(".apply(", sexp), (tmprecv ? fragment(tmprecv, sexp) : recv_code),
897
- fragment(", ", sexp), args, fragment(")", sexp)]
898
- else
899
- [dispatch, fragment("(", sexp), args, fragment(")", sexp)]
900
- end
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(")")]
901
881
  end
902
882
 
903
883
  @scope.queue_temp tmpfunc if tmpfunc
@@ -906,37 +886,35 @@ module Opal
906
886
 
907
887
  # s(:arglist, [arg [, arg ..]])
908
888
  def process_arglist(sexp, level)
909
- code = []
910
- work = []
889
+ code, work = [], []
911
890
 
912
- until sexp.empty?
913
- current = sexp.shift
891
+ sexp.each do |current|
914
892
  splat = current.first == :splat
915
- arg = process current, :expr
893
+ arg = process current
916
894
 
917
895
  if splat
918
896
  if work.empty?
919
897
  if code.empty?
920
- code << fragment("[].concat(", sexp)
898
+ code << f("[].concat(", sexp)
921
899
  code << arg
922
- code << fragment(")", sexp)
900
+ code << f(")")
923
901
  else
924
902
  code += ".concat(#{arg})"
925
903
  end
926
904
  else
927
905
  if code.empty?
928
- code << [fragment("[", sexp), work, fragment("]", sexp)]
906
+ code << [f("["), work, f("]")]
929
907
  else
930
- code << [fragment(".concat([", sexp), work, fragment("])", sexp)]
908
+ code << [f(".concat(["), work, f("])")]
931
909
  end
932
910
 
933
- code << [fragment(".concat(", sexp), arg, fragment(")", sexp)]
911
+ code << [f(".concat("), arg, f(")")]
934
912
  end
935
913
 
936
914
  work = []
937
915
  else
938
- work << fragment(", ", current) unless work.empty?
939
- work.push(*arg)
916
+ work << f(", ") unless work.empty?
917
+ work << arg
940
918
  end
941
919
  end
942
920
 
@@ -946,7 +924,7 @@ module Opal
946
924
  if code.empty?
947
925
  code = join
948
926
  else
949
- code << fragment(".concat(", sexp) << join << fragment(")", sexp)
927
+ code << f(".concat(") << join << f(")")
950
928
  end
951
929
  end
952
930
 
@@ -956,9 +934,9 @@ module Opal
956
934
  # s(:splat, sexp)
957
935
  def process_splat(sexp, level)
958
936
  if sexp.first == [:nil]
959
- [fragment("[]", sexp)]
937
+ [f("[]")]
960
938
  elsif sexp.first.first == :sym
961
- [fragment("[", sexp), process(sexp.first, :expr), fragment("]", sexp)]
939
+ [f("["), process(sexp[0]), f("]")]
962
940
  else
963
941
  process sexp.first, :recv
964
942
  end
@@ -974,24 +952,24 @@ module Opal
974
952
  @helpers[:klass] = true
975
953
 
976
954
  if Symbol === cid or String === cid
977
- base = process(s(:self), :expr)
955
+ base = process s(:self)
978
956
  name = cid.to_s
979
957
  elsif cid[0] == :colon2
980
- base = process(cid[1], :expr)
958
+ base = process(cid[1])
981
959
  name = cid[2].to_s
982
960
  elsif cid[0] == :colon3
983
- base = process(s(:js_tmp, 'Opal.Object'), :expr)
961
+ base = process(s(:js_tmp, '$opal.Object'))
984
962
  name = cid[1].to_s
985
963
  else
986
964
  raise "Bad receiver in class"
987
965
  end
988
966
 
989
- sup = sup ? process(sup, :expr) : process(s(:js_tmp, 'null'), :expr)
967
+ sup = sup ? process(sup) : process(s(:js_tmp, 'null'))
990
968
 
991
969
  indent do
992
970
  in_scope(:class) do
993
971
  @scope.name = name
994
- @scope.add_temp "#{ @scope.proto } = #{name}._proto", "__scope = #{name}._scope"
972
+ @scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
995
973
 
996
974
  if Array === body.last
997
975
  # A single statement will need a block
@@ -1007,62 +985,54 @@ module Opal
1007
985
  end
1008
986
  end
1009
987
 
1010
- body = returns(body)
1011
- body = process body, :stmt
1012
- code << fragment("\n", sexp)
988
+ body = process(returns(body), :stmt)
989
+ code << f("\n")
1013
990
  code << @scope.to_donate_methods
1014
991
 
1015
- code << fragment(@indent, sexp)
992
+ code << f(@indent)
1016
993
  code << @scope.to_vars
1017
- code << fragment("\n\n#@indent", sexp)
994
+ code << f("\n\n#@indent")
1018
995
  code << body
1019
996
  end
1020
997
  end
1021
998
 
1022
999
  spacer = "\n#{@indent}#{INDENT}"
1023
1000
  cls = "function #{name}() {};"
1024
- boot = "#{name} = __klass(__base, __super, #{name.inspect}, #{name});"
1001
+ boot = "#{name} = $klass($base, $super, #{name.inspect}, #{name});"
1025
1002
 
1026
- [fragment("(function(__base, __super){#{spacer}#{cls}#{spacer}#{boot}\n", sexp),
1027
- code, fragment("\n#@indent})", sexp), fragment("(", sexp), base, fragment(", ", sexp), sup, fragment(")", sexp)]
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)]
1028
1005
  end
1029
1006
 
1030
- # s(:sclass, recv, body)
1007
+ # Singleton class syntax. Runs body in context of singleton_class.
1008
+ # s(:sclass, recv, body) => (function() { ... }).call(recv.$singleton_class())
1031
1009
  def process_sclass(sexp, level)
1032
- recv = sexp[0]
1033
- body = sexp[1]
1034
- code = []
1010
+ recv, body, code = sexp[0], sexp[1], []
1035
1011
 
1036
1012
  in_scope(:sclass) do
1037
- @scope.add_temp "__scope = #{current_self}._scope"
1013
+ @scope.add_temp "$scope = #{current_self}._scope"
1038
1014
  @scope.add_temp "def = #{current_self}._proto"
1039
1015
 
1040
- body = process body, :stmt
1041
- code << @scope.to_vars << body
1016
+ code << @scope.to_vars << process(body, :stmt)
1042
1017
  end
1043
1018
 
1044
- result = []
1045
- result << fragment("(function(){", sexp) << code
1046
- result << fragment("}).call(__opal.singleton(", sexp)
1047
- result << process(recv, :expr) << fragment("))", sexp)
1048
- result
1019
+ [f("(function(){"), code, f("}).call("), process(recv, :recv), f(".$singleton_class())")]
1049
1020
  end
1050
1021
 
1051
1022
  # s(:module, cid, body)
1052
1023
  def process_module(sexp, level)
1053
- cid = sexp[0]
1054
- body = sexp[1]
1024
+ cid, body = sexp
1055
1025
  code = []
1056
1026
  @helpers[:module] = true
1057
1027
 
1058
1028
  if Symbol === cid or String === cid
1059
- base = process(s(:self), :expr)
1029
+ base = process(s(:self))
1060
1030
  name = cid.to_s
1061
1031
  elsif cid[0] == :colon2
1062
- base = process(cid[1], :expr)
1032
+ base = process(cid[1])
1063
1033
  name = cid[2].to_s
1064
1034
  elsif cid[0] == :colon3
1065
- base = fragment('Opal.Object', sexp)
1035
+ base = f('$opal.Object', sexp)
1066
1036
  name = cid[1].to_s
1067
1037
  else
1068
1038
  raise "Bad receiver in class"
@@ -1071,34 +1041,35 @@ module Opal
1071
1041
  indent do
1072
1042
  in_scope(:module) do
1073
1043
  @scope.name = name
1074
- @scope.add_temp "#{ @scope.proto } = #{name}._proto", "__scope = #{name}._scope"
1044
+ @scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
1075
1045
  body = process body, :stmt
1076
1046
 
1077
- code << fragment(@indent, sexp)
1078
- code.push(*@scope.to_vars)
1079
- code << fragment("\n\n#@indent", sexp)
1080
- code.push(*body)
1081
- code << fragment("\n#@ident", sexp)
1082
- code.push(*@scope.to_donate_methods)
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
1083
1053
  end
1084
1054
  end
1085
1055
 
1086
1056
  spacer = "\n#{@indent}#{INDENT}"
1087
1057
  cls = "function #{name}() {};"
1088
- boot = "#{name} = __module(__base, #{name.inspect}, #{name});"
1058
+ boot = "#{name} = $module($base, #{name.inspect}, #{name});"
1089
1059
 
1090
- code.unshift fragment("(function(__base){#{spacer}#{cls}#{spacer}#{boot}\n", sexp)
1091
- code << fragment("\n#@indent})(", sexp)
1092
- code.push(*base)
1093
- code << fragment(")", sexp)
1060
+ code.unshift f("(function($base){#{spacer}#{cls}#{spacer}#{boot}\n", sexp)
1061
+ code << f("\n#@indent})(")
1062
+ code << base
1063
+ code << f(")")
1094
1064
 
1095
1065
  code
1096
1066
  end
1097
1067
 
1098
1068
  # undef :foo
1099
1069
  # => delete MyClass.prototype.$foo
1070
+ # FIXME: we should be setting method to a stub method here
1100
1071
  def process_undef(sexp, level)
1101
- fragment("delete #{ @scope.proto }#{ mid_to_jsid sexp[0][1].to_s }", sexp)
1072
+ f("delete #{ @scope.proto }#{ mid_to_jsid sexp[0][1].to_s }", sexp)
1102
1073
  end
1103
1074
 
1104
1075
  # s(:defn, mid, s(:args), s(:scope))
@@ -1121,7 +1092,7 @@ module Opal
1121
1092
  if recvr
1122
1093
  @scope.defines_defs = true
1123
1094
  smethod = true if @scope.class_scope? && recvr.first == :self
1124
- recv = process(recvr, :expr)
1095
+ recv = process(recvr)
1125
1096
  else
1126
1097
  @scope.defines_defn = true
1127
1098
  recv = current_self
@@ -1167,54 +1138,64 @@ module Opal
1167
1138
 
1168
1139
  if block_name
1169
1140
  @scope.uses_block!
1141
+ @scope.add_arg block_name
1170
1142
  end
1171
1143
 
1172
- yielder = block_name || '__yield'
1144
+ yielder = block_name || '$yield'
1173
1145
  @scope.block_name = yielder
1174
1146
 
1175
- params = process args, :expr
1176
- stmt_code = [fragment("\n#@indent", stmts), *process(stmts, :stmt)]
1147
+ params = process args
1148
+ stmt_code = [f("\n#@indent"), process(stmts, :stmt)]
1177
1149
 
1178
1150
  opt[1..-1].each do |o|
1179
1151
  next if o[2][2] == :undefined
1180
- code << fragment("if (#{o[1]} == null) {\n#{@indent + INDENT}", o)
1181
- code << process(o, :expr)
1182
- code << fragment("\n#{@indent}}", o)
1152
+ code << f("if (#{o[1]} == null) {\n#{@indent + INDENT}", o)
1153
+ code << process(o)
1154
+ code << f("\n#{@indent}}", o)
1183
1155
  end if opt
1184
1156
 
1185
- code << fragment("#{splat} = __slice.call(arguments, #{argc});", sexp) if splat
1157
+ code << f("#{splat} = $slice.call(arguments, #{argc});", sexp) if splat
1186
1158
 
1187
1159
  scope_name = @scope.identity
1188
1160
 
1189
1161
  if @scope.uses_block?
1190
- @scope.add_temp yielder
1191
- blk = fragment(("\n%s%s = %s._p || nil, %s._p = null;\n%s" %
1192
- [@indent, yielder, scope_name, scope_name, @indent]), sexp)
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)
1193
1166
  end
1194
1167
 
1195
1168
  code.push(*stmt_code)
1196
- code.unshift blk if blk
1197
1169
 
1198
1170
  uses_super = @scope.uses_super
1199
1171
 
1200
- code = [fragment("#{arity_code}#@indent", sexp), @scope.to_vars, code]
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
1201
1182
  end
1202
1183
  end
1203
1184
 
1204
- result = [fragment("#{"#{scope_name} = " if scope_name}function(", sexp)]
1185
+ result = [f("#{"#{scope_name} = " if scope_name}function(", sexp)]
1205
1186
  result.push(*params)
1206
- result << fragment(") {\n", sexp)
1187
+ result << f(") {\n", sexp)
1207
1188
  result.push(*code)
1208
- result << fragment("\n#@indent}", sexp)
1189
+ result << f("\n#@indent}", sexp)
1209
1190
 
1210
1191
  if recvr
1211
1192
  if smethod
1212
- [fragment("#{@scope.name}.constructor.prototype['$#{mid}'] = ", sexp), result]
1193
+ [f("#{@scope.name}.constructor.prototype['$#{mid}'] = ", sexp), result]
1213
1194
  else
1214
- [recv, fragment("#{jsid} = ", sexp), result]
1195
+ [recv, f("#{jsid} = ", sexp), result]
1215
1196
  end
1216
1197
  elsif @scope.class? and @scope.name == 'Object'
1217
- [fragment("#{current_self}._defn('$#{mid}', ", sexp), result, fragment(")", sexp)]
1198
+ [f("#{current_self}._defn('$#{mid}', ", sexp), result, f(")", sexp)]
1218
1199
  elsif @scope.class_scope?
1219
1200
  @scope.methods << "$#{mid}"
1220
1201
  if uses_super
@@ -1222,13 +1203,9 @@ module Opal
1222
1203
  uses_super = "#{uses_super} = #{@scope.proto}#{jsid};\n#@indent"
1223
1204
  end
1224
1205
 
1225
- [fragment("#{uses_super}#{@scope.proto}#{jsid} = ", sexp), result]
1226
- elsif @scope.type == :iter
1227
- [fragment("def#{jsid} = ", sexp), result]
1228
- elsif @scope.type == :top
1229
- [fragment("def#{ jsid } = ", sexp), *result]
1230
- else
1231
- [fragment("def#{jsid} = ", sexp), result]
1206
+ [f("#{uses_super}#{@scope.proto}#{jsid} = ", sexp), result]
1207
+ else # :top, :iter
1208
+ [f("def#{jsid} = ", sexp), result]
1232
1209
  end
1233
1210
  end
1234
1211
 
@@ -1246,34 +1223,35 @@ module Opal
1246
1223
  aritycode = "var $arity = arguments.length;"
1247
1224
 
1248
1225
  if arity < 0 # splat or opt args
1249
- aritycode + "if ($arity < #{-(arity + 1)}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
1226
+ aritycode + "if ($arity < #{-(arity + 1)}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
1250
1227
  else
1251
- aritycode + "if ($arity !== #{arity}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
1228
+ aritycode + "if ($arity !== #{arity}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
1252
1229
  end
1253
1230
  end
1254
1231
 
1255
1232
  def process_args(exp, level)
1256
1233
  args = []
1257
1234
 
1258
- until exp.empty?
1259
- a = exp.shift.to_sym
1235
+ exp.each do |a|
1236
+ a = a.to_sym
1260
1237
  next if a.to_s == '*'
1261
- a = "#{a}$".to_sym if RESERVED.include? a.to_s
1238
+ a = lvar_to_js a
1262
1239
  @scope.add_arg a
1263
1240
  args << a
1264
1241
  end
1265
1242
 
1266
- [fragment(args.join(', '), exp)]
1243
+ f(args.join(', '), exp)
1267
1244
  end
1268
1245
 
1269
1246
  # s(:self) # => this
1270
1247
  def process_self(sexp, level)
1271
- fragment(current_self, sexp)
1248
+ f(current_self, sexp)
1272
1249
  end
1273
1250
 
1274
1251
  # Returns the current value for 'self'. This will be native
1275
1252
  # 'this' for methods and blocks, and the class name for class
1276
1253
  # and module bodies.
1254
+ # s(:self) => self or this or class name
1277
1255
  def current_self
1278
1256
  if @scope.class_scope?
1279
1257
  @scope.name
@@ -1284,60 +1262,64 @@ module Opal
1284
1262
  end
1285
1263
  end
1286
1264
 
1265
+ # true literal
1266
+ # s(:true) => true
1287
1267
  def process_true(sexp, level)
1288
- fragment("true", sexp)
1268
+ f "true", sexp
1289
1269
  end
1290
1270
 
1271
+ # false literal
1272
+ # s(:false) => false
1291
1273
  def process_false(sexp, level)
1292
- fragment("false", sexp)
1274
+ f "false", sexp
1293
1275
  end
1294
1276
 
1277
+ # nil literal
1278
+ # s(:nil) => nil
1295
1279
  def process_nil(sexp, level)
1296
- fragment("nil", sexp)
1280
+ f "nil", sexp
1297
1281
  end
1298
1282
 
1299
- # s(:array [, sexp [, sexp]])
1283
+ # s(:array [, sexp [, sexp]]) => [...]
1300
1284
  def process_array(sexp, level)
1301
- return [fragment("[]", sexp)] if sexp.empty?
1285
+ return [f("[]", sexp)] if sexp.empty?
1302
1286
 
1303
- code = []
1304
- work = []
1287
+ code, work = [], []
1305
1288
 
1306
- until sexp.empty?
1307
- current = sexp.shift
1289
+ sexp.each do |current|
1308
1290
  splat = current.first == :splat
1309
- part = process current, :expr
1291
+ part = process current
1310
1292
 
1311
1293
  if splat
1312
1294
  if work.empty?
1313
1295
  if code.empty?
1314
- code << fragment("[].concat(", sexp) << part << fragment(")", sexp)
1296
+ code << f("[].concat(", sexp) << part << f(")", sexp)
1315
1297
  else
1316
- code << fragment(".concat(", sexp) << part << fragment(")", sexp)
1298
+ code << f(".concat(", sexp) << part << f(")", sexp)
1317
1299
  end
1318
1300
  else
1319
1301
  if code.empty?
1320
- code << fragment("[", sexp) << work << fragment("]", sexp)
1302
+ code << f("[", sexp) << work << f("]", sexp)
1321
1303
  else
1322
- code << fragment(".concat([", sexp) << work << fragment("])", sexp)
1304
+ code << f(".concat([", sexp) << work << f("])", sexp)
1323
1305
  end
1324
1306
 
1325
- code << fragment(".concat(", sexp) << part << fragment(")", sexp)
1307
+ code << f(".concat(", sexp) << part << f(")", sexp)
1326
1308
  end
1327
1309
  work = []
1328
1310
  else
1329
- work << fragment(", ", current) unless work.empty?
1311
+ work << f(", ", current) unless work.empty?
1330
1312
  work << part
1331
1313
  end
1332
1314
  end
1333
1315
 
1334
1316
  unless work.empty?
1335
- join = [fragment("[", sexp), work, fragment("]", sexp)]
1317
+ join = [f("[", sexp), work, f("]", sexp)]
1336
1318
 
1337
1319
  if code.empty?
1338
1320
  code = join
1339
1321
  else
1340
- code.push([fragment(".concat(", sexp), join, fragment(")", sexp)])
1322
+ code.push([f(".concat(", sexp), join, f(")", sexp)])
1341
1323
  end
1342
1324
  end
1343
1325
 
@@ -1363,29 +1345,29 @@ module Opal
1363
1345
  keys.size.times do |i|
1364
1346
  k = keys[i][1].to_s.inspect
1365
1347
  hash_keys << k unless hash_obj.include? k
1366
- hash_obj[k] = process(vals[i], :expr)
1348
+ hash_obj[k] = process(vals[i])
1367
1349
  end
1368
1350
 
1369
1351
  result = []
1370
1352
  @helpers[:hash2] = true
1371
1353
 
1372
1354
  hash_keys.each do |k|
1373
- result << fragment(", ", sexp) unless result.empty?
1374
- result << fragment("#{k}: ", sexp)
1355
+ result << f(", ", sexp) unless result.empty?
1356
+ result << f("#{k}: ", sexp)
1375
1357
  result << hash_obj[k]
1376
1358
  end
1377
1359
 
1378
- [fragment("__hash2([#{hash_keys.join ', '}], {", sexp), result, fragment("})", sexp)]
1360
+ [f("$hash2([#{hash_keys.join ', '}], {", sexp), result, f("})", sexp)]
1379
1361
  else
1380
1362
  @helpers[:hash] = true
1381
1363
  result = []
1382
1364
 
1383
1365
  sexp.each do |p|
1384
- result << fragment(", ", p) unless result.empty?
1385
- result << process(p, :expr)
1366
+ result << f(", ", p) unless result.empty?
1367
+ result << process(p)
1386
1368
  end
1387
1369
 
1388
- [fragment("__hash(", sexp), result, fragment(")", sexp)]
1370
+ [f("$hash(", sexp), result, f(")", sexp)]
1389
1371
  end
1390
1372
  end
1391
1373
 
@@ -1401,7 +1383,7 @@ module Opal
1401
1383
  :stmt
1402
1384
  end
1403
1385
 
1404
- code << js_truthy(expr) << fragment("){", sexp)
1386
+ code << js_truthy(expr) << f("){", sexp)
1405
1387
  pre = "while ("
1406
1388
 
1407
1389
  in_while do
@@ -1411,27 +1393,26 @@ module Opal
1411
1393
 
1412
1394
  if @while_loop[:use_redo]
1413
1395
  pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
1414
- code << fragment("#{redo_var}=false;", sexp)
1396
+ code << f("#{redo_var}=false;", sexp)
1415
1397
  end
1416
1398
 
1417
1399
  code << body
1418
1400
  end
1419
1401
 
1420
- code << fragment("}", sexp)
1421
- code.unshift fragment(pre, sexp)
1402
+ code << f("}", sexp)
1403
+ code.unshift f(pre, sexp)
1422
1404
  @scope.queue_temp redo_var
1423
1405
 
1424
1406
  if stmt_level == :stmt_closure
1425
- code.unshift fragment("(function() {", sexp)
1426
- code.push fragment("; return nil; }).call(#{current_self})", sexp)
1407
+ code.unshift f("(function() {", sexp)
1408
+ code.push f("; return nil; }).call(#{current_self})", sexp)
1427
1409
  end
1428
1410
 
1429
1411
  code
1430
1412
  end
1431
1413
 
1432
1414
  def process_until(exp, level)
1433
- expr = exp[0]
1434
- stmt = exp[1]
1415
+ expr, stmt = exp
1435
1416
  redo_var = @scope.new_temp
1436
1417
  stmt_level = if level == :expr or level == :recv
1437
1418
  :stmt_closure
@@ -1441,7 +1422,7 @@ module Opal
1441
1422
 
1442
1423
  code = []
1443
1424
  pre = "while (!("
1444
- code << js_truthy(expr) << fragment(")) {", exp)
1425
+ code << js_truthy(expr) << f(")) {", exp)
1445
1426
 
1446
1427
  in_while do
1447
1428
  @while_loop[:closure] = true if stmt_level == :stmt_closure
@@ -1450,19 +1431,19 @@ module Opal
1450
1431
 
1451
1432
  if @while_loop[:use_redo]
1452
1433
  pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
1453
- code << fragment("#{redo_var}=false;", exp)
1434
+ code << f("#{redo_var}=false;", exp)
1454
1435
  end
1455
1436
 
1456
1437
  code << body
1457
1438
  end
1458
1439
 
1459
- code << fragment("}", exp)
1460
- code.unshift fragment(pre, exp)
1440
+ code << f("}", exp)
1441
+ code.unshift f(pre, exp)
1461
1442
  @scope.queue_temp redo_var
1462
1443
 
1463
1444
  if stmt_level == :stmt_closure
1464
- code.unshift fragment("(function() {", exp)
1465
- code << fragment("; return nil; }).call(#{current_self})", exp)
1445
+ code.unshift f("(function() {", exp)
1446
+ code << f("; return nil; }).call(#{current_self})", exp)
1466
1447
  end
1467
1448
 
1468
1449
  code
@@ -1477,50 +1458,59 @@ module Opal
1477
1458
 
1478
1459
  if [:class, :module].include? @scope.type
1479
1460
  @scope.methods << "$#{exp[0][1].to_s}"
1480
- fragment("%s%s = %s%s" % [@scope.proto, new, @scope.proto, old], exp)
1461
+ f("%s%s = %s%s" % [@scope.proto, new, @scope.proto, old], exp)
1481
1462
  else
1482
1463
  current = current_self
1483
- fragment("%s._proto%s = %s._proto%s" % [current, new, current, old], exp)
1464
+ f("%s._proto%s = %s._proto%s" % [current, new, current, old], exp)
1484
1465
  end
1485
1466
  end
1486
1467
 
1487
1468
  def process_masgn(sexp, level)
1488
- lhs = sexp[0]
1489
- rhs = sexp[1]
1469
+ lhs, rhs = sexp
1490
1470
  tmp = @scope.new_temp
1491
1471
  len = 0
1492
1472
  code = []
1493
1473
 
1494
- # remote :array part
1495
- lhs.shift
1496
1474
  if rhs[0] == :array
1497
1475
  len = rhs.length - 1 # we are guaranteed an array of this length
1498
- code << fragment("#{tmp} = ", sexp) << process(rhs, :expr)
1476
+ code << f("#{tmp} = ", sexp) << process(rhs)
1499
1477
  elsif rhs[0] == :to_ary
1500
- code << fragment("((#{tmp} = ", sexp) << process(rhs[1], :expr)
1501
- code << fragment(")._isArray ? #{tmp} : (#{tmp} = [#{tmp}]))", sexp)
1478
+ code << f("((#{tmp} = ", sexp) << process(rhs[1])
1479
+ code << f(")._isArray ? #{tmp} : (#{tmp} = [#{tmp}]))", sexp)
1502
1480
  elsif rhs[0] == :splat
1503
- code << fragment("(#{tmp} = ", sexp) << process(rhs[1], :expr)
1504
- code << fragment(")['$to_a'] ? (#{tmp} = #{tmp}['$to_a']()) : (#{tmp})._isArray ? #{tmp} : (#{tmp} = [#{tmp}])", sexp)
1481
+ code << f("(#{tmp} = ", sexp) << process(rhs[1])
1482
+ code << f(")['$to_a'] ? (#{tmp} = #{tmp}['$to_a']()) : (#{tmp})._isArray ? #{tmp} : (#{tmp} = [#{tmp}])", sexp)
1505
1483
  else
1506
1484
  raise "Unsupported mlhs type"
1507
1485
  end
1508
1486
 
1509
- lhs.each_with_index do |l, idx|
1510
- code << fragment(", ", sexp) unless code.empty?
1487
+ lhs[1..-1].each_with_index do |l, idx|
1488
+ code << f(", ", sexp) unless code.empty?
1511
1489
 
1512
1490
  if l.first == :splat
1513
1491
  if s = l[1]
1514
- s << s(:js_tmp, "__slice.call(#{tmp}, #{idx})")
1515
- code << process(s, :expr)
1492
+ s << s(:js_tmp, "$slice.call(#{tmp}, #{idx})")
1493
+ code << process(s)
1516
1494
  end
1517
1495
  else
1518
1496
  if idx >= len
1519
- l << s(:js_tmp, "(#{tmp}[#{idx}] == null ? nil : #{tmp}[#{idx}])")
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
1520
1509
  else
1521
- l << s(:js_tmp, "#{tmp}[#{idx}]")
1510
+ raise "bad lhs for masgn: #{l.inspect}"
1522
1511
  end
1523
- code << process(l, :expr)
1512
+
1513
+ code << process(l)
1524
1514
  end
1525
1515
  end
1526
1516
 
@@ -1529,7 +1519,7 @@ module Opal
1529
1519
  end
1530
1520
 
1531
1521
  def process_svalue(sexp, level)
1532
- process sexp.shift, level
1522
+ process sexp[0], level
1533
1523
  end
1534
1524
 
1535
1525
  # s(:lasgn, :lvar, rhs)
@@ -1539,15 +1529,15 @@ module Opal
1539
1529
  lvar = "#{lvar}$".to_sym if RESERVED.include? lvar.to_s
1540
1530
 
1541
1531
  if @irb_vars and @scope.top?
1542
- [fragment("Opal.irb_vars.#{lvar} = ", sexp), process(rhs, :expr)]
1532
+ [f("$opal.irb_vars.#{lvar} = ", sexp), process(rhs)]
1543
1533
  else
1544
1534
  @scope.add_local lvar
1545
- rhs = process(rhs, :expr)
1546
- result = [fragment(lvar, sexp), fragment(" = ", sexp), rhs]
1535
+ rhs = process(rhs)
1536
+ result = [f(lvar, sexp), f(" = ", sexp), rhs]
1547
1537
 
1548
1538
  if level == :recv
1549
- result.unshift fragment("(", sexp)
1550
- result.push fragment(")", sexp)
1539
+ result.unshift f("(", sexp)
1540
+ result.push f(")", sexp)
1551
1541
  end
1552
1542
 
1553
1543
  result
@@ -1556,42 +1546,41 @@ module Opal
1556
1546
 
1557
1547
  # s(:lvar, :lvar)
1558
1548
  def process_lvar(sexp, level)
1559
- lvar = sexp.shift.to_s
1549
+ lvar = sexp[0].to_s
1560
1550
  lvar = "#{lvar}$" if RESERVED.include? lvar
1561
1551
 
1562
1552
  if @irb_vars and @scope.top?
1563
- with_temp { |t| fragment("((#{t} = Opal.irb_vars.#{lvar}) == null ? nil : #{t})", sexp) }
1553
+ with_temp { |t| f("((#{t} = $opal.irb_vars.#{lvar}) == null ? nil : #{t})", sexp) }
1564
1554
  else
1565
- fragment(lvar, sexp)
1555
+ f(lvar, sexp)
1566
1556
  end
1567
1557
  end
1568
1558
 
1569
1559
  # s(:iasgn, :ivar, rhs)
1570
1560
  def process_iasgn(exp, level)
1571
- ivar = exp[0]
1572
- rhs = exp[1]
1561
+ ivar, rhs = exp
1573
1562
  ivar = ivar.to_s[1..-1]
1574
1563
  lhs = RESERVED.include?(ivar) ? "#{current_self}['#{ivar}']" : "#{current_self}.#{ivar}"
1575
- [fragment(lhs, exp), fragment(" = ", exp), process(rhs, :expr)]
1564
+ [f(lhs, exp), f(" = ", exp), process(rhs)]
1576
1565
  end
1577
1566
 
1578
1567
  # s(:ivar, :ivar)
1579
1568
  def process_ivar(exp, level)
1580
- ivar = exp.shift.to_s[1..-1]
1569
+ ivar = exp[0].to_s[1..-1]
1581
1570
  part = RESERVED.include?(ivar) ? "['#{ivar}']" : ".#{ivar}"
1582
1571
  @scope.add_ivar part
1583
- fragment("#{current_self}#{part}", exp)
1572
+ f("#{current_self}#{part}", exp)
1584
1573
  end
1585
1574
 
1586
1575
  # s(:gvar, gvar)
1587
1576
  def process_gvar(sexp, level)
1588
- gvar = sexp.shift.to_s[1..-1]
1577
+ gvar = sexp[0].to_s[1..-1]
1589
1578
  @helpers['gvars'] = true
1590
- fragment("__gvars[#{gvar.inspect}]", sexp)
1579
+ f("$gvars[#{gvar.inspect}]", sexp)
1591
1580
  end
1592
1581
 
1593
1582
  def process_nth_ref(sexp, level)
1594
- fragment("nil", sexp)
1583
+ f("nil", sexp)
1595
1584
  end
1596
1585
 
1597
1586
  # s(:gasgn, :gvar, rhs)
@@ -1599,34 +1588,53 @@ module Opal
1599
1588
  gvar = sexp[0].to_s[1..-1]
1600
1589
  rhs = sexp[1]
1601
1590
  @helpers['gvars'] = true
1602
- [fragment("__gvars[#{gvar.to_s.inspect}] = ", sexp), process(rhs, :expr)]
1591
+ [f("$gvars[#{gvar.to_s.inspect}] = ", sexp), process(rhs)]
1603
1592
  end
1604
1593
 
1605
1594
  # s(:const, :const)
1606
1595
  def process_const(sexp, level)
1607
- cname = sexp.shift.to_s
1596
+ cname = sexp[0].to_s
1608
1597
 
1609
1598
  if @const_missing
1610
1599
  with_temp do |t|
1611
- fragment("((#{t} = __scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})", sexp)
1600
+ f("((#{t} = $scope.#{cname}) == null ? $opal.cm(#{cname.inspect}) : #{t})", sexp)
1612
1601
  end
1613
1602
  else
1614
- fragment("__scope.#{cname}", sexp)
1603
+ f("$scope.#{cname}", sexp)
1615
1604
  end
1616
1605
  end
1617
1606
 
1618
1607
  # s(:cdecl, :const, rhs)
1619
1608
  def process_cdecl(sexp, level)
1620
1609
  const, rhs = sexp
1621
- [fragment("__scope.#{const} = ", sexp), process(rhs, :expr)]
1610
+ [f("$scope.#{const} = ", sexp), process(rhs)]
1611
+ end
1612
+
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)]
1622
1618
  end
1623
1619
 
1624
1620
  # s(:return [val])
1625
1621
  def process_return(sexp, level)
1626
- val = process(sexp.shift || s(:nil), :expr)
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
1627
 
1628
- raise SyntaxError, "void value expression: cannot return as an expression" unless level == :stmt
1629
- [fragment("return ", sexp), val]
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
1630
1638
  end
1631
1639
 
1632
1640
  # s(:xstr, content)
@@ -1634,9 +1642,9 @@ module Opal
1634
1642
  code = sexp.first.to_s
1635
1643
  code += ";" if level == :stmt and !code.include?(';')
1636
1644
 
1637
- result = fragment(code, sexp)
1645
+ result = f(code, sexp)
1638
1646
 
1639
- level == :recv ? [fragment("(", sexp), result, fragment(")", sexp)] : result
1647
+ level == :recv ? [f("(", sexp), result, f(")", sexp)] : result
1640
1648
  end
1641
1649
 
1642
1650
  # s(:dxstr, parts...)
@@ -1646,22 +1654,22 @@ module Opal
1646
1654
 
1647
1655
  sexp.each do |p|
1648
1656
  if String === p
1649
- result << fragment(p.to_s, sexp)
1657
+ result << f(p.to_s, sexp)
1650
1658
  needs_sc = true if level == :stmt and !p.to_s.include?(';')
1651
1659
  elsif p.first == :evstr
1652
1660
  result.push(*process(p.last, :stmt))
1653
1661
  elsif p.first == :str
1654
- result << fragment(p.last.to_s, p)
1662
+ result << f(p.last.to_s, p)
1655
1663
  needs_sc = true if level == :stmt and !p.last.to_s.include?(';')
1656
1664
  else
1657
1665
  raise "Bad dxstr part"
1658
1666
  end
1659
1667
  end
1660
1668
 
1661
- result << fragment(";", sexp) if needs_sc
1669
+ result << f(";", sexp) if needs_sc
1662
1670
 
1663
1671
  if level == :recv
1664
- [fragment("(", sexp), result, fragment(")", sexp)]
1672
+ [f("(", sexp), result, f(")", sexp)]
1665
1673
  else
1666
1674
  result
1667
1675
  end
@@ -1672,22 +1680,22 @@ module Opal
1672
1680
  result = []
1673
1681
 
1674
1682
  sexp.each do |p|
1675
- result << fragment(" + ", sexp) unless result.empty?
1683
+ result << f(" + ", sexp) unless result.empty?
1676
1684
  if String === p
1677
- result << fragment(p.inspect, sexp)
1685
+ result << f(p.inspect, sexp)
1678
1686
  elsif p.first == :evstr
1679
- result << fragment("(", p)
1680
- result << process(p.last, :expr)
1681
- result << fragment(")", p)
1687
+ result << f("(", p)
1688
+ result << process(p.last)
1689
+ result << f(")", p)
1682
1690
  elsif p.first == :str
1683
- result << fragment(p.last.inspect, p)
1691
+ result << f(p.last.inspect, p)
1684
1692
  else
1685
1693
  raise "Bad dstr part"
1686
1694
  end
1687
1695
  end
1688
1696
 
1689
1697
  if level == :recv
1690
- [fragment("(", sexp), result, fragment(")", sexp)]
1698
+ [f("(", sexp), result, f(")", sexp)]
1691
1699
  else
1692
1700
  result
1693
1701
  end
@@ -1697,20 +1705,20 @@ module Opal
1697
1705
  result = []
1698
1706
 
1699
1707
  sexp.each do |p|
1700
- result << fragment(" + ", sexp) unless result.empty?
1708
+ result << f(" + ", sexp) unless result.empty?
1701
1709
 
1702
1710
  if String === p
1703
- result << fragment(p.inspect, sexp)
1711
+ result << f(p.inspect, sexp)
1704
1712
  elsif p.first == :evstr
1705
- result << process(s(:call, p.last, :to_s, s(:arglist)), :expr)
1713
+ result << process(s(:call, p.last, :to_s, s(:arglist)))
1706
1714
  elsif p.first == :str
1707
- result << fragment(p.last.inspect, sexp)
1715
+ result << f(p.last.inspect, sexp)
1708
1716
  else
1709
1717
  raise "Bad dsym part"
1710
1718
  end
1711
1719
  end
1712
1720
 
1713
- [fragment("(", sexp), result, fragment(")", sexp)]
1721
+ [f("(", sexp), result, f(")", sexp)]
1714
1722
  end
1715
1723
 
1716
1724
  # s(:if, test, truthy, falsy)
@@ -1732,18 +1740,18 @@ module Opal
1732
1740
  check = js_truthy test
1733
1741
  end
1734
1742
 
1735
- result = [fragment("if (", sexp), check, fragment(") {\n", sexp)]
1743
+ result = [f("if (", sexp), check, f(") {\n", sexp)]
1736
1744
 
1737
- indent { result.push(fragment(@indent, sexp), process(truthy, :stmt)) } if truthy
1745
+ indent { result.push(f(@indent, sexp), process(truthy, :stmt)) } if truthy
1738
1746
 
1739
1747
  outdent = @indent
1740
- indent { result.push(fragment("\n#{outdent}} else {\n#@indent", sexp), process(falsy, :stmt)) } if falsy
1748
+ indent { result.push(f("\n#{outdent}} else {\n#@indent", sexp), process(falsy, :stmt)) } if falsy
1741
1749
 
1742
- result << fragment("\n#@indent}", sexp)
1750
+ result << f("\n#@indent}", sexp)
1743
1751
 
1744
1752
  if returnable
1745
- result.unshift fragment("(function() { ", sexp)
1746
- result.push fragment("; return nil; }).call(#{current_self})", sexp)
1753
+ result.unshift f("(function() { ", sexp)
1754
+ result.push f("; return nil; }).call(#{current_self})", sexp)
1747
1755
  end
1748
1756
 
1749
1757
  result
@@ -1753,14 +1761,14 @@ module Opal
1753
1761
  if sexp.first == :call
1754
1762
  mid = sexp[2]
1755
1763
  if mid == :block_given?
1756
- return process sexp, :expr
1764
+ return process sexp
1757
1765
  elsif COMPARE.include? mid.to_s
1758
- return process sexp, :expr
1766
+ return process sexp
1759
1767
  elsif mid == :"=="
1760
- return process sexp, :expr
1768
+ return process sexp
1761
1769
  end
1762
1770
  elsif [:lvar, :self].include? sexp.first
1763
- [process(sexp.dup, :expr), fragment(" !== false && ", sexp), process(sexp.dup, :expr), fragment(" !== nil", sexp)]
1771
+ [process(sexp.dup), f(" !== false && ", sexp), process(sexp.dup), f(" !== nil", sexp)]
1764
1772
  end
1765
1773
  end
1766
1774
 
@@ -1770,7 +1778,7 @@ module Opal
1770
1778
  end
1771
1779
 
1772
1780
  with_temp do |tmp|
1773
- [fragment("(#{tmp} = ", sexp), process(sexp, :expr), fragment(") !== false && #{tmp} !== nil", sexp)]
1781
+ [f("(#{tmp} = ", sexp), process(sexp), f(") !== false && #{tmp} !== nil", sexp)]
1774
1782
  end
1775
1783
  end
1776
1784
 
@@ -1784,9 +1792,9 @@ module Opal
1784
1792
 
1785
1793
  with_temp do |tmp|
1786
1794
  result = []
1787
- result << fragment("(#{tmp} = ", sexp)
1788
- result << process(sexp, :expr)
1789
- result << fragment(") === false || #{tmp} === nil", sexp)
1795
+ result << f("(#{tmp} = ", sexp)
1796
+ result << process(sexp)
1797
+ result << f(") === false || #{tmp} === nil", sexp)
1790
1798
  result
1791
1799
  end
1792
1800
  end
@@ -1799,9 +1807,9 @@ module Opal
1799
1807
 
1800
1808
  if t = js_truthy_optimize(lhs)
1801
1809
  result = []
1802
- result << fragment("((#{tmp} = ", sexp) << t
1803
- result << fragment(") ? ", sexp) << process(rhs, :expr)
1804
- result << fragment(" : #{tmp})", sexp)
1810
+ result << f("((#{tmp} = ", sexp) << t
1811
+ result << f(") ? ", sexp) << process(rhs)
1812
+ result << f(" : #{tmp})", sexp)
1805
1813
  @scope.queue_temp tmp
1806
1814
 
1807
1815
  return result
@@ -1809,19 +1817,18 @@ module Opal
1809
1817
 
1810
1818
  @scope.queue_temp tmp
1811
1819
 
1812
- [fragment("(#{tmp} = ", sexp), process(lhs, :expr), fragment(", #{tmp} !== false && #{tmp} !== nil ? ", sexp), process(rhs, :expr), fragment(" : #{tmp})", sexp)]
1820
+ [f("(#{tmp} = ", sexp), process(lhs), f(", #{tmp} !== false && #{tmp} !== nil ? ", sexp), process(rhs), f(" : #{tmp})", sexp)]
1813
1821
 
1814
1822
  end
1815
1823
 
1816
1824
  # s(:or, lhs, rhs)
1817
1825
  def process_or(sexp, level)
1818
- lhs = sexp[0]
1819
- rhs = sexp[1]
1826
+ lhs, rhs = sexp
1820
1827
 
1821
1828
  with_temp do |tmp|
1822
- lhs = process lhs, :expr
1823
- rhs = process rhs, :expr
1824
- [fragment("(((#{tmp} = ", sexp), lhs, fragment(") !== false && #{tmp} !== nil) ? #{tmp} : ", sexp), rhs, fragment(")", sexp)]
1829
+ lhs = process lhs
1830
+ rhs = process rhs
1831
+ [f("(((#{tmp} = ", sexp), lhs, f(") !== false && #{tmp} !== nil) ? #{tmp} : ", sexp), rhs, f(")", sexp)]
1825
1832
  end
1826
1833
  end
1827
1834
 
@@ -1830,10 +1837,10 @@ module Opal
1830
1837
  call = handle_yield_call sexp, level
1831
1838
 
1832
1839
  if level == :stmt
1833
- [fragment("if (", sexp), call, fragment(" === __breaker) return __breaker.$v")]
1840
+ [f("if (", sexp), call, f(" === $breaker) return $breaker.$v")]
1834
1841
  else
1835
1842
  with_temp do |tmp|
1836
- [fragment("(((#{tmp} = ", sexp), call, fragment(") === __breaker) ? __breaker.$v : #{tmp})", sexp)]
1843
+ [f("(((#{tmp} = ", sexp), call, f(") === $breaker) ? $breaker.$v : #{tmp})", sexp)]
1837
1844
  end
1838
1845
  end
1839
1846
  end
@@ -1847,7 +1854,7 @@ module Opal
1847
1854
  def process_yasgn(sexp, level)
1848
1855
  call = handle_yield_call s(*sexp[1][1..-1]), :stmt
1849
1856
 
1850
- [fragment("if ((#{sexp[0]} = ", sexp), call, fragment(") === __breaker) return __breaker.$v", sexp)]
1857
+ [f("if ((#{sexp[0]} = ", sexp), call, f(") === $breaker) return $breaker.$v", sexp)]
1851
1858
  end
1852
1859
 
1853
1860
  # Created by `#returns()` for when a yield statement should return
@@ -1856,8 +1863,8 @@ module Opal
1856
1863
  call = handle_yield_call sexp, level
1857
1864
 
1858
1865
  with_temp do |tmp|
1859
- [fragment("return #{tmp} = ", sexp), call,
1860
- fragment(", #{tmp} === __breaker ? #{tmp} : #{tmp}")]
1866
+ [f("return #{tmp} = ", sexp), call,
1867
+ f(", #{tmp} === $breaker ? #{tmp} : #{tmp}")]
1861
1868
  end
1862
1869
  end
1863
1870
 
@@ -1865,25 +1872,28 @@ module Opal
1865
1872
  @scope.uses_block!
1866
1873
 
1867
1874
  splat = sexp.any? { |s| s.first == :splat }
1868
- sexp.unshift s(:js_tmp, 'null') unless splat # self
1869
- args = process_arglist sexp, level
1870
1875
 
1871
- y = @scope.block_name || '__yield'
1876
+ if !splat and sexp.size == 1
1877
+ return [f("$opal.$yield1(#{@scope.block_name || '$yield'}, "), process(sexp[0]), f(")")]
1878
+ end
1879
+
1880
+ args = process_arglist sexp, level
1881
+ y = @scope.block_name || '$yield'
1872
1882
 
1873
1883
  if splat
1874
- [fragment("#{y}.apply(null, ", sexp), args, fragment(")", sexp)]
1884
+ [f("$opal.$yieldX(#{y}, ", sexp), args, f(")")]
1875
1885
  else
1876
- [fragment("#{y}.call(", sexp), args, fragment(")", sexp)]
1886
+ [f("$opal.$yieldX(#{y}, [", sexp), args, f("])")]
1877
1887
  end
1878
1888
  end
1879
1889
 
1880
1890
  def process_break(sexp, level)
1881
- val = sexp.empty? ? fragment('nil', sexp) : process(sexp.shift, :expr)
1891
+ val = sexp.empty? ? f('nil', sexp) : process(sexp[0])
1882
1892
  if in_while?
1883
- @while_loop[:closure] ? [fragment("return ", sexp), val, fragment("", sexp)] : fragment("break;", sexp)
1893
+ @while_loop[:closure] ? [f("return ", sexp), val, f("", sexp)] : f("break;", sexp)
1884
1894
  elsif @scope.iter?
1885
1895
  error "break must be used as a statement" unless level == :stmt
1886
- [fragment("return (__breaker.$v = ", sexp), val, fragment(", __breaker)", sexp)]
1896
+ [f("return ($breaker.$v = ", sexp), val, f(", $breaker)", sexp)]
1887
1897
  else
1888
1898
  error "void value expression: cannot use break outside of iter/while"
1889
1899
  end
@@ -1891,37 +1901,41 @@ module Opal
1891
1901
 
1892
1902
  # s(:case, expr, when1, when2, ..)
1893
1903
  def process_case(exp, level)
1894
- pre = []
1895
- code = []
1896
- @scope.add_local "$case"
1897
- expr = process exp.shift, :expr
1904
+ pre, code = [], []
1905
+
1898
1906
  # are we inside a statement_closure
1899
1907
  returnable = level != :stmt
1900
1908
  done_else = false
1901
1909
 
1902
- pre << fragment("$case = ", exp) << expr << fragment(";", exp)
1903
-
1904
- until exp.empty?
1905
- wen = exp.shift
1906
- if wen and wen.first == :when
1907
- returns(wen) if returnable
1908
- wen = process(wen, :stmt)
1909
- code << fragment("else ", exp) unless code.empty?
1910
- code << wen
1911
- elsif wen # s(:else)
1912
- done_else = true
1913
- wen = returns(wen) if returnable
1914
- code << fragment("else {", exp) << process(wen, :stmt) << fragment("}", exp)
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
1915
1929
  end
1916
1930
  end
1917
1931
 
1918
- code << fragment("else { return nil }", exp) if returnable and !done_else
1932
+ code << f("else { return nil }", exp) if returnable and !done_else
1919
1933
 
1920
1934
  code.unshift pre
1921
1935
 
1922
1936
  if returnable
1923
- code.unshift fragment("(function() { ", exp)
1924
- code << fragment(" }).call(#{current_self})", exp)
1937
+ code.unshift f("(function() { ", exp)
1938
+ code << f(" }).call(#{current_self})", exp)
1925
1939
  end
1926
1940
 
1927
1941
  code
@@ -1932,43 +1946,41 @@ module Opal
1932
1946
  #
1933
1947
  # s(:when, s(:array, foo), bar)
1934
1948
  def process_when(exp, level)
1935
- arg = exp.shift[1..-1]
1936
- body = exp.shift || s(:nil)
1937
- #body = process body, level if body
1949
+ arg = exp[0][1..-1]
1950
+ body = exp[1] || s(:nil)
1938
1951
  body = process body, level
1939
1952
 
1940
1953
  test = []
1941
- until arg.empty?
1942
- test << fragment(" || ", exp) unless test.empty?
1943
- a = arg.shift
1954
+ arg.each do |a|
1955
+ test << f(" || ") unless test.empty?
1944
1956
 
1945
1957
  if a.first == :splat # when inside another when means a splat of values
1946
- call = s(:call, s(:js_tmp, "$splt[i]"), :===, s(:arglist, s(:js_tmp, "$case")))
1947
- splt = [fragment("(function($splt) { for(var i = 0; i < $splt.length; i++) {", exp)]
1948
- splt << fragment("if (", exp) << process(call, :expr) << fragment(") { return true; }", exp)
1949
- splt << fragment("} return false; }).call(#{current_self}, ", exp)
1950
- splt << process(a[1], :expr) << fragment(")", exp)
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(")")
1951
1964
 
1952
1965
  test << splt
1953
1966
  else
1954
- call = s(:call, a, :===, s(:arglist, s(:js_tmp, "$case")))
1955
- call = process call, :expr
1956
-
1957
- test << call
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
1958
1973
  end
1959
1974
  end
1960
1975
 
1961
- [fragment("if (", exp), test, fragment(") {#@space", exp), body, fragment("#@space}", exp)]
1976
+ [f("if ("), test, f(") {#@space"), body, f("#@space}")]
1962
1977
  end
1963
1978
 
1964
1979
  # lhs =~ rhs
1965
1980
  #
1966
- # s(:match3, lhs, rhs)
1981
+ # s(:match3, lhs, rhs) # => s(:call, lhs, :=~, s(:arglist, rhs))
1967
1982
  def process_match3(sexp, level)
1968
- lhs = sexp[0]
1969
- rhs = sexp[1]
1970
- call = s(:call, lhs, :=~, s(:arglist, rhs))
1971
- process call, level
1983
+ process s(:call, sexp[0], :=~, s(:arglist, sexp[1])), level
1972
1984
  end
1973
1985
 
1974
1986
  # @@class_variable
@@ -1976,8 +1988,7 @@ module Opal
1976
1988
  # s(:cvar, name)
1977
1989
  def process_cvar(exp, level)
1978
1990
  with_temp do |tmp|
1979
- fragment(("((%s = Opal.cvars[%s]) == null ? nil : %s)" %
1980
- [tmp, exp.shift.to_s.inspect, tmp]), exp)
1991
+ f("((#{tmp} = $opal.cvars['#{exp[0]}']) == null ? nil : #{tmp})", exp)
1981
1992
  end
1982
1993
  end
1983
1994
 
@@ -1985,41 +1996,39 @@ module Opal
1985
1996
  #
1986
1997
  # s(:cvasgn, :@@name, rhs)
1987
1998
  def process_cvasgn(exp, level)
1988
- "(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expr})"
1999
+ "($opal.cvars['#{exp[0]}'] = #{process exp[1]})"
1989
2000
  end
1990
2001
 
2002
+ # s(:cvdecl, :@@foo, value) # => ($opal.cvars['@@foo'] = value)
1991
2003
  def process_cvdecl(exp, level)
1992
- [fragment("(Opal.cvars[#{exp.shift.to_s.inspect}] = ", exp), process(exp.shift, :expr), fragment(")", exp)]
2004
+ [f("($opal.cvars['#{exp[0]}'] = ", exp), process(exp[1]), f(")", exp)]
1993
2005
  end
1994
2006
 
1995
2007
  # BASE::NAME
1996
2008
  #
1997
2009
  # s(:colon2, base, :NAME)
1998
2010
  def process_colon2(sexp, level)
1999
- base = sexp[0]
2000
- cname = sexp[1].to_s
2011
+ base, cname = sexp
2001
2012
  result = []
2002
2013
 
2003
2014
  if @const_missing
2004
2015
  with_temp do |t|
2005
- base = process base, :expr
2016
+ base = process base
2006
2017
 
2007
- result << fragment("((#{t} = (", sexp) << base << fragment(")._scope).", sexp)
2008
- result << fragment("#{cname} == null ? #{t}.cm(#{cname.inspect}) : #{t}.#{cname})", sexp)
2018
+ result << f("((#{t} = (", sexp) << base << f(")._scope).", sexp)
2019
+ result << f("#{cname} == null ? #{t}.cm('#{cname}') : #{t}.#{cname})", sexp)
2009
2020
  end
2010
2021
  else
2011
- base = process base, :expr
2012
-
2013
- result << fragment("(", sexp) << base << fragment(")._scope.#{cname}", sexp)
2022
+ result << f("(", sexp) << process(base) << f(")._scope.#{cname}", sexp)
2014
2023
  end
2015
2024
 
2016
2025
  result
2017
2026
  end
2018
2027
 
2028
+ # s(:colon3, :CONST_NAME) # => $opal.Object._scope.CONST_NAME
2019
2029
  def process_colon3(exp, level)
2020
2030
  with_temp do |t|
2021
- cname = exp.shift.to_s
2022
- fragment("((#{t} = __opal.Object._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})", exp)
2031
+ f("((#{t} = $opal.Object._scope.#{exp[0]}) == null ? $opal.cm('#{exp[0]}') : #{t})", exp)
2023
2032
  end
2024
2033
  end
2025
2034
 
@@ -2028,46 +2037,68 @@ module Opal
2028
2037
  # s(:super, arg1, arg2, ...)
2029
2038
  def process_super(sexp, level)
2030
2039
  args = []
2031
- until sexp.empty?
2032
- args << fragment(", ", sexp) unless args.empty?
2033
- args << process(sexp.shift, :expr)
2040
+ sexp.each do |part|
2041
+ args << f(", ", sexp) unless args.empty?
2042
+ args << process(part)
2034
2043
  end
2035
2044
 
2036
- js_super [fragment("[", sexp), args, fragment("]", sexp)], sexp
2045
+ js_super [f("[", sexp), args, f("]", sexp)], false, sexp
2037
2046
  end
2038
2047
 
2039
2048
  # super
2040
2049
  #
2041
2050
  # s(:zsuper)
2042
2051
  def process_zsuper(exp, level)
2043
- js_super fragment("__slice.call(arguments)", exp), exp
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
2044
2058
  end
2045
2059
 
2046
- def js_super args, sexp
2060
+ def js_super args, pass_block, sexp
2047
2061
  if @scope.def_in_class?
2062
+ @scope.uses_block!
2048
2063
  mid = @scope.mid.to_s
2049
- sid = "super_#{unique_temp}"
2050
2064
 
2051
- @scope.uses_super = sid
2065
+ if @scope.uses_super
2066
+ sid = @scope.uses_super
2067
+ else
2068
+ sid = @scope.uses_super = "super_#{unique_temp}"
2069
+ end
2052
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
2053
2077
 
2054
- [fragment("#{sid}.apply(#{current_self}, ", sexp), args, fragment(")", sexp)]
2055
2078
 
2056
2079
  elsif @scope.type == :def
2080
+ @scope.uses_block!
2057
2081
  @scope.identify!
2058
2082
  cls_name = @scope.parent.name || "#{current_self}._klass._proto"
2059
2083
  jsid = mid_to_jsid @scope.mid.to_s
2060
2084
 
2085
+ if pass_block
2086
+ @scope.uses_block!
2087
+ iter = "$iter"
2088
+ else
2089
+ iter = "null"
2090
+ end
2091
+
2061
2092
  if @scope.defs
2062
- [fragment(("%s._super%s.apply(this, " % [cls_name, jsid]), sexp), args, fragment(")", sexp)]
2093
+ [f("$opal.dispatch_super(this, #{@scope.mid.to_s.inspect},", sexp), args, f(", #{iter}, #{cls_name})", sexp)]
2063
2094
  else
2064
- [fragment("#{current_self}._klass._super._proto#{jsid}.apply(#{current_self}, ", sexp), args, fragment(")", sexp)]
2095
+ [f("$opal.dispatch_super(#{current_self}, #{@scope.mid.to_s.inspect}, ", sexp), args, f(", #{iter})", sexp)]
2065
2096
  end
2066
2097
 
2067
2098
  elsif @scope.type == :iter
2068
2099
  chain, defn, mid = @scope.get_super_chain
2069
2100
  trys = chain.map { |c| "#{c}._sup" }.join ' || '
2070
- [fragment("(#{trys} || #{current_self}._klass._super._proto[#{mid}]).apply(#{current_self}, ", sexp), args, fragment(")", sexp)]
2101
+ [f("(#{trys} || #{current_self}._klass._super._proto[#{mid}]).apply(#{current_self}, ", sexp), args, f(")", sexp)]
2071
2102
  else
2072
2103
  raise "Cannot call super() from outside a method block"
2073
2104
  end
@@ -2077,14 +2108,14 @@ module Opal
2077
2108
  #
2078
2109
  # s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, rhs))
2079
2110
  def process_op_asgn_or(exp, level)
2080
- process s(:or, exp.shift, exp.shift), :expr
2111
+ process s(:or, exp[0], exp[1])
2081
2112
  end
2082
2113
 
2083
2114
  # a &&= rhs
2084
2115
  #
2085
2116
  # s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, rhs))
2086
2117
  def process_op_asgn_and(sexp, level)
2087
- process s(:and, sexp.shift, sexp.shift), :expr
2118
+ process s(:and, sexp[0], sexp[1])
2088
2119
  end
2089
2120
 
2090
2121
  # lhs[args] ||= rhs
@@ -2095,17 +2126,17 @@ module Opal
2095
2126
 
2096
2127
  with_temp do |a| # args
2097
2128
  with_temp do |r| # recv
2098
- args = process arglist[1], :expr
2099
- recv = process lhs, :expr
2129
+ args = process arglist[1]
2130
+ recv = process lhs
2100
2131
 
2101
2132
  aref = s(:call, s(:js_tmp, r), :[], s(:arglist, s(:js_tmp, a)))
2102
2133
  aset = s(:call, s(:js_tmp, r), :[]=, s(:arglist, s(:js_tmp, a), rhs))
2103
2134
  orop = s(:or, aref, aset)
2104
2135
 
2105
2136
  result = []
2106
- result << fragment("(#{a} = ", sexp) << args << fragment(", #{r} = ", sexp)
2107
- result << recv << fragment(", ", sexp) << process(orop, :expr)
2108
- result << fragment(")", sexp)
2137
+ result << f("(#{a} = ", sexp) << args << f(", #{r} = ", sexp)
2138
+ result << recv << f(", ", sexp) << process(orop)
2139
+ result << f(")", sexp)
2109
2140
  result
2110
2141
  end
2111
2142
  end
@@ -2115,10 +2146,10 @@ module Opal
2115
2146
  #
2116
2147
  # s(:op_asgn2, lhs, :b=, :+, rhs)
2117
2148
  def process_op_asgn2(sexp, level)
2118
- lhs = process sexp.shift, :expr
2119
- mid = sexp.shift.to_s[0..-2]
2120
- op = sexp.shift
2121
- rhs = sexp.shift
2149
+ lhs = process sexp[0]
2150
+ mid = sexp[1].to_s[0..-2]
2151
+ op = sexp[2]
2152
+ rhs = sexp[3]
2122
2153
 
2123
2154
  if op.to_s == "||"
2124
2155
  with_temp do |temp|
@@ -2126,7 +2157,7 @@ module Opal
2126
2157
  asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
2127
2158
  orop = s(:or, getr, asgn)
2128
2159
 
2129
- [fragment("(#{temp} = ", sexp), lhs, fragment(", ", sexp), process(orop, :expr), fragment(")", sexp)]
2160
+ [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(orop), f(")", sexp)]
2130
2161
  end
2131
2162
  elsif op.to_s == '&&'
2132
2163
  with_temp do |temp|
@@ -2134,7 +2165,7 @@ module Opal
2134
2165
  asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
2135
2166
  andop = s(:and, getr, asgn)
2136
2167
 
2137
- [fragment("(#{temp} = ", sexp), lhs, fragment(", ", sexp), process(andop, :expr), fragment(")", sexp)]
2168
+ [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(andop), f(")", sexp)]
2138
2169
  end
2139
2170
  else
2140
2171
  with_temp do |temp|
@@ -2142,14 +2173,14 @@ module Opal
2142
2173
  oper = s(:call, getr, op, s(:arglist, rhs))
2143
2174
  asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, oper))
2144
2175
 
2145
- [fragment("(#{temp} = ", sexp), lhs, fragment(", ", sexp), process(asgn, :expr), fragment(")", sexp)]
2176
+ [f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(asgn), f(")", sexp)]
2146
2177
  end
2147
2178
  end
2148
2179
  end
2149
2180
 
2150
2181
  # s(:ensure, body, ensure)
2151
2182
  def process_ensure(exp, level)
2152
- begn = exp.shift
2183
+ begn = exp[0]
2153
2184
  if level == :recv || level == :expr
2154
2185
  retn = true
2155
2186
  begn = returns begn
@@ -2157,49 +2188,49 @@ module Opal
2157
2188
 
2158
2189
  result = []
2159
2190
  body = process begn, level
2160
- ensr = exp.shift || s(:nil)
2191
+ ensr = exp[1] || s(:nil)
2161
2192
  ensr = process ensr, level
2162
2193
 
2163
- body = [fragment("try {\n", exp), body, fragment("}", exp)]
2194
+ body = [f("try {\n", exp), body, f("}", exp)]
2164
2195
 
2165
- result << body << fragment("#{@space}finally {#@space", exp) << ensr << fragment("}", exp)
2196
+ result << body << f("#{@space}finally {#@space", exp) << ensr << f("}", exp)
2166
2197
 
2167
2198
  if retn
2168
- [fragment("(function() { ", exp), result, fragment("; }).call(#{current_self})", exp)]
2199
+ [f("(function() { ", exp), result, f("; }).call(#{current_self})", exp)]
2169
2200
  else
2170
2201
  result
2171
2202
  end
2172
2203
  end
2173
2204
 
2174
2205
  def process_rescue(exp, level)
2175
- body = exp.first.first == :resbody ? s(:nil) : exp.shift
2206
+ body = exp.first.first == :resbody ? s(:nil) : exp[0]
2176
2207
  body = indent { process body, level }
2177
2208
  handled_else = false
2178
2209
 
2179
2210
  parts = []
2180
- until exp.empty?
2181
- handled_else = true unless exp.first.first == :resbody
2182
- part = indent { process exp.shift, level }
2211
+ exp[1..-1].each do |a|
2212
+ handled_else = true unless a.first == :resbody
2213
+ part = indent { process a, level }
2183
2214
 
2184
2215
  unless parts.empty?
2185
- parts << fragment("else ", exp)
2216
+ parts << f("else ", exp)
2186
2217
  end
2187
2218
 
2188
2219
  parts << part
2189
2220
  end
2190
2221
  # if no rescue statement captures our error, we should rethrow
2191
- parts << indent { fragment("else { throw $err; }", exp) } unless handled_else
2222
+ parts << indent { f("else { throw $err; }", exp) } unless handled_else
2192
2223
 
2193
2224
  code = []
2194
- code << fragment("try {#@space#{INDENT}", exp)
2225
+ code << f("try {#@space#{INDENT}", exp)
2195
2226
  code << body
2196
- code << fragment("#@space} catch ($err) {#@space", exp)
2227
+ code << f("#@space} catch ($err) {#@space", exp)
2197
2228
  code << parts
2198
- code << fragment("#@space}", exp)
2229
+ code << f("#@space}", exp)
2199
2230
 
2200
2231
  if level == :expr
2201
- code.unshift fragment("(function() { ", exp)
2202
- code << fragment(" }).call(#{current_self})", exp)
2232
+ code.unshift f("(function() { ", exp)
2233
+ code << f(" }).call(#{current_self})", exp)
2203
2234
  end
2204
2235
 
2205
2236
  code
@@ -2215,49 +2246,52 @@ module Opal
2215
2246
 
2216
2247
  err = []
2217
2248
  types.each do |t|
2218
- err << fragment(", ", exp) unless err.empty?
2249
+ err << f(", ", exp) unless err.empty?
2219
2250
  call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
2220
- a = process call, :expr
2251
+ a = process call
2221
2252
  err << a
2222
2253
  end
2223
- err << fragment("true", exp) if err.empty?
2254
+ err << f("true", exp) if err.empty?
2224
2255
 
2225
2256
  if Array === args.last and [:lasgn, :iasgn].include? args.last.first
2226
2257
  val = args.last
2227
2258
  val[2] = s(:js_tmp, "$err")
2228
- val = [process(val, :expr) , fragment(";", exp)]
2259
+ val = [process(val) , f(";", exp)]
2229
2260
  end
2230
2261
 
2231
2262
  val = [] unless val
2232
2263
 
2233
- [fragment("if (", exp), err, fragment("){#@space", exp), val, body, fragment("}", exp)]
2264
+ [f("if (", exp), err, f("){#@space", exp), val, body, f("}", exp)]
2234
2265
  end
2235
2266
 
2236
2267
  # FIXME: Hack.. grammar should remove top level begin.
2237
2268
  def process_begin(exp, level)
2238
- result = process exp[0], level
2269
+ process exp[0], level
2239
2270
  end
2240
2271
 
2241
2272
  def process_next(exp, level)
2242
2273
  if in_while?
2243
- fragment("continue;", exp)
2274
+ f("continue;", exp)
2244
2275
  else
2245
2276
  result = []
2246
- result << fragment("return ", exp)
2277
+ result << f("return ", exp)
2247
2278
 
2248
- result << (exp.empty? ? fragment('nil', exp) : process(exp.shift, :expr))
2249
- result << fragment(";", exp)
2279
+ result << (exp.empty? ? f('nil', exp) : process(exp[0]))
2280
+ result << f(";", exp)
2250
2281
 
2251
2282
  result
2252
2283
  end
2253
2284
  end
2254
2285
 
2286
+ # s(:redo) # => $redo_var = true
2287
+ # Only currently supported inside while loops. Simply sets the redo variable
2288
+ # for the loop to true.
2255
2289
  def process_redo(exp, level)
2256
2290
  if in_while?
2257
2291
  @while_loop[:use_redo] = true
2258
- fragment("#{@while_loop[:redo_var]} = true", exp)
2292
+ f("#{@while_loop[:redo_var]} = true", exp)
2259
2293
  else
2260
- fragment("REDO()", exp)
2294
+ f("REDO()", exp)
2261
2295
  end
2262
2296
  end
2263
2297
  end