opal 0.9.4 → 0.10.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +1 -0
- data/.gitignore +2 -3
- data/.gitmodules +5 -2
- data/.jshintrc +1 -8
- data/.rspec +1 -1
- data/.travis.yml +15 -23
- data/CHANGELOG.md +511 -326
- data/CODE_OF_CONDUCT.md +13 -15
- data/CONTRIBUTING.md +26 -216
- data/Gemfile +20 -12
- data/Guardfile +2 -2
- data/HACKING.md +230 -0
- data/README.md +6 -7
- data/bin/opal-mspec +1 -1
- data/config.ru +2 -2
- data/docs/faq.md +1 -1
- data/docs/source_maps.md +1 -1
- data/lib/opal.rb +1 -0
- data/lib/opal/builder.rb +1 -1
- data/lib/opal/cli.rb +30 -28
- data/lib/opal/cli_options.rb +3 -0
- data/lib/opal/cli_runners.rb +14 -1
- data/lib/opal/cli_runners/{apple_script.rb → applescript.rb} +3 -3
- data/lib/opal/cli_runners/nashorn.rb +2 -2
- data/lib/opal/cli_runners/nodejs.rb +2 -2
- data/lib/opal/cli_runners/phantom.js +24 -0
- data/lib/opal/cli_runners/phantomjs.rb +10 -10
- data/lib/opal/cli_runners/server.rb +3 -3
- data/lib/opal/compiler.rb +43 -4
- data/lib/opal/config.rb +3 -1
- data/lib/opal/errors.rb +13 -0
- data/lib/opal/fragment.rb +0 -13
- data/lib/opal/nodes.rb +10 -0
- data/lib/opal/nodes/args/initialize_kwargs.rb +28 -0
- data/lib/opal/nodes/args/kwarg.rb +29 -0
- data/lib/opal/nodes/args/kwoptarg.rb +29 -0
- data/lib/opal/nodes/args/kwrestarg.rb +39 -0
- data/lib/opal/nodes/args/mlhsarg.rb +79 -0
- data/lib/opal/nodes/args/normarg.rb +26 -0
- data/lib/opal/nodes/args/optarg.rb +27 -0
- data/lib/opal/nodes/args/post_args.rb +200 -0
- data/lib/opal/nodes/args/post_kwargs.rb +31 -0
- data/lib/opal/nodes/args/restarg.rb +33 -0
- data/lib/opal/nodes/base.rb +12 -0
- data/lib/opal/nodes/call.rb +92 -33
- data/lib/opal/nodes/def.rb +26 -169
- data/lib/opal/nodes/hash.rb +10 -4
- data/lib/opal/nodes/helpers.rb +6 -3
- data/lib/opal/nodes/inline_args.rb +61 -0
- data/lib/opal/nodes/iter.rb +73 -82
- data/lib/opal/nodes/logic.rb +12 -2
- data/lib/opal/nodes/masgn.rb +1 -2
- data/lib/opal/nodes/node_with_args.rb +141 -0
- data/lib/opal/nodes/rescue.rb +121 -43
- data/lib/opal/nodes/scope.rb +24 -5
- data/lib/opal/nodes/super.rb +122 -54
- data/lib/opal/nodes/top.rb +0 -12
- data/lib/opal/nodes/yield.rb +2 -13
- data/lib/opal/parser.rb +67 -39
- data/lib/opal/parser/grammar.rb +3319 -2961
- data/lib/opal/parser/grammar.y +234 -46
- data/lib/opal/parser/lexer.rb +105 -17
- data/lib/opal/parser/sexp.rb +4 -0
- data/lib/opal/paths.rb +4 -0
- data/lib/opal/regexp_anchors.rb +19 -1
- data/lib/opal/sprockets.rb +21 -18
- data/lib/opal/sprockets/environment.rb +0 -8
- data/lib/opal/sprockets/processor.rb +13 -16
- data/lib/opal/sprockets/server.rb +6 -12
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/corelib/array.rb +209 -131
- data/opal/corelib/basic_object.rb +7 -3
- data/opal/corelib/class.rb +11 -17
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/enumerable.rb +178 -355
- data/opal/corelib/enumerator.rb +3 -46
- data/opal/corelib/error.rb +2 -2
- data/opal/corelib/file.rb +13 -1
- data/opal/corelib/hash.rb +26 -56
- data/opal/corelib/helpers.rb +10 -0
- data/opal/corelib/kernel.rb +6 -3
- data/opal/corelib/module.rb +62 -31
- data/opal/corelib/number.rb +7 -16
- data/opal/corelib/proc.rb +24 -9
- data/opal/corelib/range.rb +4 -13
- data/opal/corelib/runtime.js +515 -378
- data/opal/corelib/string.rb +21 -49
- data/opal/corelib/struct.rb +50 -35
- data/opal/corelib/unsupported.rb +18 -30
- data/opal/opal.rb +0 -1
- data/opal/opal/mini.rb +1 -0
- data/spec/README.md +6 -4
- data/spec/filters/bugs/array.rb +0 -42
- data/spec/filters/bugs/basicobject.rb +0 -2
- data/spec/filters/bugs/bigdecimal.rb +160 -0
- data/spec/filters/bugs/class.rb +0 -5
- data/spec/filters/bugs/date.rb +1 -48
- data/spec/filters/bugs/enumerable.rb +4 -12
- data/spec/filters/bugs/enumerator.rb +0 -1
- data/spec/filters/bugs/exception.rb +4 -3
- data/spec/filters/bugs/float.rb +4 -2
- data/spec/filters/bugs/kernel.rb +25 -10
- data/spec/filters/bugs/language.rb +119 -68
- data/spec/filters/bugs/method.rb +135 -0
- data/spec/filters/bugs/module.rb +13 -28
- data/spec/filters/bugs/proc.rb +18 -8
- data/spec/filters/bugs/range.rb +0 -3
- data/spec/filters/bugs/rational.rb +4 -0
- data/spec/filters/bugs/regexp.rb +68 -36
- data/spec/filters/bugs/string.rb +1 -1
- data/spec/filters/bugs/struct.rb +0 -12
- data/spec/filters/bugs/time.rb +1 -0
- data/spec/filters/bugs/unboundmethod.rb +2 -1
- data/spec/filters/unsupported/freeze.rb +3 -1
- data/spec/filters/unsupported/language.rb +0 -7
- data/spec/filters/unsupported/privacy.rb +7 -6
- data/spec/filters/unsupported/string.rb +10 -0
- data/spec/filters/unsupported/struct.rb +3 -0
- data/spec/filters/unsupported/symbol.rb +9 -0
- data/spec/filters/unsupported/taint.rb +0 -3
- data/spec/filters/unsupported/thread.rb +1 -0
- data/spec/lib/cli_runners/phantomjs_spec.rb +39 -0
- data/spec/lib/cli_spec.rb +42 -1
- data/spec/lib/compiler/call_spec.rb +700 -0
- data/spec/lib/compiler_spec.rb +46 -28
- data/spec/lib/config_spec.rb +13 -0
- data/spec/lib/parser/call_spec.rb +18 -0
- data/spec/lib/parser/def_spec.rb +29 -0
- data/spec/lib/parser/iter_spec.rb +15 -15
- data/spec/lib/parser/lambda_spec.rb +153 -12
- data/spec/lib/parser/string_spec.rb +5 -0
- data/spec/lib/parser/undef_spec.rb +1 -1
- data/spec/lib/parser/variables_spec.rb +24 -0
- data/spec/lib/paths_spec.rb +12 -5
- data/spec/lib/spec_helper.rb +5 -0
- data/spec/lib/sprockets/processor_spec.rb +6 -5
- data/spec/lib/sprockets_spec.rb +8 -0
- data/spec/mspec-opal/formatters.rb +188 -0
- data/spec/mspec-opal/runner.rb +193 -0
- data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
- data/spec/opal/core/kernel/define_singleton_method_spec.rb +1 -1
- data/spec/opal/core/kernel/instance_variables_spec.rb +14 -0
- data/spec/opal/core/kernel/loop_spec.rb +1 -1
- data/spec/opal/core/kernel/raise_spec.rb +1 -1
- data/spec/opal/core/language/heredoc_spec.rb +42 -0
- data/spec/opal/core/language/rescue_spec.rb +18 -0
- data/spec/opal/core/language_spec.rb +22 -0
- data/spec/opal/core/module/const_defined_spec.rb +1 -2
- data/spec/opal/core/module/name_spec.rb +6 -0
- data/spec/opal/core/runtime/bridged_classes_spec.rb +14 -2
- data/spec/opal/core/runtime/rescue_spec.rb +12 -2
- data/spec/opal/core/runtime/super_spec.rb +1 -0
- data/spec/opal/core/string_spec.rb +21 -0
- data/spec/opal/stdlib/js_spec.rb +1 -1
- data/spec/opal/stdlib/native/hash_spec.rb +7 -0
- data/spec/opal/stdlib/promise/always_spec.rb +24 -5
- data/spec/opal/stdlib/promise/rescue_spec.rb +15 -6
- data/spec/opal/stdlib/promise/then_spec.rb +13 -5
- data/spec/opal/stdlib/promise/trace_spec.rb +5 -6
- data/spec/opal/stdlib/strscan/scan_spec.rb +1 -1
- data/spec/ruby_specs +122 -0
- data/spec/spec_helper.rb +3 -15
- data/stdlib/base64.rb +51 -121
- data/stdlib/bigdecimal.rb +231 -0
- data/stdlib/bigdecimal/bignumber.js.rb +11 -0
- data/stdlib/bigdecimal/kernel.rb +5 -0
- data/stdlib/date.rb +252 -10
- data/stdlib/native.rb +38 -38
- data/stdlib/nodejs/dir.rb +8 -6
- data/stdlib/nodejs/file.rb +28 -3
- data/stdlib/nodejs/node_modules/.bin/js-yaml +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esparse +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esvalidate +1 -0
- data/stdlib/nodejs/require.rb +1 -1
- data/stdlib/nodejs/yaml.rb +3 -2
- data/stdlib/opal-parser.rb +7 -2
- data/stdlib/pathname.rb +23 -1
- data/stdlib/phantomjs.rb +10 -0
- data/stdlib/promise.rb +38 -23
- data/tasks/building.rake +3 -3
- data/tasks/testing.rake +27 -14
- data/tasks/testing/mspec_special_calls.rb +1 -1
- data/tasks/testing/sprockets-phantomjs.js +4 -0
- data/test/opal/test_keyword.rb +110 -110
- data/test/opal/unsupported_and_bugs.rb +30 -0
- data/vendored-minitest/minitest/assertions.rb +1 -1
- metadata +65 -15
- data/.spectator +0 -2
- data/.spectator-mspec +0 -3
- data/opal/corelib/array/inheritance.rb +0 -127
- data/spec/rubyspecs +0 -139
data/lib/opal/nodes/hash.rb
CHANGED
@@ -5,11 +5,17 @@ module Opal
|
|
5
5
|
class HashNode < Base
|
6
6
|
handle :hash
|
7
7
|
|
8
|
-
def
|
8
|
+
def extract_keys_and_values(pairs)
|
9
9
|
keys, values = [], []
|
10
10
|
|
11
|
-
|
12
|
-
if
|
11
|
+
pairs.each_with_index do |obj, idx|
|
12
|
+
if obj.type == :kwsplat
|
13
|
+
# obj is (:kwsplat, (:hash, (:key, value), ...))
|
14
|
+
kwsplat_pairs = obj[1].children
|
15
|
+
kwsplat_keys, kwsplat_values = extract_keys_and_values(kwsplat_pairs)
|
16
|
+
keys.concat(kwsplat_keys)
|
17
|
+
values.concat(kwsplat_values)
|
18
|
+
elsif idx.even?
|
13
19
|
keys << obj
|
14
20
|
else
|
15
21
|
values << obj
|
@@ -24,7 +30,7 @@ module Opal
|
|
24
30
|
end
|
25
31
|
|
26
32
|
def compile
|
27
|
-
keys, values =
|
33
|
+
keys, values = extract_keys_and_values(children)
|
28
34
|
|
29
35
|
if simple_keys? keys
|
30
36
|
compile_hash2 keys, values
|
data/lib/opal/nodes/helpers.rb
CHANGED
@@ -23,6 +23,9 @@ module Opal
|
|
23
23
|
# Doesn't take in account utf8
|
24
24
|
BASIC_IDENTIFIER_RULES = /#{REGEXP_START}[$_a-z][$_a-z\d]*#{REGEXP_END}/i
|
25
25
|
|
26
|
+
# Defining a local function like Array may break everything
|
27
|
+
RESERVED_FUNCTION_NAMES = /#{REGEXP_START}(?:Array)#{REGEXP_END}/
|
28
|
+
|
26
29
|
|
27
30
|
def property(name)
|
28
31
|
valid_name?(name) ? ".#{name}" : "[#{name.inspect}]"
|
@@ -114,15 +117,15 @@ module Opal
|
|
114
117
|
if sexp.type == :call
|
115
118
|
mid = sexp[2]
|
116
119
|
receiver_handler_class = (receiver = sexp[1]) && compiler.handlers[receiver.type]
|
117
|
-
|
120
|
+
|
118
121
|
# Only operator calls on the truthy_optimize? node classes should be optimized.
|
119
122
|
# Monkey patch method calls might return 'self'/aka a bridged instance and need
|
120
123
|
# the nil check - see discussion at https://github.com/opal/opal/pull/1097
|
121
124
|
allow_optimization_on_type = Compiler::COMPARE.include?(mid.to_s) &&
|
122
125
|
receiver_handler_class &&
|
123
126
|
receiver_handler_class.truthy_optimize?
|
124
|
-
|
125
|
-
if allow_optimization_on_type ||
|
127
|
+
|
128
|
+
if allow_optimization_on_type ||
|
126
129
|
mid == :block_given? ||
|
127
130
|
mid == :"=="
|
128
131
|
expr(sexp)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'opal/nodes/base'
|
2
|
+
|
3
|
+
module Opal
|
4
|
+
module Nodes
|
5
|
+
# def args list
|
6
|
+
class InlineArgs < Base
|
7
|
+
handle :inline_args
|
8
|
+
|
9
|
+
def compile
|
10
|
+
push(arg_names.join(', '))
|
11
|
+
end
|
12
|
+
|
13
|
+
def arg_names
|
14
|
+
done_kwargs = false
|
15
|
+
|
16
|
+
children.inject([]) do |result, child|
|
17
|
+
case child.type
|
18
|
+
when :kwarg, :kwoptarg, :kwrestarg
|
19
|
+
unless done_kwargs
|
20
|
+
done_kwargs = true
|
21
|
+
result << '$kwargs'
|
22
|
+
end
|
23
|
+
add_arg(child)
|
24
|
+
when :mlhs
|
25
|
+
tmp = scope.next_temp
|
26
|
+
result << tmp
|
27
|
+
scope.mlhs_mapping[child] = tmp
|
28
|
+
when :arg, :optarg
|
29
|
+
arg_name = variable(child[1]).to_s
|
30
|
+
if !child.meta[:inline] && arg_name[0] != '$'
|
31
|
+
arg_name = "$#{arg_name}"
|
32
|
+
end
|
33
|
+
result << arg_name
|
34
|
+
add_arg(child)
|
35
|
+
when :restarg
|
36
|
+
# To make function.length working
|
37
|
+
# in cases like def m(*rest)
|
38
|
+
tmp_arg_name = scope.next_temp + "_rest"
|
39
|
+
result << tmp_arg_name
|
40
|
+
add_arg(child)
|
41
|
+
else
|
42
|
+
raise "Unknown argument type #{child.inspect}"
|
43
|
+
end
|
44
|
+
|
45
|
+
result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# If the argument has a name,
|
50
|
+
# we should mark it as an argument for current scope
|
51
|
+
# Otherwise, these args will be interpreted
|
52
|
+
# in the child scope as local variables
|
53
|
+
def add_arg(arg)
|
54
|
+
if arg[1]
|
55
|
+
arg_name = variable(arg[1].to_sym)
|
56
|
+
scope.add_arg(arg_name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/opal/nodes/iter.rb
CHANGED
@@ -1,46 +1,37 @@
|
|
1
|
-
require 'opal/nodes/
|
1
|
+
require 'opal/nodes/node_with_args'
|
2
2
|
|
3
3
|
module Opal
|
4
4
|
module Nodes
|
5
|
-
class IterNode <
|
5
|
+
class IterNode < NodeWithArgs
|
6
6
|
handle :iter
|
7
7
|
|
8
8
|
children :args_sexp, :body_sexp
|
9
9
|
|
10
|
+
attr_accessor :block_arg, :shadow_args
|
11
|
+
|
10
12
|
def compile
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
if args.last.is_a?(Sexp) and args.last.type == :splat
|
16
|
-
splat = args.last[1][1]
|
17
|
-
args.pop
|
18
|
-
len = args.length
|
19
|
-
end
|
13
|
+
inline_params = nil
|
14
|
+
extract_block_arg
|
15
|
+
extract_shadow_args
|
16
|
+
split_args
|
20
17
|
|
21
|
-
|
22
|
-
params << splat if splat
|
18
|
+
# require 'pry'; binding.pry
|
23
19
|
|
24
20
|
to_vars = identity = body_code = nil
|
25
21
|
|
26
22
|
in_scope do
|
23
|
+
inline_params = process(inline_args_sexp)
|
24
|
+
|
27
25
|
identity = scope.identify!
|
28
26
|
add_temp "self = #{identity}.$$s || this"
|
29
27
|
|
30
|
-
|
28
|
+
compile_shadow_args
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
push "#{splat} = $slice.call(arguments, #{len - 1});"
|
35
|
-
end
|
30
|
+
compile_inline_args
|
31
|
+
compile_post_args
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
scope.add_temp block_arg
|
40
|
-
scope_name = scope.identify!
|
41
|
-
|
42
|
-
line "#{block_arg} = #{scope_name}.$$p || nil, #{scope_name}.$$p = null;"
|
43
|
-
end
|
33
|
+
compile_block_arg
|
34
|
+
compile_norm_args
|
44
35
|
|
45
36
|
body_code = stmt(body)
|
46
37
|
to_vars = scope.to_vars
|
@@ -50,86 +41,86 @@ module Opal
|
|
50
41
|
|
51
42
|
unshift to_vars
|
52
43
|
|
53
|
-
unshift "(#{identity} = function(
|
54
|
-
push "}, #{identity}.$$s = self,
|
44
|
+
unshift "(#{identity} = function(", inline_params, "){"
|
45
|
+
push "}, #{identity}.$$s = self,"
|
46
|
+
push " #{identity}.$$brk = $brk," if compiler.has_break?
|
47
|
+
push " #{identity})"
|
55
48
|
end
|
56
49
|
|
57
|
-
def
|
58
|
-
args.
|
59
|
-
|
60
|
-
arg = variable(arg[1])
|
50
|
+
def norm_args
|
51
|
+
@norm_args ||= args[1..-1].select { |arg| arg.type == :arg }
|
52
|
+
end
|
61
53
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
elsif arg.type == :array
|
68
|
-
vars = {}
|
69
|
-
arg[1..-1].each_with_index do |_arg, _idx|
|
70
|
-
_arg = variable(_arg[1])
|
71
|
-
unless vars.has_key?(_arg) || params.include?(_arg)
|
72
|
-
vars[_arg] = "#{params[idx]}[#{_idx}]"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
push "var #{ vars.map{|k, v| "#{k} = #{v}"}.join(', ') };"
|
76
|
-
else
|
77
|
-
raise "Bad block arg type"
|
78
|
-
end
|
54
|
+
def compile_norm_args
|
55
|
+
norm_args.each do |arg|
|
56
|
+
arg = variable(arg[1])
|
57
|
+
push "if (#{arg} == null) #{arg} = nil;"
|
79
58
|
end
|
80
59
|
end
|
81
60
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
61
|
+
def compile_block_arg
|
62
|
+
if block_arg
|
63
|
+
scope.block_name = block_arg
|
64
|
+
scope.add_temp block_arg
|
65
|
+
scope_name = scope.identify!
|
66
|
+
|
67
|
+
line "#{block_arg} = #{scope_name}.$$p || nil, #{scope_name}.$$p = null;"
|
88
68
|
end
|
89
69
|
end
|
90
70
|
|
91
|
-
# does this iter define a block_pass
|
92
71
|
def extract_block_arg
|
93
|
-
if args.last.is_a?(Sexp) and args.last.type == :block_pass
|
94
|
-
block_arg = args.pop
|
95
|
-
|
72
|
+
if args.is_a?(Sexp) && args.last.is_a?(Sexp) and args.last.type == :block_pass
|
73
|
+
self.block_arg = args.pop[1][1].to_sym
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def compile_shadow_args
|
78
|
+
shadow_args.each do |shadow_arg|
|
79
|
+
scope.add_local(shadow_arg.last)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def extract_shadow_args
|
84
|
+
if args.is_a?(Sexp)
|
85
|
+
@shadow_args = []
|
86
|
+
args.children.each_with_index do |arg, idx|
|
87
|
+
if arg.type == :shadowarg
|
88
|
+
@shadow_args << args.delete(arg)
|
89
|
+
end
|
90
|
+
end
|
96
91
|
end
|
97
92
|
end
|
98
93
|
|
99
94
|
def args
|
100
|
-
if Fixnum === args_sexp or args_sexp.nil?
|
101
|
-
s(:
|
102
|
-
elsif args_sexp.type == :lasgn
|
103
|
-
s(:
|
95
|
+
sexp = if Fixnum === args_sexp or args_sexp.nil?
|
96
|
+
s(:args)
|
97
|
+
elsif args_sexp.is_a?(Sexp) && args_sexp.type == :lasgn
|
98
|
+
s(:args, s(:arg, *args_sexp[1]))
|
104
99
|
else
|
105
100
|
args_sexp[1]
|
106
101
|
end
|
102
|
+
|
103
|
+
# compacting _ arguments into a single one (only the first one leaves in the sexp)
|
104
|
+
caught_blank_argument = false
|
105
|
+
|
106
|
+
sexp.each_with_index do |part, idx|
|
107
|
+
if part.is_a?(Sexp) && part.last == :_
|
108
|
+
if caught_blank_argument
|
109
|
+
sexp.delete_at(idx)
|
110
|
+
end
|
111
|
+
caught_blank_argument = true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
sexp
|
107
116
|
end
|
108
117
|
|
109
118
|
def body
|
110
119
|
compiler.returns(body_sexp || s(:nil))
|
111
120
|
end
|
112
121
|
|
113
|
-
|
114
|
-
|
115
|
-
#
|
116
|
-
# s(:args, parts...) => ["a", "b", "break$"]
|
117
|
-
def args_to_params(sexp)
|
118
|
-
result = []
|
119
|
-
sexp.each do |arg|
|
120
|
-
if arg[0] == :lasgn
|
121
|
-
ref = variable(arg[1])
|
122
|
-
next if ref == :_ && result.include?(ref)
|
123
|
-
self.add_arg ref
|
124
|
-
result << ref
|
125
|
-
elsif arg[0] == :array
|
126
|
-
result << scope.next_temp
|
127
|
-
else
|
128
|
-
raise "Bad js_block_arg: #{arg[0]}"
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
result
|
122
|
+
def mlhs_args
|
123
|
+
scope.mlhs_mapping.keys
|
133
124
|
end
|
134
125
|
end
|
135
126
|
end
|
data/lib/opal/nodes/logic.rb
CHANGED
@@ -40,8 +40,18 @@ module Opal
|
|
40
40
|
|
41
41
|
def compile_iter
|
42
42
|
error "break must be used as a statement" unless stmt?
|
43
|
-
|
44
|
-
|
43
|
+
compiler.has_break!
|
44
|
+
line 'Opal.brk(', break_val, ', $brk)'
|
45
|
+
end
|
46
|
+
|
47
|
+
def break_val
|
48
|
+
if value.nil?
|
49
|
+
expr(s(:nil))
|
50
|
+
elsif children.size > 1
|
51
|
+
expr(s(:array, *children))
|
52
|
+
else
|
53
|
+
expr(value)
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
data/lib/opal/nodes/masgn.rb
CHANGED
@@ -3,8 +3,7 @@ require 'opal/nodes/base'
|
|
3
3
|
module Opal
|
4
4
|
module Nodes
|
5
5
|
class MassAssignNode < Base
|
6
|
-
|
7
|
-
SIMPLE_ASSIGNMENT = [:lasgn, :iasgn, :lvar, :gasgn]
|
6
|
+
SIMPLE_ASSIGNMENT = [:lasgn, :iasgn, :lvar, :gasgn, :cdecl]
|
8
7
|
|
9
8
|
handle :masgn
|
10
9
|
children :lhs, :rhs
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'opal/nodes/scope'
|
2
|
+
|
3
|
+
module Opal
|
4
|
+
module Nodes
|
5
|
+
class NodeWithArgs < ScopeNode
|
6
|
+
attr_accessor :mlhs_args
|
7
|
+
attr_accessor :used_kwargs
|
8
|
+
attr_accessor :mlhs_mapping
|
9
|
+
attr_accessor :working_arguments
|
10
|
+
attr_writer :inline_args
|
11
|
+
attr_accessor :kwargs_initialized
|
12
|
+
|
13
|
+
attr_reader :inline_args, :post_args
|
14
|
+
|
15
|
+
def initialize(*)
|
16
|
+
super
|
17
|
+
|
18
|
+
@mlhs_args = {}
|
19
|
+
@used_kwargs = []
|
20
|
+
@mlhs_mapping = {}
|
21
|
+
@working_arguments = nil
|
22
|
+
@in_mlhs = false
|
23
|
+
@kwargs_initialized = false
|
24
|
+
|
25
|
+
@inline_args = []
|
26
|
+
@post_args = []
|
27
|
+
|
28
|
+
@post_args_started = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def split_args
|
32
|
+
args = self.args[1..-1]
|
33
|
+
args.each_with_index do |arg, idx|
|
34
|
+
last_argument = (idx == args.length - 1)
|
35
|
+
case arg.type
|
36
|
+
when :arg, :mlhs, :kwarg, :kwoptarg, :kwrestarg
|
37
|
+
if @post_args_started
|
38
|
+
@post_args << arg
|
39
|
+
else
|
40
|
+
@inline_args << arg
|
41
|
+
end
|
42
|
+
when :restarg
|
43
|
+
@post_args_started = true
|
44
|
+
@post_args << arg
|
45
|
+
when :optarg
|
46
|
+
if args[idx, args.length].any? { |next_arg| next_arg.type != :optarg && next_arg.type != :restarg }
|
47
|
+
@post_args_started = true
|
48
|
+
end
|
49
|
+
# otherwise we have:
|
50
|
+
# a. ... + optarg + [optargs]
|
51
|
+
# b. ... + optarg + [optargs] + restarg
|
52
|
+
# and these cases are simple, we can handle args in inline mode
|
53
|
+
|
54
|
+
if @post_args_started
|
55
|
+
@post_args << arg
|
56
|
+
else
|
57
|
+
@inline_args << arg
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
inline_args.each do |inline_arg|
|
63
|
+
inline_arg.meta[:inline] = true
|
64
|
+
end
|
65
|
+
|
66
|
+
optimize_args!
|
67
|
+
end
|
68
|
+
|
69
|
+
def opt_args
|
70
|
+
@opt_args ||= args[1..-1].select { |arg| arg.first == :optarg }
|
71
|
+
end
|
72
|
+
|
73
|
+
def rest_arg
|
74
|
+
@rest_arg ||= args[1..-1].find { |arg| arg.first == :restarg }
|
75
|
+
end
|
76
|
+
|
77
|
+
def keyword_args
|
78
|
+
@keyword_args ||= args[1..-1].select do |arg|
|
79
|
+
[:kwarg, :kwoptarg, :kwrestarg].include? arg.first
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def inline_args_sexp
|
84
|
+
s(:inline_args, *args[1..-1])
|
85
|
+
end
|
86
|
+
|
87
|
+
def post_args_sexp
|
88
|
+
s(:post_args, *post_args)
|
89
|
+
end
|
90
|
+
|
91
|
+
def compile_inline_args
|
92
|
+
inline_args.each do |inline_arg|
|
93
|
+
push process(inline_arg)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def compile_post_args
|
98
|
+
push process(post_args_sexp)
|
99
|
+
end
|
100
|
+
|
101
|
+
def compile_block_arg
|
102
|
+
if scope.uses_block?
|
103
|
+
scope_name = scope.identity
|
104
|
+
yielder = scope.block_name
|
105
|
+
|
106
|
+
add_temp "$iter = #{scope_name}.$$p"
|
107
|
+
add_temp "#{yielder} = $iter || nil"
|
108
|
+
|
109
|
+
line "#{scope_name}.$$p = null;"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def with_inline_args(args)
|
114
|
+
old_inline_args = inline_args
|
115
|
+
self.inline_args = args
|
116
|
+
yield
|
117
|
+
self.inline_args = old_inline_args
|
118
|
+
end
|
119
|
+
|
120
|
+
def in_mlhs
|
121
|
+
old_mlhs = @in_mlhs
|
122
|
+
@in_mlhs = true
|
123
|
+
yield
|
124
|
+
@in_mlhs = old_mlhs
|
125
|
+
end
|
126
|
+
|
127
|
+
def in_mlhs?
|
128
|
+
@in_mlhs
|
129
|
+
end
|
130
|
+
|
131
|
+
def optimize_args!
|
132
|
+
# Simple cases like def m(a,b,*rest) can be processed inline
|
133
|
+
if post_args.length == 1 && post_args.first.type == :restarg
|
134
|
+
rest_arg = post_args.pop
|
135
|
+
rest_arg.meta[:offset] = inline_args.length
|
136
|
+
inline_args << rest_arg
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|