opal 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -9
  3. data/CHANGELOG.md +349 -0
  4. data/Gemfile +7 -8
  5. data/README.md +25 -3
  6. data/Rakefile +4 -2
  7. data/bin/opal +1 -1
  8. data/examples/rack/Gemfile +3 -0
  9. data/examples/rack/app/application.rb +13 -0
  10. data/examples/rack/app/user.rb +21 -0
  11. data/examples/rack/config.ru +7 -0
  12. data/examples/rack/index.html.erb +10 -0
  13. data/examples/sinatra/Gemfile +4 -0
  14. data/examples/sinatra/app/application.rb +7 -0
  15. data/examples/sinatra/config.ru +21 -0
  16. data/lib/mspec/opal/rake_task.rb +29 -8
  17. data/lib/mspec/opal/runner.rb +5 -4
  18. data/lib/opal.rb +1 -0
  19. data/lib/opal/builder.rb +0 -28
  20. data/lib/opal/cli.rb +0 -14
  21. data/lib/opal/compiler.rb +12 -11
  22. data/lib/opal/fragment.rb +8 -1
  23. data/lib/opal/nodes/array.rb +1 -1
  24. data/lib/opal/nodes/base.rb +4 -0
  25. data/lib/opal/nodes/call.rb +6 -2
  26. data/lib/opal/nodes/call_special.rb +1 -1
  27. data/lib/opal/nodes/class.rb +2 -2
  28. data/lib/opal/nodes/constants.rb +3 -1
  29. data/lib/opal/nodes/helpers.rb +23 -14
  30. data/lib/opal/nodes/if.rb +16 -9
  31. data/lib/opal/nodes/literal.rb +37 -5
  32. data/lib/opal/nodes/logic.rb +7 -1
  33. data/lib/opal/nodes/module.rb +2 -2
  34. data/lib/opal/nodes/scope.rb +13 -2
  35. data/lib/opal/nodes/top.rb +9 -0
  36. data/lib/opal/nodes/variables.rb +5 -2
  37. data/lib/opal/parser.rb +306 -71
  38. data/lib/opal/parser/grammar.rb +2667 -2775
  39. data/lib/opal/parser/grammar.y +177 -233
  40. data/lib/opal/parser/lexer.rb +511 -427
  41. data/lib/opal/parser/sexp.rb +15 -3
  42. data/lib/opal/source_map.rb +8 -4
  43. data/lib/opal/sprockets.rb +4 -0
  44. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  45. data/lib/opal/sprockets/environment.rb +21 -0
  46. data/lib/opal/sprockets/erb.rb +30 -0
  47. data/lib/opal/sprockets/processor.rb +127 -0
  48. data/lib/opal/sprockets/server.rb +166 -0
  49. data/lib/opal/util.rb +29 -0
  50. data/lib/opal/version.rb +1 -1
  51. data/opal.gemspec +1 -1
  52. data/opal/corelib/array.rb +106 -187
  53. data/opal/corelib/array/inheritance.rb +113 -0
  54. data/opal/corelib/basic_object.rb +6 -2
  55. data/opal/corelib/boolean.rb +4 -0
  56. data/opal/corelib/class.rb +2 -0
  57. data/opal/corelib/complex.rb +3 -0
  58. data/opal/corelib/enumerable.rb +75 -8
  59. data/opal/corelib/enumerator.rb +2 -0
  60. data/opal/corelib/error.rb +23 -23
  61. data/opal/corelib/hash.rb +5 -5
  62. data/opal/corelib/helpers.rb +51 -16
  63. data/opal/corelib/io.rb +7 -24
  64. data/opal/corelib/kernel.rb +23 -11
  65. data/opal/corelib/module.rb +44 -47
  66. data/opal/corelib/nil_class.rb +4 -0
  67. data/opal/corelib/numeric.rb +101 -15
  68. data/opal/corelib/range.rb +2 -0
  69. data/opal/corelib/rational.rb +3 -0
  70. data/opal/corelib/regexp.rb +36 -17
  71. data/opal/corelib/runtime.js +22 -7
  72. data/opal/corelib/string.rb +213 -110
  73. data/opal/corelib/string/inheritance.rb +78 -0
  74. data/opal/corelib/struct.rb +8 -0
  75. data/opal/corelib/time.rb +54 -42
  76. data/opal/corelib/variables.rb +24 -0
  77. data/opal/opal.rb +5 -27
  78. data/spec/cli/compiler_spec.rb +136 -0
  79. data/spec/cli/dependency_resolver_spec.rb +40 -0
  80. data/spec/cli/lexer_spec.rb +110 -0
  81. data/spec/cli/parser/alias_spec.rb +26 -0
  82. data/spec/cli/parser/and_spec.rb +13 -0
  83. data/spec/cli/parser/attrasgn_spec.rb +28 -0
  84. data/spec/cli/parser/begin_spec.rb +42 -0
  85. data/spec/cli/parser/block_spec.rb +12 -0
  86. data/spec/cli/parser/break_spec.rb +17 -0
  87. data/spec/cli/parser/call_spec.rb +139 -0
  88. data/spec/cli/parser/class_spec.rb +35 -0
  89. data/spec/cli/parser/comments_spec.rb +11 -0
  90. data/spec/cli/parser/def_spec.rb +61 -0
  91. data/spec/cli/parser/if_spec.rb +26 -0
  92. data/spec/cli/parser/iter_spec.rb +59 -0
  93. data/spec/cli/parser/lambda_spec.rb +64 -0
  94. data/spec/cli/parser/literal_spec.rb +113 -0
  95. data/spec/cli/parser/masgn_spec.rb +37 -0
  96. data/spec/cli/parser/module_spec.rb +27 -0
  97. data/spec/cli/parser/not_spec.rb +27 -0
  98. data/spec/cli/parser/op_asgn1_spec.rb +23 -0
  99. data/spec/cli/parser/op_asgn2_spec.rb +23 -0
  100. data/spec/cli/parser/or_spec.rb +13 -0
  101. data/spec/cli/parser/return_spec.rb +17 -0
  102. data/spec/cli/parser/sclass_spec.rb +21 -0
  103. data/spec/cli/parser/string_spec.rb +269 -0
  104. data/spec/cli/parser/super_spec.rb +20 -0
  105. data/spec/cli/parser/undef_spec.rb +15 -0
  106. data/spec/cli/parser/unless_spec.rb +13 -0
  107. data/spec/cli/parser/variables_spec.rb +92 -0
  108. data/spec/cli/parser/while_spec.rb +15 -0
  109. data/spec/cli/parser/yield_spec.rb +20 -0
  110. data/spec/cli/spec_helper.rb +31 -11
  111. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  112. data/spec/opal/core/date_spec.rb +122 -0
  113. data/spec/opal/core/language/predefined_spec.rb +1 -1
  114. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  115. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  116. data/spec/opal/filters/bugs/array.rb +96 -87
  117. data/spec/opal/filters/bugs/basic_object.rb +9 -0
  118. data/spec/opal/filters/bugs/class.rb +16 -0
  119. data/spec/opal/filters/bugs/enumerable.rb +54 -0
  120. data/spec/opal/filters/bugs/language.rb +37 -3
  121. data/spec/opal/filters/bugs/math.rb +93 -0
  122. data/spec/opal/filters/bugs/nil.rb +7 -0
  123. data/spec/opal/filters/bugs/numeric.rb +19 -0
  124. data/spec/opal/filters/bugs/opal.rb +12 -0
  125. data/spec/opal/filters/bugs/regexp.rb +0 -2
  126. data/spec/opal/filters/bugs/string.rb +317 -19
  127. data/spec/opal/filters/bugs/struct.rb +29 -0
  128. data/spec/opal/filters/bugs/time.rb +130 -9
  129. data/spec/opal/filters/unsupported/encoding.rb +52 -4
  130. data/spec/opal/filters/unsupported/enumerator.rb +0 -3
  131. data/spec/opal/filters/unsupported/integer_size.rb +7 -0
  132. data/spec/opal/filters/unsupported/method_added.rb +10 -0
  133. data/spec/opal/filters/unsupported/mutable_strings.rb +299 -1
  134. data/spec/opal/filters/unsupported/private_constants.rb +30 -0
  135. data/spec/opal/filters/unsupported/private_methods.rb +16 -0
  136. data/spec/opal/filters/unsupported/random.rb +4 -0
  137. data/spec/opal/filters/unsupported/tainted.rb +53 -0
  138. data/spec/opal/filters/unsupported/trusted.rb +5 -0
  139. data/spec/opal/rubyspecs +167 -234
  140. data/spec/opal/spec_helper.rb +3 -0
  141. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  142. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  143. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  144. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  145. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  146. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  147. data/stdlib/base64.rb +152 -0
  148. data/stdlib/date.rb +82 -49
  149. data/{opal/corelib → stdlib}/encoding.rb +3 -1
  150. data/stdlib/erb.rb +0 -1
  151. data/stdlib/json.rb +10 -26
  152. data/stdlib/math.rb +370 -0
  153. data/stdlib/native.rb +40 -33
  154. data/stdlib/opal-parser.rb +7 -4
  155. data/stdlib/promise.rb +292 -0
  156. data/stdlib/strscan.rb +1 -1
  157. data/stdlib/template.rb +1 -3
  158. data/stdlib/time.rb +9 -0
  159. metadata +143 -204
  160. data/doc/compiler.md +0 -42
  161. data/doc/compiler_options.md +0 -5
  162. data/doc/examples/node_http_server.rb +0 -49
  163. data/doc/external_libraries.md +0 -9
  164. data/doc/generated_javascript.md +0 -272
  165. data/doc/home.md +0 -17
  166. data/doc/method_missing.md +0 -58
  167. data/doc/static_applications.md +0 -60
  168. data/doc/using_ruby_from_javascript.md +0 -18
  169. data/doc/using_sprockets.md +0 -65
  170. data/spec/opal/core/numeric/abs_spec.rb +0 -12
  171. data/spec/opal/core/numeric/downto_spec.rb +0 -19
  172. data/spec/opal/core/numeric/equal_value_spec.rb +0 -9
  173. data/spec/opal/core/numeric/even_spec.rb +0 -21
  174. data/spec/opal/core/numeric/magnitude_spec.rb +0 -12
  175. data/spec/opal/core/numeric/odd_spec.rb +0 -21
  176. data/spec/opal/core/string/chop_spec.rb +0 -10
  177. data/spec/opal/core/string/chr_spec.rb +0 -13
  178. data/spec/opal/core/string/clone_spec.rb +0 -8
  179. data/spec/opal/core/string/comparison_spec.rb +0 -13
  180. data/spec/opal/core/string/dup_spec.rb +0 -8
  181. data/spec/opal/core/string/element_reference_spec.rb +0 -96
  182. data/spec/opal/core/string/fixtures/classes.rb +0 -49
  183. data/spec/opal/core/string/format_spec.rb +0 -9
  184. data/spec/opal/core/string/freeze_spec.rb +0 -15
  185. data/spec/opal/core/string/gsub_spec.rb +0 -31
  186. data/spec/opal/core/string/lines_spec.rb +0 -9
  187. data/spec/opal/core/string/ljust_spec.rb +0 -32
  188. data/spec/opal/core/string/lstrip_spec.rb +0 -7
  189. data/spec/opal/core/string/match_spec.rb +0 -49
  190. data/spec/opal/core/string/next_spec.rb +0 -10
  191. data/spec/opal/core/string/ord_spec.rb +0 -9
  192. data/spec/opal/core/string/partition_spec.rb +0 -10
  193. data/spec/opal/core/string/rindex_spec.rb +0 -50
  194. data/spec/opal/core/string/rjust_spec.rb +0 -32
  195. data/spec/opal/core/string/rstrip_spec.rb +0 -7
  196. data/spec/opal/core/string/scan_spec.rb +0 -66
  197. data/spec/opal/core/string/slice_spec.rb +0 -74
  198. data/spec/opal/core/string/split_spec.rb +0 -5
  199. data/spec/opal/core/string/strip_spec.rb +0 -6
  200. data/spec/opal/core/string/sub_spec.rb +0 -38
  201. data/spec/opal/core/string/succ_spec.rb +0 -10
  202. data/spec/opal/core/string/sum_spec.rb +0 -5
  203. data/spec/opal/core/string/to_f_spec.rb +0 -14
  204. data/spec/opal/core/string/to_i_spec.rb +0 -25
  205. data/spec/opal/core/string/tr_s_spec.rb +0 -31
  206. data/spec/opal/core/string/tr_spec.rb +0 -31
  207. data/spec/opal/filters/bugs/parser.rb +0 -10
  208. data/spec/opal/filters/unsupported/immutable_strings.rb +0 -24
  209. data/spec/opal/filters/unsupported/string_subclasses.rb +0 -8
  210. data/spec/opal/parser/alias_spec.rb +0 -26
  211. data/spec/opal/parser/and_spec.rb +0 -13
  212. data/spec/opal/parser/array_spec.rb +0 -22
  213. data/spec/opal/parser/attrasgn_spec.rb +0 -28
  214. data/spec/opal/parser/begin_spec.rb +0 -42
  215. data/spec/opal/parser/block_spec.rb +0 -12
  216. data/spec/opal/parser/break_spec.rb +0 -17
  217. data/spec/opal/parser/call_spec.rb +0 -131
  218. data/spec/opal/parser/class_spec.rb +0 -35
  219. data/spec/opal/parser/const_spec.rb +0 -13
  220. data/spec/opal/parser/cvar_spec.rb +0 -11
  221. data/spec/opal/parser/def_spec.rb +0 -61
  222. data/spec/opal/parser/false_spec.rb +0 -17
  223. data/spec/opal/parser/file_spec.rb +0 -7
  224. data/spec/opal/parser/gvar_spec.rb +0 -13
  225. data/spec/opal/parser/hash_spec.rb +0 -17
  226. data/spec/opal/parser/heredoc_spec.rb +0 -30
  227. data/spec/opal/parser/iasgn_spec.rb +0 -9
  228. data/spec/opal/parser/if_spec.rb +0 -26
  229. data/spec/opal/parser/int_spec.rb +0 -13
  230. data/spec/opal/parser/iter_spec.rb +0 -59
  231. data/spec/opal/parser/ivar_spec.rb +0 -9
  232. data/spec/opal/parser/lambda_spec.rb +0 -64
  233. data/spec/opal/parser/lasgn_spec.rb +0 -8
  234. data/spec/opal/parser/line_spec.rb +0 -8
  235. data/spec/opal/parser/lvar_spec.rb +0 -38
  236. data/spec/opal/parser/masgn_spec.rb +0 -37
  237. data/spec/opal/parser/module_spec.rb +0 -27
  238. data/spec/opal/parser/nil_spec.rb +0 -17
  239. data/spec/opal/parser/not_spec.rb +0 -27
  240. data/spec/opal/parser/nth_ref_spec.rb +0 -13
  241. data/spec/opal/parser/op_asgn1_spec.rb +0 -23
  242. data/spec/opal/parser/op_asgn2_spec.rb +0 -23
  243. data/spec/opal/parser/or_spec.rb +0 -13
  244. data/spec/opal/parser/parse_spec.rb +0 -66
  245. data/spec/opal/parser/regexp_spec.rb +0 -16
  246. data/spec/opal/parser/return_spec.rb +0 -17
  247. data/spec/opal/parser/sclass_spec.rb +0 -21
  248. data/spec/opal/parser/self_spec.rb +0 -17
  249. data/spec/opal/parser/str_spec.rb +0 -107
  250. data/spec/opal/parser/string_spec.rb +0 -8
  251. data/spec/opal/parser/super_spec.rb +0 -20
  252. data/spec/opal/parser/true_spec.rb +0 -17
  253. data/spec/opal/parser/undef_spec.rb +0 -15
  254. data/spec/opal/parser/unless_spec.rb +0 -13
  255. data/spec/opal/parser/while_spec.rb +0 -15
  256. data/spec/opal/parser/xstr_spec.rb +0 -116
  257. data/spec/opal/parser/yield_spec.rb +0 -20
@@ -77,7 +77,7 @@ module Opal
77
77
  with_temp do |a| # args
78
78
  with_temp do |r| # recv
79
79
  cur = s(:call, s(:js_tmp, r), :[], s(:arglist, s(:js_tmp, a)))
80
- rhs = s(:call, cur, :+, s(:arglist, self.rhs))
80
+ rhs = s(:call, cur, op.to_sym, s(:arglist, self.rhs))
81
81
  call = s(:call, s(:js_tmp, r), :[]=, s(:arglist, s(:js_tmp, a), rhs))
82
82
 
83
83
  push "(#{a} = ", expr(first_arg), ", #{r} = ", expr(lhs)
@@ -17,8 +17,8 @@ module Opal
17
17
 
18
18
  in_scope do
19
19
  scope.name = name
20
- add_temp "#{scope.proto} = $#{name}._proto"
21
- add_temp "$scope = $#{name}._scope"
20
+ add_temp "#{scope.proto} = self._proto"
21
+ add_temp "$scope = self._scope"
22
22
 
23
23
  body_code = self.body_code
24
24
  empty_line
@@ -8,7 +8,9 @@ module Opal
8
8
  children :name
9
9
 
10
10
  def compile
11
- if compiler.const_missing?
11
+ if name == :DATA and compiler.eof_content
12
+ push("$__END__")
13
+ elsif compiler.const_missing?
12
14
  with_temp do |tmp|
13
15
  push "((#{tmp} = $scope.#{name}) == null ? $opal.cm('#{name}') : #{tmp})"
14
16
  end
@@ -3,31 +3,40 @@ module Opal
3
3
  module Helpers
4
4
 
5
5
  # Reserved javascript keywords - we cannot create variables with the
6
- # same name
7
- RESERVED = %w[
8
- arguments break case catch char class const continue debugger default
9
- delete do else enum export extends false finally for function if import
10
- in instanceof let native new return static switch super this throw try
11
- true typeof var void while with undefined
12
- ]
6
+ # same name (ref: http://stackoverflow.com/a/9337272/601782)
7
+ ES51_RESERVED_WORD = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/
8
+
9
+ # ES3 reserved words that aren’t ES5.1 reserved words
10
+ ES3_RESERVED_WORD_EXCLUSIVE = /^(?:int|byte|char|goto|long|final|float|short|double|native|throws|boolean|abstract|volatile|transient|synchronized)$/
11
+
12
+ # Immutable properties of the global object
13
+ IMMUTABLE_PROPS = /^(?:NaN|Infinity|undefined)$/
14
+
15
+ # Doesn't take in account utf8
16
+ BASIC_IDENTIFIER_RULES = /^[$_a-z][$_a-z\d]*$/i
17
+
13
18
 
14
19
  def property(name)
15
- reserved?(name) ? "['#{name}']" : ".#{name}"
20
+ valid_name?(name) ? ".#{name}" : "[#{name.inspect}]"
16
21
  end
17
22
 
18
- def reserved?(name)
19
- RESERVED.include? name
23
+ def valid_name?(name)
24
+ BASIC_IDENTIFIER_RULES =~ name and not(
25
+ ES51_RESERVED_WORD =~ name or
26
+ ES3_RESERVED_WORD_EXCLUSIVE =~ name or
27
+ IMMUTABLE_PROPS =~ name
28
+ )
20
29
  end
21
30
 
22
31
  def variable(name)
23
- reserved?(name.to_s) ? "#{name}$" : name
32
+ valid_name?(name.to_s) ? name : "#{name}$"
24
33
  end
25
34
 
26
35
  # Converts a ruby lvar/arg name to a js identifier. Not all ruby names
27
36
  # are valid in javascript. A $ suffix is added to non-valid names.
28
37
  # varibales
29
38
  def lvar_to_js(var)
30
- var = "#{var}$" if RESERVED.include? var.to_s
39
+ var = "#{var}$" unless valid_name? var.to_s
31
40
  var.to_sym
32
41
  end
33
42
 
@@ -67,7 +76,7 @@ module Opal
67
76
  end
68
77
 
69
78
  with_temp do |tmp|
70
- [fragment("(#{tmp} = "), expr(sexp), fragment(") !== false && #{tmp} !== nil")]
79
+ [fragment("((#{tmp} = "), expr(sexp), fragment(") !== nil && (!#{tmp}._isBoolean || #{tmp} == true))")]
71
80
  end
72
81
  end
73
82
 
@@ -81,7 +90,7 @@ module Opal
81
90
  end
82
91
 
83
92
  with_temp do |tmp|
84
- [fragment("(#{tmp} = "), expr(sexp), fragment(") === false || #{tmp} === nil")]
93
+ [fragment("((#{tmp} = "), expr(sexp), fragment(") === nil || (#{tmp}._isBoolean && #{tmp} == false))")]
85
94
  end
86
95
  end
87
96
 
@@ -7,21 +7,20 @@ module Opal
7
7
 
8
8
  children :test, :true_body, :false_body
9
9
 
10
+ RUBY_ENGINE_CHECK = [:call, [:const, :RUBY_ENGINE],
11
+ :==, [:arglist, [:str, "opal"]]]
12
+
13
+ RUBY_PLATFORM_CHECK = [:call, [:const, :RUBY_PLATFORM],
14
+ :==, [:arglist, [:str, "opal"]]]
15
+
10
16
  def compile
11
17
  truthy, falsy = self.truthy, self.falsy
12
18
 
13
- push "if ("
14
-
15
- # optimize unless (we don't want a else() unless we need to)
16
- if falsy and !truthy
17
- truthy = falsy
19
+ if skip_check_present?
18
20
  falsy = nil
19
- push js_falsy(test)
20
- else
21
- push js_truthy(test)
22
21
  end
23
22
 
24
- push ") {"
23
+ push "if (", js_truthy(test), ") {"
25
24
 
26
25
  # skip if-body if no truthy sexp
27
26
  indent { line stmt(truthy) } if truthy
@@ -44,6 +43,14 @@ module Opal
44
43
  wrap "(function() {", "; return nil; })()" if needs_wrapper?
45
44
  end
46
45
 
46
+ # pre-processing only effects falsy blocks. If engine is
47
+ # opal, then falsy block gets generated as normal. Unless
48
+ # engine is opal then that code gets generated as the
49
+ # falsy block
50
+ def skip_check_present?
51
+ test == RUBY_ENGINE_CHECK or test == RUBY_PLATFORM_CHECK
52
+ end
53
+
47
54
  def truthy
48
55
  needs_wrapper? ? compiler.returns(true_body || s(:nil)) : true_body
49
56
  end
@@ -44,14 +44,38 @@ module Opal
44
44
  class RegexpNode < Base
45
45
  handle :regexp
46
46
 
47
- children :value
47
+ children :value, :flags
48
48
 
49
49
  def compile
50
- push((value == // ? /^/ : value).inspect)
50
+ if value == ''
51
+ push('/^/')
52
+ else
53
+ push "#{Regexp.new(value).inspect}#{flags}"
54
+ end
55
+ end
56
+ end
57
+
58
+ module XStringLineSplitter
59
+ def compile_split_lines(value, sexp)
60
+ idx = 0
61
+ value.each_line do |line|
62
+ if idx == 0
63
+ push line
64
+ else
65
+ line_sexp = s()
66
+ line_sexp.source = [sexp.line + idx, 0]
67
+ frag = Fragment.new(line, line_sexp)
68
+ push frag
69
+ end
70
+
71
+ idx += 1
72
+ end
51
73
  end
52
74
  end
53
75
 
54
76
  class XStringNode < Base
77
+ include XStringLineSplitter
78
+
55
79
  handle :xstr
56
80
 
57
81
  children :value
@@ -61,11 +85,16 @@ module Opal
61
85
  end
62
86
 
63
87
  def compile
64
- push value.to_s
88
+ compile_split_lines(value.to_s, @sexp)
89
+
65
90
  push ';' if needs_semicolon?
66
91
 
67
92
  wrap '(', ')' if recv?
68
93
  end
94
+
95
+ def start_line
96
+ @sexp.line
97
+ end
69
98
  end
70
99
 
71
100
  class DynamicStringNode < Base
@@ -115,6 +144,8 @@ module Opal
115
144
  end
116
145
 
117
146
  class DynamicXStringNode < Base
147
+ include XStringLineSplitter
148
+
118
149
  handle :dxstr
119
150
 
120
151
  def requires_semicolon(code)
@@ -126,12 +157,13 @@ module Opal
126
157
 
127
158
  children.each do |part|
128
159
  if String === part
129
- push part.to_s
160
+ compile_split_lines(part.to_s, @sexp)
161
+
130
162
  needs_semicolon = true if requires_semicolon(part.to_s)
131
163
  elsif part.type == :evstr
132
164
  push expr(part[1])
133
165
  elsif part.type == :str
134
- push part.last.to_s
166
+ compile_split_lines(part.last.to_s, part)
135
167
  needs_semicolon = true if requires_semicolon(part.last.to_s)
136
168
  else
137
169
  raise "Bad dxstr part"
@@ -148,7 +148,13 @@ module Opal
148
148
  children :value
149
149
 
150
150
  def return_val
151
- expr_or_nil value
151
+ if value.nil?
152
+ expr(s(:nil))
153
+ elsif children.size > 1
154
+ expr(s(:array, *children))
155
+ else
156
+ expr(value)
157
+ end
152
158
  end
153
159
 
154
160
  def return_in_iter?
@@ -31,8 +31,8 @@ module Opal
31
31
  end
32
32
 
33
33
  def name_and_base
34
- if Symbol === cid or String === cid
35
- [cid.to_s, 'self']
34
+ if cid.type == :const
35
+ [cid[1].to_s, 'self']
36
36
  elsif cid.type == :colon2
37
37
  [cid[2].to_s, expr(cid[1])]
38
38
  elsif cid.type == :colon3
@@ -15,6 +15,7 @@ module Opal
15
15
 
16
16
  attr_reader :scope_name
17
17
  attr_reader :ivars
18
+ attr_reader :gvars
18
19
 
19
20
  attr_accessor :mid
20
21
 
@@ -37,6 +38,7 @@ module Opal
37
38
  @temps = []
38
39
  @args = []
39
40
  @ivars = []
41
+ @gvars = []
40
42
  @parent = nil
41
43
  @queue = []
42
44
  @unique = 'a'
@@ -124,9 +126,14 @@ module Opal
124
126
  "if (self#{ivar} == null) self#{ivar} = nil;\n"
125
127
  end
126
128
 
129
+ gv = gvars.map do |gvar|
130
+ "if ($gvars#{gvar} == null) $gvars#{gvar} = nil;\n"
131
+ end
132
+
127
133
  indent = @compiler.parser_indent
128
- res = vars.empty? ? '' : "var #{vars.join ', '};"
129
- str = ivars.empty? ? res : "#{res}\n#{indent}#{iv.join indent}"
134
+ str = vars.empty? ? '' : "var #{vars.join ', '};\n"
135
+ str += "#{indent}#{iv.join indent}" unless ivars.empty?
136
+ str += "#{indent}#{gv.join indent}" unless gvars.empty?
130
137
 
131
138
  if class? and !@proto_ivars.empty?
132
139
  #raise "FIXME to_vars"
@@ -156,6 +163,10 @@ module Opal
156
163
  end
157
164
  end
158
165
 
166
+ def add_scope_gvar(gvar)
167
+ @gvars << gvar unless @gvars.include? gvar
168
+ end
169
+
159
170
  def add_proto_ivar(ivar)
160
171
  @proto_ivars << ivar unless @proto_ivars.include? ivar
161
172
  end
@@ -27,6 +27,7 @@ module Opal
27
27
 
28
28
  compile_method_stubs
29
29
  compile_irb_vars
30
+ compile_end_construct
30
31
 
31
32
  line body_code
32
33
  end
@@ -57,6 +58,14 @@ module Opal
57
58
  end
58
59
  end
59
60
 
61
+ # Any special __END__ content in code
62
+ def compile_end_construct
63
+ if content = compiler.eof_content
64
+ line "var $__END__ = Opal.Object.$new();"
65
+ line "$__END__.$read = function() { return #{content.inspect}; };"
66
+ end
67
+ end
68
+
60
69
  def version_comment
61
70
  "/* Generated by Opal #{Opal::VERSION} */"
62
71
  end
@@ -88,7 +88,9 @@ module Opal
88
88
 
89
89
  def compile
90
90
  helper :gvars
91
- push "$gvars[#{var_name.inspect}]"
91
+ name = property var_name
92
+ add_gvar name
93
+ push "$gvars#{name}"
92
94
  end
93
95
  end
94
96
 
@@ -103,7 +105,8 @@ module Opal
103
105
 
104
106
  def compile
105
107
  helper :gvars
106
- push "$gvars[#{var_name.inspect}] = "
108
+ name = property var_name
109
+ push "$gvars#{name} = "
107
110
  push expr(value)
108
111
  end
109
112
  end
@@ -9,9 +9,10 @@ module Opal
9
9
  attr_reader :lexer, :file, :scope
10
10
 
11
11
  def parse(source, file = '(string)')
12
- @lexer = Lexer.new(source, file)
13
12
  @file = file
14
13
  @scopes = []
14
+ @lexer = Lexer.new(source, file)
15
+ @lexer.parser = self
15
16
 
16
17
  self.parse_to_sexp
17
18
  end
@@ -29,9 +30,7 @@ module Opal
29
30
  end
30
31
 
31
32
  def s(*parts)
32
- sexp = Sexp.new(parts)
33
- sexp.line = @lexer.line
34
- sexp
33
+ Sexp.new(parts)
35
34
  end
36
35
 
37
36
  def push_scope(type = nil)
@@ -48,29 +47,161 @@ module Opal
48
47
  end
49
48
 
50
49
  def on_error(t, val, vstack)
51
- raise "parse error on value #{val.inspect} (#{token_to_str(t) || '?'}) :#{@file}:#{lexer.line}"
50
+ raise "parse error on value #{value(val).inspect} (#{token_to_str(t) || '?'}) :#{@file}:#{lexer.line}"
51
+ end
52
+
53
+ def value(tok)
54
+ tok[0]
55
+ end
56
+
57
+ def source(tok)
58
+ tok ? tok[1] : nil
59
+ end
60
+
61
+ def s0(type, source)
62
+ sexp = s(type)
63
+ sexp.source = source
64
+ sexp
65
+ end
66
+
67
+ def s1(type, first, source)
68
+ sexp = s(type, first)
69
+ sexp.source = source
70
+ sexp
71
+ end
72
+
73
+ def new_nil(tok)
74
+ s0(:nil, source(tok))
75
+ end
76
+
77
+ def new_self(tok)
78
+ s0(:self, source(tok))
79
+ end
80
+
81
+ def new_true(tok)
82
+ s0(:true, source(tok))
83
+ end
84
+
85
+ def new_false(tok)
86
+ s0(:false, source(tok))
87
+ end
88
+
89
+ def new___FILE__(tok)
90
+ s1(:str, self.file, source(tok))
91
+ end
92
+
93
+ def new___LINE__(tok)
94
+ s1(:int, lexer.line, source(tok))
95
+ end
96
+
97
+ def new_ident(tok)
98
+ s1(:identifier, value(tok).to_sym, source(tok))
99
+ end
100
+
101
+ def new_int(tok)
102
+ s1(:int, value(tok), source(tok))
103
+ end
104
+
105
+ def new_float(tok)
106
+ s1(:float, value(tok), source(tok))
107
+ end
108
+
109
+ def new_ivar(tok)
110
+ s1(:ivar, value(tok).to_sym, source(tok))
111
+ end
112
+
113
+ def new_gvar(tok)
114
+ s1(:gvar, value(tok).to_sym, source(tok))
115
+ end
116
+
117
+ def new_cvar(tok)
118
+ s1(:cvar, value(tok).to_sym, source(tok))
119
+ end
120
+
121
+ def new_const(tok)
122
+ s1(:const, value(tok).to_sym, source(tok))
123
+ end
124
+
125
+ def new_colon2(lhs, tok, name)
126
+ sexp = s(:colon2, lhs, value(name).to_sym)
127
+ sexp.source = source(tok)
128
+ sexp
129
+ end
130
+
131
+ def new_colon3(tok, name)
132
+ s1(:colon3, value(name).to_sym, source(name))
133
+ end
134
+
135
+ def new_sym(tok)
136
+ s1(:sym, value(tok).to_sym, source(tok))
137
+ end
138
+
139
+ def new_alias(kw, new, old)
140
+ sexp = s(:alias, new, old)
141
+ sexp.source = source(kw)
142
+ sexp
143
+ end
144
+
145
+ def new_break(kw, args=nil)
146
+ if args.nil?
147
+ sexp = s(:break)
148
+ elsif args.length == 1
149
+ sexp = s(:break, args[0])
150
+ else
151
+ sexp = s(:break, s(:array, *args))
152
+ end
153
+
154
+ sexp
155
+ end
156
+
157
+ def new_return(kw, args=nil)
158
+ if args.nil?
159
+ sexp = s(:return)
160
+ elsif args.length == 1
161
+ sexp = s(:return, args[0])
162
+ else
163
+ sexp = s(:return, s(:array, *args))
164
+ end
165
+
166
+ sexp
167
+ end
168
+
169
+ def new_next(kw, args=[])
170
+ if args.length == 1
171
+ sexp = s(:next, args[0])
172
+ else
173
+ sexp = s(:next, s(:array, *args))
174
+ end
175
+
176
+ sexp
52
177
  end
53
178
 
54
179
  def new_block(stmt = nil)
55
- s = s(:block)
56
- s << stmt if stmt
57
- s
180
+ sexp = s(:block)
181
+ sexp << stmt if stmt
182
+ sexp
58
183
  end
59
184
 
60
185
  def new_compstmt(block)
61
- if block.size == 1
62
- nil
63
- elsif block.size == 2
64
- block[1]
186
+ comp = if block.size == 1
187
+ nil
188
+ elsif block.size == 2
189
+ block[1]
190
+ else
191
+ block
192
+ end
193
+
194
+ if comp && comp.type == :begin && comp.size == 2
195
+ result = comp[1]
65
196
  else
66
- block.line = block[1].line
67
- block
197
+ result = comp
68
198
  end
199
+
200
+ result
69
201
  end
70
202
 
71
203
  def new_body(compstmt, res, els, ens)
72
204
  s = compstmt || s(:block)
73
- s.line = compstmt.line if compstmt
74
205
 
75
206
  if res
76
207
  s = s(:rescue, s)
@@ -81,40 +212,87 @@ module Opal
81
212
  ens ? s(:ensure, s, ens) : s
82
213
  end
83
214
 
84
- def new_def(line, recv, name, args, body)
215
+ def new_def(kw, recv, name, args, body, end_tok)
85
216
  body = s(:block, body) if body.type != :block
86
217
  body << s(:nil) if body.size == 1
87
- args.line = line
88
- s = s(:def, recv, name.to_sym, args, body)
89
- s.line = line
90
- s.end_line = @lexer.line
91
- s
218
+
219
+ sexp = s(:def, recv, value(name).to_sym, args, body)
220
+ sexp.source = source(kw)
221
+ sexp
92
222
  end
93
223
 
94
- def new_class(path, sup, body)
95
- s(:class, path, sup, body)
224
+ def new_class(start, path, sup, body, endt)
225
+ sexp = s(:class, path, sup, body)
226
+ sexp.source = source(start)
227
+ sexp
96
228
  end
97
229
 
98
- def new_sclass(expr, body)
99
- s(:sclass, expr, body)
230
+ def new_sclass(kw, expr, body, end_tok)
231
+ sexp = s(:sclass, expr, body)
232
+ sexp.source = source(kw)
233
+ sexp
100
234
  end
101
235
 
102
- def new_module(path, body)
103
- s(:module, path, body)
236
+ def new_module(kw, path, body, end_tok)
237
+ sexp = s(:module, path, body)
238
+ sexp.source = source(kw)
239
+ sexp
104
240
  end
105
241
 
106
242
  def new_iter(args, body)
243
+ args ||= nil
107
244
  s = s(:iter, args)
108
245
  s << body if body
109
- s.end_line = @lexer.line
110
246
  s
111
247
  end
112
248
 
113
- def new_if(expr, stmt, tail)
114
- s = s(:if, expr, stmt, tail)
115
- s.line = expr.line
116
- s.end_line = @lexer.line
117
- s
249
+ def new_if(if_tok, expr, stmt, tail)
250
+ sexp = s(:if, expr, stmt, tail)
251
+ sexp.source = source(if_tok)
252
+ sexp
253
+ end
254
+
255
+ def new_while(kw, test, body)
256
+ sexp = s(:while, test, body)
257
+ sexp.source = source(kw)
258
+ sexp
259
+ end
260
+
261
+ def new_until(kw, test, body)
262
+ sexp = s(:until, test, body)
263
+ sexp.source = source(kw)
264
+ sexp
265
+ end
266
+
267
+ def new_rescue_mod(kw, expr, resc)
268
+ sexp = s(:rescue_mod, expr, resc)
269
+ sexp.source = source(kw)
270
+ sexp
271
+ end
272
+
273
+ def new_array(start, args, finish)
274
+ args ||= []
275
+ sexp = s(:array, *args)
276
+ sexp.source = source(start)
277
+ sexp
278
+ end
279
+
280
+ def new_hash(open, assocs, close)
281
+ sexp = s(:hash, *assocs)
282
+ sexp.source = source(open)
283
+ sexp
284
+ end
285
+
286
+ def new_not(kw, expr)
287
+ s1(:not, expr, source(kw))
288
+ end
289
+
290
+ def new_paren(open, expr, close)
291
+ if expr.nil? or expr == [:block]
292
+ s1(:paren, s0(:nil, source(open)), source(open))
293
+ else
294
+ s1(:paren, expr, source(open))
295
+ end
118
296
  end
119
297
 
120
298
  def new_args(norm, opt, rest, block)
@@ -171,7 +349,7 @@ module Opal
171
349
 
172
350
  if rest
173
351
  r = rest.to_s[1..-1].to_sym
174
- res << s(:splat, s(:lasgn, r))
352
+ res << new_splat(nil, s(:lasgn, r))
175
353
  scope.add_local r
176
354
  end
177
355
 
@@ -193,25 +371,42 @@ module Opal
193
371
  end
194
372
 
195
373
  def new_call(recv, meth, args = nil)
196
- call = s(:call, recv, meth)
197
- args = s(:arglist) unless args
198
- args.type = :arglist if args.type == :array
199
- call << args
200
-
201
- if recv
202
- call.line = recv.line
203
- elsif args[1]
204
- call.line = args[1].line
205
- end
374
+ args ||= []
375
+ sexp = s(:call, recv, value(meth).to_sym, s(:arglist, *args))
376
+ sexp.source = source(meth)
377
+ sexp
378
+ end
206
379
 
207
- # fix arglist spilling over into next line if no args
208
- if args.length == 1
209
- args.line = call.line
210
- else
211
- args.line = args[1].line
212
- end
380
+ def new_binary_call(recv, meth, arg)
381
+ new_call(recv, meth, [arg])
382
+ end
383
+
384
+ def new_unary_call(op, recv)
385
+ new_call(recv, op, [])
386
+ end
387
+
388
+ def new_and(lhs, tok, rhs)
389
+ sexp = s(:and, lhs, rhs)
390
+ sexp.source = source(tok)
391
+ sexp
392
+ end
393
+
394
+ def new_or(lhs, tok, rhs)
395
+ sexp = s(:or, lhs, rhs)
396
+ sexp.source = source(tok)
397
+ sexp
398
+ end
213
399
 
214
- call
400
+ def new_irange(beg, op, finish)
401
+ sexp = s(:irange, beg, finish)
402
+ sexp.source = source(op)
403
+ sexp
404
+ end
405
+
406
+ def new_erange(beg, op, finish)
407
+ sexp = s(:erange, beg, finish)
408
+ sexp.source = source(op)
409
+ sexp
215
410
  end
216
411
 
217
412
  def add_block_pass(arglist, block)
@@ -219,8 +414,16 @@ module Opal
219
414
  arglist
220
415
  end
221
416
 
417
+ def new_block_pass(amper_tok, val)
418
+ s1(:block_pass, val, source(amper_tok))
419
+ end
420
+
421
+ def new_splat(tok, value)
422
+ s1(:splat, value, source(tok))
423
+ end
424
+
222
425
  def new_op_asgn(op, lhs, rhs)
223
- case op
426
+ case value(op).to_sym
224
427
  when :"||"
225
428
  result = s(:op_asgn_or, new_gettable(lhs))
226
429
  result << (lhs << rhs)
@@ -229,15 +432,31 @@ module Opal
229
432
  result << (lhs << rhs)
230
433
  else
231
434
  result = lhs
232
- result << new_call(new_gettable(lhs), op, s(:arglist, rhs))
435
+ result << new_call(new_gettable(lhs), op, [rhs])
233
436
 
234
437
  end
235
438
 
236
- result.line = lhs.line
237
439
  result
238
440
  end
239
441
 
240
- def new_assign(lhs, rhs)
442
+ def new_op_asgn1(lhs, args, op, rhs)
443
+ arglist = s(:arglist, *args)
444
+ sexp = s(:op_asgn1, lhs, arglist, value(op), rhs)
445
+ sexp.source = source(op)
446
+ sexp
447
+ end
448
+
449
+ def op_to_setter(op)
450
+ "#{value(op)}=".to_sym
451
+ end
452
+
453
+ def new_attrasgn(recv, op, args=[])
454
+ arglist = s(:arglist, *args)
455
+ sexp = s(:attrasgn, recv, op, arglist)
456
+ sexp
457
+ end
458
+
459
+ def new_assign(lhs, tok, rhs)
241
460
  case lhs.type
242
461
  when :iasgn, :cdecl, :lasgn, :gasgn, :cvdecl, :nth_ref
243
462
  lhs << rhs
@@ -288,11 +507,13 @@ module Opal
288
507
  s(:gvar, ref[1])
289
508
  when :cvdecl
290
509
  s(:cvar, ref[1])
510
+ when :cdecl
511
+ s(:const, ref[1])
291
512
  else
292
513
  raise "Bad new_gettable ref: #{ref.type}"
293
514
  end
294
515
 
295
- res.line = ref.line
516
+ res.source = ref.source
296
517
  res
297
518
  end
298
519
 
@@ -311,32 +532,36 @@ module Opal
311
532
  # returns for __FILE__ as it is converted into str
312
533
  ref
313
534
  when :identifier
314
- if scope.has_local? ref[1]
315
- s(:lvar, ref[1])
316
- else
317
- s(:call, nil, ref[1], s(:arglist))
318
- end
535
+ result = if scope.has_local? ref[1]
536
+ s(:lvar, ref[1])
537
+ else
538
+ s(:call, nil, ref[1], s(:arglist))
539
+ end
540
+
541
+ result.source = ref.source
542
+ result
319
543
  else
320
544
  raise "Bad var_ref type: #{ref.type}"
321
545
  end
322
546
  end
323
547
 
324
- def new_super(args)
325
- args = (args || s(:arglist))
326
-
327
- if args.type == :array
328
- args.type = :arglist
548
+ def new_super(kw, args)
549
+ if args.nil?
550
+ sexp = s(:super, nil)
551
+ else
552
+ sexp = s(:super, s(:arglist, *args))
329
553
  end
330
554
 
331
- s(:super, args)
555
+ sexp.source = source(kw)
556
+ sexp
332
557
  end
333
558
 
334
559
  def new_yield(args)
335
- args = (args || s(:arglist))[1..-1]
560
+ args ||= []
336
561
  s(:yield, *args)
337
562
  end
338
563
 
339
- def new_xstr(str)
564
+ def new_xstr(start_t, str, end_t)
340
565
  return s(:xstr, '') unless str
341
566
  case str.type
342
567
  when :str then str.type = :xstr
@@ -344,6 +569,8 @@ module Opal
344
569
  when :evstr then str = s(:dxstr, '', str)
345
570
  end
346
571
 
572
+ str.source = source(start_t)
573
+
347
574
  str
348
575
  end
349
576
 
@@ -360,6 +587,10 @@ module Opal
360
587
  str
361
588
  end
362
589
 
590
+ def new_evstr(str)
591
+ s(:evstr, str)
592
+ end
593
+
363
594
  def new_str(str)
364
595
  # cover empty strings
365
596
  return s(:str, "") unless str
@@ -379,10 +610,10 @@ module Opal
379
610
  end
380
611
 
381
612
  def new_regexp(reg, ending)
382
- return s(:regexp, //) unless reg
613
+ return s(:regexp, '') unless reg
383
614
  case reg.type
384
615
  when :str
385
- s(:regexp, Regexp.new(reg[1], ending))
616
+ s(:regexp, reg[1], value(ending))
386
617
  when :evstr
387
618
  s(:dregx, "", reg)
388
619
  when :dstr
@@ -405,5 +636,9 @@ module Opal
405
636
  str << str2
406
637
  str
407
638
  end
639
+
640
+ def new_str_content(tok)
641
+ s1(:str, value(tok), source(tok))
642
+ end
408
643
  end
409
644
  end