opal 0.3.6 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|