opal 0.3.18 → 0.3.19

Sign up to get free protection for your applications and to get access to all the features.
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