opal 0.3.2 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +85 -127
- data/bin/opal +3 -3
- data/lib/core.rb +114 -0
- data/{gems/core/lib → lib}/core/array.rb +68 -187
- data/{gems/core/lib → lib}/core/basic_object.rb +22 -5
- data/lib/core/class.rb +38 -0
- data/{gems/core/lib → lib}/core/dir.rb +1 -1
- data/lib/core/enumerable.rb +33 -0
- data/{gems/core/lib → lib}/core/error.rb +1 -4
- data/{gems/core/lib → lib}/core/false_class.rb +0 -0
- data/{gems/core/lib → lib}/core/file.rb +11 -3
- data/{gems/core/lib → lib}/core/hash.rb +12 -0
- data/{gems/core/lib → lib}/core/kernel.rb +114 -86
- data/lib/core/match_data.rb +33 -0
- data/lib/core/module.rb +97 -0
- data/{gems/core/lib → lib}/core/nil_class.rb +0 -0
- data/{gems/core/lib → lib}/core/numeric.rb +5 -0
- data/{gems/core/lib → lib}/core/object.rb +0 -0
- data/{gems/core/lib → lib}/core/proc.rb +13 -3
- data/{gems/core/lib → lib}/core/range.rb +10 -0
- data/{gems/core/lib → lib}/core/regexp.rb +33 -1
- data/{gems/core/lib → lib}/core/string.rb +25 -10
- data/{gems/core/lib → lib}/core/symbol.rb +3 -3
- data/{gems/core/lib → lib}/core/top_self.rb +0 -0
- data/{gems/core/lib → lib}/core/true_class.rb +0 -0
- data/lib/dev.rb +169 -0
- data/{gems/ospec/lib → lib}/ospec.rb +1 -0
- data/lib/ospec/autorun.rb +8 -0
- data/{gems/ospec/lib → lib}/ospec/dsl.rb +2 -2
- data/{gems/ospec/lib → lib}/ospec/example.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/example/before_and_after_hooks.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/example/errors.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/example/example_group.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/example/example_group_factory.rb +0 -3
- data/{gems/ospec/lib → lib}/ospec/example/example_group_hierarchy.rb +4 -3
- data/{gems/ospec/lib → lib}/ospec/example/example_group_methods.rb +1 -1
- data/{gems/ospec/lib → lib}/ospec/example/example_group_proxy.rb +3 -2
- data/{gems/ospec/lib → lib}/ospec/example/example_methods.rb +1 -1
- data/{gems/ospec/lib → lib}/ospec/example/example_proxy.rb +7 -7
- data/{gems/ospec/lib → lib}/ospec/expectations.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/expectations/errors.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/expectations/fail_with.rb +4 -3
- data/{gems/ospec/lib → lib}/ospec/expectations/handler.rb +6 -0
- data/lib/ospec/helpers/scratch.rb +18 -0
- data/{gems/ospec/lib → lib}/ospec/matchers.rb +2 -2
- data/{gems/ospec/lib → lib}/ospec/matchers/be.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/matchers/generated_descriptions.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/matchers/operator_matcher.rb +2 -0
- data/lib/ospec/matchers/raise_error.rb +38 -0
- data/lib/ospec/runner.rb +90 -0
- data/{gems/ospec/lib → lib}/ospec/runner/example_group_runner.rb +10 -13
- data/lib/ospec/runner/formatter/html_formatter.rb +139 -0
- data/{gems/ospec/lib → lib}/ospec/runner/formatter/terminal_formatter.rb +0 -0
- data/{gems/ospec/lib → lib}/ospec/runner/options.rb +1 -3
- data/{gems/ospec/lib → lib}/ospec/runner/reporter.rb +0 -9
- data/lib/racc/parser.rb +165 -0
- data/lib/strscan.rb +52 -0
- data/{lib → opal_lib}/opal.rb +2 -0
- data/opal_lib/opal/build_methods.rb +51 -0
- data/opal_lib/opal/builder.rb +164 -0
- data/opal_lib/opal/bundle.rb +70 -0
- data/opal_lib/opal/command.rb +68 -0
- data/{lib → opal_lib}/opal/context.rb +21 -9
- data/{lib → opal_lib}/opal/context/console.rb +0 -2
- data/opal_lib/opal/context/file_system.rb +34 -0
- data/{lib → opal_lib}/opal/context/loader.rb +26 -8
- data/opal_lib/opal/gem.rb +84 -0
- data/{lib → opal_lib}/opal/rake/builder_task.rb +2 -2
- data/opal_lib/opal/rake/spec_task.rb +32 -0
- data/{lib → opal_lib}/opal/ruby/nodes.rb +730 -109
- data/{lib → opal_lib}/opal/ruby/parser.rb +90 -23
- data/opal_lib/opal/ruby/ruby_parser.rb +4862 -0
- data/opal_lib/opal/ruby/ruby_parser.y +1454 -0
- data/opal_lib/opal/version.rb +4 -0
- data/runtime/class.js +359 -0
- data/runtime/debug.js +84 -0
- data/runtime/fs.js +199 -0
- data/runtime/init.js +558 -0
- data/runtime/loader.js +351 -0
- data/runtime/module.js +109 -0
- data/runtime/post.js +10 -0
- data/runtime/pre.js +7 -0
- data/runtime/runtime.js +351 -0
- metadata +88 -175
- data/.gitignore +0 -7
- data/Changelog +0 -31
- data/LICENSE +0 -75
- data/Rakefile +0 -86
- data/gems/core/README.md +0 -14
- data/gems/core/Rakefile +0 -8
- data/gems/core/core.gemspec +0 -13
- data/gems/core/lib/core.rb +0 -34
- data/gems/core/lib/core/class.rb +0 -31
- data/gems/core/lib/core/module.rb +0 -100
- data/gems/core/lib/core/vm.rb +0 -16
- data/gems/core/spec/core/array/append_spec.rb +0 -30
- data/gems/core/spec/core/array/assoc_spec.rb +0 -29
- data/gems/core/spec/core/array/at_spec.rb +0 -37
- data/gems/core/spec/core/array/clear_spec.rb +0 -22
- data/gems/core/spec/core/array/collect_bang_spec.rb +0 -27
- data/gems/core/spec/core/array/collect_spec.rb +0 -27
- data/gems/core/spec/core/array/compact_spec.rb +0 -41
- data/gems/core/spec/core/array/concat_spec.rb +0 -15
- data/gems/core/spec/core/array/constructor_spec.rb +0 -14
- data/gems/core/spec/core/array/each_spec.rb +0 -9
- data/gems/core/spec/core/array/element_reference_spec.rb +0 -4
- data/gems/core/spec/core/array/first_spec.rb +0 -35
- data/gems/core/spec/core/array/include_spec.rb +0 -9
- data/gems/core/spec/core/array/join_spec.rb +0 -6
- data/gems/core/spec/core/array/last_spec.rb +0 -51
- data/gems/core/spec/core/array/length_spec.rb +0 -6
- data/gems/core/spec/core/array/map_spec.rb +0 -33
- data/gems/core/spec/core/array/reverse_spec.rb +0 -6
- data/gems/core/spec/core/builtin_constants/builtin_constants_spec.rb +0 -7
- data/gems/core/spec/core/false/and_spec.rb +0 -10
- data/gems/core/spec/core/false/inspect_spec.rb +0 -6
- data/gems/core/spec/core/false/or_spec.rb +0 -10
- data/gems/core/spec/core/false/to_s_spec.rb +0 -6
- data/gems/core/spec/core/false/xor_spec.rb +0 -10
- data/gems/core/spec/core/file/join_spec.rb +0 -19
- data/gems/core/spec/core/hash/assoc_spec.rb +0 -32
- data/gems/core/spec/core/kernel/instance_eval_spec.rb +0 -0
- data/gems/core/spec/core/kernel/loop_spec.rb +0 -24
- data/gems/core/spec/core/kernel/raise_spec.rb +0 -0
- data/gems/core/spec/core/module/attr_accessor_spec.rb +0 -28
- data/gems/core/spec/core/number/lt_spec.rb +0 -12
- data/gems/core/spec/core/string/sub_spec.rb +0 -24
- data/gems/core/spec/core/true/and_spec.rb +0 -10
- data/gems/core/spec/core/true/inspect_spec.rb +0 -6
- data/gems/core/spec/core/true/or_spec.rb +0 -10
- data/gems/core/spec/core/true/to_s_spec.rb +0 -6
- data/gems/core/spec/core/true/xor_spec.rb +0 -10
- data/gems/core/spec/language/and_spec.rb +0 -61
- data/gems/core/spec/language/array_spec.rb +0 -68
- data/gems/core/spec/language/block_spec.rb +0 -38
- data/gems/core/spec/language/break_spec.rb +0 -36
- data/gems/core/spec/language/case_spec.rb +0 -103
- data/gems/core/spec/language/def_spec.rb +0 -21
- data/gems/core/spec/language/eigenclass_spec.rb +0 -60
- data/gems/core/spec/language/file_spec.rb +0 -13
- data/gems/core/spec/language/fixtures/block.rb +0 -21
- data/gems/core/spec/language/fixtures/super.rb +0 -293
- data/gems/core/spec/language/hash_spec.rb +0 -29
- data/gems/core/spec/language/if_spec.rb +0 -54
- data/gems/core/spec/language/loop_spec.rb +0 -11
- data/gems/core/spec/language/metaclass_spec.rb +0 -21
- data/gems/core/spec/language/method_spec.rb +0 -124
- data/gems/core/spec/language/next_spec.rb +0 -25
- data/gems/core/spec/language/or_spec.rb +0 -34
- data/gems/core/spec/language/redo_spec.rb +0 -24
- data/gems/core/spec/language/regexp_spec.rb +0 -26
- data/gems/core/spec/language/rescue_spec.rb +0 -20
- data/gems/core/spec/language/return_spec.rb +0 -47
- data/gems/core/spec/language/string_spec.rb +0 -25
- data/gems/core/spec/language/super_spec.rb +0 -32
- data/gems/core/spec/language/until_spec.rb +0 -157
- data/gems/core/spec/language/variables_spec.rb +0 -155
- data/gems/core/spec/language/while_spec.rb +0 -163
- data/gems/core/spec/spec_helper.rb +0 -5
- data/gems/core_fs/README.md +0 -19
- data/gems/dev/Rakefile +0 -5
- data/gems/dev/lib/dev.js +0 -99
- data/gems/dev/lib/dev/generator.js +0 -1264
- data/gems/dev/lib/dev/parser.js +0 -979
- data/gems/dev/lib/dev/ruby_parser.js +0 -1088
- data/gems/dev/lib/dev/ruby_parser.y +0 -1267
- data/gems/dev/lib/dev/string_scanner.js +0 -38
- data/gems/dev/tools/racc2js/README.md +0 -39
- data/gems/dev/tools/racc2js/math_parser.js +0 -222
- data/gems/dev/tools/racc2js/math_parser.rb +0 -133
- data/gems/dev/tools/racc2js/math_parser.y +0 -28
- data/gems/dev/tools/racc2js/parser.js +0 -218
- data/gems/dev/tools/racc2js/racc2js.rb +0 -153
- data/gems/json/README.md +0 -4
- data/gems/json/json.gemspec +0 -14
- data/gems/json/lib/json.rb +0 -64
- data/gems/json/lib/json/ext.rb +0 -51
- data/gems/json/lib/json/json2.js +0 -481
- data/gems/ospec/README.md +0 -0
- data/gems/ospec/lib/ospec/autorun.rb +0 -3
- data/gems/ospec/lib/ospec/runner.rb +0 -40
- data/gems/ospec/lib/ospec/runner/formatter/html_formatter.rb +0 -91
- data/gems/ospec/ospec.gemspec +0 -0
- data/gems/rquery/README.md +0 -9
- data/gems/rquery/lib/rquery.rb +0 -10
- data/gems/rquery/lib/rquery/ajax.rb +0 -4
- data/gems/rquery/lib/rquery/css.rb +0 -96
- data/gems/rquery/lib/rquery/document.rb +0 -25
- data/gems/rquery/lib/rquery/element.rb +0 -292
- data/gems/rquery/lib/rquery/event.rb +0 -108
- data/gems/rquery/lib/rquery/jquery.js +0 -8177
- data/gems/rquery/lib/rquery/request.rb +0 -138
- data/gems/rquery/lib/rquery/response.rb +0 -49
- data/gems/rquery/rquery.gemspec +0 -16
- data/lib/opal.js +0 -1597
- data/lib/opal/builder.rb +0 -117
- data/lib/opal/bundle.rb +0 -131
- data/lib/opal/command.rb +0 -11
- data/lib/opal/context/file_system.rb +0 -19
- data/lib/opal/gem.rb +0 -153
- data/lib/opal/ruby/ruby_parser.rb +0 -5170
- data/lib/opal/ruby/ruby_parser.y +0 -1298
- data/opal.gemspec +0 -15
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
module Opal
|
2
|
+
class RubyParser < Racc::Parser
|
2
3
|
|
3
4
|
# Indent for generated code scopes; 2 spaces, never use tabs
|
4
5
|
INDENT = ' '
|
@@ -90,6 +91,28 @@ class Opal::RubyParser < Racc::Parser
|
|
90
91
|
@temp_queue = []
|
91
92
|
# ivars..we need to make sure these exist (make sure they are nil if new)
|
92
93
|
@ivars = []
|
94
|
+
|
95
|
+
# keep tabs on whether in while loop or not
|
96
|
+
@while_scope = 0
|
97
|
+
@while_scope_stack = []
|
98
|
+
end
|
99
|
+
|
100
|
+
def push_while_scope(while_scope)
|
101
|
+
@while_scope_stack << while_scope
|
102
|
+
@while_scope += 1
|
103
|
+
end
|
104
|
+
|
105
|
+
def pop_while_scope
|
106
|
+
@while_scope_stack.pop
|
107
|
+
@while_scope -= 1
|
108
|
+
end
|
109
|
+
|
110
|
+
def in_while_scope?
|
111
|
+
@while_scope > 0
|
112
|
+
end
|
113
|
+
|
114
|
+
def while_scope
|
115
|
+
@while_scope_stack.last
|
93
116
|
end
|
94
117
|
|
95
118
|
def ensure_ivar(name)
|
@@ -163,45 +186,76 @@ class Opal::RubyParser < Racc::Parser
|
|
163
186
|
# keep track of the current line number in the generator
|
164
187
|
attr_accessor :line
|
165
188
|
|
189
|
+
# expose top level options... useful for certain nodes to know if we are
|
190
|
+
# debug mode etc
|
191
|
+
attr_reader :opts
|
192
|
+
|
166
193
|
def initialize(statements)
|
167
194
|
super nil, statements
|
168
195
|
@file_helpers = []
|
169
196
|
@line = 1
|
170
197
|
@mm_ids = []
|
198
|
+
|
199
|
+
@symbol_refs = {}
|
200
|
+
@symbol_count = 1
|
201
|
+
|
202
|
+
@regexp_refs = []
|
171
203
|
end
|
172
204
|
|
173
|
-
# Register a method name that needs to be called to $opal.mm. This method
|
174
|
-
# will remove duplicates.
|
175
205
|
def register_mm_id(mid)
|
176
206
|
@mm_ids << mid unless @mm_ids.include? mid
|
177
207
|
end
|
178
208
|
|
209
|
+
def register_symbol(sym)
|
210
|
+
if ref = @symbol_refs[sym]
|
211
|
+
ref
|
212
|
+
else
|
213
|
+
ref = @symbol_refs[sym] = "$symbol_#{@symbol_count}"
|
214
|
+
@symbol_count += 1
|
215
|
+
ref
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
179
219
|
def generate(opts, level)
|
220
|
+
@opts = opts
|
180
221
|
code = []
|
181
|
-
|
222
|
+
@statements.returns
|
223
|
+
# code << super(opts, level)
|
224
|
+
code << @statements.generate(opts, level)
|
225
|
+
|
226
|
+
pre = 'function $$(){'
|
227
|
+
post = "\n}\n"
|
228
|
+
# post = "\n\n}\nvar nil, $ac, $super, $break, $class, $def, $symbol, $range, "
|
229
|
+
# post += '$hash, $B, Qtrue, Qfalse, $cg;'
|
230
|
+
# local vars... only if we used any..
|
231
|
+
unless @scope_vars.empty?
|
232
|
+
post += "var #{@scope_vars.join ', '};"
|
233
|
+
end
|
182
234
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
235
|
+
post += 'var nil = $rb.Qnil, $ac = $rb.ac, $super = $rb.S, $break = $rb.B, '
|
236
|
+
post += '$class = $rb.dc, $defn = $rb.dm, $defs = $rb.ds, $symbol = $rb.Y, '
|
237
|
+
post += '$hash = $rb.H, $B = $rb.P, Qtrue = $rb.Qtrue, Qfalse = $rb.Qfalse, '
|
238
|
+
post += '$cg = $rb.cg, $range = $rb.G'
|
187
239
|
|
188
|
-
#
|
189
|
-
|
190
|
-
|
191
|
-
pre += mm_ids
|
240
|
+
# symbols
|
241
|
+
@symbol_refs.each do |val, sym|
|
242
|
+
post += ", #{sym} = $symbol('#{val}')"
|
192
243
|
end
|
193
244
|
|
194
|
-
|
195
|
-
|
196
|
-
|
245
|
+
post += ';'
|
246
|
+
|
247
|
+
if @mm_ids.length > 0
|
248
|
+
post += "$rb.mm(['#{ @mm_ids.join "', '" }']);"
|
197
249
|
end
|
198
250
|
|
199
251
|
# ivars
|
200
252
|
@ivars.each do |ivar|
|
201
|
-
|
253
|
+
post += "if (self['#{ivar}'] == undefined) { self['#{ivar}'] = nil; }"
|
202
254
|
end
|
203
255
|
|
204
|
-
|
256
|
+
post += "return $$();\n"
|
257
|
+
|
258
|
+
pre + code.join('') + post
|
205
259
|
end
|
206
260
|
end
|
207
261
|
|
@@ -229,7 +283,7 @@ class Opal::RubyParser < Racc::Parser
|
|
229
283
|
return NilNode.new.generate(opts, level) if @nodes.empty?
|
230
284
|
|
231
285
|
@nodes.each do |node|
|
232
|
-
node_code = node.process opts,
|
286
|
+
node_code = node.process opts, level
|
233
287
|
|
234
288
|
if level <= LEVEL_TOP_CLOSURE
|
235
289
|
# to prevent lots of trailing whitespace when we generate statements
|
@@ -274,6 +328,8 @@ class Opal::RubyParser < Racc::Parser
|
|
274
328
|
|
275
329
|
class NumericNode < BaseNode
|
276
330
|
|
331
|
+
attr_accessor :value
|
332
|
+
|
277
333
|
def initialize(val)
|
278
334
|
@line = val[:line]
|
279
335
|
@value = val[:value]
|
@@ -292,7 +348,7 @@ class Opal::RubyParser < Racc::Parser
|
|
292
348
|
end
|
293
349
|
|
294
350
|
def generate(opts, level)
|
295
|
-
|
351
|
+
opts[:top].register_symbol @value
|
296
352
|
end
|
297
353
|
end
|
298
354
|
|
@@ -315,8 +371,6 @@ class Opal::RubyParser < Racc::Parser
|
|
315
371
|
def mid_to_jsid(id)
|
316
372
|
return ".$m['#{id}']" if /[\!\=\?\+\-\*\/\^\&\%\@\|\[\]\<\>\~]/ =~ id
|
317
373
|
|
318
|
-
# FIXME: if our id is a reserved word in js, we need to also wrap it in
|
319
|
-
# brackets.
|
320
374
|
return ".$m['#{id}']" if js_reserved_words.include? id
|
321
375
|
|
322
376
|
# default we just do .method_name
|
@@ -332,26 +386,48 @@ class Opal::RubyParser < Racc::Parser
|
|
332
386
|
end
|
333
387
|
|
334
388
|
def generate(opts, level)
|
335
|
-
|
389
|
+
# Special handlers
|
390
|
+
if @recv.is_a? NumericNode and @mid == '-@'
|
391
|
+
@recv.value = "-#{@recv.value}"
|
392
|
+
return @recv.generate opts, level
|
393
|
+
|
394
|
+
elsif @mid == "block_given?"
|
395
|
+
# name = opts[:scope].set_uses_block
|
396
|
+
return "($yy == $y.y ? Qfalse : Qtrue)"
|
397
|
+
end
|
336
398
|
|
337
|
-
|
338
|
-
|
399
|
+
code = ''
|
400
|
+
arg_res = []
|
401
|
+
recv = nil
|
402
|
+
mid = @mid
|
339
403
|
tmp_recv = opts[:scope].temp_local
|
340
404
|
|
405
|
+
opts[:top].register_mm_id @mid
|
406
|
+
|
341
407
|
# receiver
|
342
408
|
if @recv.is_a? NumericNode
|
343
409
|
recv = "(#{@recv.process opts, LEVEL_EXPR})"
|
344
410
|
elsif @recv
|
345
411
|
recv = @recv.process opts, LEVEL_EXPR
|
346
412
|
else
|
347
|
-
recv = SelfNode.new
|
413
|
+
@recv = SelfNode.new
|
414
|
+
recv = "self"
|
415
|
+
mid = '$' + mid
|
348
416
|
end
|
349
417
|
|
350
|
-
|
351
|
-
|
418
|
+
mid = mid_to_jsid(mid)
|
419
|
+
|
420
|
+
if @recv.is_a? SelfNode
|
421
|
+
recv_code = recv
|
422
|
+
recv_arg = recv
|
423
|
+
elsif @recv.is_a?(IdentifierNode) and @recv.local_variable?(opts)
|
424
|
+
recv_code = recv
|
425
|
+
recv_arg = recv
|
426
|
+
else
|
427
|
+
recv_code = "(#{tmp_recv} = #{recv})"
|
428
|
+
recv_arg = "#{tmp_recv}"
|
429
|
+
end
|
352
430
|
|
353
|
-
# Register our method_id to ensure $opal.mm gets it
|
354
|
-
opts[:top].register_mm_id @mid
|
355
431
|
|
356
432
|
args = @args
|
357
433
|
# normal args
|
@@ -367,18 +443,13 @@ class Opal::RubyParser < Racc::Parser
|
|
367
443
|
end
|
368
444
|
|
369
445
|
if @block
|
370
|
-
# tmp_self = opts[:scope].temp_local
|
371
|
-
tmp_args = opts[:scope].temp_local
|
372
446
|
block = @block.generate opts, LEVEL_TOP
|
373
|
-
arg_res.unshift
|
447
|
+
arg_res.unshift recv_arg
|
374
448
|
|
375
|
-
code = "(
|
376
|
-
code += "
|
377
|
-
code += ", ($block.f = #{tmp_recv}#{mid}).apply(#{tmp_recv}, #{tmp_args}))"
|
449
|
+
code = "($B.f = #{recv_code}#{mid}, ($B.p ="
|
450
|
+
code += "#{block}).$proc =[self], $B.f)(#{arg_res.join ', '})"
|
378
451
|
|
379
452
|
opts[:scope].queue_temp tmp_recv
|
380
|
-
opts[:scope].queue_temp tmp_args
|
381
|
-
|
382
453
|
code
|
383
454
|
|
384
455
|
# &to_proc. Note, this must not reassign the $self for the proc.. we are
|
@@ -386,16 +457,12 @@ class Opal::RubyParser < Racc::Parser
|
|
386
457
|
#
|
387
458
|
# FIXME need to actually call to_proc.
|
388
459
|
elsif args[3]
|
389
|
-
|
390
|
-
|
391
|
-
arg_res.unshift tmp_recv
|
460
|
+
arg_res.unshift recv_arg
|
392
461
|
|
393
|
-
code = "(
|
394
|
-
code += "
|
395
|
-
code += ", ($block.f = #{tmp_recv}#{mid}).apply(#{tmp_recv}, #{tmp_args}))"
|
462
|
+
code = "($B.p = #{args[3].process opts, LEVEL_LIST}, "
|
463
|
+
code += "$B.f = #{recv_code}#{mid})(#{arg_res.join ', '})"
|
396
464
|
|
397
465
|
opts[:scope].queue_temp tmp_recv
|
398
|
-
opts[:scope].queue_temp tmp_args
|
399
466
|
|
400
467
|
code
|
401
468
|
|
@@ -403,22 +470,20 @@ class Opal::RubyParser < Racc::Parser
|
|
403
470
|
else
|
404
471
|
# splat args
|
405
472
|
if args[1]
|
406
|
-
arg_res.unshift
|
473
|
+
arg_res.unshift recv_arg
|
407
474
|
splat = args[1].generate(opts, LEVEL_EXPR)
|
408
|
-
splat_args = arg_res.empty? ? splat : "[#{arg_res.join ', '}].concat(#{splat})"
|
475
|
+
splat_args = arg_res.empty? ? "#{splat}" : "[#{arg_res.join ', '}].concat(#{splat})"
|
409
476
|
# when using splat, our this val for apply may need a tmp var
|
410
477
|
# to save just outputting it twice (have to follow recv path twice)
|
411
478
|
splat_recv = recv
|
412
|
-
result = "
|
479
|
+
result = "#{recv_code}" + mid + ".apply(nil, #{splat_args})"
|
413
480
|
|
414
481
|
opts[:scope].queue_temp tmp_recv
|
415
482
|
result
|
416
483
|
else
|
417
|
-
arg_res.unshift
|
484
|
+
arg_res.unshift recv_arg
|
418
485
|
|
419
|
-
result = "
|
420
|
-
|
421
|
-
# requeue the tmp receiver as we are done with it and return
|
486
|
+
result = "#{recv_code}#{mid}(#{arg_res.join(', ')})"
|
422
487
|
opts[:scope].queue_temp tmp_recv
|
423
488
|
result
|
424
489
|
end
|
@@ -466,7 +531,7 @@ class Opal::RubyParser < Racc::Parser
|
|
466
531
|
if @base.nil?
|
467
532
|
code += SelfNode.new.generate(opts, level)
|
468
533
|
else
|
469
|
-
code +=
|
534
|
+
code += @base.generate(opts, level)
|
470
535
|
end
|
471
536
|
|
472
537
|
code += ', '
|
@@ -479,9 +544,14 @@ class Opal::RubyParser < Racc::Parser
|
|
479
544
|
|
480
545
|
# scope
|
481
546
|
scope = { :indent => opts[:indent] + INDENT, :top => opts[:top], :scope => self }
|
547
|
+
@statements.returns
|
482
548
|
stmt = @statements.generate scope, LEVEL_TOP
|
483
549
|
|
484
|
-
|
550
|
+
if @scope_vars.empty?
|
551
|
+
code += ('function(self) { ' + stmt)
|
552
|
+
else
|
553
|
+
code += "function(self) {var #{@scope_vars.join ', '};#{stmt}"
|
554
|
+
end
|
485
555
|
|
486
556
|
# fix line ending
|
487
557
|
code += fix_line_number opts, @end_line
|
@@ -495,7 +565,6 @@ class Opal::RubyParser < Racc::Parser
|
|
495
565
|
|
496
566
|
def initialize(cls, path, sup, body, _end)
|
497
567
|
super nil, body
|
498
|
-
@scope_vars << 'self = this'
|
499
568
|
@line = cls[:line]
|
500
569
|
@base = path[0]
|
501
570
|
@cls_name = path[1]
|
@@ -507,7 +576,7 @@ class Opal::RubyParser < Racc::Parser
|
|
507
576
|
code = '$class('
|
508
577
|
|
509
578
|
# base
|
510
|
-
code += (@base.nil? ? SelfNode.new.generate(opts, level) :
|
579
|
+
code += (@base.nil? ? SelfNode.new.generate(opts, level) : @base.generate(opts, level))
|
511
580
|
code += ', '
|
512
581
|
|
513
582
|
# superclass
|
@@ -519,8 +588,14 @@ class Opal::RubyParser < Racc::Parser
|
|
519
588
|
|
520
589
|
# scope
|
521
590
|
scope = { :indent => opts[:indent] + INDENT, :top => opts[:top], :scope => self }
|
591
|
+
@statements.returns
|
522
592
|
stmt = @statements.generate scope, level
|
523
|
-
|
593
|
+
|
594
|
+
if @scope_vars.empty?
|
595
|
+
code += "function(self) {#{stmt}"
|
596
|
+
else
|
597
|
+
code += "function(self) { var #{@scope_vars.join ', '};#{stmt}"
|
598
|
+
end
|
524
599
|
|
525
600
|
# fix trailing line number
|
526
601
|
code += fix_line_number opts, @end_line
|
@@ -530,6 +605,41 @@ class Opal::RubyParser < Racc::Parser
|
|
530
605
|
end
|
531
606
|
end
|
532
607
|
|
608
|
+
class ClassShiftNode < ScopeNode
|
609
|
+
|
610
|
+
def initialize(cls, expr, body, endn)
|
611
|
+
super nil, body
|
612
|
+
@line = cls[:line]
|
613
|
+
@expr = expr
|
614
|
+
@end_line = endn[:line]
|
615
|
+
end
|
616
|
+
|
617
|
+
def generate(opts, level)
|
618
|
+
code = '$class('
|
619
|
+
|
620
|
+
# base
|
621
|
+
code += @expr.generate(opts, level)
|
622
|
+
code += ', nil, nil, '
|
623
|
+
|
624
|
+
# scope
|
625
|
+
scope = { :indent => opts[:indent] + INDENT, :top => opts[:top], :scope => self }
|
626
|
+
@statements.returns
|
627
|
+
stmt = @statements.generate scope, level
|
628
|
+
|
629
|
+
if @scope_vars.empty?
|
630
|
+
code += "function(self) {#{stmt}"
|
631
|
+
else
|
632
|
+
code += "function(self) { var #{@scope_vars.join ', '};#{stmt}"
|
633
|
+
end
|
634
|
+
|
635
|
+
# fix trailing line number
|
636
|
+
code += fix_line_number opts, @end_line
|
637
|
+
|
638
|
+
code += opts[:indent] + '}, 1)'
|
639
|
+
code
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
533
643
|
class DefNode < ScopeNode
|
534
644
|
|
535
645
|
def initialize(defn, singleton, fname, args, body, endn)
|
@@ -544,11 +654,11 @@ class Opal::RubyParser < Racc::Parser
|
|
544
654
|
end
|
545
655
|
|
546
656
|
def generate(opts, level)
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
657
|
+
if @singleton
|
658
|
+
code = "$defs(#{@singleton.generate opts, level}, "
|
659
|
+
else
|
660
|
+
code = "$defn(self, "
|
661
|
+
end
|
552
662
|
|
553
663
|
# method id
|
554
664
|
code += "'#{@fname[:value]}', "
|
@@ -571,6 +681,8 @@ class Opal::RubyParser < Racc::Parser
|
|
571
681
|
end
|
572
682
|
end
|
573
683
|
|
684
|
+
arity = method_args.length
|
685
|
+
|
574
686
|
# optional args
|
575
687
|
if args[1]
|
576
688
|
args[1].each do |arg|
|
@@ -582,23 +694,27 @@ class Opal::RubyParser < Racc::Parser
|
|
582
694
|
|
583
695
|
# rest args
|
584
696
|
if args[2]
|
585
|
-
|
586
|
-
|
587
|
-
|
697
|
+
if args[2][:value] != "*"
|
698
|
+
param_variable args[2][:value]
|
699
|
+
method_args << args[2][:value]
|
700
|
+
pre_code += "#{args[2][:value]} = [].slice.call(arguments, #{method_args.length});"
|
701
|
+
end
|
588
702
|
end
|
589
703
|
|
704
|
+
arity = (-arity) - 1 if args[1] or args[2]
|
705
|
+
|
590
706
|
# block arg
|
591
707
|
if args[3]
|
592
708
|
param_variable args[3][:value]
|
593
709
|
@block_arg_name = args[3][:value]
|
710
|
+
pre_code += "var #{args[3][:value]} = (($yy == $y.y) ? nil: $yy);"
|
594
711
|
end
|
595
712
|
|
596
713
|
@body.returns
|
597
714
|
stmt = @body.generate scope, LEVEL_TOP
|
598
|
-
|
599
715
|
method_args.unshift 'self'
|
600
716
|
|
601
|
-
code += "function(#{method_args.join ', '}) {
|
717
|
+
code += "function(#{method_args.join ', '}) {"
|
602
718
|
|
603
719
|
# local vars... only if we used any..
|
604
720
|
unless @scope_vars.empty?
|
@@ -607,19 +723,23 @@ class Opal::RubyParser < Racc::Parser
|
|
607
723
|
|
608
724
|
# ivars
|
609
725
|
@ivars.each do |ivar|
|
610
|
-
pre_code += "
|
726
|
+
pre_code += "self['#{ivar}']==undefined&&(self['#{ivar}']=nil);"
|
611
727
|
end
|
612
728
|
|
613
|
-
# block
|
729
|
+
# block support
|
614
730
|
if @block_arg_name
|
615
|
-
|
616
|
-
|
731
|
+
|
732
|
+
block_code = "var $y = $B, $yy, $ys, $yb = $y.b;"
|
733
|
+
block_code += "if ($y.f == arguments.callee) { $yy = $y.p; }"
|
734
|
+
block_code += "else { $yy = $y.y; }"
|
735
|
+
block_code += "$y.f = nil ;$ys = $yy.$proc[0];"
|
736
|
+
pre_code = block_code + pre_code
|
617
737
|
end
|
618
738
|
|
619
739
|
code += (pre_code + stmt)
|
620
740
|
|
621
741
|
# fix trailing end and 0/1 for normal/singleton
|
622
|
-
code += (fix_line_number(opts, @end_line) + "}, #{
|
742
|
+
code += (fix_line_number(opts, @end_line) + "}, #{arity})")
|
623
743
|
|
624
744
|
code
|
625
745
|
end
|
@@ -685,8 +805,8 @@ class Opal::RubyParser < Racc::Parser
|
|
685
805
|
class ArrayNode < BaseNode
|
686
806
|
|
687
807
|
def initialize(parts, begn, endn)
|
688
|
-
@line = begn[:line]
|
689
|
-
@end_line = endn[:line]
|
808
|
+
@line = begn[:line] || 0
|
809
|
+
@end_line = endn[:line] || 0
|
690
810
|
@args = parts
|
691
811
|
end
|
692
812
|
|
@@ -694,15 +814,23 @@ class Opal::RubyParser < Racc::Parser
|
|
694
814
|
# on a new line are indented to that of the array beg/end
|
695
815
|
def generate(opts, level)
|
696
816
|
parts = @args[0].map { |arg| arg.process opts, LEVEL_LIST }
|
697
|
-
"[#{parts.join ', '}#{fix_line_number opts, @end_line}]"
|
817
|
+
code = "[#{parts.join ', '}#{fix_line_number opts, @end_line}]"
|
818
|
+
|
819
|
+
if @args[1]
|
820
|
+
res = "#{code}.concat(#{@args[1].generate opts, LEVEL_EXPR})"
|
821
|
+
else
|
822
|
+
res = code
|
823
|
+
end
|
824
|
+
|
825
|
+
res
|
698
826
|
end
|
699
827
|
end
|
700
828
|
|
701
829
|
class HashNode < BaseNode
|
702
830
|
|
703
831
|
def initialize(parts, begn, endn)
|
704
|
-
@line = begn[:line]
|
705
|
-
@end_line = endn[:line]
|
832
|
+
@line = begn[:line] || 0
|
833
|
+
@end_line = endn[:line] || 0
|
706
834
|
@parts = parts
|
707
835
|
end
|
708
836
|
|
@@ -715,6 +843,7 @@ class Opal::RubyParser < Racc::Parser
|
|
715
843
|
class IfNode < BaseNode
|
716
844
|
|
717
845
|
def initialize(begn, expr, stmt, tail, endn)
|
846
|
+
@type = begn[:value]
|
718
847
|
@line = begn[:line]
|
719
848
|
@end_line = endn[:line]
|
720
849
|
@expr = expr
|
@@ -740,9 +869,12 @@ class Opal::RubyParser < Racc::Parser
|
|
740
869
|
end
|
741
870
|
|
742
871
|
def generate(opts, level)
|
743
|
-
code
|
872
|
+
code = ''
|
873
|
+
done_else = false
|
874
|
+
tail = nil
|
875
|
+
old_indent = opts[:indent]
|
744
876
|
|
745
|
-
opts[:indent]
|
877
|
+
opts[:indent] = opts[:indent] + INDENT
|
746
878
|
|
747
879
|
# stmt_level is level_top, unless we are an expression.. then it is level_top_closure..
|
748
880
|
stmt_level = (level == LEVEL_EXPR ? LEVEL_TOP_CLOSURE : LEVEL_TOP)
|
@@ -752,20 +884,27 @@ class Opal::RubyParser < Racc::Parser
|
|
752
884
|
@level_expr = true
|
753
885
|
end
|
754
886
|
|
755
|
-
|
887
|
+
expr = @expr.generate opts, LEVEL_EXPR
|
888
|
+
expr = "(#{expr})" if @expr.is_a? NumericNode
|
889
|
+
|
890
|
+
# code += "if ((#{@expr.generate opts, LEVEL_EXPR}).$r) {#{@stmt.process opts, stmt_level}"
|
891
|
+
code += "if (#{@type == 'if' ? '' : '!'}#{expr}.$r) {#{@stmt.process opts, stmt_level}"
|
756
892
|
|
757
893
|
@tail.each do |tail|
|
758
894
|
opts[:indent] = old_indent
|
759
|
-
code
|
895
|
+
code = code + fix_line_number(opts, tail[0][:line])
|
760
896
|
|
761
897
|
if tail[0][:value] == 'elsif'
|
762
|
-
|
763
|
-
|
764
|
-
code +=
|
898
|
+
expr = tail[1].generate opts, LEVEL_EXPR
|
899
|
+
expr = "(#{expr})" if tail[1].is_a? NumericNode
|
900
|
+
code += "} else if (#{expr}.$r) {"
|
901
|
+
# code += "} else if ((#{tail[1].generate opts, LEVEL_EXPR}).$r) {"
|
902
|
+
opts[:indent] = opts[:indent] + INDENT
|
903
|
+
code = code + tail[2].process(opts, stmt_level)
|
765
904
|
else
|
766
905
|
done_else = true
|
767
906
|
code += '} else {'
|
768
|
-
opts[:indent]
|
907
|
+
opts[:indent] = opts[:indent] + INDENT
|
769
908
|
code += tail[1].process(opts, stmt_level)
|
770
909
|
end
|
771
910
|
end
|
@@ -780,11 +919,92 @@ class Opal::RubyParser < Racc::Parser
|
|
780
919
|
code += (fix_line_number(opts, @end_line) + '}')
|
781
920
|
|
782
921
|
# if we were an expression, we need to wrap ourself as closure
|
922
|
+
code = "(function() {#{code}})()" if level == LEVEL_EXPR
|
923
|
+
code
|
924
|
+
end
|
925
|
+
end
|
926
|
+
|
927
|
+
class CaseNode < BaseNode
|
928
|
+
|
929
|
+
def initialize(begn, expr, body, endn)
|
930
|
+
@line = begn[:line]
|
931
|
+
@expr = expr
|
932
|
+
@body = body
|
933
|
+
@end_line = endn[:line]
|
934
|
+
end
|
935
|
+
|
936
|
+
def returns
|
937
|
+
@body.each do |part|
|
938
|
+
if part[0][:value] == 'when'
|
939
|
+
part[2].returns
|
940
|
+
else
|
941
|
+
part[1].returns
|
942
|
+
end
|
943
|
+
end
|
944
|
+
self
|
945
|
+
end
|
946
|
+
|
947
|
+
def generate(opts, level)
|
948
|
+
code = ''
|
949
|
+
done_else = false
|
950
|
+
tail = nil
|
951
|
+
old_indent = opts[:indent]
|
952
|
+
|
953
|
+
opts[:indent] = opts[:indent] + INDENT
|
954
|
+
|
955
|
+
stmt_level = (level == LEVEL_EXPR ? LEVEL_TOP_CLOSURE : LEVEL_TOP)
|
956
|
+
|
957
|
+
if stmt_level == LEVEL_TOP_CLOSURE
|
958
|
+
returns
|
959
|
+
@level_expr = true
|
960
|
+
end
|
961
|
+
|
962
|
+
expr = @expr.generate opts, LEVEL_EXPR
|
963
|
+
case_ref = opts[:scope].temp_local
|
964
|
+
|
965
|
+
code += "#{case_ref} = #{expr};"
|
966
|
+
|
967
|
+
@body.each_with_index do |part, idx|
|
968
|
+
opts[:indent] = old_indent
|
969
|
+
code += fix_line_number opts, part[0][:line]
|
970
|
+
|
971
|
+
if part[0][:value] == 'when'
|
972
|
+
code += (idx == 0 ? "if" : "} else if")
|
973
|
+
parts = part[1].map do |expr|
|
974
|
+
CallNode.new(expr,
|
975
|
+
{:value => '===' },
|
976
|
+
[[TempNode.new(case_ref)]]
|
977
|
+
).generate(opts, LEVEL_EXPR) + '.$r'
|
978
|
+
end
|
979
|
+
opts[:indent] = opts[:indent] + INDENT
|
980
|
+
code += " (#{parts.join ' || '}) {#{part[2].process opts, stmt_level}"
|
981
|
+
else
|
982
|
+
code += "} else {#{part[1].process opts, stmt_level}"
|
983
|
+
end
|
984
|
+
end
|
985
|
+
|
986
|
+
opts[:indent] = old_indent
|
987
|
+
|
988
|
+
opts[:scope].queue_temp case_ref
|
989
|
+
code += (fix_line_number(opts, @end_line) + '}')
|
990
|
+
|
783
991
|
code = "(function() {#{code})()" if level == LEVEL_EXPR
|
784
992
|
code
|
785
993
|
end
|
786
994
|
end
|
787
995
|
|
996
|
+
class TempNode < BaseNode
|
997
|
+
|
998
|
+
def initialize(val)
|
999
|
+
@val = val
|
1000
|
+
@line = 0
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def generate(opts, level)
|
1004
|
+
@val
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
788
1008
|
class ConstantNode < BaseNode
|
789
1009
|
|
790
1010
|
def initialize(name)
|
@@ -797,7 +1017,7 @@ class Opal::RubyParser < Racc::Parser
|
|
797
1017
|
end
|
798
1018
|
|
799
1019
|
def generate(opts, level)
|
800
|
-
"
|
1020
|
+
"$cg(#{SelfNode.new.generate opts, level}, '#{@name}')"
|
801
1021
|
end
|
802
1022
|
end
|
803
1023
|
|
@@ -811,7 +1031,7 @@ class Opal::RubyParser < Racc::Parser
|
|
811
1031
|
|
812
1032
|
def generate(opts, level)
|
813
1033
|
# FIXME This should really be 'const at'.. const_get will relook all the way up chain
|
814
|
-
"
|
1034
|
+
"$cg(#{@lhs.generate opts, level}, '#{@name}')"
|
815
1035
|
end
|
816
1036
|
end
|
817
1037
|
|
@@ -840,17 +1060,22 @@ class Opal::RubyParser < Racc::Parser
|
|
840
1060
|
return "#{SelfNode.new.generate(opts, level)}['#{@lhs.value}'] = #{@rhs.generate(opts, LEVEL_EXPR)}"
|
841
1061
|
|
842
1062
|
elsif @lhs.is_a? GvarNode
|
843
|
-
return "
|
1063
|
+
return "$rb.gs('#{@lhs.value}', #{@rhs.generate(opts, LEVEL_EXPR)})"
|
844
1064
|
|
845
1065
|
elsif @lhs.is_a? IdentifierNode
|
846
1066
|
opts[:scope].ensure_variable @lhs.value
|
1067
|
+
|
1068
|
+
# optimize yield assigning
|
1069
|
+
if @rhs.is_a?(YieldNode) and level == LEVEL_TOP
|
1070
|
+
return @rhs.generate_assign(opts, @lhs)
|
1071
|
+
end
|
847
1072
|
return @lhs.value + " = " + @rhs.generate(opts, LEVEL_EXPR)
|
848
1073
|
|
849
1074
|
elsif @lhs.is_a? ArefNode
|
850
1075
|
return AsetNode.new(@lhs.recv, @lhs.arefs, @rhs).process(opts, level)
|
851
1076
|
|
852
1077
|
elsif @lhs.is_a? ConstantNode
|
853
|
-
return "
|
1078
|
+
return "$rb.cs(self, '#{@lhs.value}', #{@rhs.generate(opts, LEVEL_EXPR)})"
|
854
1079
|
|
855
1080
|
elsif @lhs.is_a? CallNode
|
856
1081
|
return CallNode.new(@lhs.recv, { :value => @lhs.mid + '=', :line => @line }, [[@rhs]]).generate(opts, level);
|
@@ -861,6 +1086,54 @@ class Opal::RubyParser < Racc::Parser
|
|
861
1086
|
end
|
862
1087
|
end
|
863
1088
|
|
1089
|
+
class MlhsAssignNode < BaseNode
|
1090
|
+
|
1091
|
+
def initialize(node, lhs, rhs)
|
1092
|
+
@line = node[:line]
|
1093
|
+
@lhs = lhs
|
1094
|
+
@rhs = rhs
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
def generate(opts, level)
|
1098
|
+
@lhs.inspect
|
1099
|
+
@generator_opts = opts
|
1100
|
+
'(' + generate_mlhs_context(@lhs, @rhs) + ')'
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
def generate_mlhs_context(arr, rhs)
|
1104
|
+
puts "mlhs node at #@line"
|
1105
|
+
parts = []
|
1106
|
+
|
1107
|
+
tmp_recv = @generator_opts[:scope].temp_local
|
1108
|
+
tmp_len = @generator_opts[:scope].temp_local
|
1109
|
+
rhs_code = rhs.generate @generator_opts, LEVEL_EXPR
|
1110
|
+
|
1111
|
+
parts << "#{tmp_recv} = #{rhs_code}"
|
1112
|
+
parts << "(#{tmp_recv}.$flags & $rb.T_ARRAY) || (#{tmp_recv} = [#{tmp_recv}])"
|
1113
|
+
parts << "#{tmp_len} = #{tmp_recv}.length"
|
1114
|
+
|
1115
|
+
if arr[0]
|
1116
|
+
arr[0].each_with_index do |part, idx|
|
1117
|
+
if part.is_a? Array
|
1118
|
+
parts.push generate_mlhs_context part, rhs
|
1119
|
+
else
|
1120
|
+
assign = AssignNode.new part, TempNode.new("#{tmp_recv}[#{idx}]")
|
1121
|
+
code = assign.generate @generator_opts, LEVEL_EXPR
|
1122
|
+
parts.push "#{idx} < #{tmp_len} ? #{code} : nil"
|
1123
|
+
# parts.push assign.generate @generator_opts, LEVE<D-/>L_EXPR
|
1124
|
+
end
|
1125
|
+
end
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
parts << tmp_recv
|
1129
|
+
|
1130
|
+
@generator_opts[:scope].queue_temp tmp_recv
|
1131
|
+
@generator_opts[:scope].queue_temp tmp_len
|
1132
|
+
|
1133
|
+
parts.join ', '
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
|
864
1137
|
class OpAsgnNode < BaseNode
|
865
1138
|
|
866
1139
|
def initialize(asgn, lhs, rhs)
|
@@ -900,7 +1173,6 @@ class Opal::RubyParser < Racc::Parser
|
|
900
1173
|
end
|
901
1174
|
|
902
1175
|
class IdentifierNode < BaseNode
|
903
|
-
|
904
1176
|
attr_reader :value
|
905
1177
|
|
906
1178
|
def initialize(val)
|
@@ -908,6 +1180,10 @@ class Opal::RubyParser < Racc::Parser
|
|
908
1180
|
@value = val[:value]
|
909
1181
|
end
|
910
1182
|
|
1183
|
+
def local_variable?(opts)
|
1184
|
+
opts[:scope].find_variable(@value) ? true : false
|
1185
|
+
end
|
1186
|
+
|
911
1187
|
def generate(opts, level)
|
912
1188
|
if opts[:scope].find_variable @value
|
913
1189
|
@value
|
@@ -943,6 +1219,8 @@ class Opal::RubyParser < Racc::Parser
|
|
943
1219
|
elsif @parts.length == 1
|
944
1220
|
if @parts[0][0] == 'string_content'
|
945
1221
|
@join + @parts[0][1][:value] + @join
|
1222
|
+
elsif @parts[0][0] == 'string_dbegin'
|
1223
|
+
CallNode.new(@parts[0][1], { :value => 'to_s', :line => 0 }, [[]]).generate(opts, level)
|
946
1224
|
end
|
947
1225
|
|
948
1226
|
else
|
@@ -1006,6 +1284,18 @@ class Opal::RubyParser < Racc::Parser
|
|
1006
1284
|
args[0].each do |arg|
|
1007
1285
|
param_variable arg[:value]
|
1008
1286
|
method_args << arg[:value]
|
1287
|
+
|
1288
|
+
# Argument checking.. If normal args are required but not passed
|
1289
|
+
# they just default to nil. Lambdas have the same effect as
|
1290
|
+
# methods, so we check this by wrapping lambdas in an anon
|
1291
|
+
# function that knows the arity of this block. So here, make all
|
1292
|
+
# norm args nil if not present.
|
1293
|
+
#
|
1294
|
+
# Also, this is optional, and can be turned on/off for
|
1295
|
+
# performance gains.
|
1296
|
+
if true
|
1297
|
+
pre_code += "if (#{arg[:value]} === undefined) { #{arg[:value]} = nil; }"
|
1298
|
+
end
|
1009
1299
|
end
|
1010
1300
|
end
|
1011
1301
|
|
@@ -1015,17 +1305,26 @@ class Opal::RubyParser < Racc::Parser
|
|
1015
1305
|
opt_arg_name = arg[0][:value]
|
1016
1306
|
param_variable opt_arg_name
|
1017
1307
|
method_args << arg[0][:value]
|
1018
|
-
pre_code += "if (#{opt_arg_name}
|
1308
|
+
pre_code += "if (#{opt_arg_name} === undefined) { #{opt_arg_name} = #{arg[1].generate(opts, level)};}"
|
1019
1309
|
end
|
1020
1310
|
end
|
1021
1311
|
|
1022
1312
|
# rest args
|
1023
1313
|
if args[2]
|
1314
|
+
# ignore rest arg if it is anonymous
|
1315
|
+
unless args[2][:value] == '*'
|
1024
1316
|
rest_arg_name = args[2][:value]
|
1025
1317
|
# FIXME if we just pass '*', then we make a tmp variable name for it..
|
1026
1318
|
param_variable rest_arg_name
|
1027
1319
|
method_args << rest_arg_name
|
1028
|
-
pre_code += "#{rest_arg_name} = [].slice.call(
|
1320
|
+
pre_code += "#{rest_arg_name} = [].slice.call($A, #{method_args.length});"
|
1321
|
+
end
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
# block arg
|
1325
|
+
if args[3]
|
1326
|
+
param_variable args[3][:value]
|
1327
|
+
@block_arg_name = args[3][:value]
|
1029
1328
|
end
|
1030
1329
|
end
|
1031
1330
|
|
@@ -1033,13 +1332,33 @@ class Opal::RubyParser < Racc::Parser
|
|
1033
1332
|
stmt = @stmt.process scope, LEVEL_TOP
|
1034
1333
|
method_args.unshift 'self'
|
1035
1334
|
|
1335
|
+
block_var = opts[:scope].temp_local
|
1336
|
+
# code += "(#{block_var} = "
|
1337
|
+
|
1036
1338
|
code += "function(#{method_args.join ', '}) {"
|
1037
|
-
|
1339
|
+
|
1038
1340
|
unless @scope_vars.empty?
|
1039
1341
|
code += " var #{@scope_vars.join ', '};"
|
1040
1342
|
end
|
1041
1343
|
|
1344
|
+
# block arg
|
1345
|
+
if @block_arg_name
|
1346
|
+
pre_code += "var $yield, #@block_arg_name; if ($B.f == arguments.callee && $B.p != nil) { #@block_arg_name = "
|
1347
|
+
pre_code += "$yield = $B.p; } else { #@block_arg_name = nil; "
|
1348
|
+
pre_code += "$yield = $B.y; } $B.p = $B.f = nil;"
|
1349
|
+
pre_code += "var $yself = $yield.$proc[0];"
|
1350
|
+
|
1351
|
+
stmt = "try{" + stmt
|
1352
|
+
|
1353
|
+
# catch break statements
|
1354
|
+
stmt += "} catch (__err__) {if(__err__.$keyword == 2) {return __err__.$value;} throw __err__;}"
|
1355
|
+
end
|
1356
|
+
|
1042
1357
|
code += (pre_code + stmt + fix_line_number(opts, @end_line) + "}")
|
1358
|
+
|
1359
|
+
# code += ", #{block_var}.$arity = 0, #{block_var}.$meth = null"
|
1360
|
+
# code += ", #{block_var})"
|
1361
|
+
opts[:scope].queue_temp block_var
|
1043
1362
|
code
|
1044
1363
|
end
|
1045
1364
|
end
|
@@ -1123,7 +1442,8 @@ class Opal::RubyParser < Racc::Parser
|
|
1123
1442
|
end
|
1124
1443
|
|
1125
1444
|
def generate(opts, level)
|
1126
|
-
(@arefs[0]
|
1445
|
+
@arefs[0] || (@arefs[0] = [])
|
1446
|
+
@arefs[0] << @val
|
1127
1447
|
CallNode.new(@recv, { :line => @line, :value => '[]='}, @arefs ).generate(opts, level)
|
1128
1448
|
end
|
1129
1449
|
end
|
@@ -1160,36 +1480,239 @@ class Opal::RubyParser < Racc::Parser
|
|
1160
1480
|
end
|
1161
1481
|
end
|
1162
1482
|
|
1163
|
-
class
|
1483
|
+
class YieldNode < BaseNode
|
1484
|
+
|
1485
|
+
def initialize(start, args)
|
1486
|
+
@line = start[:line]
|
1487
|
+
@args = args
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
# Get basic yielding code yield(yself,...)
|
1491
|
+
def yield_code(opts)
|
1492
|
+
block_code = "$yy"
|
1493
|
+
|
1494
|
+
parts = []
|
1495
|
+
|
1496
|
+
if @args[0]
|
1497
|
+
@args[0].each { |arg| parts << arg.generate(opts, LEVEL_EXPR) }
|
1498
|
+
end
|
1499
|
+
|
1500
|
+
if @args[1]
|
1501
|
+
parts.unshift '$ys'
|
1502
|
+
code = "#{block_code}(null, [#{parts.join ', '}].concat(#{@args[1].generate(opts, LEVEL_EXPR)}))"
|
1503
|
+
else
|
1504
|
+
parts.unshift '$ys'
|
1505
|
+
code = "#{block_code}(#{parts.join ', '})"
|
1506
|
+
end
|
1164
1507
|
|
1165
|
-
|
1166
|
-
@line = given[:line]
|
1508
|
+
code
|
1167
1509
|
end
|
1168
1510
|
|
1169
1511
|
def generate(opts, level)
|
1170
|
-
|
1171
|
-
|
1512
|
+
# need to get block from nearest method
|
1513
|
+
block = opts[:scope].set_uses_block
|
1514
|
+
code = yield_code opts
|
1515
|
+
|
1516
|
+
if level == LEVEL_TOP
|
1517
|
+
"if (#{code} == $yb) { return $yb.$value; }"
|
1518
|
+
else
|
1519
|
+
# basically we need to return out of this method and we are not
|
1520
|
+
# top level so we will need to throw and error which is caught
|
1521
|
+
# directly inside this method which just returns the break
|
1522
|
+
# value. We should warn that the given code is going to cause
|
1523
|
+
# a try/catch statement to be added to check for this. i.e. this
|
1524
|
+
# can/should be optimized out in the source code
|
1525
|
+
tmp = opts[:scope].temp_local
|
1526
|
+
"((#{tmp} = #{code}) == $yb ? $break() : #{tmp})"
|
1527
|
+
end
|
1528
|
+
end
|
1529
|
+
|
1530
|
+
# special generator for assigning to variable. We know we will be
|
1531
|
+
# top level if this is called.
|
1532
|
+
def generate_assign(opts, lhs)
|
1533
|
+
"if ((#{lhs.value} = #{yield_code opts}) == $yb) { return $yb.$value; }"
|
1172
1534
|
end
|
1173
1535
|
end
|
1174
1536
|
|
1175
|
-
class
|
1537
|
+
class BreakNode < BaseNode
|
1176
1538
|
|
1177
1539
|
def initialize(start, args)
|
1178
1540
|
@line = start[:line]
|
1179
1541
|
@args = args
|
1180
1542
|
end
|
1181
1543
|
|
1544
|
+
# as we either throw or return ourself we can ignore the
|
1545
|
+
# request to return ourself if last statement
|
1546
|
+
def returns
|
1547
|
+
self
|
1548
|
+
end
|
1549
|
+
|
1182
1550
|
def generate(opts, level)
|
1183
|
-
|
1184
|
-
|
1551
|
+
code = []
|
1552
|
+
|
1553
|
+
if @args[0]
|
1554
|
+
@args[0].each { |arg| code << arg.generate(opts, LEVEL_EXPR) }
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
case code.length
|
1558
|
+
when 0
|
1559
|
+
code = "nil"
|
1560
|
+
when 1
|
1561
|
+
code = code[0]
|
1562
|
+
else
|
1563
|
+
code = '[' + code.join(', ') + ']'
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
if opts[:scope].in_while_scope?
|
1567
|
+
while_scope = opts[:scope].while_scope
|
1568
|
+
tmp_break_val = while_scope.set_captures_break
|
1569
|
+
"#{tmp_break_val} = #{code}; break"
|
1570
|
+
elsif opts[:scope].is_a? BlockNode
|
1571
|
+
if level == LEVEL_TOP
|
1572
|
+
"return ($B.b.$value = #{code}, $B.b)"
|
1573
|
+
else
|
1574
|
+
# block must have a try/catch wrapper inside to detect
|
1575
|
+
# breaks and return the break value if a break is fired.
|
1576
|
+
# We should also warn that the ruby code is not optimized
|
1577
|
+
# and suggest it is reconfigured to avoid the (possibly)
|
1578
|
+
# expensive try/catch block.
|
1579
|
+
"$break(#{code})"
|
1580
|
+
end
|
1581
|
+
else
|
1582
|
+
"$break(#{code})"
|
1583
|
+
end
|
1584
|
+
end
|
1585
|
+
end
|
1586
|
+
|
1587
|
+
class NextNode < BaseNode
|
1588
|
+
|
1589
|
+
def initialize(start, args)
|
1590
|
+
@line = start[:line]
|
1591
|
+
@args = args
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
def returns
|
1595
|
+
self
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
def generate(opts, level)
|
1599
|
+
code = []
|
1600
|
+
|
1601
|
+
if @args[0]
|
1602
|
+
@args[0].each { |arg| code << arg.generate(opts, LEVEL_EXPR) }
|
1603
|
+
end
|
1604
|
+
|
1605
|
+
case code.length
|
1606
|
+
when 0
|
1607
|
+
code = "nil"
|
1608
|
+
when 1
|
1609
|
+
code = code[0]
|
1610
|
+
else
|
1611
|
+
code = '[' + code.join(', ') + ']'
|
1612
|
+
end
|
1613
|
+
|
1614
|
+
if opts[:scope].in_while_scope?
|
1615
|
+
"continue"
|
1616
|
+
else
|
1617
|
+
# if in block
|
1618
|
+
"return #{code}"
|
1619
|
+
# else if in while/until loop
|
1620
|
+
|
1621
|
+
end
|
1622
|
+
end
|
1623
|
+
end
|
1624
|
+
|
1625
|
+
class RedoNode < BaseNode
|
1626
|
+
|
1627
|
+
def initialize(start)
|
1628
|
+
@line = start[:line]
|
1629
|
+
end
|
1630
|
+
|
1631
|
+
def generate(opts, level)
|
1632
|
+
if opts[:scope].in_while_scope?
|
1633
|
+
"#{opts[:scope].while_scope.redo_var} = true"
|
1634
|
+
else
|
1635
|
+
"REDO()"
|
1636
|
+
end
|
1637
|
+
end
|
1638
|
+
end
|
1639
|
+
|
1640
|
+
class WhileNode < BaseNode
|
1641
|
+
|
1642
|
+
attr_reader :redo_var
|
1643
|
+
|
1644
|
+
def initialize(begn, exp, stmt, endn)
|
1645
|
+
@line = begn[:line]
|
1646
|
+
@type = begn[:value]
|
1647
|
+
@expr = exp
|
1648
|
+
@stmt = stmt
|
1649
|
+
@end_line = endn[:line]
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
def returns
|
1653
|
+
@returns = true
|
1654
|
+
self
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
def set_captures_break
|
1658
|
+
tmp = @current_scope.temp_local
|
1659
|
+
@captures_break = tmp
|
1660
|
+
end
|
1661
|
+
|
1662
|
+
def generate(opts, level)
|
1663
|
+
@current_scope = opts[:scope]
|
1664
|
+
stmt_level = (level == LEVEL_EXPR ? LEVEL_TOP_CLOSURE : LEVEL_TOP)
|
1665
|
+
truthy = @type == 'while' ? '' : '!'
|
1666
|
+
|
1667
|
+
if stmt_level == LEVEL_TOP_CLOSURE
|
1668
|
+
returns
|
1669
|
+
@level_expr = true
|
1670
|
+
end
|
1671
|
+
|
1672
|
+
@redo_var = eval_expr = opts[:scope].temp_local
|
1673
|
+
code = "#{eval_expr} = false; while (#{eval_expr} || #{truthy}("
|
1674
|
+
code += @expr.generate opts, LEVEL_EXPR
|
1675
|
+
code += ").$r) {#{eval_expr} = false;"
|
1676
|
+
|
1677
|
+
opts[:scope].push_while_scope self
|
1678
|
+
|
1679
|
+
code += @stmt.process opts, LEVEL_TOP
|
1185
1680
|
|
1186
|
-
|
1681
|
+
opts[:scope].pop_while_scope
|
1682
|
+
|
1683
|
+
code += fix_line_number opts, @end_line
|
1684
|
+
code += "}"
|
1685
|
+
|
1686
|
+
opts[:scope].queue_temp eval_expr
|
1687
|
+
|
1688
|
+
return_value = "nil"
|
1689
|
+
|
1690
|
+
if @captures_break
|
1691
|
+
code = "#@captures_break = nil; #{code}"
|
1692
|
+
opts[:scope].queue_temp @captures_break
|
1693
|
+
return_value = @captures_break
|
1694
|
+
end
|
1695
|
+
|
1696
|
+
code = "(function() {#{code} return #{return_value};})()" if stmt_level == LEVEL_TOP_CLOSURE
|
1697
|
+
code
|
1698
|
+
end
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
class SuperNode < BaseNode
|
1702
|
+
|
1703
|
+
def initialize(start, args)
|
1704
|
+
@line = start[:line]
|
1705
|
+
@args = args
|
1706
|
+
end
|
1707
|
+
|
1708
|
+
def generate(opts, level)
|
1709
|
+
parts = []
|
1187
1710
|
|
1188
1711
|
if @args[0]
|
1189
1712
|
@args[0].each { |arg| parts << arg.generate(opts, LEVEL_EXPR) }
|
1190
1713
|
end
|
1191
1714
|
|
1192
|
-
"
|
1715
|
+
"$super(arguments.callee, self, [#{parts.join ', '}])"
|
1193
1716
|
end
|
1194
1717
|
end
|
1195
1718
|
|
@@ -1214,6 +1737,9 @@ class Opal::RubyParser < Racc::Parser
|
|
1214
1737
|
else
|
1215
1738
|
# this really should return array of return vals
|
1216
1739
|
code = NilNode.new.generate opts, level
|
1740
|
+
code = []
|
1741
|
+
args[0].each { |arg| code << arg.generate(opts, LEVEL_EXPR) }
|
1742
|
+
code = code = '[' + code.join(', ') + ']'
|
1217
1743
|
end
|
1218
1744
|
|
1219
1745
|
# if we are in a block, we need to throw return to nearest mthod
|
@@ -1241,16 +1767,16 @@ class Opal::RubyParser < Racc::Parser
|
|
1241
1767
|
def generate(opts, level)
|
1242
1768
|
code = "try {"
|
1243
1769
|
old_indent = opts[:indent]
|
1244
|
-
opts[:indent]
|
1770
|
+
opts[:indent] = opts[:indent] + INDENT
|
1245
1771
|
|
1246
1772
|
code += @body.process opts, LEVEL_TOP
|
1247
1773
|
code += "} catch (__err__) {"
|
1248
1774
|
|
1249
1775
|
@body.opt_rescue.each do |res|
|
1250
1776
|
code += "#{fix_line_number opts, res[0][:line]}if (true){"
|
1251
|
-
opts[:indent]
|
1252
|
-
opts[:scope].ensure_variable res[2].value
|
1253
|
-
code += (res[2].value + " = __err__;")
|
1777
|
+
opts[:indent] = opts[:indent] + INDENT
|
1778
|
+
opts[:scope].ensure_variable res[2].value if res[2]
|
1779
|
+
code += (res[2].value + " = __err__;") if res[2]
|
1254
1780
|
code += "#{res[3].process opts, LEVEL_TOP}}"
|
1255
1781
|
opts[:indent] = old_indent + INDENT
|
1256
1782
|
end
|
@@ -1262,6 +1788,20 @@ class Opal::RubyParser < Racc::Parser
|
|
1262
1788
|
end
|
1263
1789
|
end
|
1264
1790
|
|
1791
|
+
class TernaryNode < BaseNode
|
1792
|
+
|
1793
|
+
def initialize(expr, truthy, falsy)
|
1794
|
+
@line = expr.line
|
1795
|
+
@expr = expr
|
1796
|
+
@true = truthy
|
1797
|
+
@false = falsy
|
1798
|
+
end
|
1799
|
+
|
1800
|
+
def generate(opts, level)
|
1801
|
+
"(#{@expr.generate opts, LEVEL_EXPR}.$r ? #{@true.generate opts, LEVEL_EXPR} : #{@false.generate opts, LEVEL_EXPR})"
|
1802
|
+
end
|
1803
|
+
end
|
1804
|
+
|
1265
1805
|
class GvarNode < BaseNode
|
1266
1806
|
|
1267
1807
|
attr_reader :value
|
@@ -1272,7 +1812,7 @@ class Opal::RubyParser < Racc::Parser
|
|
1272
1812
|
end
|
1273
1813
|
|
1274
1814
|
def generate(opts, level)
|
1275
|
-
"
|
1815
|
+
"$rb.gg('#{@value}')"
|
1276
1816
|
end
|
1277
1817
|
end
|
1278
1818
|
|
@@ -1295,8 +1835,89 @@ class Opal::RubyParser < Racc::Parser
|
|
1295
1835
|
end
|
1296
1836
|
|
1297
1837
|
def generate(opts, level)
|
1298
|
-
@val
|
1838
|
+
"(#{@val})"
|
1839
|
+
end
|
1840
|
+
end
|
1841
|
+
|
1842
|
+
class RegexpNode < BaseNode
|
1843
|
+
|
1844
|
+
def initialize(begn, parts)
|
1845
|
+
@line = begn[:line]
|
1846
|
+
@parts = parts
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
def generate(opts, level)
|
1850
|
+
parts = @parts.map do |part|
|
1851
|
+
if part[0] == 'string_content'
|
1852
|
+
part[1][:value]
|
1853
|
+
elsif part[0] == 'string_dbegin'
|
1854
|
+
part[1].generate opts, LEVEL_EXPR
|
1855
|
+
end
|
1856
|
+
end
|
1857
|
+
|
1858
|
+
"/#{parts.join ''}/"
|
1859
|
+
end
|
1860
|
+
end
|
1861
|
+
|
1862
|
+
class WordsNode < BaseNode
|
1863
|
+
|
1864
|
+
def initialize(begn, parts, endn)
|
1865
|
+
@line = begn[:line]
|
1866
|
+
@parts = parts
|
1867
|
+
@end_line = endn[:line]
|
1868
|
+
end
|
1869
|
+
|
1870
|
+
def generate(opts, level)
|
1871
|
+
parts = @parts.map do |part|
|
1872
|
+
if part[0] == 'string_content'
|
1873
|
+
part[1][:value].inspect
|
1874
|
+
else
|
1875
|
+
CallNode.new(part[1], {:value => 'to_s', :line => @line }, []).generate(opts, LEVEL_EXPR)
|
1876
|
+
end
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
'[' + parts.join(', ') + ']'
|
1880
|
+
end
|
1881
|
+
end
|
1882
|
+
|
1883
|
+
class RangeNode < BaseNode
|
1884
|
+
|
1885
|
+
def initialize(range, beg, last)
|
1886
|
+
@line = beg.line
|
1887
|
+
@beg = beg
|
1888
|
+
@last = last
|
1889
|
+
@range = range[:value]
|
1890
|
+
@end_line = last.line
|
1891
|
+
end
|
1892
|
+
|
1893
|
+
def generate(opts, level)
|
1894
|
+
beg = @beg.generate opts, LEVEL_EXPR
|
1895
|
+
last = @last.generate opts, LEVEL_EXPR
|
1896
|
+
excl = @range == '...'
|
1897
|
+
"$range(#{beg}, #{last}, #{excl})"
|
1898
|
+
end
|
1899
|
+
end
|
1900
|
+
|
1901
|
+
class UndefNode < BaseNode
|
1902
|
+
|
1903
|
+
def initialize(start, parts)
|
1904
|
+
@line = start[:line]
|
1905
|
+
@parts = parts
|
1906
|
+
end
|
1907
|
+
|
1908
|
+
def generate(opts, level)
|
1909
|
+
parts = @parts.map do |a|
|
1910
|
+
if a.is_a? SymbolNode
|
1911
|
+
a.generate opts, level
|
1912
|
+
else
|
1913
|
+
'"' + a[:value] + '"'
|
1914
|
+
end
|
1915
|
+
end
|
1916
|
+
parts.unshift 'self'
|
1917
|
+
"$rb.um(#{parts.join ', '})"
|
1299
1918
|
end
|
1300
1919
|
end
|
1301
1920
|
end
|
1921
|
+
end
|
1922
|
+
|
1302
1923
|
|