opal 0.3.6 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +69 -97
- data/bin/opal +2 -2
- data/{lib/core → corelib}/array.rb +85 -56
- data/corelib/boolean.rb +20 -0
- data/corelib/class.rb +58 -0
- data/{lib → corelib}/core.rb +2 -50
- data/corelib/dir.rb +22 -0
- data/{lib/core → corelib}/enumerable.rb +0 -0
- data/corelib/error.rb +19 -0
- data/{lib/core → corelib}/file.rb +7 -9
- data/{lib/core → corelib}/hash.rb +104 -144
- data/{lib/core → corelib}/kernel.rb +38 -44
- data/corelib/load_order +21 -0
- data/{lib/core → corelib}/match_data.rb +0 -0
- data/{lib/core → corelib}/module.rb +12 -8
- data/{lib/core → corelib}/nil_class.rb +2 -2
- data/{lib/core → corelib}/numeric.rb +37 -100
- data/corelib/object.rb +37 -0
- data/{lib/core → corelib}/proc.rb +3 -3
- data/corelib/range.rb +27 -0
- data/{lib/core → corelib}/regexp.rb +1 -1
- data/{lib/core → corelib}/string.rb +16 -107
- data/{lib/core → corelib}/top_self.rb +0 -0
- data/lib/opal.rb +7 -0
- data/lib/opal/browserify.rb +34 -0
- data/{opal_lib → lib}/opal/builder.rb +70 -24
- data/lib/opal/command.rb +52 -0
- data/lib/opal/context.rb +197 -0
- data/{opal_lib/opal/ruby/parser.rb → lib/opal/lexer.rb} +20 -4
- data/{opal_lib/opal/ruby → lib/opal}/nodes.rb +238 -127
- data/lib/opal/parser.rb +4894 -0
- data/{opal_lib/opal/ruby/ruby_parser.y → lib/opal/parser.y} +38 -18
- data/lib/rbp.rb +2 -0
- data/lib/rbp/package.rb +49 -0
- data/runtime/class.js +216 -189
- data/runtime/fs.js +2 -2
- data/runtime/init.js +242 -244
- data/runtime/loader.js +78 -99
- data/runtime/module.js +34 -40
- data/runtime/post.js +2 -2
- data/runtime/pre.js +1 -1
- data/runtime/runtime.js +129 -135
- data/{lib → stdlib}/dev.rb +10 -10
- data/{lib → stdlib}/racc/parser.rb +0 -6
- data/{lib → stdlib}/strscan.rb +4 -4
- metadata +57 -105
- data/lib/core/basic_object.rb +0 -51
- data/lib/core/class.rb +0 -38
- data/lib/core/dir.rb +0 -26
- data/lib/core/error.rb +0 -75
- data/lib/core/false_class.rb +0 -81
- data/lib/core/object.rb +0 -6
- data/lib/core/range.rb +0 -27
- data/lib/core/symbol.rb +0 -42
- data/lib/core/true_class.rb +0 -41
- data/lib/ospec.rb +0 -7
- data/lib/ospec/autorun.rb +0 -8
- data/lib/ospec/dsl.rb +0 -15
- data/lib/ospec/example.rb +0 -11
- data/lib/ospec/example/before_and_after_hooks.rb +0 -56
- data/lib/ospec/example/errors.rb +0 -17
- data/lib/ospec/example/example_group.rb +0 -12
- data/lib/ospec/example/example_group_factory.rb +0 -18
- data/lib/ospec/example/example_group_hierarchy.rb +0 -21
- data/lib/ospec/example/example_group_methods.rb +0 -100
- data/lib/ospec/example/example_group_proxy.rb +0 -15
- data/lib/ospec/example/example_methods.rb +0 -46
- data/lib/ospec/example/example_proxy.rb +0 -18
- data/lib/ospec/expectations.rb +0 -19
- data/lib/ospec/expectations/errors.rb +0 -8
- data/lib/ospec/expectations/fail_with.rb +0 -9
- data/lib/ospec/expectations/handler.rb +0 -33
- data/lib/ospec/helpers/scratch.rb +0 -18
- data/lib/ospec/matchers.rb +0 -24
- data/lib/ospec/matchers/be.rb +0 -1
- data/lib/ospec/matchers/generated_descriptions.rb +0 -20
- data/lib/ospec/matchers/operator_matcher.rb +0 -54
- data/lib/ospec/matchers/raise_error.rb +0 -38
- data/lib/ospec/runner.rb +0 -90
- data/lib/ospec/runner/example_group_runner.rb +0 -41
- data/lib/ospec/runner/formatter/html_formatter.rb +0 -139
- data/lib/ospec/runner/formatter/terminal_formatter.rb +0 -48
- data/lib/ospec/runner/options.rb +0 -34
- data/lib/ospec/runner/reporter.rb +0 -82
- data/opal_lib/opal.rb +0 -16
- data/opal_lib/opal/build_methods.rb +0 -51
- data/opal_lib/opal/bundle.rb +0 -70
- data/opal_lib/opal/command.rb +0 -68
- data/opal_lib/opal/context.rb +0 -81
- data/opal_lib/opal/context/console.rb +0 -10
- data/opal_lib/opal/context/file_system.rb +0 -34
- data/opal_lib/opal/context/loader.rb +0 -135
- data/opal_lib/opal/gem.rb +0 -84
- data/opal_lib/opal/rake/builder_task.rb +0 -44
- data/opal_lib/opal/rake/spec_task.rb +0 -32
- data/opal_lib/opal/ruby/ruby_parser.rb +0 -4862
- data/opal_lib/opal/version.rb +0 -4
- data/runtime/debug.js +0 -84
data/lib/opal/command.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Opal
|
2
|
+
|
3
|
+
class Command
|
4
|
+
|
5
|
+
# Valid command line arguments
|
6
|
+
COMMANDS = [:help, :irb, :compile, :bundle, :exec, :eval]
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
command = args.shift
|
10
|
+
|
11
|
+
if command and COMMANDS.include?(command.to_sym)
|
12
|
+
__send__ command.to_sym, *args
|
13
|
+
elsif command and File.exists? command
|
14
|
+
eval command
|
15
|
+
else
|
16
|
+
help
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def help
|
21
|
+
puts "need to print help"
|
22
|
+
end
|
23
|
+
|
24
|
+
# desc "irb", "Opens interactive opal/ruby repl"
|
25
|
+
def irb
|
26
|
+
ctx = Opal::Context.new
|
27
|
+
ctx.start_repl
|
28
|
+
end
|
29
|
+
|
30
|
+
def eval(path = nil)
|
31
|
+
return "no path given for eval" unless path
|
32
|
+
|
33
|
+
abort "path does not exist `#{path}'" unless File.exist? path
|
34
|
+
|
35
|
+
ctx = Opal::Context.new
|
36
|
+
ctx.require_file File.expand_path(path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def compile(path)
|
40
|
+
puts Opal::Parser.new(File.read(path)).parse!.generate_top
|
41
|
+
end
|
42
|
+
|
43
|
+
# desc "bundle", "Bundle the gem in the given directory ready for browser"
|
44
|
+
# method_options :out => :string
|
45
|
+
def bundle
|
46
|
+
opts = options
|
47
|
+
bundle = Opal::Bundle.new(Opal::Gem.new(Dir.getwd))
|
48
|
+
bundle.build opts
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/lib/opal/context.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
module Opal
|
2
|
+
class Context
|
3
|
+
|
4
|
+
def initialize(root_dir = Dir.getwd)
|
5
|
+
@root_dir = root_dir
|
6
|
+
@builder = Opal::Builder.new
|
7
|
+
|
8
|
+
@load_paths = resolve_load_paths
|
9
|
+
end
|
10
|
+
|
11
|
+
# Looks through vendor/ directory and adds all relevant load paths
|
12
|
+
def resolve_load_paths
|
13
|
+
Dir['vendor/*/package.yml'].map do |package|
|
14
|
+
File.expand_path File.join(File.dirname(package), 'lib')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Setup the context. This basically loads opal.js into our context, and
|
19
|
+
# replace the loader etc with our custom loader for a Ruby environment. The
|
20
|
+
# default "browser" loader cannot access files from disk.
|
21
|
+
def setup_v8
|
22
|
+
return if @v8
|
23
|
+
|
24
|
+
begin
|
25
|
+
require 'v8'
|
26
|
+
rescue LoadError => e
|
27
|
+
abort "therubyracer is required for running javascript. Install it with `gem install therubyracer`"
|
28
|
+
end
|
29
|
+
|
30
|
+
@v8 = V8::Context.new
|
31
|
+
@v8['console'] = Console.new
|
32
|
+
|
33
|
+
eval @builder.build_core, '(opal)'
|
34
|
+
opal = @v8['opal']
|
35
|
+
opal['fs'] = FileSystem.new self
|
36
|
+
|
37
|
+
# FIXME: we cant use a ruby array as a js array :(
|
38
|
+
opal['loader'] = Loader.new self, eval("[]")
|
39
|
+
|
40
|
+
@load_paths.each do |path|
|
41
|
+
eval "opal.loader.paths.push('#{path}')"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def eval(code, file = nil)
|
47
|
+
@v8.eval code, file
|
48
|
+
end
|
49
|
+
|
50
|
+
# Require the given id as if it was required in the context. This simply
|
51
|
+
# passes the require through to the underlying context.
|
52
|
+
def require_file(path)
|
53
|
+
setup_v8
|
54
|
+
eval "opal.run(function() {opal.require('#{path}');});", path
|
55
|
+
finish
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set ARGV for the context
|
59
|
+
def argv=(args)
|
60
|
+
puts "setting argv to #{args.inspect}"
|
61
|
+
eval "opal.runtime.cs(opal.runtime.Object, 'ARGV', #{args.inspect});"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Start normal js repl
|
65
|
+
def start_repl
|
66
|
+
require 'readline'
|
67
|
+
setup_v8
|
68
|
+
|
69
|
+
loop do
|
70
|
+
# on SIGINT lets just return from the loop..
|
71
|
+
trap("SIGINT") { finish; return }
|
72
|
+
line = Readline.readline '>> ', true
|
73
|
+
|
74
|
+
# if we type exit, then we need to close down context
|
75
|
+
if line == "exit"
|
76
|
+
break
|
77
|
+
end
|
78
|
+
|
79
|
+
puts "=> #{eval_ruby line, '(opal)'}"
|
80
|
+
end
|
81
|
+
|
82
|
+
finish
|
83
|
+
end
|
84
|
+
|
85
|
+
def eval_ruby(content, line = "")
|
86
|
+
begin
|
87
|
+
code = Opal::Parser.new(content).parse!.generate_top
|
88
|
+
code = "opal.run(function() {var $rb = opal.runtime, self = $rb.top, __FILE__ = '(opal)';" + code + "});"
|
89
|
+
# puts code
|
90
|
+
@v8['$opal_irb_result'] = eval code, line
|
91
|
+
eval "!($opal_irb_result == null || !$opal_irb_result.m$inspect) ? $opal_irb_result.m$inspect() : '(Object does not support #inspect)'"
|
92
|
+
rescue => e
|
93
|
+
puts e
|
94
|
+
puts("\t" + e.backtrace.join("\n\t"))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Finishes the context, i.e. tidy everything up. This will cause
|
99
|
+
# the opal runtime to do it's at_exit() calls (if applicable) and
|
100
|
+
# then the v8 context will de removed. It can be reset by calling
|
101
|
+
# #setup_v8
|
102
|
+
def finish
|
103
|
+
return unless @v8
|
104
|
+
eval "opal.runtime.do_at_exit()", "(opal)"
|
105
|
+
|
106
|
+
@v8 = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
# Console class is used to mimic the console object in web browsers
|
110
|
+
# to allow simple debugging to the stdout.
|
111
|
+
class Console
|
112
|
+
def log(*str)
|
113
|
+
puts str.join("\n")
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# FileSystem is used to interact with the file system from the ruby
|
119
|
+
# version of opal. The methods on this class replace the default ones
|
120
|
+
# made available in the web browser.
|
121
|
+
class FileSystem
|
122
|
+
|
123
|
+
def initialize(context)
|
124
|
+
@context = context
|
125
|
+
end
|
126
|
+
|
127
|
+
def cwd
|
128
|
+
Dir.getwd
|
129
|
+
end
|
130
|
+
|
131
|
+
def glob(*arr)
|
132
|
+
Dir.glob arr
|
133
|
+
end
|
134
|
+
|
135
|
+
def exist_p(path)
|
136
|
+
File.exist? path
|
137
|
+
end
|
138
|
+
|
139
|
+
def expand_path(filename, dir_string = nil)
|
140
|
+
File.expand_path filename, dir_string
|
141
|
+
end
|
142
|
+
|
143
|
+
def dirname(file)
|
144
|
+
File.dirname file
|
145
|
+
end
|
146
|
+
|
147
|
+
def join(*parts)
|
148
|
+
File.join *parts
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Loader for v8 context
|
153
|
+
class Loader
|
154
|
+
|
155
|
+
attr_reader :paths
|
156
|
+
|
157
|
+
def initialize(context, paths)
|
158
|
+
@context = context
|
159
|
+
@paths = paths
|
160
|
+
end
|
161
|
+
|
162
|
+
def resolve_lib(id)
|
163
|
+
resolved = find_lib id
|
164
|
+
raise "Cannot find lib `#{id}'" unless resolved
|
165
|
+
|
166
|
+
resolved
|
167
|
+
end
|
168
|
+
|
169
|
+
def find_lib(id)
|
170
|
+
@paths.each do |path|
|
171
|
+
candidate = File.join path, "#{id}.rb"
|
172
|
+
return candidate if File.exists? candidate
|
173
|
+
|
174
|
+
candidate = File.join path, id
|
175
|
+
return candidate if File.exists? candidate
|
176
|
+
end
|
177
|
+
|
178
|
+
return File.expand_path id if File.exists? id
|
179
|
+
return File.expand_path(id + '.rb') if File.exists?(id + '.rb')
|
180
|
+
|
181
|
+
nil
|
182
|
+
end
|
183
|
+
|
184
|
+
def ruby_file_contents(filename)
|
185
|
+
Opal::Parser.new(File.read(filename)).parse!.generate_top
|
186
|
+
end
|
187
|
+
|
188
|
+
def wrap(content, filename)
|
189
|
+
code = "(function($rb, self, __FILE__) { #{content} });"
|
190
|
+
@context.eval code, filename
|
191
|
+
# code
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
@@ -1,11 +1,12 @@
|
|
1
1
|
|
2
|
-
require 'opal/
|
3
|
-
require 'opal/
|
2
|
+
require 'opal/parser'
|
3
|
+
require 'opal/nodes'
|
4
|
+
|
4
5
|
|
5
6
|
require 'strscan'
|
6
7
|
|
7
8
|
module Opal
|
8
|
-
class
|
9
|
+
class Parser < Racc::Parser
|
9
10
|
|
10
11
|
class RubyLexingError < StandardError
|
11
12
|
|
@@ -29,7 +30,6 @@ module Opal
|
|
29
30
|
|
30
31
|
def next_token
|
31
32
|
t = get_next_token
|
32
|
-
# puts "returning token #{t.inspect}"
|
33
33
|
t[1] = { :value => t[1], :line => @line_number }
|
34
34
|
t
|
35
35
|
end
|
@@ -725,6 +725,14 @@ module Opal
|
|
725
725
|
@lex_state = :expr_end
|
726
726
|
return :NIL, scanner.matched
|
727
727
|
|
728
|
+
when 'undefined'
|
729
|
+
@lex_state = :expr_end
|
730
|
+
return :UNDEFINED, scanner.matched
|
731
|
+
|
732
|
+
when 'null'
|
733
|
+
@lex_state = :expr_end
|
734
|
+
return :NULL, scanner.matched
|
735
|
+
|
728
736
|
when '__LINE__'
|
729
737
|
@lex_state = :expr_end
|
730
738
|
return :LINE, @line_number.to_s
|
@@ -809,6 +817,14 @@ module Opal
|
|
809
817
|
@lex_state = :expr_beg
|
810
818
|
return :WHILE_MOD, scanner.matched
|
811
819
|
|
820
|
+
when 'for'
|
821
|
+
@lex_state = :expr_beg
|
822
|
+
return :FOR, scanner.matched
|
823
|
+
|
824
|
+
when 'in'
|
825
|
+
@lex_state = :expr_beg
|
826
|
+
return :IN, scanner.matched
|
827
|
+
|
812
828
|
when 'until'
|
813
829
|
return :WHILE, scanner.matched if @lex_state == :expr_beg
|
814
830
|
@lex_state = :expr_beg
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Opal
|
2
|
-
class
|
2
|
+
class Parser < Racc::Parser
|
3
3
|
|
4
4
|
# Indent for generated code scopes; 2 spaces, never use tabs
|
5
5
|
INDENT = ' '
|
@@ -8,6 +8,7 @@ module Opal
|
|
8
8
|
LEVEL_TOP_CLOSURE = 1 # normal top level, but wrapped in js closure
|
9
9
|
LEVEL_LIST = 2
|
10
10
|
LEVEL_EXPR = 3
|
11
|
+
LEVEL_COMPARE = 4 # comparison of if statement etc
|
11
12
|
|
12
13
|
# Base node for generators. All other nodes inherit from this
|
13
14
|
class BaseNode
|
@@ -69,6 +70,27 @@ module Opal
|
|
69
70
|
|
70
71
|
code
|
71
72
|
end
|
73
|
+
|
74
|
+
# Reserved js words - we cannot just generate properties with these names
|
75
|
+
# as they will cause a parse error, so we need to wrap them in brackets.
|
76
|
+
def js_reserved_words
|
77
|
+
%w[break case catch continue debugger default delete do else finally
|
78
|
+
for function if in instanceof new return switch this throw try typeof
|
79
|
+
var void while with class enum export extends import super true false]
|
80
|
+
end
|
81
|
+
|
82
|
+
def generate_truthy_test(expr, opts)
|
83
|
+
if expr.is_a? ComparisonNode
|
84
|
+
expr.generate opts, LEVEL_EXPR
|
85
|
+
else
|
86
|
+
tmp = opts[:scope].temp_local
|
87
|
+
code = expr.generate opts, LEVEL_EXPR
|
88
|
+
res = "(#{tmp} = #{code}, #{tmp} !== false && #{tmp} !== nil)"
|
89
|
+
opts[:scope].queue_temp tmp
|
90
|
+
res
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
72
94
|
end
|
73
95
|
|
74
96
|
# Scope nodes. All scope nodes inherit from this node, including: method,
|
@@ -194,26 +216,6 @@ module Opal
|
|
194
216
|
super nil, statements
|
195
217
|
@file_helpers = []
|
196
218
|
@line = 1
|
197
|
-
@mm_ids = []
|
198
|
-
|
199
|
-
@symbol_refs = {}
|
200
|
-
@symbol_count = 1
|
201
|
-
|
202
|
-
@regexp_refs = []
|
203
|
-
end
|
204
|
-
|
205
|
-
def register_mm_id(mid)
|
206
|
-
@mm_ids << mid unless @mm_ids.include? mid
|
207
|
-
end
|
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
219
|
end
|
218
220
|
|
219
221
|
def generate(opts, level)
|
@@ -225,32 +227,26 @@ module Opal
|
|
225
227
|
|
226
228
|
pre = 'function $$(){'
|
227
229
|
post = "\n}\n"
|
228
|
-
|
229
|
-
# post += '$hash, $B, Qtrue, Qfalse, $cg;'
|
230
|
-
# local vars... only if we used any..
|
230
|
+
|
231
231
|
unless @scope_vars.empty?
|
232
232
|
post += "var #{@scope_vars.join ', '};"
|
233
233
|
end
|
234
234
|
|
235
|
-
post += 'var nil = $rb.Qnil, $
|
236
|
-
post += '$class = $rb.dc, $defn = $rb.dm, $defs = $rb.ds, $
|
237
|
-
post += '$
|
238
|
-
post += '$cg = $rb.cg, $range = $rb.G'
|
239
|
-
|
240
|
-
# symbols
|
241
|
-
@symbol_refs.each do |val, sym|
|
242
|
-
post += ", #{sym} = $symbol('#{val}')"
|
243
|
-
end
|
235
|
+
post += 'var nil = $rb.Qnil, $super = $rb.S, $break = $rb.B, '
|
236
|
+
post += '$class = $rb.dc, $defn = $rb.dm, $defs = $rb.ds, $cg = $rb.cg, '
|
237
|
+
post += '$range = $rb.G, $hash = $rb.H, $B = $rb.P'
|
244
238
|
|
245
239
|
post += ';'
|
246
240
|
|
247
|
-
if @mm_ids.length > 0
|
248
|
-
post += "$rb.mm(['#{ @mm_ids.join "', '" }']);"
|
249
|
-
end
|
250
|
-
|
251
241
|
# ivars
|
252
242
|
@ivars.each do |ivar|
|
253
|
-
|
243
|
+
if js_reserved_words.include? ivar
|
244
|
+
ivar_name = "self['#{ivar}']"
|
245
|
+
else
|
246
|
+
ivar_name = "self.#{ivar}"
|
247
|
+
end
|
248
|
+
|
249
|
+
post += "#{ivar_name}===undefined&&(#{ivar_name}=nil);"
|
254
250
|
end
|
255
251
|
|
256
252
|
post += "return $$();\n"
|
@@ -348,7 +344,7 @@ module Opal
|
|
348
344
|
end
|
349
345
|
|
350
346
|
def generate(opts, level)
|
351
|
-
|
347
|
+
"'#{@value}'"
|
352
348
|
end
|
353
349
|
end
|
354
350
|
|
@@ -369,20 +365,10 @@ module Opal
|
|
369
365
|
end
|
370
366
|
|
371
367
|
def mid_to_jsid(id)
|
372
|
-
return "
|
373
|
-
|
374
|
-
return ".$m['#{id}']" if js_reserved_words.include? id
|
368
|
+
return "['#{id}']" if /[\!\=\?\+\-\*\/\^\&\%\@\|\[\]\<\>\~]/ =~ id
|
375
369
|
|
376
370
|
# default we just do .method_name
|
377
|
-
'
|
378
|
-
end
|
379
|
-
|
380
|
-
# Reserved js words - we cannot just generate properties with these names
|
381
|
-
# as they will cause a parse error, so we need to wrap them in brackets.
|
382
|
-
def js_reserved_words
|
383
|
-
%w[break case catch continue debugger default delete do else finally
|
384
|
-
for function if in instanceof new return switch this throw try typeof
|
385
|
-
var void while with class enum export extends import super]
|
371
|
+
'.' + id
|
386
372
|
end
|
387
373
|
|
388
374
|
def generate(opts, level)
|
@@ -393,16 +379,13 @@ module Opal
|
|
393
379
|
|
394
380
|
elsif @mid == "block_given?"
|
395
381
|
# name = opts[:scope].set_uses_block
|
396
|
-
return "($yy
|
382
|
+
return "($yy !== $y.y)"
|
397
383
|
end
|
398
384
|
|
399
385
|
code = ''
|
400
386
|
arg_res = []
|
401
387
|
recv = nil
|
402
|
-
mid = @mid
|
403
|
-
tmp_recv = opts[:scope].temp_local
|
404
|
-
|
405
|
-
opts[:top].register_mm_id @mid
|
388
|
+
mid = 'm$' + @mid
|
406
389
|
|
407
390
|
# receiver
|
408
391
|
if @recv.is_a? NumericNode
|
@@ -410,25 +393,11 @@ module Opal
|
|
410
393
|
elsif @recv
|
411
394
|
recv = @recv.process opts, LEVEL_EXPR
|
412
395
|
else
|
413
|
-
@recv = SelfNode.new
|
414
396
|
recv = "self"
|
415
|
-
mid = '$' + mid
|
416
397
|
end
|
417
398
|
|
418
399
|
mid = mid_to_jsid(mid)
|
419
400
|
|
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
|
430
|
-
|
431
|
-
|
432
401
|
args = @args
|
433
402
|
# normal args
|
434
403
|
if args[0]
|
@@ -443,11 +412,12 @@ module Opal
|
|
443
412
|
end
|
444
413
|
|
445
414
|
if @block
|
415
|
+
tmp_recv = opts[:scope].temp_local
|
446
416
|
block = @block.generate opts, LEVEL_TOP
|
447
|
-
arg_res.unshift
|
417
|
+
arg_res.unshift tmp_recv
|
448
418
|
|
449
|
-
code = "($B.f = #{
|
450
|
-
code += "#{block}).$
|
419
|
+
code = "(#{tmp_recv} = #{recv}, $B.f = #{tmp_recv}#{mid}, ($B.p ="
|
420
|
+
code += "#{block}).$self=self, $B.f).call(#{arg_res.join ', '})"
|
451
421
|
|
452
422
|
opts[:scope].queue_temp tmp_recv
|
453
423
|
code
|
@@ -457,10 +427,11 @@ module Opal
|
|
457
427
|
#
|
458
428
|
# FIXME need to actually call to_proc.
|
459
429
|
elsif args[3]
|
460
|
-
|
430
|
+
tmp_recv = opts[:scope].temp_local
|
431
|
+
arg_res.unshift tmp_recv
|
461
432
|
|
462
433
|
code = "($B.p = #{args[3].process opts, LEVEL_LIST}, "
|
463
|
-
code += "$B.f = #{
|
434
|
+
code += "$B.f = (#{tmp_recv} = #{recv})#{mid}).call(#{arg_res.join ', '})"
|
464
435
|
|
465
436
|
opts[:scope].queue_temp tmp_recv
|
466
437
|
|
@@ -470,21 +441,18 @@ module Opal
|
|
470
441
|
else
|
471
442
|
# splat args
|
472
443
|
if args[1]
|
473
|
-
|
444
|
+
tmp_recv = opts[:scope].temp_local
|
474
445
|
splat = args[1].generate(opts, LEVEL_EXPR)
|
475
446
|
splat_args = arg_res.empty? ? "#{splat}" : "[#{arg_res.join ', '}].concat(#{splat})"
|
476
447
|
# when using splat, our this val for apply may need a tmp var
|
477
448
|
# to save just outputting it twice (have to follow recv path twice)
|
478
449
|
splat_recv = recv
|
479
|
-
result = "#{
|
450
|
+
result = "(#{tmp_recv} = #{recv})" + mid + ".apply(#{tmp_recv}, #{splat_args})"
|
480
451
|
|
481
452
|
opts[:scope].queue_temp tmp_recv
|
482
453
|
result
|
483
454
|
else
|
484
|
-
arg_res.
|
485
|
-
|
486
|
-
result = "#{recv_code}#{mid}(#{arg_res.join(', ')})"
|
487
|
-
opts[:scope].queue_temp tmp_recv
|
455
|
+
result = "#{recv}#{mid}(#{arg_res.join(', ')})"
|
488
456
|
result
|
489
457
|
end
|
490
458
|
end
|
@@ -514,6 +482,28 @@ module Opal
|
|
514
482
|
end
|
515
483
|
end
|
516
484
|
|
485
|
+
class UndefinedNode < BaseNode
|
486
|
+
|
487
|
+
def initialize(val)
|
488
|
+
@line = val[:line]
|
489
|
+
end
|
490
|
+
|
491
|
+
def generate(opts, level)
|
492
|
+
'undefined'
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
class NullNode < BaseNode
|
497
|
+
|
498
|
+
def initialize(val)
|
499
|
+
@line = val[:line]
|
500
|
+
end
|
501
|
+
|
502
|
+
def generate(opts, level)
|
503
|
+
'null'
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
517
507
|
class ModuleNode < ScopeNode
|
518
508
|
|
519
509
|
def initialize(mod, path, body, _end)
|
@@ -688,7 +678,13 @@ module Opal
|
|
688
678
|
args[1].each do |arg|
|
689
679
|
param_variable arg[0][:value]
|
690
680
|
method_args << arg[0][:value]
|
691
|
-
|
681
|
+
|
682
|
+
# undefined is a special case... we use it to make core libs have
|
683
|
+
# right arity, but we dont want overhead of checking for no arg.
|
684
|
+
# i.e. non given arg will be undefined, not nil..
|
685
|
+
unless arg[1].is_a? UndefinedNode
|
686
|
+
pre_code += "if (#{arg[0][:value]} == undefined) {#{arg[0][:value]} = #{arg[1].generate(opts, LEVEL_EXPR)};}"
|
687
|
+
end
|
692
688
|
end
|
693
689
|
end
|
694
690
|
|
@@ -697,10 +693,11 @@ module Opal
|
|
697
693
|
if args[2][:value] != "*"
|
698
694
|
param_variable args[2][:value]
|
699
695
|
method_args << args[2][:value]
|
700
|
-
pre_code += "#{args[2][:value]} = [].slice.call(arguments, #{method_args.length});"
|
696
|
+
pre_code += "#{args[2][:value]} = [].slice.call(arguments, #{method_args.length - 1});"
|
701
697
|
end
|
702
698
|
end
|
703
699
|
|
700
|
+
# arity not currently used..could use it for debug mode?
|
704
701
|
arity = (-arity) - 1 if args[1] or args[2]
|
705
702
|
|
706
703
|
# block arg
|
@@ -712,9 +709,8 @@ module Opal
|
|
712
709
|
|
713
710
|
@body.returns
|
714
711
|
stmt = @body.generate scope, LEVEL_TOP
|
715
|
-
method_args.unshift 'self'
|
716
712
|
|
717
|
-
code += "function(#{method_args.join ', '}) {"
|
713
|
+
code += "function(#{method_args.join ', '}) { var self = this;"
|
718
714
|
|
719
715
|
# local vars... only if we used any..
|
720
716
|
unless @scope_vars.empty?
|
@@ -723,7 +719,13 @@ module Opal
|
|
723
719
|
|
724
720
|
# ivars
|
725
721
|
@ivars.each do |ivar|
|
726
|
-
|
722
|
+
if js_reserved_words.include? ivar
|
723
|
+
ivar_name = "self['#{ivar}']"
|
724
|
+
else
|
725
|
+
ivar_name = "self.#{ivar}"
|
726
|
+
end
|
727
|
+
|
728
|
+
pre_code += "if (#{ivar_name} == undefined) { #{ivar_name} = nil; }"
|
727
729
|
end
|
728
730
|
|
729
731
|
# block support
|
@@ -732,14 +734,14 @@ module Opal
|
|
732
734
|
block_code = "var $y = $B, $yy, $ys, $yb = $y.b;"
|
733
735
|
block_code += "if ($y.f == arguments.callee) { $yy = $y.p; }"
|
734
736
|
block_code += "else { $yy = $y.y; }"
|
735
|
-
block_code += "$y.f = nil ;$ys = $yy.$
|
737
|
+
block_code += "$y.f = nil ;$ys = $yy.$self;"
|
736
738
|
pre_code = block_code + pre_code
|
737
739
|
end
|
738
740
|
|
739
741
|
code += (pre_code + stmt)
|
740
742
|
|
741
743
|
# fix trailing end and 0/1 for normal/singleton
|
742
|
-
code += (fix_line_number(opts, @end_line) + "}
|
744
|
+
code += (fix_line_number(opts, @end_line) + "})")
|
743
745
|
|
744
746
|
code
|
745
747
|
end
|
@@ -748,6 +750,7 @@ module Opal
|
|
748
750
|
class BodyStatementsNode < BaseNode
|
749
751
|
|
750
752
|
attr_reader :opt_rescue
|
753
|
+
attr_reader :opt_ensure
|
751
754
|
|
752
755
|
def initialize(stmt, optrescue, optelse, optensure)
|
753
756
|
@statements = stmt
|
@@ -777,7 +780,7 @@ module Opal
|
|
777
780
|
def generate(opts, level)
|
778
781
|
res = '(('
|
779
782
|
tmp = opts[:scope].temp_local
|
780
|
-
res += "#{tmp} = #{@lhs.generate opts, LEVEL_LIST})
|
783
|
+
res += "(#{tmp} = #{@lhs.generate opts, LEVEL_LIST}), #{tmp} != false && #{tmp} != nil) ? "
|
781
784
|
res += "#{tmp} : #{@rhs.generate opts, LEVEL_LIST})"
|
782
785
|
opts[:scope].queue_temp tmp
|
783
786
|
res
|
@@ -795,7 +798,7 @@ module Opal
|
|
795
798
|
def generate(opts, level)
|
796
799
|
res = '(('
|
797
800
|
tmp = opts[:scope].temp_local
|
798
|
-
res += "#{tmp} = #{@lhs.generate opts, LEVEL_LIST})
|
801
|
+
res += "(#{tmp} = #{@lhs.generate opts, LEVEL_LIST}), #{tmp} != false && #{tmp} != nil) ? "
|
799
802
|
res += "#{@rhs.generate opts, LEVEL_LIST} : #{tmp})"
|
800
803
|
opts[:scope].queue_temp tmp
|
801
804
|
res
|
@@ -822,7 +825,7 @@ module Opal
|
|
822
825
|
res = code
|
823
826
|
end
|
824
827
|
|
825
|
-
res
|
828
|
+
"#{res}"
|
826
829
|
end
|
827
830
|
end
|
828
831
|
|
@@ -884,20 +887,18 @@ module Opal
|
|
884
887
|
@level_expr = true
|
885
888
|
end
|
886
889
|
|
887
|
-
expr = @expr
|
888
|
-
expr = "(#{expr})" if @expr.is_a? NumericNode
|
889
|
-
|
890
|
+
expr = generate_truthy_test @expr, opts
|
890
891
|
# code += "if ((#{@expr.generate opts, LEVEL_EXPR}).$r) {#{@stmt.process opts, stmt_level}"
|
891
|
-
code += "if (#{@type == 'if' ? '' : '!'}#{expr}
|
892
|
+
code += "if (#{@type == 'if' ? '' : '!'}#{expr}) {#{@stmt.process opts, stmt_level}"
|
892
893
|
|
893
894
|
@tail.each do |tail|
|
894
895
|
opts[:indent] = old_indent
|
895
896
|
code = code + fix_line_number(opts, tail[0][:line])
|
896
897
|
|
897
898
|
if tail[0][:value] == 'elsif'
|
898
|
-
expr = tail[1]
|
899
|
-
|
900
|
-
code += "} else if (#{expr}
|
899
|
+
expr = generate_truthy_test tail[1], opts
|
900
|
+
|
901
|
+
code += "} else if (#{expr}) {"
|
901
902
|
# code += "} else if ((#{tail[1].generate opts, LEVEL_EXPR}).$r) {"
|
902
903
|
opts[:indent] = opts[:indent] + INDENT
|
903
904
|
code = code + tail[2].process(opts, stmt_level)
|
@@ -971,10 +972,10 @@ module Opal
|
|
971
972
|
if part[0][:value] == 'when'
|
972
973
|
code += (idx == 0 ? "if" : "} else if")
|
973
974
|
parts = part[1].map do |expr|
|
974
|
-
CallNode.new(expr,
|
975
|
+
generate_truthy_test CallNode.new(expr,
|
975
976
|
{:value => '===' },
|
976
977
|
[[TempNode.new(case_ref)]]
|
977
|
-
)
|
978
|
+
), opts
|
978
979
|
end
|
979
980
|
opts[:indent] = opts[:indent] + INDENT
|
980
981
|
code += " (#{parts.join ' || '}) {#{part[2].process opts, stmt_level}"
|
@@ -988,7 +989,7 @@ module Opal
|
|
988
989
|
opts[:scope].queue_temp case_ref
|
989
990
|
code += (fix_line_number(opts, @end_line) + '}')
|
990
991
|
|
991
|
-
code = "(function() {#{code})()" if level == LEVEL_EXPR
|
992
|
+
code = "(function() {#{code}})()" if level == LEVEL_EXPR
|
992
993
|
code
|
993
994
|
end
|
994
995
|
end
|
@@ -1057,7 +1058,14 @@ module Opal
|
|
1057
1058
|
|
1058
1059
|
def generate(opts, level)
|
1059
1060
|
if @lhs.is_a? IvarNode
|
1060
|
-
|
1061
|
+
ivar_name = @lhs.value.slice 1, @lhs.value.length
|
1062
|
+
ivar_rhs = @rhs.generate opts, LEVEL_EXPR
|
1063
|
+
|
1064
|
+
return "self['#{ivar_name}'] = #{ivar_rhs}" if js_reserved_words.include? ivar_name
|
1065
|
+
return "self.#{ivar_name} = #{ivar_rhs}"
|
1066
|
+
|
1067
|
+
elsif @lhs.is_a? CvarNode
|
1068
|
+
return "$rb.cvs('#{@lhs.value}', #{@rhs.generate opts, LEVEL_EXPR})"
|
1061
1069
|
|
1062
1070
|
elsif @lhs.is_a? GvarNode
|
1063
1071
|
return "$rb.gs('#{@lhs.value}', #{@rhs.generate(opts, LEVEL_EXPR)})"
|
@@ -1167,8 +1175,25 @@ module Opal
|
|
1167
1175
|
end
|
1168
1176
|
|
1169
1177
|
def generate(opts, level)
|
1170
|
-
|
1171
|
-
|
1178
|
+
var_name = @value.slice 1, @value.length
|
1179
|
+
opts[:scope].ensure_ivar var_name
|
1180
|
+
|
1181
|
+
return "self['#{var_name}']" if js_reserved_words.include? var_name
|
1182
|
+
"self.#{var_name}"
|
1183
|
+
end
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
class CvarNode < BaseNode
|
1187
|
+
|
1188
|
+
attr_reader :value
|
1189
|
+
|
1190
|
+
def initialize(val)
|
1191
|
+
@line = val[:line]
|
1192
|
+
@value = val[:value]
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
def generate(opts, level)
|
1196
|
+
"$rb.cvg('#{@value}')"
|
1172
1197
|
end
|
1173
1198
|
end
|
1174
1199
|
|
@@ -1228,7 +1253,8 @@ module Opal
|
|
1228
1253
|
if part[0] == 'string_content'
|
1229
1254
|
@join + part[1][:value] + @join
|
1230
1255
|
elsif part[0] == 'string_dbegin'
|
1231
|
-
|
1256
|
+
"(" + part[1].generate(opts, LEVEL_EXPR) + ").m$to_s()"
|
1257
|
+
# CallNode.new(part[1], { :value => 'to_s', :line => 0 }, [[]]).generate(opts, level)
|
1232
1258
|
end
|
1233
1259
|
end
|
1234
1260
|
|
@@ -1237,6 +1263,49 @@ module Opal
|
|
1237
1263
|
end
|
1238
1264
|
end
|
1239
1265
|
|
1266
|
+
class ComparisonNode < BaseNode
|
1267
|
+
|
1268
|
+
def initialize(op, lhs, rhs)
|
1269
|
+
@line = op[:line]
|
1270
|
+
@op = op[:value]
|
1271
|
+
@lhs = lhs
|
1272
|
+
@rhs = rhs
|
1273
|
+
end
|
1274
|
+
|
1275
|
+
def generate(opts, level)
|
1276
|
+
lhs = @lhs.generate opts, LEVEL_EXPR
|
1277
|
+
lhs = "(#{lhs})" if @lhs.is_a? NumericNode
|
1278
|
+
rhs = @rhs.generate opts, LEVEL_EXPR
|
1279
|
+
|
1280
|
+
if @op == '!='
|
1281
|
+
"!#{lhs}['m$=='](#{rhs})"
|
1282
|
+
else
|
1283
|
+
"#{lhs}['m$#{@op}'](#{rhs})"
|
1284
|
+
end
|
1285
|
+
end
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
class UnaryNode < BaseNode
|
1289
|
+
|
1290
|
+
def initialize(op, val)
|
1291
|
+
@line = op[:line]
|
1292
|
+
@op = op[:value]
|
1293
|
+
@val = val
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
def generate(opts, level)
|
1297
|
+
if @op == '!'
|
1298
|
+
tmp = opts[:scope].temp_local
|
1299
|
+
expr = @val.generate opts, LEVEL_EXPR
|
1300
|
+
res = "(#{tmp} = #{expr}, #{tmp} === false || #{tmp} === nil)"
|
1301
|
+
opts[:scope].queue_temp tmp
|
1302
|
+
res
|
1303
|
+
else
|
1304
|
+
"#{@op}#{@val.generate opts, level}"
|
1305
|
+
end
|
1306
|
+
end
|
1307
|
+
end
|
1308
|
+
|
1240
1309
|
class TrueNode < BaseNode
|
1241
1310
|
|
1242
1311
|
def initialize(val)
|
@@ -1244,7 +1313,7 @@ module Opal
|
|
1244
1313
|
end
|
1245
1314
|
|
1246
1315
|
def generate(opts, level)
|
1247
|
-
"
|
1316
|
+
"true"
|
1248
1317
|
end
|
1249
1318
|
end
|
1250
1319
|
|
@@ -1255,7 +1324,7 @@ module Opal
|
|
1255
1324
|
end
|
1256
1325
|
|
1257
1326
|
def generate(opts, level)
|
1258
|
-
"
|
1327
|
+
"false"
|
1259
1328
|
end
|
1260
1329
|
end
|
1261
1330
|
|
@@ -1293,7 +1362,7 @@ module Opal
|
|
1293
1362
|
#
|
1294
1363
|
# Also, this is optional, and can be turned on/off for
|
1295
1364
|
# performance gains.
|
1296
|
-
if
|
1365
|
+
if false
|
1297
1366
|
pre_code += "if (#{arg[:value]} === undefined) { #{arg[:value]} = nil; }"
|
1298
1367
|
end
|
1299
1368
|
end
|
@@ -1317,7 +1386,7 @@ module Opal
|
|
1317
1386
|
# FIXME if we just pass '*', then we make a tmp variable name for it..
|
1318
1387
|
param_variable rest_arg_name
|
1319
1388
|
method_args << rest_arg_name
|
1320
|
-
pre_code += "#{rest_arg_name} = [].slice.call(
|
1389
|
+
pre_code += "#{rest_arg_name} = [].slice.call(arguments, #{method_args.length - 1});"
|
1321
1390
|
end
|
1322
1391
|
end
|
1323
1392
|
|
@@ -1325,17 +1394,17 @@ module Opal
|
|
1325
1394
|
if args[3]
|
1326
1395
|
param_variable args[3][:value]
|
1327
1396
|
@block_arg_name = args[3][:value]
|
1397
|
+
pre_code += "var #{args[3][:value]} = (($yy == $y.y) ? nil: $yy);"
|
1328
1398
|
end
|
1329
1399
|
end
|
1330
1400
|
|
1331
1401
|
@stmt.returns
|
1332
1402
|
stmt = @stmt.process scope, LEVEL_TOP
|
1333
|
-
method_args.unshift 'self'
|
1334
1403
|
|
1335
1404
|
block_var = opts[:scope].temp_local
|
1336
1405
|
# code += "(#{block_var} = "
|
1337
1406
|
|
1338
|
-
code += "function(#{method_args.join ', '}) {"
|
1407
|
+
code += "function(#{method_args.join ', '}) { var self = this;"
|
1339
1408
|
|
1340
1409
|
unless @scope_vars.empty?
|
1341
1410
|
code += " var #{@scope_vars.join ', '};"
|
@@ -1343,15 +1412,11 @@ module Opal
|
|
1343
1412
|
|
1344
1413
|
# block arg
|
1345
1414
|
if @block_arg_name
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
stmt = "try{" + stmt
|
1352
|
-
|
1353
|
-
# catch break statements
|
1354
|
-
stmt += "} catch (__err__) {if(__err__.$keyword == 2) {return __err__.$value;} throw __err__;}"
|
1415
|
+
block_code = "var $y = $B, $yy, $ys, $yb = $y.b;"
|
1416
|
+
block_code += "if ($y.f == arguments.callee) { $yy = $y.p; }"
|
1417
|
+
block_code += "else { $yy = $y.y; }"
|
1418
|
+
block_code += "$y.f = nil ;$ys = $yy.o$s;"
|
1419
|
+
pre_code = block_code + pre_code
|
1355
1420
|
end
|
1356
1421
|
|
1357
1422
|
code += (pre_code + stmt + fix_line_number(opts, @end_line) + "}")
|
@@ -1471,8 +1536,10 @@ module Opal
|
|
1471
1536
|
# if we return, make sure our stmt does
|
1472
1537
|
@stmt.returns if @returns
|
1473
1538
|
|
1474
|
-
|
1475
|
-
|
1539
|
+
expr = generate_truthy_test @expr, opts
|
1540
|
+
|
1541
|
+
r = "if(#{@type == 'if' ? '' : '!'}(#{expr}"
|
1542
|
+
r += ")) {#{@stmt.process(opts, LEVEL_TOP)}}"
|
1476
1543
|
|
1477
1544
|
# also, if we return, we need to ensure we have an else conditional
|
1478
1545
|
r += " else { return nil; }" if @returns
|
@@ -1499,10 +1566,10 @@ module Opal
|
|
1499
1566
|
|
1500
1567
|
if @args[1]
|
1501
1568
|
parts.unshift '$ys'
|
1502
|
-
code = "#{block_code}(
|
1569
|
+
code = "#{block_code}.apply($ys, [#{parts.join ', '}].concat(#{@args[1].generate(opts, LEVEL_EXPR)}))"
|
1503
1570
|
else
|
1504
1571
|
parts.unshift '$ys'
|
1505
|
-
code = "#{block_code}(#{parts.join ', '})"
|
1572
|
+
code = "#{block_code}.call(#{parts.join ', '})"
|
1506
1573
|
end
|
1507
1574
|
|
1508
1575
|
code
|
@@ -1671,8 +1738,8 @@ module Opal
|
|
1671
1738
|
|
1672
1739
|
@redo_var = eval_expr = opts[:scope].temp_local
|
1673
1740
|
code = "#{eval_expr} = false; while (#{eval_expr} || #{truthy}("
|
1674
|
-
code += @expr
|
1675
|
-
code += ")
|
1741
|
+
code += generate_truthy_test @expr, opts
|
1742
|
+
code += ")) {#{eval_expr} = false;"
|
1676
1743
|
|
1677
1744
|
opts[:scope].push_while_scope self
|
1678
1745
|
|
@@ -1698,6 +1765,43 @@ module Opal
|
|
1698
1765
|
end
|
1699
1766
|
end
|
1700
1767
|
|
1768
|
+
class ForNode < BaseNode
|
1769
|
+
|
1770
|
+
def initialize(begn, vars, expr, compstmt, endn)
|
1771
|
+
@line = begn[:line]
|
1772
|
+
@vars = vars
|
1773
|
+
@expr = expr
|
1774
|
+
@stmt = compstmt
|
1775
|
+
@end_line = endn[:line]
|
1776
|
+
end
|
1777
|
+
|
1778
|
+
def returns
|
1779
|
+
@returns = true
|
1780
|
+
self
|
1781
|
+
end
|
1782
|
+
|
1783
|
+
def generate(opts, level)
|
1784
|
+
@current_scope = opts[:scope]
|
1785
|
+
stmt_level = (level == LEVEL_EXPR ? LEVEL_TOP_CLOSURE : LEVEL_TOP)
|
1786
|
+
|
1787
|
+
if stmt_level == LEVEL_TOP_CLOSURE
|
1788
|
+
returns
|
1789
|
+
@level_expr = true
|
1790
|
+
end
|
1791
|
+
|
1792
|
+
idx = opts[:scope].temp_local
|
1793
|
+
ref = opts[:scope].temp_local
|
1794
|
+
len = opts[:scope].temp_local
|
1795
|
+
code = "for (#{idx} = 0, #{ref} = #{@expr.generate opts, LEVEL_EXPR}"
|
1796
|
+
code += ", #{len} = #{ref}.length; #{idx} < #{len}; #{idx}++) {"
|
1797
|
+
|
1798
|
+
code += @stmt.process opts, LEVEL_TOP
|
1799
|
+
|
1800
|
+
code += fix_line_number opts, @end_line
|
1801
|
+
code += "}"
|
1802
|
+
end
|
1803
|
+
end
|
1804
|
+
|
1701
1805
|
class SuperNode < BaseNode
|
1702
1806
|
|
1703
1807
|
def initialize(start, args)
|
@@ -1781,6 +1885,12 @@ module Opal
|
|
1781
1885
|
opts[:indent] = old_indent + INDENT
|
1782
1886
|
end
|
1783
1887
|
|
1888
|
+
if opt_ensure = @body.opt_ensure
|
1889
|
+
# puts "optional ensure!"
|
1890
|
+
code += "} finally {"
|
1891
|
+
code += opt_ensure.process opts, LEVEL_TOP
|
1892
|
+
end
|
1893
|
+
|
1784
1894
|
|
1785
1895
|
opts[:indent] = old_indent
|
1786
1896
|
code += (fix_line_number(opts, @end_line) + "}")
|
@@ -1798,7 +1908,8 @@ module Opal
|
|
1798
1908
|
end
|
1799
1909
|
|
1800
1910
|
def generate(opts, level)
|
1801
|
-
|
1911
|
+
test = generate_truthy_test @expr, opts
|
1912
|
+
"(#{test} ? #{@true.generate opts, LEVEL_EXPR} : #{@false.generate opts, LEVEL_EXPR})"
|
1802
1913
|
end
|
1803
1914
|
end
|
1804
1915
|
|