opal 0.3.27 → 0.3.28

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 (148) hide show
  1. data/.gitignore +2 -1
  2. data/CONTRIBUTING.md +24 -0
  3. data/README.md +6 -5
  4. data/Rakefile +12 -2
  5. data/core/array.rb +3 -31
  6. data/core/enumerable.rb +32 -4
  7. data/core/hash.rb +218 -186
  8. data/core/json.rb +3 -2
  9. data/core/kernel.rb +28 -28
  10. data/core/numeric.rb +2 -2
  11. data/core/runtime.js +0 -1
  12. data/lib/opal.rb +4 -2
  13. data/lib/opal/grammar.rb +6 -2
  14. data/lib/opal/grammar.y +3 -0
  15. data/lib/opal/lexer.rb +25 -10
  16. data/lib/opal/parser.rb +75 -34
  17. data/lib/opal/scope.rb +7 -7
  18. data/lib/opal/version.rb +1 -1
  19. data/opal.gemspec +1 -1
  20. data/spec/core/array/reduce_spec.rb +31 -0
  21. data/spec/{opal → core}/array/to_json_spec.rb +0 -0
  22. data/spec/core/boolean/and_spec.rb +17 -0
  23. data/spec/core/boolean/inspect_spec.rb +9 -0
  24. data/spec/core/boolean/or_spec.rb +17 -0
  25. data/spec/{opal → core}/boolean/singleton_class_spec.rb +0 -0
  26. data/spec/{opal → core}/boolean/to_json_spec.rb +1 -1
  27. data/spec/core/boolean/to_s_spec.rb +9 -0
  28. data/spec/core/boolean/xor_spec.rb +17 -0
  29. data/spec/{opal → core}/class/bridge_class_spec.rb +0 -0
  30. data/spec/{opal → core}/class/instance_methods_spec.rb +0 -0
  31. data/spec/core/class/last_value_spec.rb +68 -0
  32. data/spec/core/enumerable/detect_spec.rb +1 -1
  33. data/spec/core/enumerable/find_spec.rb +1 -1
  34. data/spec/{opal → core}/hash/to_json_spec.rb +0 -0
  35. data/spec/{opal → core}/hash/to_native_spec.rb +0 -0
  36. data/spec/{opal → core}/json/parse_spec.rb +0 -0
  37. data/spec/core/kernel/block_given.rb +30 -0
  38. data/spec/core/kernel/methods_spec.rb +11 -0
  39. data/spec/core/kernel/p_spec.rb +13 -0
  40. data/spec/{opal → core}/kernel/to_json_spec.rb +0 -0
  41. data/spec/{opal → core}/nil/to_json_spec.rb +0 -0
  42. data/spec/core/numeric/abs_spec.rb +12 -0
  43. data/spec/core/numeric/bit_and_spec.rb +7 -0
  44. data/spec/core/numeric/bit_or_spec.rb +8 -0
  45. data/spec/core/numeric/bit_xor_spec.rb +6 -0
  46. data/spec/core/numeric/ceil_spec.rb +8 -0
  47. data/spec/core/numeric/chr_spec.rb +8 -0
  48. data/spec/core/numeric/comparison_spec.rb +24 -0
  49. data/spec/core/numeric/complement_spec.rb +8 -0
  50. data/spec/core/numeric/divide_spec.rb +10 -0
  51. data/spec/core/numeric/downto_spec.rb +19 -0
  52. data/spec/core/numeric/eql_spec.rb +9 -0
  53. data/spec/core/numeric/even_spec.rb +21 -0
  54. data/spec/core/numeric/exponent_spec.rb +33 -0
  55. data/spec/core/numeric/floor_spec.rb +8 -0
  56. data/spec/core/numeric/gt_spec.rb +11 -0
  57. data/spec/core/numeric/gte_spec.rb +12 -0
  58. data/spec/core/numeric/integer_spec.rb +9 -0
  59. data/spec/core/numeric/left_shift_spec.rb +21 -0
  60. data/spec/core/numeric/lt_spec.rb +11 -0
  61. data/spec/core/numeric/lte_spec.rb +12 -0
  62. data/spec/core/numeric/magnitude_spec.rb +12 -0
  63. data/spec/core/numeric/minus_spec.rb +8 -0
  64. data/spec/core/numeric/modulo_spec.rb +19 -0
  65. data/spec/core/numeric/multiply_spec.rb +9 -0
  66. data/spec/core/numeric/next_spec.rb +9 -0
  67. data/spec/core/numeric/odd_spec.rb +21 -0
  68. data/spec/core/numeric/ord_spec.rb +9 -0
  69. data/spec/core/numeric/plus_spec.rb +8 -0
  70. data/spec/core/numeric/pred_spec.rb +7 -0
  71. data/spec/core/numeric/right_shift_spec.rb +25 -0
  72. data/spec/core/numeric/succ_spec.rb +9 -0
  73. data/spec/core/numeric/times_spec.rb +36 -0
  74. data/spec/core/numeric/to_f_spec.rb +7 -0
  75. data/spec/core/numeric/to_i_spec.rb +7 -0
  76. data/spec/{opal → core}/numeric/to_json_spec.rb +0 -0
  77. data/spec/core/numeric/to_s_spec.rb +8 -0
  78. data/spec/core/numeric/uminus_spec.rb +9 -0
  79. data/spec/core/numeric/upto_spec.rb +19 -0
  80. data/spec/core/numeric/zero_spec.rb +7 -0
  81. data/spec/{opal → core}/runtime/call_spec.rb +0 -0
  82. data/spec/{opal → core}/runtime/class_hierarchy_spec.rb +0 -0
  83. data/spec/{opal → core}/runtime/def_spec.rb +0 -0
  84. data/spec/{opal → core}/runtime/defined_spec.rb +0 -0
  85. data/spec/{opal → core}/runtime/super_spec.rb +0 -0
  86. data/spec/{opal → core}/string/demodulize_spec.rb +0 -0
  87. data/spec/{opal → core}/string/to_json_spec.rb +0 -0
  88. data/spec/{opal → core}/string/underscore_spec.rb +0 -0
  89. data/spec/{opal → core}/strscan/check_spec.rb +0 -0
  90. data/spec/{opal → core}/strscan/scan_spec.rb +0 -0
  91. data/spec/{lib/grammar → grammar}/alias_spec.rb +0 -0
  92. data/spec/{lib/grammar → grammar}/and_spec.rb +0 -0
  93. data/spec/{lib/grammar → grammar}/array_spec.rb +0 -0
  94. data/spec/{lib/grammar → grammar}/attrasgn_spec.rb +0 -0
  95. data/spec/{lib/grammar → grammar}/begin_spec.rb +0 -0
  96. data/spec/{lib/grammar → grammar}/block_spec.rb +0 -0
  97. data/spec/{lib/grammar → grammar}/break_spec.rb +0 -0
  98. data/spec/{lib/grammar → grammar}/call_spec.rb +23 -1
  99. data/spec/{lib/grammar → grammar}/class_spec.rb +0 -0
  100. data/spec/{lib/grammar → grammar}/const_spec.rb +0 -0
  101. data/spec/{lib/grammar → grammar}/cvar_spec.rb +0 -0
  102. data/spec/{lib/grammar → grammar}/def_spec.rb +0 -0
  103. data/spec/{lib/grammar → grammar}/false_spec.rb +0 -0
  104. data/spec/{lib/grammar → grammar}/file_spec.rb +0 -0
  105. data/spec/{lib/grammar → grammar}/gvar_spec.rb +0 -0
  106. data/spec/{lib/grammar → grammar}/hash_spec.rb +0 -0
  107. data/spec/{lib/grammar → grammar}/iasgn_spec.rb +0 -0
  108. data/spec/{lib/grammar → grammar}/if_spec.rb +0 -0
  109. data/spec/{lib/grammar → grammar}/iter_spec.rb +0 -0
  110. data/spec/{lib/grammar → grammar}/ivar_spec.rb +0 -0
  111. data/spec/{lib/grammar → grammar}/lambda_spec.rb +0 -0
  112. data/spec/{lib/grammar → grammar}/lasgn_spec.rb +0 -0
  113. data/spec/{lib/grammar → grammar}/line_spec.rb +0 -0
  114. data/spec/{lib/grammar → grammar}/lvar_spec.rb +0 -0
  115. data/spec/{lib/grammar → grammar}/masgn_spec.rb +0 -0
  116. data/spec/{lib/grammar → grammar}/module_spec.rb +0 -0
  117. data/spec/{lib/grammar → grammar}/nil_spec.rb +0 -0
  118. data/spec/{lib/grammar → grammar}/not_spec.rb +0 -0
  119. data/spec/{lib/grammar → grammar}/op_asgn1_spec.rb +0 -0
  120. data/spec/{lib/grammar → grammar}/op_asgn2_spec.rb +0 -0
  121. data/spec/{lib/grammar → grammar}/or_spec.rb +0 -0
  122. data/spec/{lib/grammar → grammar}/return_spec.rb +0 -0
  123. data/spec/{lib/grammar → grammar}/sclass_spec.rb +0 -0
  124. data/spec/{lib/grammar → grammar}/self_spec.rb +0 -0
  125. data/spec/{lib/grammar → grammar}/str_spec.rb +7 -0
  126. data/spec/{lib/grammar → grammar}/super_spec.rb +0 -0
  127. data/spec/{lib/grammar → grammar}/true_spec.rb +0 -0
  128. data/spec/{lib/grammar → grammar}/undef_spec.rb +0 -0
  129. data/spec/{lib/grammar → grammar}/unless_spec.rb +0 -0
  130. data/spec/{lib/grammar → grammar}/while_spec.rb +0 -0
  131. data/spec/{lib/grammar → grammar}/xstr_spec.rb +0 -0
  132. data/spec/{lib/grammar → grammar}/yield_spec.rb +0 -0
  133. data/spec/language/string_spec.rb +5 -0
  134. data/spec/{lib/parser → parser}/simple_spec.rb +0 -0
  135. metadata +231 -159
  136. data/spec/core/false/and_spec.rb +0 -9
  137. data/spec/core/false/inspect_spec.rb +0 -5
  138. data/spec/core/false/or_spec.rb +0 -9
  139. data/spec/core/false/to_s_spec.rb +0 -5
  140. data/spec/core/false/xor_spec.rb +0 -9
  141. data/spec/core/true/and_spec.rb +0 -9
  142. data/spec/core/true/inspect_spec.rb +0 -5
  143. data/spec/core/true/or_spec.rb +0 -9
  144. data/spec/core/true/to_s_spec.rb +0 -5
  145. data/spec/core/true/xor_spec.rb +0 -9
  146. data/spec/lib/erb_parser/simple.erb +0 -1
  147. data/spec/opal/kernel/attribute_spec.rb +0 -57
  148. data/spec/opal/runtime/method_missing_spec.rb +0 -17
data/core/json.rb CHANGED
@@ -38,12 +38,13 @@ module JSON
38
38
  return arr;
39
39
  }
40
40
  else {
41
- var hash = #{ {} }, v, map = hash.map;
41
+ var hash = #{ {} }, v, map = hash.map, keys = hash.keys;
42
42
 
43
43
  for (var k in value) {
44
44
  if (__hasOwn.call(value, k)) {
45
45
  v = to_opal(value[k]);
46
- map[k] = [k, v];
46
+ keys.push(k);
47
+ map[k] = v;
47
48
  }
48
49
  }
49
50
  }
data/core/kernel.rb CHANGED
@@ -11,6 +11,23 @@ module Kernel
11
11
  `#{self} == other`
12
12
  end
13
13
 
14
+ def methods(all = true)
15
+ %x{
16
+ var methods = [];
17
+ for(var k in #{self}) {
18
+ if(k[0] == "$" && typeof (#{self})[k] === "function") {
19
+ if(all === #{false} || all === #{nil}) {
20
+ if(!Object.hasOwnProperty.call(#{self}, k)) {
21
+ continue;
22
+ }
23
+ }
24
+ methods.push(k.substr(1));
25
+ }
26
+ }
27
+ return methods;
28
+ }
29
+ end
30
+
14
31
  def __send__(symbol, *args, &block)
15
32
  %x{
16
33
  return #{self}['$' + symbol].apply(#{self}, args);
@@ -32,32 +49,6 @@ module Kernel
32
49
  }
33
50
  end
34
51
 
35
- def attribute_get(name)
36
- %x{
37
- var meth = '$' + name;
38
- if (#{self}[meth]) {
39
- return #{self}[meth]();
40
- }
41
-
42
- meth += '?';
43
- if (#{self}[meth]) {
44
- return #{self}[meth]()
45
- }
46
-
47
- return nil;
48
- }
49
- end
50
-
51
- def attribute_set(name, value)
52
- %x{
53
- if (#{self}['$' + name + '=']) {
54
- return #{self}['$' + name + '='](value);
55
- }
56
-
57
- return nil;
58
- }
59
- end
60
-
61
52
  def class
62
53
  `return #{self}._klass`
63
54
  end
@@ -103,7 +94,7 @@ module Kernel
103
94
  to_s
104
95
  end
105
96
 
106
- def instance_eval(string=undefined, &block)
97
+ def instance_eval(&block)
107
98
  %x{
108
99
  if (block === nil) {
109
100
  no_block_given();
@@ -206,12 +197,21 @@ module Kernel
206
197
  def puts(*strs)
207
198
  %x{
208
199
  for (var i = 0; i < strs.length; i++) {
209
- __opal.puts(#{ `strs[i]`.to_s });
200
+ if(strs[i] instanceof Array) {
201
+ #{ puts *strs }
202
+ } else {
203
+ __opal.puts(#{ `strs[i]`.to_s });
204
+ }
210
205
  }
211
206
  }
212
207
  nil
213
208
  end
214
209
 
210
+ def p(*args)
211
+ `console.log.apply(console, args);`
212
+ args.length <= 1 ? args[0] : args
213
+ end
214
+
215
215
  alias print puts
216
216
 
217
217
  def raise(exception, string)
data/core/numeric.rb CHANGED
@@ -161,7 +161,7 @@ class Numeric < `Number`
161
161
 
162
162
  def times(&block)
163
163
  %x{
164
- for (var i = 0; i <= #{self}; i++) {
164
+ for (var i = 0; i < #{self}; i++) {
165
165
  if (block.call(__context, i) === __breaker) {
166
166
  return __breaker.$v;
167
167
  }
@@ -189,7 +189,7 @@ class Numeric < `Number`
189
189
 
190
190
  def upto(finish, &block)
191
191
  %x{
192
- for (var i = 0; i <= finish; i++) {
192
+ for (var i = #{self}; i <= finish; i++) {
193
193
  if (block.call(__context, i) === __breaker) {
194
194
  return __breaker.$v;
195
195
  }
data/core/runtime.js CHANGED
@@ -89,7 +89,6 @@ Opal.module = function(base, id, constructor) {
89
89
  klass = boot_class(Class, constructor);
90
90
  klass._name = (base === Object ? id : base._name + '::' + id);
91
91
 
92
- klass._isModule = true;
93
92
  klass.$included_in = [];
94
93
 
95
94
  var const_alloc = function() {};
data/lib/opal.rb CHANGED
@@ -28,11 +28,13 @@ module Opal
28
28
  core_dir = Opal.core_dir
29
29
  load_order = File.join core_dir, 'load_order'
30
30
  corelib = File.read(load_order).strip.split.map do |c|
31
- File.read File.join(core_dir, "#{c}.rb")
31
+ file = File.join(core_dir, "#{c}.rb")
32
+ source = File.read file
33
+ Opal.parse source, file
32
34
  end
33
35
 
34
36
  runtime = File.read(File.join core_dir, 'runtime.js')
35
- corelib = Opal.parse corelib.join("\n"), '(corelib)'
37
+ corelib = corelib.join("\n")
36
38
 
37
39
  [
38
40
  "// Opal v#{Opal::VERSION}",
data/lib/opal/grammar.rb CHANGED
@@ -2091,7 +2091,7 @@ racc_reduce_table = [
2091
2091
  1, 186, :_reduce_none,
2092
2092
  0, 219, :_reduce_253,
2093
2093
  4, 186, :_reduce_254,
2094
- 4, 186, :_reduce_none,
2094
+ 4, 186, :_reduce_255,
2095
2095
  3, 186, :_reduce_256,
2096
2096
  3, 186, :_reduce_257,
2097
2097
  2, 186, :_reduce_258,
@@ -3817,7 +3817,11 @@ def _reduce_254(val, _values, result)
3817
3817
  result
3818
3818
  end
3819
3819
 
3820
- # reduce 255 omitted
3820
+ def _reduce_255(val, _values, result)
3821
+ result = val[1]
3822
+
3823
+ result
3824
+ end
3821
3825
 
3822
3826
  def _reduce_256(val, _values, result)
3823
3827
  result = val[1] || s(:nil)
data/lib/opal/grammar.y CHANGED
@@ -729,6 +729,9 @@ primary:
729
729
  result.line = val[1]
730
730
  }
731
731
  | tLPAREN_ARG expr opt_nl ')'
732
+ {
733
+ result = val[1]
734
+ }
732
735
  | PAREN_BEG compstmt ')'
733
736
  {
734
737
  result = val[1] || s(:nil)
data/lib/opal/lexer.rb CHANGED
@@ -7,10 +7,6 @@ class Array
7
7
  end
8
8
 
9
9
  module Opal
10
- Sexp = ::Array
11
-
12
- # Any exceptions with parsing of file will raise this error
13
- class OpalParseError < Exception; end
14
10
 
15
11
  class Grammar < Racc::Parser
16
12
 
@@ -27,7 +23,7 @@ module Opal
27
23
  end
28
24
 
29
25
  def s(*parts)
30
- sexp = Sexp.new(parts)
26
+ sexp = Array.new(parts)
31
27
  sexp.line = @line
32
28
  sexp
33
29
  end
@@ -43,7 +39,7 @@ module Opal
43
39
  end
44
40
 
45
41
  def on_error(t, val, vstack)
46
- raise OpalParseError, "parse error on value #{val.inspect} (line #{@line})"
42
+ raise "parse error on value #{val.inspect} :#{@file}:#{@line}"
47
43
  end
48
44
 
49
45
  class LexerScope
@@ -731,6 +727,11 @@ module Opal
731
727
  return :OP_ASGN, '/'
732
728
  elsif @lex_state == :expr_fname
733
729
  @lex_state = :expr_end
730
+ elsif @lex_state == :expr_cmdarg || @lex_state == :expr_arg
731
+ if !scanner.check(/\s/) && space_seen
732
+ @string_parse = { :beg => '/', :end => '/', :interpolate => true, :regexp => true }
733
+ return :REGEXP_BEG, scanner.matched
734
+ end
734
735
  end
735
736
 
736
737
  return '/', '/'
@@ -747,7 +748,9 @@ module Opal
747
748
  result = scanner.matched
748
749
  if [:expr_beg, :expr_mid].include? @lex_state
749
750
  result = :PAREN_BEG
750
- elsif space_seen
751
+ elsif space_seen && [:expr_arg, :expr_cmdarg].include?(@lex_state)
752
+ result = :tLPAREN_ARG
753
+ else
751
754
  result = '('
752
755
  end
753
756
 
@@ -979,7 +982,7 @@ module Opal
979
982
  return '>=', scanner.matched
980
983
  elsif scanner.scan(/\>/)
981
984
  if @lex_state == :expr_fname
982
- @lex_state = :expr_end
985
+ @lex_state = :expr_arg
983
986
  else
984
987
  @lex_state = :expr_beg
985
988
  end
@@ -987,7 +990,8 @@ module Opal
987
990
  end
988
991
 
989
992
  elsif scanner.scan(/->/)
990
- @lex_state = :expr_arg
993
+ # FIXME: # should be :expr_arg, but '(' breaks it...
994
+ @lex_state = :expr_end
991
995
  @start_of_lambda = true
992
996
  return [:LAMBDA, scanner.matched]
993
997
 
@@ -1009,6 +1013,13 @@ module Opal
1009
1013
  return [:OP_ASGN, result]
1010
1014
  end
1011
1015
 
1016
+ if @lex_state == :expr_cmdarg || @lex_state == :expr_arg
1017
+ if !scanner.check(/\s/) && space_seen
1018
+ @lex_state = :expr_mid
1019
+ return [sign, sign]
1020
+ end
1021
+ end
1022
+
1012
1023
  @lex_state = :expr_beg
1013
1024
  return [result, result]
1014
1025
 
@@ -1019,6 +1030,10 @@ module Opal
1019
1030
  return '?', scanner.matched
1020
1031
  end
1021
1032
 
1033
+ unless scanner.check(/\ |\t|\r/)
1034
+ @lex_state = :expr_end
1035
+ return :STRING, scanner.scan(/./)
1036
+ end
1022
1037
  #if scanner.scan(/\\/)
1023
1038
  #c = if scanner.scan(/n/)
1024
1039
  #"\n"
@@ -1367,7 +1382,7 @@ module Opal
1367
1382
  end
1368
1383
  return [false, false] if scanner.eos?
1369
1384
 
1370
- raise OpalParseError, "Unexpected content in parsing stream `#{scanner.peek 5}`"
1385
+ raise "Unexpected content in parsing stream `#{scanner.peek 5}` :#{@file}:#{@line}"
1371
1386
  end
1372
1387
  end
1373
1388
  end
data/lib/opal/parser.rb CHANGED
@@ -129,7 +129,7 @@ module Opal
129
129
  #
130
130
  # @result [Array]
131
131
  def s(*parts)
132
- sexp = Sexp.new(parts)
132
+ sexp = Array.new(parts)
133
133
  sexp.line = @line
134
134
  sexp
135
135
  end
@@ -339,6 +339,7 @@ module Opal
339
339
  sexp[0] = :returnable_yield
340
340
  sexp
341
341
  when :scope
342
+ sexp[1] = returns sexp[1]
342
343
  sexp
343
344
  when :block
344
345
  if sexp.length > 1
@@ -350,6 +351,9 @@ module Opal
350
351
  when :when
351
352
  sexp[2] = returns(sexp[2])
352
353
  sexp
354
+ when :rescue
355
+ sexp[1] = returns sexp[1]
356
+ sexp
353
357
  when :ensure
354
358
  sexp[1] = returns sexp[1]
355
359
  sexp
@@ -387,13 +391,13 @@ module Opal
387
391
  end
388
392
 
389
393
  # More than one expression in a row will be grouped by the grammar
390
- # into a block sexp. A block sexp just holds any number of other
394
+ # into a block sexp. A block sexp just holds any number of other
391
395
  # sexps.
392
396
  #
393
397
  # s(:block, s(:str, "hey"), s(:lit, 42))
394
398
  #
395
399
  # A block can actually be empty. As opal requires real values to
396
- # be returned (to appease javascript values), a nil sexp
400
+ # be returned (to appease javascript values), a nil sexp
397
401
  # s(:nil) will be generated if the block is empty.
398
402
  #
399
403
  # @return [String]
@@ -423,7 +427,7 @@ module Opal
423
427
  # generated as a top level member. This is because if a yield
424
428
  # is returned by a break statement, then the method must return.
425
429
  #
426
- # As inline expressions in javascript cannot return, the block
430
+ # As inline expressions in javascript cannot return, the block
427
431
  # must be rewritten.
428
432
  #
429
433
  # For example, a yield inside an array:
@@ -470,7 +474,7 @@ module Opal
470
474
  def process_scope(sexp, level)
471
475
  stmt = sexp.shift
472
476
  if stmt
473
- stmt = returns stmt unless @scope.donates_methods
477
+ stmt = returns stmt unless @scope.class_scope?
474
478
  code = process stmt, :stmt
475
479
  else
476
480
  code = "nil"
@@ -506,7 +510,11 @@ module Opal
506
510
 
507
511
  def js_block_given(sexp, level)
508
512
  @scope.uses_block!
509
- "(#{@scope.block_name} !== nil)"
513
+ if @scope.block_name
514
+ "(#{@scope.block_name} !== nil)"
515
+ else
516
+ "false"
517
+ end
510
518
  end
511
519
 
512
520
  def handle_block_given(sexp, reverse = false)
@@ -601,8 +609,11 @@ module Opal
601
609
 
602
610
  # s(:not, sexp)
603
611
  def process_not(sexp, level)
604
- code = "!#{process sexp.shift, :expr}"
605
- code
612
+ with_temp do |tmp|
613
+ "(#{tmp} = #{process(sexp.shift, :expr)}, (#{tmp} === nil || #{tmp} === false))"
614
+ end
615
+ # code = "!#{process sexp.shift, :expr}"
616
+ # code
606
617
  end
607
618
 
608
619
  def process_block_pass(exp, level)
@@ -736,7 +747,7 @@ module Opal
736
747
  end
737
748
  end
738
749
 
739
- out.join ", \n#@indent"
750
+ out.join(", \n#@indent") + ', nil'
740
751
  end
741
752
 
742
753
  def handle_alias_native(sexp)
@@ -782,7 +793,7 @@ module Opal
782
793
 
783
794
  splat = arglist[1..-1].any? { |a| a.first == :splat }
784
795
 
785
- if Sexp === arglist.last and arglist.last.first == :block_pass
796
+ if Array === arglist.last and arglist.last.first == :block_pass
786
797
  block = process s(:js_tmp, process(arglist.pop, :expr)), :expr
787
798
  elsif iter
788
799
  block = iter
@@ -795,7 +806,7 @@ module Opal
795
806
  elsif splat and recv != [:self] and recv[0] != :lvar
796
807
  tmprecv = @scope.new_temp
797
808
  end
798
-
809
+
799
810
  args = ""
800
811
 
801
812
  recv_code = process recv, :recv
@@ -893,19 +904,33 @@ module Opal
893
904
  in_scope(:class) do
894
905
  @scope.name = name
895
906
  @scope.add_temp "#{ @scope.proto } = #{name}.prototype", "__scope = #{name}._scope"
896
- @scope.donates_methods = true
907
+
908
+ if Array === body.last
909
+ # A single statement will need a block
910
+ needs_block = body.last.first != :block
911
+ body.last.first == :block
912
+ last_body_statement = needs_block ? body.last : body.last.last
913
+
914
+ if last_body_statement and Array === last_body_statement
915
+ if [:defn, :defs].include? last_body_statement.first
916
+ body[-1] = s(:block, body[-1]) if needs_block
917
+ body.last << s(:nil)
918
+ end
919
+ end
920
+ end
921
+
922
+ body = returns(body)
897
923
  body = process body, :stmt
898
- code = @indent + @scope.to_vars + "\n\n#@indent" + body
899
- code += "\n#{@scope.to_donate_methods}"
924
+ code = "\n#{@scope.to_donate_methods}"
925
+ code += @indent + @scope.to_vars + "\n\n#@indent" + body
900
926
  end
901
927
  end
902
928
 
903
929
  spacer = "\n#{@indent}#{INDENT}"
904
930
  cls = "function #{name}() {};"
905
931
  boot = "#{name} = __klass(__base, __super, #{name.inspect}, #{name});"
906
- comment = "#{spacer}// line #{ sexp.line }, #{ @file }, class #{ name }"
907
932
 
908
- "(function(__base, __super){#{comment}#{spacer}#{cls}#{spacer}#{boot}\n#{code}\n#{@indent}})(#{base}, #{sup})"
933
+ "(function(__base, __super){#{spacer}#{cls}#{spacer}#{boot}\n#{code}\n#{@indent}})(#{base}, #{sup})"
909
934
  end
910
935
 
911
936
  # s(:sclass, recv, body)
@@ -948,7 +973,6 @@ module Opal
948
973
  in_scope(:module) do
949
974
  @scope.name = name
950
975
  @scope.add_temp "#{ @scope.proto } = #{name}.prototype", "__scope = #{name}._scope"
951
- @scope.donates_methods = true
952
976
  body = process body, :stmt
953
977
  code = @indent + @scope.to_vars + "\n\n#@indent" + body + "\n#@indent" + @scope.to_donate_methods
954
978
  end
@@ -957,9 +981,8 @@ module Opal
957
981
  spacer = "\n#{@indent}#{INDENT}"
958
982
  cls = "function #{name}() {};"
959
983
  boot = "#{name} = __module(__base, #{name.inspect}, #{name});"
960
- comment = "#{spacer}// line #{ sexp.line }, #{ @file }, module #{ name }"
961
984
 
962
- "(function(__base){#{comment}#{spacer}#{cls}#{spacer}#{boot}\n#{code}\n#{@indent}})(#{base})"
985
+ "(function(__base){#{spacer}#{cls}#{spacer}#{boot}\n#{code}\n#{@indent}})(#{base})"
963
986
  end
964
987
 
965
988
  def process_undef(exp, level)
@@ -1008,7 +1031,7 @@ module Opal
1008
1031
  uses_super = nil
1009
1032
 
1010
1033
  # opt args if last arg is sexp
1011
- opt = args.pop if Sexp === args.last
1034
+ opt = args.pop if Array === args.last
1012
1035
 
1013
1036
  # block name &block
1014
1037
  if args.last.to_s.start_with? '&'
@@ -1071,18 +1094,10 @@ module Opal
1071
1094
 
1072
1095
  defcode = "#{"#{scope_name} = " if scope_name}function(#{params}) {\n#{code}\n#@indent}"
1073
1096
 
1074
- comment = "// line #{line}, #{@file}"
1075
-
1076
- if @scope.class_scope?
1077
- comment += ", #{ @scope.name }#{ recvr ? '.' : '#' }#{ mid }"
1078
- end
1079
-
1080
- comment += "\n#{@indent}"
1081
-
1082
1097
  if recvr
1083
1098
  if smethod
1084
1099
  @scope.smethods << "$#{mid}"
1085
- "#{ comment }#{ @scope.name }#{jsid} = #{defcode}"
1100
+ "#{ @scope.name }#{jsid} = #{defcode}"
1086
1101
  else
1087
1102
  "#{ recv }#{ jsid } = #{ defcode }"
1088
1103
  end
@@ -1092,7 +1107,7 @@ module Opal
1092
1107
  @scope.add_temp uses_super
1093
1108
  uses_super = "#{uses_super} = #{@scope.proto}#{jsid};\n#@indent"
1094
1109
  end
1095
- "#{ comment }#{uses_super}#{ @scope.proto }#{jsid} = #{defcode}"
1110
+ "#{uses_super}#{ @scope.proto }#{jsid} = #{defcode}"
1096
1111
  elsif @scope.type == :iter
1097
1112
  "def#{jsid} = #{defcode}"
1098
1113
  elsif @scope.type == :top
@@ -1195,8 +1210,34 @@ module Opal
1195
1210
 
1196
1211
  # s(:hash, key1, val1, key2, val2...)
1197
1212
  def process_hash(sexp, level)
1198
- @helpers[:hash] = true
1199
- "__hash(#{sexp.map { |p| process p, :expr }.join ', '})"
1213
+ keys = []
1214
+ vals = []
1215
+
1216
+ sexp.each_with_index do |obj, idx|
1217
+ if idx.even?
1218
+ keys << obj
1219
+ else
1220
+ vals << obj
1221
+ end
1222
+ end
1223
+
1224
+ if keys.all? { |k| [:lit, :str].include? k[0] }
1225
+ hash_obj = {}
1226
+ hash_keys = []
1227
+ keys.size.times do |i|
1228
+ k = process(keys[i], :expr)
1229
+ hash_keys << k unless hash_obj.include? k
1230
+ hash_obj[k] = process(vals[i], :expr)
1231
+ end
1232
+
1233
+ map = hash_keys.map { |k| "#{k}: #{hash_obj[k]}"}
1234
+
1235
+ @helpers[:hash2] = true
1236
+ "__hash2([#{hash_keys.join ', '}], {#{map.join(', ')}})"
1237
+ else
1238
+ @helpers[:hash] = true
1239
+ "__hash(#{sexp.map { |p| process p, :expr }.join ', '})"
1240
+ end
1200
1241
  end
1201
1242
 
1202
1243
  # s(:while, exp, block, true)
@@ -1862,7 +1903,7 @@ module Opal
1862
1903
  }.join ', '
1863
1904
  err = "true" if err.empty?
1864
1905
 
1865
- if Sexp === args.last and [:lasgn, :iasgn].include? args.last.first
1906
+ if Array === args.last and [:lasgn, :iasgn].include? args.last.first
1866
1907
  val = args.last
1867
1908
  val[2] = s(:js_tmp, "$err")
1868
1909
  val = process(val, :expr) + ";"
@@ -1895,4 +1936,4 @@ module Opal
1895
1936
  end
1896
1937
  end
1897
1938
  end
1898
- end
1939
+ end