opal 0.3.18 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +1 -3
  3. data/README.md +472 -10
  4. data/Rakefile +10 -52
  5. data/core/array.rb +9 -14
  6. data/core/basic_object.rb +7 -10
  7. data/core/boolean.rb +5 -1
  8. data/core/class.rb +15 -38
  9. data/core/dir.rb +89 -0
  10. data/core/enumerable.rb +133 -57
  11. data/core/error.rb +15 -1
  12. data/core/file.rb +85 -0
  13. data/core/hash.rb +186 -32
  14. data/core/kernel.rb +30 -31
  15. data/core/load_order +4 -2
  16. data/core/module.rb +42 -62
  17. data/core/numeric.rb +7 -1
  18. data/core/object.rb +1 -1
  19. data/core/proc.rb +6 -2
  20. data/core/range.rb +16 -28
  21. data/core/regexp.rb +3 -3
  22. data/core/runtime.js +281 -350
  23. data/core/string.rb +100 -110
  24. data/docs/CNAME +1 -0
  25. data/docs/Rakefile +55 -0
  26. data/docs/css/styles.css +50 -0
  27. data/docs/css/syntax.css +63 -0
  28. data/docs/layout/post.html +3 -0
  29. data/docs/layout/pre.html +11 -0
  30. data/examples/dependencies/app.rb +3 -0
  31. data/lib/opal.rb +2 -1
  32. data/lib/opal/builder.rb +36 -10
  33. data/lib/opal/builder_task.rb +51 -24
  34. data/lib/opal/grammar.rb +2509 -2439
  35. data/lib/opal/grammar.y +38 -5
  36. data/lib/opal/lexer.rb +18 -2
  37. data/lib/opal/parser.rb +375 -349
  38. data/lib/opal/scope.rb +24 -2
  39. data/lib/opal/version.rb +1 -1
  40. data/spec/builder/build_order_spec.rb +20 -0
  41. data/spec/builder/lib_name_for_spec.rb +24 -0
  42. data/spec/grammar/call_spec.rb +9 -6
  43. data/spec/grammar/lambda_spec.rb +64 -0
  44. data/spec/grammar/sclass_spec.rb +5 -3
  45. data/{core/spec → test}/core/array/allocate_spec.rb +0 -0
  46. data/{core/spec → test}/core/array/append_spec.rb +0 -0
  47. data/{core/spec → test}/core/array/assoc_spec.rb +0 -0
  48. data/{core/spec → test}/core/array/at_spec.rb +0 -0
  49. data/{core/spec → test}/core/array/clear_spec.rb +0 -0
  50. data/{core/spec → test}/core/array/clone_spec.rb +0 -0
  51. data/{core/spec → test}/core/array/collect_spec.rb +0 -0
  52. data/{core/spec → test}/core/array/compact_spec.rb +0 -0
  53. data/{core/spec → test}/core/array/concat_spec.rb +0 -0
  54. data/{core/spec → test}/core/array/constructor_spec.rb +0 -0
  55. data/{core/spec → test}/core/array/count_spec.rb +0 -0
  56. data/{core/spec → test}/core/array/delete_at_spec.rb +0 -0
  57. data/{core/spec → test}/core/array/delete_if_spec.rb +0 -0
  58. data/{core/spec → test}/core/array/delete_spec.rb +0 -0
  59. data/{core/spec → test}/core/array/each_index_spec.rb +0 -0
  60. data/{core/spec → test}/core/array/each_spec.rb +0 -0
  61. data/{core/spec → test}/core/array/element_reference_spec.rb +0 -0
  62. data/{core/spec → test}/core/array/empty_spec.rb +0 -0
  63. data/{core/spec → test}/core/array/eql_spec.rb +0 -0
  64. data/{core/spec → test}/core/array/fetch_spec.rb +0 -0
  65. data/{core/spec → test}/core/array/first_spec.rb +0 -0
  66. data/{core/spec → test}/core/array/flatten_spec.rb +0 -0
  67. data/{core/spec → test}/core/array/include_spec.rb +0 -0
  68. data/{core/spec → test}/core/array/insert_spec.rb +0 -0
  69. data/{core/spec → test}/core/array/last_spec.rb +0 -0
  70. data/{core/spec → test}/core/array/length_spec.rb +0 -0
  71. data/{core/spec → test}/core/array/map_spec.rb +0 -0
  72. data/{core/spec → test}/core/array/plus_spec.rb +0 -0
  73. data/{core/spec → test}/core/array/pop_spec.rb +0 -0
  74. data/{core/spec → test}/core/array/push_spec.rb +0 -0
  75. data/{core/spec → test}/core/array/rassoc_spec.rb +0 -0
  76. data/{core/spec → test}/core/array/reject_spec.rb +0 -0
  77. data/{core/spec → test}/core/array/replace_spec.rb +0 -0
  78. data/{core/spec → test}/core/array/reverse_each_spec.rb +0 -0
  79. data/{core/spec → test}/core/array/reverse_spec.rb +0 -0
  80. data/{core/spec → test}/core/array/size_spec.rb +0 -0
  81. data/{core/spec → test}/core/array/to_ary_spec.rb +0 -0
  82. data/{core/spec → test}/core/array/uniq_spec.rb +0 -0
  83. data/{core/spec → test}/core/array/zip_spec.rb +0 -0
  84. data/test/core/class/fixtures/classes.rb +9 -0
  85. data/test/core/class/new_spec.rb +108 -0
  86. data/{core/spec → test}/core/enumerable/all_spec.rb +0 -0
  87. data/{core/spec → test}/core/enumerable/any_spec.rb +0 -0
  88. data/{core/spec → test}/core/enumerable/collect_spec.rb +0 -0
  89. data/{core/spec → test}/core/enumerable/count_spec.rb +0 -0
  90. data/test/core/enumerable/detect_spec.rb +48 -0
  91. data/test/core/enumerable/drop_spec.rb +17 -0
  92. data/test/core/enumerable/drop_while_spec.rb +24 -0
  93. data/test/core/enumerable/each_with_index_spec.rb +11 -0
  94. data/test/core/enumerable/each_with_object_spec.rb +17 -0
  95. data/test/core/enumerable/entries_spec.rb +6 -0
  96. data/test/core/enumerable/find_all_spec.rb +13 -0
  97. data/test/core/enumerable/find_index_spec.rb +45 -0
  98. data/test/core/enumerable/find_spec.rb +48 -0
  99. data/test/core/enumerable/first_spec.rb +40 -0
  100. data/{core/spec → test}/core/enumerable/fixtures/classes.rb +19 -0
  101. data/test/core/enumerable/grep_spec.rb +21 -0
  102. data/test/core/enumerable/take_spec.rb +40 -0
  103. data/test/core/enumerable/to_a_spec.rb +6 -0
  104. data/{core/spec → test}/core/false/and_spec.rb +0 -0
  105. data/{core/spec → test}/core/false/inspect_spec.rb +0 -0
  106. data/{core/spec → test}/core/false/or_spec.rb +0 -0
  107. data/{core/spec → test}/core/false/to_s_spec.rb +0 -0
  108. data/{core/spec → test}/core/false/xor_spec.rb +0 -0
  109. data/test/core/file/expand_path_spec.rb +20 -0
  110. data/{core/spec → test}/core/hash/allocate_spec.rb +0 -0
  111. data/{core/spec → test}/core/hash/assoc_spec.rb +0 -0
  112. data/{core/spec → test}/core/hash/clear_spec.rb +0 -0
  113. data/{core/spec → test}/core/hash/clone_spec.rb +0 -0
  114. data/test/core/hash/default_spec.rb +9 -0
  115. data/{core/spec → test}/core/hash/delete_if_spec.rb +0 -0
  116. data/test/core/hash/each_key_spec.rb +15 -0
  117. data/test/core/hash/each_pair_spec.rb +30 -0
  118. data/test/core/hash/each_spec.rb +30 -0
  119. data/test/core/hash/each_value_spec.rb +15 -0
  120. data/{core/spec → test}/core/hash/element_reference_spec.rb +14 -0
  121. data/{core/spec → test}/core/hash/element_set_spec.rb +1 -0
  122. data/test/core/hash/empty_spec.rb +10 -0
  123. data/test/core/hash/fetch_spec.rb +24 -0
  124. data/test/core/hash/flatten_spec.rb +46 -0
  125. data/test/core/hash/has_key_spec.rb +24 -0
  126. data/test/core/hash/has_value_spec.rb +12 -0
  127. data/test/core/hash/include_spec.rb +24 -0
  128. data/test/core/hash/index_spec.rb +13 -0
  129. data/test/core/hash/indexes_spec.rb +9 -0
  130. data/test/core/hash/indices_spec.rb +9 -0
  131. data/test/core/hash/invert_spec.rb +12 -0
  132. data/test/core/hash/keep_if_spec.rb +18 -0
  133. data/test/core/hash/key_spec.rb +24 -0
  134. data/test/core/hash/keys_spec.rb +10 -0
  135. data/test/core/hash/length_spec.rb +10 -0
  136. data/test/core/hash/member_spec.rb +24 -0
  137. data/{core/spec → test}/core/hash/merge_spec.rb +0 -0
  138. data/{core/spec → test}/core/hash/new_spec.rb +0 -0
  139. data/test/core/hash/rassoc_spec.rb +34 -0
  140. data/test/core/hash/replace_spec.rb +7 -0
  141. data/test/core/hash/select_spec.rb +52 -0
  142. data/test/core/hash/shift_spec.rb +19 -0
  143. data/test/core/hash/size_spec.rb +10 -0
  144. data/test/core/hash/update_spec.rb +17 -0
  145. data/test/core/hash/value_spec.rb +12 -0
  146. data/test/core/hash/values_at_spec.rb +9 -0
  147. data/test/core/hash/values_spec.rb +7 -0
  148. data/test/core/kernel/eql_spec.rb +15 -0
  149. data/test/core/kernel/equal_value_spec.rb +12 -0
  150. data/test/core/kernel/loop_spec.rb +23 -0
  151. data/test/core/kernel/nil_spec.rb +7 -0
  152. data/test/core/kernel/proc_spec.rb +9 -0
  153. data/test/core/kernel/rand_spec.rb +14 -0
  154. data/test/core/kernel/respond_to_spec.rb +24 -0
  155. data/test/core/kernel/send_spec.rb +56 -0
  156. data/test/core/kernel/tap_spec.rb +10 -0
  157. data/test/core/kernel/to_s_spec.rb +5 -0
  158. data/{core/spec → test}/core/matchdata/to_a_spec.rb +0 -0
  159. data/{core/spec → test}/core/nil/and_spec.rb +0 -0
  160. data/{core/spec → test}/core/nil/inspect_spec.rb +0 -0
  161. data/{core/spec → test}/core/nil/nil_spec.rb +0 -0
  162. data/{core/spec → test}/core/nil/or_spec.rb +0 -0
  163. data/{core/spec → test}/core/nil/to_a_spec.rb +0 -0
  164. data/{core/spec → test}/core/nil/to_f_spec.rb +0 -0
  165. data/{core/spec → test}/core/nil/to_i_spec.rb +0 -0
  166. data/{core/spec → test}/core/nil/to_s_spec.rb +0 -0
  167. data/{core/spec → test}/core/nil/xor_spec.rb +0 -0
  168. data/{core/spec → test}/core/numeric/equal_value_spec.rb +0 -0
  169. data/test/core/range/begin_spec.rb +9 -0
  170. data/test/core/range/case_compare_spec.rb +16 -0
  171. data/test/core/range/end_spec.rb +9 -0
  172. data/{core/spec → test}/core/regexp/match_spec.rb +0 -0
  173. data/test/core/string/capitalize_spec.rb +10 -0
  174. data/test/core/string/casecmp_spec.rb +16 -0
  175. data/test/core/string/chomp_spec.rb +43 -0
  176. data/test/core/string/chop_spec.rb +10 -0
  177. data/test/core/string/chr_spec.rb +13 -0
  178. data/test/core/string/comparison_spec.rb +13 -0
  179. data/test/core/string/downcase_spec.rb +6 -0
  180. data/test/core/string/element_reference_spec.rb +72 -0
  181. data/test/core/string/empty_spec.rb +8 -0
  182. data/test/core/string/end_with_spec.rb +12 -0
  183. data/test/core/string/fixtures/classes.rb +3 -0
  184. data/test/core/string/gsub_spec.rb +17 -0
  185. data/test/core/string/include_spec.rb +12 -0
  186. data/test/core/string/intern_spec.rb +9 -0
  187. data/test/core/string/length_spec.rb +9 -0
  188. data/test/core/string/lstrip_spec.rb +7 -0
  189. data/test/core/string/match_spec.rb +27 -0
  190. data/test/core/string/next_spec.rb +10 -0
  191. data/test/core/string/ord_spec.rb +9 -0
  192. data/test/core/string/partition_spec.rb +10 -0
  193. data/test/core/string/reverse_spec.rb +7 -0
  194. data/test/core/string/rstrip_spec.rb +7 -0
  195. data/test/core/string/size_spec.rb +9 -0
  196. data/test/core/string/slice_spec.rb +72 -0
  197. data/test/core/string/split_spec.rb +5 -0
  198. data/test/core/string/start_with_spec.rb +12 -0
  199. data/test/core/string/strip_spec.rb +6 -0
  200. data/test/core/string/sub_spec.rb +22 -0
  201. data/test/core/string/succ_spec.rb +10 -0
  202. data/test/core/string/sum_spec.rb +5 -0
  203. data/test/core/string/swapcase_spec.rb +18 -0
  204. data/test/core/string/to_a_spec.rb +9 -0
  205. data/test/core/string/to_f_spec.rb +14 -0
  206. data/test/core/string/to_i_spec.rb +25 -0
  207. data/test/core/string/to_s_spec.rb +13 -0
  208. data/test/core/string/to_str_spec.rb +13 -0
  209. data/test/core/string/to_sym_spec.rb +9 -0
  210. data/test/core/string/upcase_spec.rb +6 -0
  211. data/test/core/symbol/to_proc_spec.rb +12 -0
  212. data/{core/spec → test}/core/true/and_spec.rb +0 -0
  213. data/{core/spec → test}/core/true/inspect_spec.rb +0 -0
  214. data/{core/spec → test}/core/true/or_spec.rb +0 -0
  215. data/{core/spec → test}/core/true/to_s_spec.rb +0 -0
  216. data/{core/spec → test}/core/true/xor_spec.rb +0 -0
  217. data/test/index.html +11 -0
  218. data/{core/spec → test}/language/alias_spec.rb +4 -0
  219. data/{core/spec → test}/language/and_spec.rb +0 -0
  220. data/{core/spec → test}/language/array_spec.rb +0 -0
  221. data/{core/spec → test}/language/block_spec.rb +0 -0
  222. data/{core/spec → test}/language/break_spec.rb +0 -0
  223. data/{core/spec → test}/language/case_spec.rb +0 -0
  224. data/{core/spec → test}/language/defined_spec.rb +0 -0
  225. data/{core/spec → test}/language/ensure_spec.rb +0 -0
  226. data/test/language/fixtures/yield.rb +23 -0
  227. data/{core/spec → test}/language/hash_spec.rb +0 -0
  228. data/{core/spec → test}/language/if_spec.rb +0 -0
  229. data/test/language/literal_lambda_spec.rb +47 -0
  230. data/{core/spec → test}/language/loop_spec.rb +0 -0
  231. data/{core/spec → test}/language/metaclass_spec.rb +0 -0
  232. data/{core/spec → test}/language/next_spec.rb +0 -0
  233. data/{core/spec → test}/language/or_spec.rb +0 -0
  234. data/{core/spec → test}/language/predefined_spec.rb +0 -0
  235. data/{core/spec → test}/language/regexp_spec.rb +0 -0
  236. data/{core/spec → test}/language/send_spec.rb +0 -0
  237. data/{core/spec → test}/language/singleton_class_spec.rb +0 -0
  238. data/{core/spec → test}/language/super_spec.rb +0 -0
  239. data/{core/spec → test}/language/symbol_spec.rb +0 -0
  240. data/{core/spec → test}/language/undef_spec.rb +0 -0
  241. data/{core/spec → test}/language/unless_spec.rb +0 -0
  242. data/{core/spec → test}/language/until_spec.rb +0 -0
  243. data/{core/spec → test}/language/variables_spec.rb +0 -0
  244. data/{core/spec → test}/language/while_spec.rb +0 -0
  245. data/test/language/yield_spec.rb +100 -0
  246. data/test/opal/array/subclassing_spec.rb +32 -0
  247. data/test/opal/class/bridge_class_spec.rb +37 -0
  248. data/test/opal/exception/subclassing_spec.rb +17 -0
  249. data/test/opal/runtime/_methods_spec.rb +48 -0
  250. data/test/opal/runtime/class_hierarchy_spec.rb +22 -0
  251. data/test/opal/runtime/def_spec.rb +23 -0
  252. data/test/opal/string/subclassing_spec.rb +26 -0
  253. data/test/spec_helper.rb +3 -0
  254. metadata +437 -111
  255. data/core/spec/core/class/new_spec.rb +0 -16
  256. data/core/spec/core/hash/default_spec.rb +0 -4
  257. data/core/spec/core/symbol/to_proc_spec.rb +0 -6
  258. data/core/spec/index.html +0 -11
  259. data/spec/builder/build_source_spec.rb +0 -52
@@ -14,7 +14,7 @@ token CLASS MODULE DEF UNDEF BEGIN RESCUE ENSURE END IF UNLESS
14
14
  '~' '%' '/' '+' '-' '<' '>' '|' '!' '^'
15
15
  LCURLY '}' BACK_REF2 SYMBOL_BEG STRING_BEG XSTRING_BEG REGEXP_BEG
16
16
  WORDS_BEG AWORDS_BEG STRING_DBEG STRING_DVAR STRING_END STRING
17
- SYMBOL '\\n' '?' ':' ',' SPACE ';' LABEL
17
+ SYMBOL '\\n' '?' ':' ',' SPACE ';' LABEL LAMBDA LAMBEG DO_LAMBDA
18
18
 
19
19
  prechigh
20
20
  right '!' '~' '+@'
@@ -453,19 +453,19 @@ arg:
453
453
  }
454
454
  | arg '+' arg
455
455
  {
456
- result = new_call val[0], :"+", s(:arglist, val[2])
456
+ result = s(:operator, :"+", val[0], val[2])
457
457
  }
458
458
  | arg '-' arg
459
459
  {
460
- result = new_call val[0], :"-", s(:arglist, val[2])
460
+ result = s(:operator, :"-", val[0], val[2])
461
461
  }
462
462
  | arg '*' arg
463
463
  {
464
- result = new_call val[0], :"*", s(:arglist, val[2])
464
+ result = s(:operator, :"*", val[0], val[2])
465
465
  }
466
466
  | arg '/' arg
467
467
  {
468
- result = new_call val[0], :"/", s(:arglist, val[2])
468
+ result = s(:operator, :"/", val[0], val[2])
469
469
  }
470
470
  | arg '%' arg
471
471
  {
@@ -784,6 +784,10 @@ primary:
784
784
  result = val[1]
785
785
  result[1] = val[0]
786
786
  }
787
+ | LAMBDA lambda
788
+ {
789
+ result = val[1]
790
+ }
787
791
  | IF expr_value then compstmt if_tail END
788
792
  {
789
793
  result = new_if val[1], val[3], val[4]
@@ -937,6 +941,35 @@ do:
937
941
  | ':'
938
942
  | DO_COND
939
943
 
944
+ lambda:
945
+ f_larglist lambda_body
946
+ {
947
+ call = new_call nil, :lambda, s(:arglist)
948
+ result = new_iter call, val[0], val[1]
949
+ }
950
+
951
+ f_larglist:
952
+ '(' block_var_args ')'
953
+ {
954
+ result = val[1]
955
+ }
956
+ | '(' ')'
957
+ {
958
+ result = nil
959
+ }
960
+ | block_var_args
961
+ | none
962
+
963
+ lambda_body:
964
+ LAMBEG compstmt '}'
965
+ {
966
+ result = val[1]
967
+ }
968
+ | DO_LAMBDA compstmt END
969
+ {
970
+ result = val[1]
971
+ }
972
+
940
973
  if_tail:
941
974
  opt_else
942
975
  {
@@ -617,6 +617,8 @@ module Opal
617
617
  else
618
618
  c = if scanner.scan(/n/)
619
619
  "\n"
620
+ elsif scanner.scan(/r/)
621
+ "\r"
620
622
  else
621
623
  # escaped char doesnt need escaping, so just return it
622
624
  scanner.scan(/./)
@@ -985,6 +987,11 @@ module Opal
985
987
  return '>', '>'
986
988
  end
987
989
 
990
+ elsif scanner.scan(/->/)
991
+ @lex_state = :expr_arg
992
+ @start_of_lambda = true
993
+ return [:LAMBDA, scanner.matched]
994
+
988
995
  elsif scanner.scan(/[+-]/)
989
996
  result = scanner.matched
990
997
  sign = result + '@'
@@ -1110,7 +1117,12 @@ module Opal
1110
1117
  return ',', scanner.matched
1111
1118
 
1112
1119
  elsif scanner.scan(/\{/)
1113
- if [:expr_end, :expr_arg, :expr_cmdarg].include? @lex_state
1120
+ if @start_of_lambda
1121
+ @start_of_lambda = false
1122
+ @lex_state = :expr_beg
1123
+ return [:LAMBEG, scanner.matched]
1124
+
1125
+ elsif [:expr_end, :expr_arg, :expr_cmdarg].include? @lex_state
1114
1126
  result = :LCURLY
1115
1127
  elsif @lex_state == :expr_endarg
1116
1128
  result = :LBRACE_ARG
@@ -1183,7 +1195,11 @@ module Opal
1183
1195
  #puts cond?
1184
1196
  #puts cmdarg?
1185
1197
  #nputs @lex_state
1186
- if cond?
1198
+ if @start_of_lambda
1199
+ @start_of_lambda = false
1200
+ @lex_state = :expr_beg
1201
+ return [:DO_LAMBDA, scanner.matched]
1202
+ elsif cond?
1187
1203
  @lex_state = :expr_beg
1188
1204
  return :DO_COND, matched
1189
1205
  elsif cmdarg? && @lex_state != :expr_cmdarg
@@ -13,16 +13,9 @@ module Opal
13
13
  class Parser
14
14
  INDENT = ' '
15
15
 
16
- LEVEL = [:statement, :statement_closure, :list, :expression, :receiver]
16
+ LEVEL = [:stmt, :stmt_closure, :list, :expr, :recv]
17
17
 
18
- # Maths operators
19
- MATH = %w(+ - / * %)
20
-
21
- # Comparison operators
22
- COMPARE = %w(< <= > >=)
23
-
24
- # All Operators that can be optimized in method calls
25
- CALL_OPERATORS = MATH + COMPARE
18
+ COMPARE = %w[< > <= >=]
26
19
 
27
20
  # Reserved javascript keywords - we cannot create variables with the
28
21
  # same name
@@ -60,25 +53,40 @@ module Opal
60
53
  :** => 'pow'
61
54
  }
62
55
 
63
- # Type info for flags of objects. This helps identify the type of object
64
- # being dealt with
65
- TYPES = {
66
- class: 0x0001,
67
- module: 0x0002,
68
- object: 0x0004,
69
- boolean: 0x0008,
70
- string: 0x0010,
71
- array: 0x0020,
72
- number: 0x0040,
73
- proc: 0x0080,
74
- hash: 0x0100,
75
- range: 0x0200,
76
- iclass: 0x0400,
77
- singleton: 0x0800
78
- }
79
-
80
56
  STATEMENTS = [:xstr, :dxstr]
81
57
 
58
+ DEBUG_CODE = <<-CODE
59
+ var __const_get = function(const_table, id) {
60
+ if (const_table && const_table[id]) {
61
+ return const_table[id];
62
+ }
63
+
64
+ throw new Error('uninitialized constant ' + id);
65
+ };
66
+
67
+ var __send = function(recv, mid, jsid, block) {
68
+ var args = Array.prototype.slice.call(arguments, 4);
69
+
70
+ if (recv == null) {
71
+ throw new Error("cannot send '" + mid + "' to null");
72
+ }
73
+
74
+ var func = recv[jsid];
75
+
76
+ if (!func) {
77
+ throw new Error(recv + " does not respond to '" + mid + "'");
78
+ }
79
+
80
+ func._p = block;
81
+
82
+ return func.apply(recv, args);
83
+ };
84
+
85
+ var __send_splat = function(recv, mid, jsid, block, splat) {
86
+ return __send.apply(null, [recv, mid, jsid, block].concat(splat));
87
+ };
88
+ CODE
89
+
82
90
  attr_reader :grammar
83
91
 
84
92
  def self.parse(str)
@@ -90,13 +98,10 @@ module Opal
90
98
  end
91
99
 
92
100
  def parse(source, file = '(file)')
93
- @file = file
94
- @helpers = {
101
+ @file = file
102
+ @helpers = {
95
103
  :breaker => true,
96
- :klass => true,
97
- :const_get => true,
98
104
  :slice => true
99
- # :nil => true
100
105
  }
101
106
 
102
107
  @grammar = Grammar.new
@@ -104,6 +109,14 @@ module Opal
104
109
  top @grammar.parse(source, file)
105
110
  end
106
111
 
112
+ def raise(msg)
113
+ super "#{msg} :#{@file}:#{@line}"
114
+ end
115
+
116
+ def parser_indent
117
+ @indent
118
+ end
119
+
107
120
  def s(*parts)
108
121
  sexp = parts
109
122
  sexp.line = @line
@@ -126,7 +139,7 @@ module Opal
126
139
 
127
140
  # guaranteed unique id per file..
128
141
  def unique_temp
129
- "$TMP_#{@unique += 1}"
142
+ "TMP_#{@unique += 1}"
130
143
  end
131
144
 
132
145
  def top(sexp, options = {})
@@ -135,30 +148,30 @@ module Opal
135
148
 
136
149
  in_scope(:top) do
137
150
  indent {
138
- code = @indent + process(s(:scope, sexp), :statement)
151
+ code = @indent + process(s(:scope, sexp), :stmt)
139
152
  }
140
153
 
141
- vars << "__scope = Opal.constants"
142
- vars << "nil = Opal.nil"
143
- # vars.concat @scope.locals.map { |t| "#{t}" }
144
- # vars.concat @scope.temps.map { |t| t }
145
- vars.concat @helpers.keys.map { |h| "__#{h} = Opal.#{h}" }
154
+ vars << "__opal = Opal"
155
+ vars << "__scope = __opal"
156
+ vars << "nil = __opal.nil"
157
+ vars.concat @helpers.keys.map { |h| "__#{h} = __opal.#{h}" }
146
158
 
147
159
  code = "var #{vars.join ', '};\n" + @scope.to_vars + "\n" + code
148
160
  end
149
161
 
150
- pre = "(function() {\n"
162
+ pre = "function() {\n"
151
163
  post = ""
152
164
 
165
+ pre += DEBUG_CODE if @debug
153
166
  uniques = []
154
167
 
155
- @unique.times { |i| uniques << "$TMP_#{i+1}" }
168
+ @unique.times { |i| uniques << "TMP_#{i+1}" }
156
169
 
157
170
  unless uniques.empty?
158
171
  post += ";var #{uniques.join ', '};"
159
172
  end
160
173
 
161
- post += "\n}).call(Opal.top);\n"
174
+ post += "\n}"
162
175
 
163
176
  pre + code + post
164
177
  end
@@ -203,13 +216,11 @@ module Opal
203
216
  end
204
217
 
205
218
  def process(sexp, level)
206
- # puts "PROCESS: (#{level})"
207
- # puts " #{sexp.inspect}"
208
219
  type = sexp.shift
220
+ meth = "process_#{type}"
221
+ raise "Unsupported sexp: #{type}" unless respond_to? meth
209
222
 
210
- raise "Unsupported sexp: #{type}" unless respond_to? type
211
-
212
- __send__ type, sexp, level
223
+ __send__ meth, sexp, level
213
224
  end
214
225
 
215
226
  def returns(sexp)
@@ -259,7 +270,7 @@ module Opal
259
270
  !STATEMENTS.include?(sexp.first)
260
271
  end
261
272
 
262
- def block(sexp, level)
273
+ def process_block(sexp, level)
263
274
  result = []
264
275
  sexp << s(:nil) if sexp.empty?
265
276
 
@@ -273,58 +284,56 @@ module Opal
273
284
  result.join "\n#@indent"
274
285
  end
275
286
 
276
- def scope(sexp, level)
287
+ def process_scope(sexp, level)
277
288
  stmt = sexp.shift
278
- stmt = returns stmt unless @scope.donates_methods
279
- code = process stmt, :statement
289
+ if stmt
290
+ stmt = returns stmt unless @scope.donates_methods
291
+ code = process stmt, :stmt
292
+ else
293
+ code = "nil"
294
+ end
280
295
 
281
296
  code
282
297
  end
283
298
 
284
299
  # s(:js_return, sexp)
285
- def js_return(sexp, level)
286
- "return #{process sexp.shift, :expression}"
300
+ def process_js_return(sexp, level)
301
+ "return #{process sexp.shift, :expr}"
287
302
  end
288
303
 
289
304
  # s(:js_tmp, str)
290
- def js_tmp(sexp, level)
305
+ def process_js_tmp(sexp, level)
291
306
  sexp.shift.to_s
292
307
  end
293
308
 
294
- def js_operator_call(sexp, level)
295
- recv = sexp[0]
296
- meth = sexp[1]
297
- arglist = sexp[2]
309
+ def process_operator(sexp, level)
310
+ meth, recv, arg = sexp
298
311
  mid = mid_to_jsid meth.to_s
299
312
 
300
313
  a = @scope.new_temp
301
314
  b = @scope.new_temp
302
- l = process recv, :expression
303
- r = process arglist[1], :expression
304
-
305
- res = "(#{a} = #{l}, #{b} = #{r}, typeof(#{a}) === "
306
- res += "'number' ? #{a} #{meth} #{b} : #{a}.#{mid}"
307
- res += "(#{b}))"
315
+ l = process recv, :expr
316
+ r = process arg, :expr
308
317
 
309
318
  @scope.queue_temp a
310
319
  @scope.queue_temp b
311
320
 
312
- res
321
+ "(%s = %s, %s = %s, typeof(%s) === 'number' ? %s %s %s : %s.%s(%s))" %
322
+ [a, l, b, r, a, a, meth.to_s, b, a, mid, b]
313
323
  end
314
324
 
315
- # s(:js_block_given)
316
325
  def js_block_given(sexp, level)
317
326
  @scope.uses_block!
318
- "!!#{@scope.block_name}"
327
+ "(#{@scope.block_name} !== nil)"
319
328
  end
320
329
 
321
330
  # s(:lit, 1)
322
331
  # s(:lit, :foo)
323
- def lit(sexp, level)
332
+ def process_lit(sexp, level)
324
333
  val = sexp.shift
325
334
  case val
326
335
  when Numeric
327
- level == :receiver ? "(#{val.inspect})" : val.inspect
336
+ level == :recv ? "(#{val.inspect})" : val.inspect
328
337
  when Symbol
329
338
  val.to_s.inspect
330
339
  when Regexp
@@ -337,32 +346,36 @@ module Opal
337
346
  end
338
347
  end
339
348
 
340
- def dregx(sexp, level)
349
+ def process_dregx(sexp, level)
341
350
  parts = sexp.map do |part|
342
351
  if String === part
343
352
  part.inspect
344
353
  elsif part[0] == :str
345
- process part, :expression
354
+ process part, :expr
346
355
  else
347
- process part[1], :expression
356
+ process part[1], :expr
348
357
  end
349
358
  end
350
359
 
351
360
  "(new RegExp(#{parts.join ' + '}))"
352
361
  end
353
362
 
354
- def dot2(sexp, level)
363
+ def process_dot2(sexp, level)
364
+ lhs = process sexp[0], :expr
365
+ rhs = process sexp[1], :expr
355
366
  @helpers[:range] = true
356
- "__range(#{process sexp[0], :expression}, #{process sexp[1], :expression}, false)"
367
+ "__range(%s, %s, false)" % [lhs, rhs]
357
368
  end
358
369
 
359
- def dot3(sexp, level)
370
+ def process_dot3(sexp, level)
371
+ lhs = process sexp[0], :expr
372
+ rhs = process sexp[1], :expr
360
373
  @helpers[:range] = true
361
- "__range(#{process sexp[0], :expression}, #{process sexp[1], :expression}, true)"
374
+ "__range(%s, %s, true)" % [lhs, rhs]
362
375
  end
363
376
 
364
377
  # s(:str, "string")
365
- def str(sexp, level)
378
+ def process_str(sexp, level)
366
379
  str = sexp.shift
367
380
  if str == @file
368
381
  @uses_file = true
@@ -372,7 +385,7 @@ module Opal
372
385
  end
373
386
  end
374
387
 
375
- def defined(sexp, level)
388
+ def process_defined(sexp, level)
376
389
  part = sexp[0]
377
390
  case part[0]
378
391
  when :self
@@ -385,7 +398,7 @@ module Opal
385
398
  "false".inspect
386
399
  when :call
387
400
  mid = mid_to_jsid part[2].to_s
388
- recv = part[1] ? process(part[1], :expression) : 'this'
401
+ recv = part[1] ? process(part[1], :expr) : 'this'
389
402
  "(#{recv}.#{mid} ? 'method' : nil)"
390
403
  else
391
404
  raise "bad defined? part: #{part[0]}"
@@ -393,30 +406,18 @@ module Opal
393
406
  end
394
407
 
395
408
  # s(:not, sexp)
396
- def not(sexp, level)
397
- code = "!#{process sexp.shift, :expression}"
409
+ def process_not(sexp, level)
410
+ code = "!#{process sexp.shift, :expr}"
398
411
  code
399
412
  end
400
413
 
401
- def block_pass(exp, level)
402
- pass = process exp.shift, level
403
- return "(#{pass} || function(){})"
404
- tmp = @scope.new_temp
405
-
406
- to_proc = process(s(:call, s(:js_tmp, tmp), :to_proc, s(:arglist)), :expression)
407
-
408
- code = "(#{tmp} = #{pass}, (typeof(#{tmp}) === 'function' || #{tmp} == null ? #{tmp} : #{to_proc}))"
409
-
410
- @scope.queue_temp tmp
411
-
412
- code
414
+ def process_block_pass(exp, level)
415
+ process(s(:call, exp.shift, :to_proc, s(:arglist)), :expr)
413
416
  end
414
417
 
415
418
  # s(:iter, call, block_args [, body)
416
- def iter(sexp, level)
417
- call = sexp[0]
418
- args = sexp[1]
419
- body = sexp[2]
419
+ def process_iter(sexp, level)
420
+ call, args, body = sexp
420
421
 
421
422
  body ||= s(:nil)
422
423
  body = returns body
@@ -460,7 +461,7 @@ module Opal
460
461
  code += "var #{block_arg} = _$ || nil, $context = #{block_arg}.$S;"
461
462
  end
462
463
 
463
- code += "\n#@indent" + process(body, :statement)
464
+ code += "\n#@indent" + process(body, :stmt)
464
465
 
465
466
  code = "\n#@indent#{@scope.to_vars}\n#@indent#{code}"
466
467
 
@@ -468,11 +469,17 @@ module Opal
468
469
  end
469
470
  end
470
471
 
472
+ tmp = @scope.new_temp
473
+
471
474
  itercode = "function(#{params.join ', '}) {\n#{code}\n#@indent}"
472
475
  itercode = "#{scope_name} = #{itercode}" if scope_name
473
- call << itercode
474
476
 
475
- process call, level
477
+ call << ("(%s = %s, %s._s = this, %s)" % [tmp, itercode, tmp, tmp])
478
+
479
+ res = process call, level
480
+ @scope.queue_temp tmp
481
+
482
+ res
476
483
  end
477
484
 
478
485
  def js_block_args(sexp)
@@ -488,8 +495,7 @@ module Opal
488
495
  # recv.mid = rhs
489
496
  #
490
497
  # s(recv, :mid=, s(:arglist, rhs))
491
-
492
- def attrasgn(exp, level)
498
+ def process_attrasgn(exp, level)
493
499
  recv = exp[0]
494
500
  mid = exp[1]
495
501
  arglist = exp[2]
@@ -497,35 +503,69 @@ module Opal
497
503
  return process(s(:call, recv, mid, arglist), level)
498
504
  end
499
505
 
500
- # s(:math_op, :op, lhs, rhs)
501
- def math_op(exp, level)
502
- op = exp[0]
503
- lhs = exp[1]
504
- rhs = exp[2]
506
+ # Used to generate optimized attr_reader, attr_writer and
507
+ # attr_accessor methods. These are optimized to avoid the added
508
+ # cost of converting the method id's into jsid's at runtime.
509
+ #
510
+ # This method will only be called if all the given ids are strings
511
+ # or symbols. Any dynamic arguments will default to being called
512
+ # using the Module#attr_* methods as expected.
513
+ #
514
+ # @param [Symbol] meth :attr_{reader,writer,accessor}
515
+ # @param [Array<Sexp>] attrs array of s(:lit) or s(:str)
516
+ # @return [String] precompiled attr methods
517
+ def attr_optimize(meth, attrs)
518
+ out = []
519
+
520
+ attrs.each do |attr|
521
+ ivar = attr[1].to_s
522
+
523
+ unless meth == :attr_writer
524
+ attr = mid_to_jsid ivar
525
+ check = "this.#{ivar} == null ? nil : this.#{ivar}"
526
+ out << "def.#{attr} = function() { return #{check}; }"
527
+ end
528
+
529
+ unless meth == :attr_reader
530
+ attr = mid_to_jsid "#{ivar}="
531
+ out << "def.#{attr} = function(val) { return this.#{ivar} = val }"
532
+ end
533
+ end
505
534
 
506
- "#{process lhs, level} #{op} #{process rhs, level}"
535
+ out.join ", \n#@indent"
507
536
  end
508
537
 
509
538
  # s(:call, recv, :mid, s(:arglist))
510
539
  # s(:call, nil, :mid, s(:arglist))
511
- def call(sexp, level)
512
- recv = sexp[0]
513
- meth = sexp[1]
514
- arglist = sexp[2]
515
- iter = sexp[3]
516
-
540
+ def process_call(sexp, level)
541
+ recv, meth, arglist, iter = sexp
517
542
  mid = mid_to_jsid meth.to_s
518
543
 
519
- return js_operator_call(sexp, level) if CALL_OPERATORS.include? meth.to_s
520
- return js_block_given(sexp, level) if meth == :block_given?
544
+ case meth
545
+ when :attr_reader, :attr_writer, :attr_accessor
546
+ attrs = arglist[1..-1]
547
+ if @scope.class_scope? && attrs.all? { |a| [:lit, :str].include? a.first }
548
+ return attr_optimize meth, attrs
549
+ end
550
+ when :block_given?
551
+ return js_block_given(sexp, level)
552
+ when :require
553
+ # path = arglist[1]
554
+
555
+ # if path and path[0] == :str
556
+ # path_name = path[1].sub(/^opal\//, '')
557
+ # @requires << path_name
558
+ # return "nil"
559
+ # else
560
+ # raise "Opal cannot do dynamic requires"
561
+ # end
562
+ end
521
563
 
522
564
  splat = arglist[1..-1].any? { |a| a.first == :splat }
523
565
 
524
566
  if Array === arglist.last and arglist.last.first == :block_pass
525
- tmpmeth = @scope.new_temp
526
- block = process s(:js_tmp, process(arglist.pop, :expression)), :expression
567
+ block = process s(:js_tmp, process(arglist.pop, :expr)), :expr
527
568
  elsif iter
528
- tmpmeth = @scope.new_temp
529
569
  block = iter
530
570
  end
531
571
 
@@ -537,22 +577,22 @@ module Opal
537
577
  tmprecv = @scope.new_temp
538
578
  end
539
579
 
540
- recv_code = process recv, :receiver
580
+ recv_code = process recv, :recv
541
581
  args = ""
542
582
 
543
583
  @scope.queue_temp tmprecv if tmprecv
544
- @scope.queue_temp tmpmeth if tmpmeth
545
584
 
546
- if tmpmeth and !splat
547
- arglist.insert 1, s(:js_tmp, tmprecv)
548
- end
585
+ args = process arglist, :expr
549
586
 
550
- args = process arglist, :expression
587
+ if block
588
+ dispatch = "(%s = %s, %s.%s._p = %s, %s.%s" %
589
+ [tmprecv, recv_code, tmprecv, mid, block, tmprecv, mid]
551
590
 
552
- if tmpmeth
553
- dispatch = "(((#{tmpmeth} = (#{tmprecv} = #{recv_code})"
554
- dispatch += ".#{mid})._p = #{block})._s = this, #{tmpmeth})"
555
- splat ? "#{dispatch}.apply(#{tmprecv}, #{args})" : "#{dispatch}.call(#{args})"
591
+ if splat
592
+ "%s.apply(%s, %s))" % [dispatch, tmprecv, args]
593
+ else
594
+ "%s(%s))" % [dispatch, args]
595
+ end
556
596
  else
557
597
  dispatch = tmprecv ? "(#{tmprecv} = #{recv_code}).#{mid}" : "#{recv_code}.#{mid}"
558
598
  splat ? "#{dispatch}.apply(#{tmprecv || recv_code}, #{args})" : "#{dispatch}(#{args})"
@@ -560,18 +600,18 @@ module Opal
560
600
  end
561
601
 
562
602
  # s(:arglist, [arg [, arg ..]])
563
- def arglist(sexp, level)
603
+ def process_arglist(sexp, level)
564
604
  code = ''
565
605
  work = []
566
606
 
567
607
  until sexp.empty?
568
608
  splat = sexp.first.first == :splat
569
- arg = process sexp.shift, :expression
609
+ arg = process sexp.shift, :expr
570
610
 
571
611
  if splat
572
612
  if work.empty?
573
613
  if code.empty?
574
- code += arg
614
+ code += "[].concat(#{arg})"
575
615
  else
576
616
  code += ".concat(#{arg})"
577
617
  end
@@ -596,75 +636,77 @@ module Opal
596
636
  end
597
637
 
598
638
  # s(:splat, sexp)
599
- def splat(sexp, level)
639
+ def process_splat(sexp, level)
600
640
  return "[]" if sexp.first == [:nil]
601
- return "[#{process sexp.first, :expression}]" if sexp.first.first == :lit
602
- process sexp.first, :receiver
641
+ return "[#{process sexp.first, :expr}]" if sexp.first.first == :lit
642
+ process sexp.first, :recv
603
643
  end
604
644
 
605
645
  # s(:class, cid, super, body)
606
- def class(sexp, level)
607
- cid = sexp[0]
608
- sup = sexp[1]
609
- body = sexp[2]
646
+ def process_class(sexp, level)
647
+ cid, sup, body = sexp
648
+
649
+ body[1] = s(:nil) unless body[1]
650
+
610
651
  code = nil
652
+ @helpers[:klass] = @helpers[:donate] = true
611
653
 
612
654
  if Symbol === cid or String === cid
613
- donates_methods = (cid === :Object || cid === :BasicObject)
614
655
  base = 'this'
615
656
  name = cid.to_s.inspect
616
657
  elsif cid[0] == :colon2
617
- base = process(cid[1], :expression)
658
+ base = process(cid[1], :expr)
618
659
  name = cid[2].to_s.inspect
619
660
  elsif cid[0] == :colon3
620
- donates_methods = (cid[1] === :Object || cid[1] === :BasicObject)
621
661
  base = 'Opal.Object'
622
662
  name = cid[1].to_s.inspect
623
663
  else
624
664
  raise "Bad receiver in class"
625
665
  end
626
666
 
627
- sup = sup ? process(sup, :expression) : 'null'
667
+ sup = sup ? process(sup, :expr) : 'null'
628
668
 
629
669
  indent do
630
670
  in_scope(:class) do
631
- @scope.donates_methods = donates_methods
632
- code = @indent + @scope.to_vars + "\n#@indent" + process(body, :statement)
633
- code += "\n#{@scope.to_donate_methods}" if @scope.donates_methods
671
+ @scope.donates_methods = true
672
+ code = @indent + @scope.to_vars + "\n#@indent" + process(body, :stmt)
673
+ code += "\n#{@scope.to_donate_methods}"
634
674
  end
635
675
  end
636
676
 
637
- "__klass(#{base}, #{sup}, #{name}, function() {\n#{code}\n#@indent}, 0)"
677
+ "__klass(#{base}, #{sup}, #{name}, function() {\n#{code}\n#@indent})"
638
678
  end
639
679
 
640
680
  # s(:sclass, recv, body)
641
- def sclass(sexp, level)
681
+ def process_sclass(sexp, level)
642
682
  recv = sexp[0]
643
683
  body = sexp[1]
644
684
  code = nil
645
- base = process recv, :expression
685
+ base = process recv, :expr
686
+ @helpers[:sklass] = true
646
687
 
647
688
  in_scope(:sclass) do
648
- code = @scope.to_vars + process(body, :statement)
689
+ code = @scope.to_vars + process(body, :stmt)
649
690
  end
650
691
 
651
- "__klass(#{base}, null, null, function() {#{code}}, 2)"
692
+ "__sklass(#{base}, function() {#{code}})"
652
693
  end
653
694
 
654
695
  # s(:module, cid, body)
655
- def module(sexp, level)
696
+ def process_module(sexp, level)
656
697
  cid = sexp[0]
657
698
  body = sexp[1]
658
699
  code = nil
700
+ @helpers[:module] = @helpers[:donate] = true
659
701
 
660
702
  if Symbol === cid or String === cid
661
703
  base = 'this'
662
704
  name = cid.to_s.inspect
663
705
  elsif cid[0] == :colon2
664
- base = process(cid[1], :expression)
706
+ base = process(cid[1], :expr)
665
707
  name = cid[2].to_s.inspect
666
708
  elsif cid[0] == :colon3
667
- base = 'opal.Object'
709
+ base = 'Opal.Object'
668
710
  name = cid[1].to_s.inspect
669
711
  else
670
712
  raise "Bad receiver in class"
@@ -673,20 +715,26 @@ module Opal
673
715
  indent do
674
716
  in_scope(:module) do
675
717
  @scope.donates_methods = true
676
- code = @indent + @scope.to_vars + "\n#@indent" + process(body, :statement) + "\n#@indent" + @scope.to_donate_methods
718
+ code = @indent + @scope.to_vars + "\n#@indent" + process(body, :stmt) + "\n#@indent" + @scope.to_donate_methods
677
719
  end
678
720
  end
679
721
 
680
- "__klass(#{base}, null, #{name}, function() {\n#{code}\n#@indent}, 1)"
722
+ "__module(#{base}, #{name}, function() {\n#{code}\n#@indent})"
681
723
  end
682
724
 
683
- def undef(exp, level)
725
+ def process_undef(exp, level)
684
726
  @helpers[:undef] = true
685
- "__undef(this, #{process exp.shift, :expression})"
727
+ jsid = mid_to_jsid exp[0][1].to_s
728
+
729
+ # "__undef(this, #{jsid.inspect})"
730
+ # FIXME: maybe add this to donate(). it will be undefined, so
731
+ # when added to includees it will actually undefine methods there
732
+ # too.
733
+ "delete def.#{jsid}"
686
734
  end
687
735
 
688
736
  # s(:defn, mid, s(:args), s(:scope))
689
- def defn(sexp, level)
737
+ def process_defn(sexp, level)
690
738
  mid = sexp[0]
691
739
  args = sexp[1]
692
740
  stmts = sexp[2]
@@ -694,7 +742,7 @@ module Opal
694
742
  end
695
743
 
696
744
  # s(:defs, recv, mid, s(:args), s(:scope))
697
- def defs(sexp, level)
745
+ def process_defs(sexp, level)
698
746
  recv = sexp[0]
699
747
  mid = sexp[1]
700
748
  args = sexp[2]
@@ -706,11 +754,10 @@ module Opal
706
754
  mid = mid_to_jsid mid.to_s
707
755
 
708
756
  if recvr
709
- @helpers[:defs] = true
710
- type = '__defs'
711
- recv = process(recvr, :expression)
757
+ @scope.defines_defs = true
758
+ recv = process(recvr, :expr)
712
759
  else
713
- type = 'Opal.defn'
760
+ @scope.defines_defn = true
714
761
  recv = 'this'
715
762
  end
716
763
 
@@ -750,25 +797,25 @@ module Opal
750
797
  yielder = block_name || '__yield'
751
798
  @scope.block_name = yielder
752
799
 
753
- params = process args, :expression
800
+ params = process args, :expr
754
801
 
755
802
  opt[1..-1].each do |o|
756
803
  next if o[2][2] == :undefined
757
- id = process s(:lvar, o[1]), :expression
758
- code += "if (#{id} == null) {\n#@indent#{INDENT}#{process o, :expression};\n#@indent}"
804
+ id = process s(:lvar, o[1]), :expr
805
+ code += "if (#{id} == null) {\n#@indent#{INDENT}#{process o, :expr};\n#@indent}"
759
806
  end if opt
760
807
 
761
808
  code += "#{splat} = __slice.call(arguments, #{len});" if splat
762
- code += "\n#@indent" + process(stmts, :statement)
809
+ code += "\n#@indent" + process(stmts, :stmt)
763
810
 
764
811
  # Returns the identity name if identified, nil otherwise
765
812
  scope_name = @scope.identity
766
813
 
767
814
  if @scope.uses_block?
768
- @scope.add_local '__context'
769
- @scope.add_local yielder
770
- blk = "\n#{@indent}if (#{yielder} = #{scope_name}._p) {\n#{@indent + INDENT}__context = #{yielder}._s"
771
- blk += ";\n#{@indent + INDENT}#{scope_name}._p = null;\n#{@indent}}"
815
+ @scope.add_temp '__context'
816
+ @scope.add_temp yielder
817
+ blk = "\n#{@indent}#{yielder} = #{scope_name}._p || nil;\n#{@indent}__context = #{yielder}._s"
818
+ blk += ";\n#{@indent}#{scope_name}._p = null;\n#{@indent}"
772
819
  code = blk + code
773
820
  end
774
821
 
@@ -782,18 +829,21 @@ module Opal
782
829
 
783
830
  defcode = "#{"#{scope_name} = " if scope_name}function(#{params}) {\n#{code}\n#@indent}"
784
831
 
785
- if @debug
786
- "#{type}(#{recv}, '#{mid}', #{defcode}, FILE, #{line})"
787
- elsif recvr
788
- "#{type}(#{recv}, '#{mid}', #{defcode})"
832
+ if recvr
833
+ # FIXME: need to donate()
834
+ "#{recv}.$singleton_class()._proto.#{mid} = #{defcode}"
789
835
  elsif @scope.type == :class
790
- @scope.methods << mid if @scope.donates_methods
836
+ @scope.methods << mid# if @scope.donates_methods
791
837
  "def.#{mid} = #{defcode}"
792
838
  elsif @scope.type == :module
793
839
  @scope.methods << mid
794
840
  "def.#{mid} = #{defcode}"
841
+ elsif @scope.type == :iter
842
+ # FIXME: this should also donate()
843
+ "def.#{mid} = #{defcode}"
795
844
  else
796
- "#{type}(#{recv}, '#{mid}', #{defcode})"
845
+ # FIXME: this should also donate()
846
+ "def.#{mid} = #{defcode}"
797
847
  end
798
848
  end
799
849
 
@@ -813,7 +863,7 @@ module Opal
813
863
  end
814
864
  end
815
865
 
816
- def args(exp, level)
866
+ def process_args(exp, level)
817
867
  args = []
818
868
 
819
869
  until exp.empty?
@@ -827,24 +877,21 @@ module Opal
827
877
  end
828
878
 
829
879
  # s(:self) # => this
830
- def self(sexp, level)
880
+ def process_self(sexp, level)
831
881
  'this'
832
882
  end
833
883
 
834
884
  # s(:true) # => true
835
885
  # s(:false) # => false
836
- %w(true false).each do |name|
837
- define_method name do |exp, level|
886
+ # s(:nil) # => nil
887
+ %w(true false nil).each do |name|
888
+ define_method "process_#{name}" do |exp, level|
838
889
  name
839
890
  end
840
891
  end
841
892
 
842
- def nil(*)
843
- "nil"
844
- end
845
-
846
893
  # s(:array [, sexp [, sexp]])
847
- def array(sexp, level)
894
+ def process_array(sexp, level)
848
895
  return '[]' if sexp.empty?
849
896
 
850
897
  code = ''
@@ -852,7 +899,7 @@ module Opal
852
899
 
853
900
  until sexp.empty?
854
901
  splat = sexp.first.first == :splat
855
- part = process sexp.shift, :expression
902
+ part = process sexp.shift, :expr
856
903
 
857
904
  if splat
858
905
  if work.empty?
@@ -877,27 +924,28 @@ module Opal
877
924
  end
878
925
 
879
926
  # s(:hash, key1, val1, key2, val2...)
880
- def hash(sexp, level)
881
- "Opal.hash(#{sexp.map { |p| process p, :expression }.join ', '})"
927
+ def process_hash(sexp, level)
928
+ @helpers[:hash] = true
929
+ "__hash(#{sexp.map { |p| process p, :expr }.join ', '})"
882
930
  end
883
931
 
884
932
  # s(:while, exp, block, true)
885
- def while(sexp, level)
933
+ def process_while(sexp, level)
886
934
  expr = sexp[0]
887
935
  stmt = sexp[1]
888
936
  redo_var = @scope.new_temp
889
- stmt_level = if level == :expression or level == :receiver
890
- :statement_closure
937
+ stmt_level = if level == :expr or level == :recv
938
+ :stmt_closure
891
939
  else
892
- :statement
940
+ :stmt
893
941
  end
894
942
  pre = "while ("
895
943
  code = "#{js_truthy expr}){"
896
944
 
897
945
  in_while do
898
- @while_loop[:closure] = true if stmt_level == :statement_closure
946
+ @while_loop[:closure] = true if stmt_level == :stmt_closure
899
947
  @while_loop[:redo_var] = redo_var
900
- body = process(stmt, :statement)
948
+ body = process(stmt, :stmt)
901
949
 
902
950
  if @while_loop[:use_redo]
903
951
  pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
@@ -911,29 +959,29 @@ module Opal
911
959
  code = pre + code
912
960
  @scope.queue_temp redo_var
913
961
 
914
- if stmt_level == :statement_closure
962
+ if stmt_level == :stmt_closure
915
963
  code = "(function() {#{code}; return nil;}).call(this)"
916
964
  end
917
965
 
918
966
  code
919
967
  end
920
968
 
921
- def until(exp, level)
969
+ def process_until(exp, level)
922
970
  expr = exp[0]
923
971
  stmt = exp[1]
924
972
  redo_var = @scope.new_temp
925
- stmt_level = if level == :expression or level == :receiver
926
- :statement_closure
973
+ stmt_level = if level == :expr or level == :recv
974
+ :stmt_closure
927
975
  else
928
- :statement
976
+ :stmt
929
977
  end
930
978
  pre = "while (!("
931
979
  code = "#{js_truthy expr})) {"
932
980
 
933
981
  in_while do
934
- @while_loop[:closure] = true if stmt_level == :statement_closure
982
+ @while_loop[:closure] = true if stmt_level == :stmt_closure
935
983
  @while_loop[:redo_var] = redo_var
936
- body = process(stmt, :statement)
984
+ body = process(stmt, :stmt)
937
985
 
938
986
  if @while_loop[:use_redo]
939
987
  pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
@@ -947,7 +995,7 @@ module Opal
947
995
  code = pre + code
948
996
  @scope.queue_temp redo_var
949
997
 
950
- if stmt_level == :statement_closure
998
+ if stmt_level == :stmt_closure
951
999
  code = "(function() {#{code}; return nil;}).call(this)"
952
1000
  end
953
1001
 
@@ -958,14 +1006,16 @@ module Opal
958
1006
  # alias foo bar
959
1007
  #
960
1008
  # s(:alias, s(:lit, :foo), s(:lit, :bar))
961
- def alias(exp, level)
1009
+ def process_alias(exp, level)
962
1010
  @helpers['alias'] = true
963
- new = exp[0]
964
- old = exp[1]
965
- "__alias(this, #{process new, :expression}, #{process old, :expression})"
1011
+ new = mid_to_jsid exp[0][1].to_s
1012
+ old = mid_to_jsid exp[1][1].to_s
1013
+ # "__alias(this, #{new.inspect}, #{old.inspect})"
1014
+ @scope.methods << new
1015
+ "def.#{new} = def.#{old}"
966
1016
  end
967
1017
 
968
- def masgn(sexp, level)
1018
+ def process_masgn(sexp, level)
969
1019
  lhs = sexp[0]
970
1020
  rhs = sexp[1]
971
1021
  tmp = @scope.new_temp
@@ -975,11 +1025,11 @@ module Opal
975
1025
  lhs.shift
976
1026
  if rhs[0] == :array
977
1027
  len = rhs.length - 1 # we are guaranteed an array of this length
978
- code = ["#{tmp} = #{process rhs, :expression}"]
1028
+ code = ["#{tmp} = #{process rhs, :expr}"]
979
1029
  elsif rhs[0] == :to_ary
980
- code = ["#{tmp} = [#{process rhs[1], :expression}]"]
1030
+ code = ["#{tmp} = [#{process rhs[1], :expr}]"]
981
1031
  elsif rhs[0] == :splat
982
- code = ["#{tmp} = #{process rhs[1], :expression}"]
1032
+ code = ["#{tmp} = #{process rhs[1], :expr}"]
983
1033
  else
984
1034
  raise "Unsupported mlhs type"
985
1035
  end
@@ -989,14 +1039,14 @@ module Opal
989
1039
  if l.first == :splat
990
1040
  s = l[1]
991
1041
  s << s(:js_tmp, "__slice.call(#{tmp}, #{idx})")
992
- code << process(s, :expression)
1042
+ code << process(s, :expr)
993
1043
  else
994
1044
  if idx >= len
995
1045
  l << s(:js_tmp, "(#{tmp}[#{idx}] == null ? nil : #{tmp}[#{idx}])")
996
1046
  else
997
1047
  l << s(:js_tmp, "#{tmp}[#{idx}]")
998
1048
  end
999
- code << process(l, :expression)
1049
+ code << process(l, :expr)
1000
1050
  end
1001
1051
  end
1002
1052
 
@@ -1004,38 +1054,38 @@ module Opal
1004
1054
  code.join ', '
1005
1055
  end
1006
1056
 
1007
- def svalue(sexp, level)
1057
+ def process_svalue(sexp, level)
1008
1058
  process sexp.shift, level
1009
1059
  end
1010
1060
 
1011
1061
  # s(:lasgn, :lvar, rhs)
1012
- def lasgn(sexp, level)
1062
+ def process_lasgn(sexp, level)
1013
1063
  lvar = sexp[0]
1014
1064
  rhs = sexp[1]
1015
1065
  lvar = "#{lvar}$".intern if RESERVED.include? lvar.to_s
1016
1066
  @scope.add_local lvar
1017
- res = "#{lvar} = #{process rhs, :expression}"
1018
- level == :receiver ? "(#{res})" : res
1067
+ res = "#{lvar} = #{process rhs, :expr}"
1068
+ level == :recv ? "(#{res})" : res
1019
1069
  end
1020
1070
 
1021
1071
  # s(:lvar, :lvar)
1022
- def lvar(exp, level)
1072
+ def process_lvar(exp, level)
1023
1073
  lvar = exp.shift.to_s
1024
1074
  lvar = "#{lvar}$" if RESERVED.include? lvar
1025
1075
  lvar
1026
1076
  end
1027
1077
 
1028
1078
  # s(:iasgn, :ivar, rhs)
1029
- def iasgn(exp, level)
1079
+ def process_iasgn(exp, level)
1030
1080
  ivar = exp[0]
1031
1081
  rhs = exp[1]
1032
1082
  ivar = ivar.to_s[1..-1]
1033
1083
  lhs = RESERVED.include?(ivar) ? "this['#{ivar}']" : "this.#{ivar}"
1034
- "#{lhs} = #{process rhs, :expression}"
1084
+ "#{lhs} = #{process rhs, :expr}"
1035
1085
  end
1036
1086
 
1037
1087
  # s(:ivar, :ivar)
1038
- def ivar(exp, level)
1088
+ def process_ivar(exp, level)
1039
1089
  ivar = exp.shift.to_s[1..-1]
1040
1090
  part = RESERVED.include?(ivar) ? "['#{ivar}']" : ".#{ivar}"
1041
1091
  @scope.add_ivar part
@@ -1043,63 +1093,58 @@ module Opal
1043
1093
  end
1044
1094
 
1045
1095
  # s(:gvar, gvar)
1046
- def gvar(sexp, level)
1096
+ def process_gvar(sexp, level)
1047
1097
  gvar = sexp.shift.to_s
1048
1098
  @helpers['gvars'] = true
1049
1099
  "__gvars[#{gvar.inspect}]"
1050
1100
  end
1051
1101
 
1052
1102
  # s(:gasgn, :gvar, rhs)
1053
- def gasgn(sexp, level)
1103
+ def process_gasgn(sexp, level)
1054
1104
  gvar = sexp[0]
1055
1105
  rhs = sexp[1]
1056
1106
  @helpers['gvars'] = true
1057
- "__gvars[#{gvar.to_s.inspect}] = #{process rhs, :expression}"
1107
+ "__gvars[#{gvar.to_s.inspect}] = #{process rhs, :expr}"
1058
1108
  end
1059
1109
 
1060
1110
  # s(:const, :const)
1061
- def const(sexp, level)
1111
+ def process_const(sexp, level)
1062
1112
  if @debug
1063
- "Opal.const_get(__scope, #{sexp.shift.to_s.inspect})"
1113
+ "__const_get(__scope, #{sexp.shift.to_s.inspect})"
1064
1114
  else
1065
1115
  "__scope.#{sexp.shift}"
1066
1116
  end
1067
1117
  end
1068
1118
 
1069
1119
  # s(:cdecl, :const, rhs)
1070
- def cdecl(sexp, level)
1120
+ def process_cdecl(sexp, level)
1071
1121
  const = sexp[0]
1072
1122
  rhs = sexp[1]
1073
- "__scope.#{const} = #{process rhs, :expression}"
1123
+ "__scope.#{const} = #{process rhs, :expr}"
1074
1124
  end
1075
1125
 
1076
1126
  # s(:return [val])
1077
- def return(sexp, level)
1078
- val = process(sexp.shift || s(:nil), :expression)
1127
+ def process_return(sexp, level)
1128
+ val = process(sexp.shift || s(:nil), :expr)
1079
1129
 
1080
- if level == :statement
1081
- "return #{val}"
1082
- else
1083
- "$return(#{val})"
1084
- end
1130
+ raise "Cannot return as an expression" unless level == :stmt
1131
+ "return #{val}"
1085
1132
  end
1086
1133
 
1087
1134
  # s(:xstr, content)
1088
- def xstr(sexp, level)
1135
+ def process_xstr(sexp, level)
1089
1136
  code = sexp.first.to_s
1090
- code += ";" if level == :statement and !code.include?(';')
1091
- code = "(#{code})" if level == :receiver
1092
-
1093
- code
1137
+ code += ";" if level == :stmt and !code.include?(';')
1138
+ level == :recv ? "(#{code})" : code
1094
1139
  end
1095
1140
 
1096
1141
  # s(:dxstr, parts...)
1097
- def dxstr(sexp, level)
1142
+ def process_dxstr(sexp, level)
1098
1143
  code = sexp.map do |p|
1099
1144
  if String === p
1100
1145
  p.to_s
1101
1146
  elsif p.first == :evstr
1102
- process p.last, :statement
1147
+ process p.last, :stmt
1103
1148
  elsif p.first == :str
1104
1149
  p.last.to_s
1105
1150
  else
@@ -1107,18 +1152,18 @@ module Opal
1107
1152
  end
1108
1153
  end.join
1109
1154
 
1110
- code += ";" if level == :statement and !code.include?(';')
1111
- code = "(#{code})" if level == :receiver
1155
+ code += ";" if level == :stmt and !code.include?(';')
1156
+ code = "(#{code})" if level == :recv
1112
1157
  code
1113
1158
  end
1114
1159
 
1115
1160
  # s(:dstr, parts..)
1116
- def dstr(sexp, level)
1161
+ def process_dstr(sexp, level)
1117
1162
  parts = sexp.map do |p|
1118
1163
  if String === p
1119
1164
  p.inspect
1120
1165
  elsif p.first == :evstr
1121
- process p.last, :expression
1166
+ process p.last, :expr
1122
1167
  elsif p.first == :str
1123
1168
  p.last.inspect
1124
1169
  else
@@ -1127,15 +1172,15 @@ module Opal
1127
1172
  end
1128
1173
 
1129
1174
  res = parts.join ' + '
1130
- level == :receiver ? "(#{res})" : res
1175
+ level == :recv ? "(#{res})" : res
1131
1176
  end
1132
1177
 
1133
- def dsym(sexp, level)
1178
+ def process_dsym(sexp, level)
1134
1179
  parts = sexp.map do |p|
1135
1180
  if String === p
1136
1181
  p.inspect
1137
1182
  elsif p.first == :evstr
1138
- process(s(:call, p.last, :to_s, s(:arglist)), :expression)
1183
+ process(s(:call, p.last, :to_s, s(:arglist)), :expr)
1139
1184
  elsif p.first == :str
1140
1185
  p.last.inspect
1141
1186
  else
@@ -1147,22 +1192,21 @@ module Opal
1147
1192
  end
1148
1193
 
1149
1194
  # s(:if, test, truthy, falsy)
1150
- def if(sexp, level)
1151
- test = sexp[0]
1152
- truthy = sexp[1]
1153
- falsy = sexp[2]
1195
+ def process_if(sexp, level)
1196
+ test, truthy, falsy = sexp
1197
+ returnable = (level == :expr or level == :recv)
1154
1198
 
1155
- if level == :expression or level == :receiver
1199
+ if returnable
1156
1200
  truthy = returns(truthy || s(:nil))
1157
1201
  falsy = returns(falsy || s(:nil))
1158
1202
  end
1159
1203
 
1160
1204
  code = "if (#{js_truthy test}) {\n"
1161
- indent { code += @indent + process(truthy, :statement) } if truthy
1162
- indent { code += "\n#@indent} else {\n#@indent#{process falsy, :statement}" } if falsy
1205
+ indent { code += @indent + process(truthy, :stmt) } if truthy
1206
+ indent { code += "\n#@indent} else {\n#@indent#{process falsy, :stmt}" } if falsy
1163
1207
  code += "\n#@indent}"
1164
1208
 
1165
- code = "(function() { #{code}; return nil; }).call(this)" if level == :expression or level == :receiver
1209
+ code = "(function() { #{code}; return nil; }).call(this)" if returnable
1166
1210
 
1167
1211
  code
1168
1212
  end
@@ -1171,9 +1215,9 @@ module Opal
1171
1215
  if sexp.first == :call
1172
1216
  mid = sexp[2]
1173
1217
  if mid == :block_given?
1174
- return process sexp, :expression
1218
+ return process sexp, :expr
1175
1219
  elsif COMPARE.include? mid.to_s
1176
- return process sexp, :expression
1220
+ return process sexp, :expr
1177
1221
  end
1178
1222
  end
1179
1223
  end
@@ -1184,89 +1228,72 @@ module Opal
1184
1228
  end
1185
1229
 
1186
1230
  tmp = @scope.new_temp
1187
- code = "(#{tmp} = #{process sexp, :expression}) !== false && #{tmp} !== nil"
1188
1231
  @scope.queue_temp tmp
1189
1232
 
1190
- code
1233
+ "(%s = %s) !== false && %s !== nil" % [tmp, process(sexp, :expr), tmp]
1191
1234
  end
1192
1235
 
1193
1236
  # s(:and, lhs, rhs)
1194
- def and(sexp, level)
1237
+ def process_and(sexp, level)
1195
1238
  lhs = sexp[0]
1196
1239
  rhs = sexp[1]
1197
1240
  t = nil
1198
1241
  tmp = @scope.new_temp
1199
1242
 
1200
1243
  if t = js_truthy_optimize(lhs)
1201
- return "(#{tmp} = #{t} ? #{process rhs, :expression} : #{tmp})".tap {
1244
+ return "(#{tmp} = #{t} ? #{process rhs, :expr} : #{tmp})".tap {
1202
1245
  @scope.queue_temp tmp
1203
1246
  }
1204
1247
  end
1205
1248
 
1206
- code = "((#{tmp} = #{process lhs, :expression}, #{tmp} !== false && "
1207
- code += "#{tmp} !== nil) ? #{process rhs, :expression} : #{tmp})"
1208
1249
  @scope.queue_temp tmp
1209
1250
 
1210
- code
1251
+ "(%s = %s, %s !== false && %s !== nil ? %s : %s)" %
1252
+ [tmp, process(lhs, :expr), tmp, tmp, process(rhs, :expr), tmp]
1211
1253
  end
1212
1254
 
1213
1255
  # s(:or, lhs, rhs)
1214
- def or(sexp, level)
1256
+ def process_or(sexp, level)
1215
1257
  lhs = sexp[0]
1216
1258
  rhs = sexp[1]
1217
1259
  t = nil
1218
1260
  tmp = @scope.new_temp
1219
1261
 
1220
1262
  if t = js_truthy_optimize(lhs)
1221
- return "(#{tmp} = #{t} ? #{tmp} : #{process rhs, :expression})".tap {
1263
+ return "(#{tmp} = #{t} ? #{tmp} : #{process rhs, :expr})".tap {
1222
1264
  @scope.queue_temp tmp
1223
1265
  }
1224
1266
  end
1225
1267
 
1226
- code = "(#{tmp} = #{process lhs, :expression}, #{tmp} !== false && "
1227
- code += "#{tmp} !== nil ? #{tmp} : #{process rhs, :expression})"
1228
1268
  @scope.queue_temp tmp
1229
1269
 
1230
- code
1270
+ "(%s = %s, %s !== false && %s !== nil ? %s : %s)" %
1271
+ [tmp, process(lhs, :expr), tmp, tmp, tmp, process(rhs, :expr)]
1231
1272
  end
1232
1273
 
1233
1274
  # s(:yield, arg1, arg2)
1234
- def yield(sexp, level)
1235
- # puts sexp.inspect
1236
- # puts level.inspect
1275
+ #
1276
+ # FIXME: yield as an expression (when used with js_return) should have the
1277
+ # right action. We should then warn when used as an expression in other cases
1278
+ # that we would need to use a try/catch/throw block (which is slow and bad
1279
+ # mmmkay).
1280
+ def process_yield(sexp, level)
1237
1281
  @scope.uses_block!
1238
1282
  splat = sexp.any? { |s| s.first == :splat }
1239
- # sexp.unshift s(:js_tmp, 'null')
1240
1283
  sexp.unshift s(:js_tmp, '__context') unless splat
1241
- args = arglist(sexp, level)
1284
+ args = process_arglist(sexp, level)
1242
1285
 
1243
1286
  yielder = @scope.block_name || '__yield'
1244
1287
 
1245
- call = if splat
1246
- "#{yielder}.apply(__context, #{args})"
1247
- else
1248
- "#{yielder}.call(#{args})"
1249
- end
1250
-
1251
- # FIXME: yield as an expression (when used with js_return) should have the
1252
- # right action. We should then warn when used as an expression in other cases
1253
- # that we would need to use a try/catch/throw block (which is slow and bad
1254
- # mmmkay).
1255
-
1256
- # if level == :receiver or level == :expression
1257
- # tmp = @scope.new_temp
1258
- # @scope.catches_break!
1259
- # code = "((#{tmp} = #{call}) === __breaker ? #{tmp}.$t() : #{tmp})"
1260
- # @scope.queue_temp tmp
1261
- # else
1262
- code = call
1263
- # end
1264
-
1265
- code
1288
+ if splat
1289
+ "#{yielder}.apply(__context, #{args})"
1290
+ else
1291
+ "#{yielder}.call(#{args})"
1292
+ end
1266
1293
  end
1267
1294
 
1268
- def break(exp, level)
1269
- val = exp.empty? ? 'nil' : process(exp.shift, :expression)
1295
+ def process_break(exp, level)
1296
+ val = exp.empty? ? 'nil' : process(exp.shift, :expr)
1270
1297
  if in_while?
1271
1298
  if @while_loop[:closure]
1272
1299
  "return #{val};"
@@ -1279,25 +1306,25 @@ module Opal
1279
1306
  end
1280
1307
 
1281
1308
  # s(:case, expr, when1, when2, ..)
1282
- def case(exp, level)
1309
+ def process_case(exp, level)
1283
1310
  code = []
1284
1311
  @scope.add_local "$case"
1285
- expr = process exp.shift, :expression
1312
+ expr = process exp.shift, :expr
1286
1313
  # are we inside a statement_closure
1287
- returnable = level != :statement
1314
+ returnable = level != :stmt
1288
1315
  done_else = false
1289
1316
 
1290
1317
  until exp.empty?
1291
1318
  wen = exp.shift
1292
1319
  if wen and wen.first == :when
1293
1320
  returns(wen) if returnable
1294
- wen = process(wen, :statement)
1321
+ wen = process(wen, :stmt)
1295
1322
  wen = "else #{wen}" unless code.empty?
1296
1323
  code << wen
1297
1324
  elsif wen # s(:else)
1298
1325
  done_else = true
1299
1326
  wen = returns(wen) if returnable
1300
- code << "else {#{process wen, :statement}}"
1327
+ code << "else {#{process wen, :stmt}}"
1301
1328
  end
1302
1329
  end
1303
1330
 
@@ -1312,7 +1339,7 @@ module Opal
1312
1339
  # bar
1313
1340
  #
1314
1341
  # s(:when, s(:array, foo), bar)
1315
- def when(exp, level)
1342
+ def process_when(exp, level)
1316
1343
  arg = exp.shift[1..-1]
1317
1344
  body = exp.shift
1318
1345
  body = process body, level if body
@@ -1324,26 +1351,26 @@ module Opal
1324
1351
  if a.first == :when # when inside another when means a splat of values
1325
1352
  call = s(:call, s(:js_tmp, "$splt[i]"), :===, s(:arglist, s(:js_tmp, "$case")))
1326
1353
  splt = "(function($splt) {for(var i = 0; i < $splt.length; i++) {"
1327
- splt += "if (#{process call, :expression}) { return true; }"
1328
- splt += "} return false; }).call(this, #{process a[1], :expression})"
1354
+ splt += "if (#{process call, :expr}) { return true; }"
1355
+ splt += "} return false; }).call(this, #{process a[1], :expr})"
1329
1356
 
1330
1357
  test << splt
1331
1358
  else
1332
1359
  call = s(:call, a, :===, s(:arglist, s(:js_tmp, "$case")))
1333
- call = process call, :expression
1360
+ call = process call, :expr
1334
1361
  # call = "else " unless test.empty?
1335
1362
 
1336
1363
  test << call
1337
1364
  end
1338
1365
  end
1339
1366
 
1340
- "if (#{test.join " || "}) {\n#{body}\n}"
1367
+ "if (%s) {\n%s\n}" % [test.join(' || '), body]
1341
1368
  end
1342
1369
 
1343
1370
  # lhs =~ rhs
1344
1371
  #
1345
1372
  # s(:match3, lhs, rhs)
1346
- def match3(sexp, level)
1373
+ def process_match3(sexp, level)
1347
1374
  lhs = sexp[0]
1348
1375
  rhs = sexp[1]
1349
1376
  call = s(:call, lhs, :=~, s(:arglist, rhs))
@@ -1353,68 +1380,67 @@ module Opal
1353
1380
  # @@class_variable
1354
1381
  #
1355
1382
  # s(:cvar, name)
1356
- def cvar(exp, level)
1383
+ def process_cvar(exp, level)
1357
1384
  tmp = @scope.new_temp
1358
- code = "((#{tmp} = Opal.cvars[#{exp.shift.to_s.inspect}]) == null ? null : #{tmp})"
1359
1385
  @scope.queue_temp tmp
1360
- code
1386
+ "((%s = Opal.cvars[%s]) == null ? nil : %s)" % [tmp, exp.shift.to_s.inspect, tmp]
1361
1387
  end
1362
1388
 
1363
1389
  # @@name = rhs
1364
1390
  #
1365
1391
  # s(:cvasgn, :@@name, rhs)
1366
- def cvasgn(exp, level)
1367
- "(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expression})"
1392
+ def process_cvasgn(exp, level)
1393
+ "(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expr})"
1368
1394
  end
1369
1395
 
1370
- def cvdecl(exp, level)
1371
- "(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expression})"
1396
+ def process_cvdecl(exp, level)
1397
+ "(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expr})"
1372
1398
  end
1373
1399
 
1374
1400
  # BASE::NAME
1375
1401
  #
1376
1402
  # s(:colon2, base, :NAME)
1377
- def colon2(sexp, level)
1403
+ def process_colon2(sexp, level)
1378
1404
  base = sexp[0]
1379
1405
  name = sexp[1]
1380
- "Opal.const_get((#{process base, :expression})._scope, #{name.to_s.inspect})"
1406
+ "(%s)._scope.%s" % [process(base, :expr), name.to_s]
1381
1407
  end
1382
1408
 
1383
- def colon3(exp, level)
1384
- "Opal.const_get(Opal.Object._scope, #{exp.shift.to_s.inspect})"
1409
+ def process_colon3(exp, level)
1410
+ "__opal.Object._scope.#{exp.shift.to_s}"
1385
1411
  end
1386
1412
 
1387
1413
  # super a, b, c
1388
1414
  #
1389
1415
  # s(:super, arg1, arg2, ...)
1390
- def super(sexp, level)
1416
+ def process_super(sexp, level)
1391
1417
  args = []
1392
1418
  until sexp.empty?
1393
- args << process(sexp.shift, :expression)
1419
+ args << process(sexp.shift, :expr)
1394
1420
  end
1395
1421
 
1396
- # args.unshift 'null'
1397
-
1398
1422
  js_super "[#{ args.join ', ' }]"
1399
1423
  end
1400
1424
 
1401
1425
  # super
1402
1426
  #
1403
1427
  # s(:zsuper)
1404
- def zsuper(exp, level)
1405
-
1428
+ def process_zsuper(exp, level)
1406
1429
  js_super "__slice.call(arguments)"
1407
1430
  end
1408
1431
 
1409
1432
  def js_super args
1410
1433
  if @scope.type == :def
1411
- mid = @scope.mid
1412
1434
  identity = @scope.identify!
1413
- "Opal.zuper(#{identity}, '#{mid}', this, #{args})"
1435
+
1436
+ # FIXME: only use `._proto` when inside normal def. remove it
1437
+ # for `def self.foo`.
1438
+ "__class._super._proto.#{@scope.mid}.apply(this, #{args})"
1414
1439
 
1415
1440
  elsif @scope.type == :iter
1416
1441
  chain, defn, mid = @scope.get_super_chain
1417
- "Opal.dsuper([#{chain.join ', '}], #{defn}, #{mid}, this, #{args})"
1442
+ trys = chain.map { |c| "#{c}._jsid" }.join ' || '
1443
+ "this._klass._super._proto[#{trys} || #{mid}].apply(this, #{args})"
1418
1444
 
1419
1445
  else
1420
1446
  raise "Cannot call super() from outside a method block"
@@ -1424,19 +1450,19 @@ module Opal
1424
1450
  # a ||= rhs
1425
1451
  #
1426
1452
  # s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, rhs))
1427
- def op_asgn_or(exp, level)
1428
- process s(:or, exp.shift, exp.shift), :expression
1453
+ def process_op_asgn_or(exp, level)
1454
+ process s(:or, exp.shift, exp.shift), :expr
1429
1455
  end
1430
1456
 
1431
- def op_asgn1(sexp, level)
1457
+ def process_op_asgn1(sexp, level)
1432
1458
  "'FIXME(op_asgn1)'"
1433
1459
  end
1434
1460
 
1435
1461
  # lhs.b += rhs
1436
1462
  #
1437
1463
  # s(:op_asgn2, lhs, :b=, :+, rhs)
1438
- def op_asgn2(exp, level)
1439
- lhs = process exp.shift, :expression
1464
+ def process_op_asgn2(exp, level)
1465
+ lhs = process exp.shift, :expr
1440
1466
  mid = exp.shift.to_s[0..-2]
1441
1467
  op = exp.shift
1442
1468
  rhs = exp.shift
@@ -1449,16 +1475,16 @@ module Opal
1449
1475
  oper = s(:call, getr, op, s(:arglist, rhs))
1450
1476
  asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, oper))
1451
1477
 
1452
- "(#{temp} = #{lhs}, #{process asgn, :expression})".tap {
1478
+ "(#{temp} = #{lhs}, #{process asgn, :expr})".tap {
1453
1479
  @scope.queue_temp temp
1454
1480
  }
1455
1481
  end
1456
1482
  end
1457
1483
 
1458
1484
  # s(:ensure, body, ensure)
1459
- def ensure(exp, level)
1485
+ def process_ensure(exp, level)
1460
1486
  begn = exp.shift
1461
- if level == :receiver || level == :expression
1487
+ if level == :recv || level == :expr
1462
1488
  retn = true
1463
1489
  begn = returns begn
1464
1490
  end
@@ -1473,7 +1499,7 @@ module Opal
1473
1499
  res
1474
1500
  end
1475
1501
 
1476
- def rescue(exp, level)
1502
+ def process_rescue(exp, level)
1477
1503
  body = exp.first.first == :resbody ? s(:nil) : exp.shift
1478
1504
  body = process body, level
1479
1505
 
@@ -1486,13 +1512,13 @@ module Opal
1486
1512
  # if no rescue statement captures our error, we should rethrow
1487
1513
  parts << "else { throw $err; }"
1488
1514
 
1489
- code = "try {\n#{body}\n} catch ($err) {\n#{parts.join "\n"}\n}"
1490
- code = "(function() { #{code} }).call(this)" if level == :expression
1515
+ code = "try {\n#@indent#{body}\n#@indent} catch ($err) {\n#@indent#{parts.join "\n"}\n}"
1516
+ code = "(function() { #{code} }).call(this)" if level == :expr
1491
1517
 
1492
1518
  code
1493
1519
  end
1494
1520
 
1495
- def resbody(exp, level)
1521
+ def process_resbody(exp, level)
1496
1522
  args = exp[0]
1497
1523
  body = exp[1]
1498
1524
  body = process(body || s(:nil), level)
@@ -1500,7 +1526,7 @@ module Opal
1500
1526
 
1501
1527
  err = types.map { |t|
1502
1528
  call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
1503
- a = process call, :expression
1529
+ a = process call, :expr
1504
1530
  #puts a
1505
1531
  a
1506
1532
  }.join ', '
@@ -1509,7 +1535,7 @@ module Opal
1509
1535
  if Array === args.last and [:lasgn, :iasgn].include? args.last.first
1510
1536
  val = args.last
1511
1537
  val[2] = s(:js_tmp, "$err")
1512
- val = process(val, :expression) + ";"
1538
+ val = process(val, :expr) + ";"
1513
1539
  end
1514
1540
 
1515
1541
  "if (#{err}) {\n#{val}#{body}}"
@@ -1517,12 +1543,12 @@ module Opal
1517
1543
  end
1518
1544
 
1519
1545
  # FIXME: Hack.. grammar should remove top level begin.
1520
- def begin(exp, level)
1546
+ def process_begin(exp, level)
1521
1547
  process exp[0], level
1522
1548
  end
1523
1549
 
1524
- def next(exp, level)
1525
- val = exp.empty? ? 'nil' : process(exp.shift, :expression)
1550
+ def process_next(exp, level)
1551
+ val = exp.empty? ? 'nil' : process(exp.shift, :expr)
1526
1552
  if in_while?
1527
1553
  "continue;"
1528
1554
  else
@@ -1530,7 +1556,7 @@ module Opal
1530
1556
  end
1531
1557
  end
1532
1558
 
1533
- def redo(exp, level)
1559
+ def process_redo(exp, level)
1534
1560
  if in_while?
1535
1561
  @while_loop[:use_redo] = true
1536
1562
  "#{@while_loop[:redo_var]} = true"
@@ -1539,4 +1565,4 @@ module Opal
1539
1565
  end
1540
1566
  end
1541
1567
  end
1542
- end
1568
+ end