opal 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +3 -0
- data/.travis.yml +0 -4
- data/README.md +6 -0
- data/Rakefile +30 -6
- data/bin/opal +6 -82
- data/corelib/{opal/array.rb → array.rb} +40 -56
- data/corelib/{opal/basic_object.rb → basic_object.rb} +2 -2
- data/corelib/{opal/boolean.rb → boolean.rb} +0 -8
- data/corelib/class.rb +47 -0
- data/corelib/{opal/comparable.rb → comparable.rb} +0 -0
- data/corelib/{opal/enumerable.rb → enumerable.rb} +208 -141
- data/corelib/{opal/enumerator.rb → enumerator.rb} +3 -3
- data/corelib/{opal/error.rb → error.rb} +1 -0
- data/corelib/{opal/hash.rb → hash.rb} +67 -56
- data/corelib/io.rb +39 -0
- data/corelib/{opal/kernel.rb → kernel.rb} +35 -31
- data/corelib/{opal/class.rb → module.rb} +29 -57
- data/corelib/native.rb +148 -0
- data/corelib/{opal/nil_class.rb → nil_class.rb} +2 -10
- data/corelib/{opal/numeric.rb → numeric.rb} +39 -14
- data/corelib/opal.rb +42 -25
- data/corelib/{opal/proc.rb → proc.rb} +3 -3
- data/corelib/{opal/range.rb → range.rb} +5 -1
- data/corelib/{opal/regexp.rb → regexp.rb} +0 -0
- data/corelib/{opal/runtime.js → runtime.js} +96 -188
- data/corelib/{opal/string.rb → string.rb} +20 -15
- data/corelib/struct.rb +139 -0
- data/corelib/{opal/time.rb → time.rb} +0 -0
- data/lib/opal.rb +4 -0
- data/lib/opal/cli.rb +79 -32
- data/lib/opal/cli_options.rb +91 -0
- data/lib/opal/erb.rb +41 -8
- data/lib/opal/grammar.rb +24 -10
- data/lib/opal/grammar.y +15 -4
- data/lib/opal/grammar_helpers.rb +4 -0
- data/lib/opal/lexer.rb +214 -143
- data/lib/opal/parser.rb +596 -562
- data/lib/opal/require_parser.rb +1 -1
- data/lib/opal/source_map.rb +15 -30
- data/lib/opal/target_scope.rb +24 -5
- data/lib/opal/version.rb +1 -1
- data/mri_spec/cli_spec.rb +18 -0
- data/mri_spec/fixtures/opal_file.rb +2 -0
- data/mri_spec/spec_helper.rb +17 -0
- data/opal.gemspec +5 -2
- data/spec/{rubyspec/filters → filters}/bugs/alias.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/ancestors.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/array.rb +0 -0
- data/spec/filters/bugs/array/combination.rb +11 -0
- data/spec/filters/bugs/array/count.rb +3 -0
- data/spec/filters/bugs/array/delete_if.rb +3 -0
- data/spec/filters/bugs/array/drop.rb +3 -0
- data/spec/filters/bugs/array/drop_while.rb +5 -0
- data/spec/filters/bugs/array/eql.rb +3 -0
- data/spec/filters/bugs/array/flatten.rb +9 -0
- data/spec/filters/bugs/array/minus.rb +5 -0
- data/spec/filters/bugs/array/multipliy.rb +9 -0
- data/spec/filters/bugs/array/new.rb +3 -0
- data/spec/filters/bugs/array/pop.rb +6 -0
- data/spec/filters/bugs/array/rassoc.rb +4 -0
- data/spec/filters/bugs/array/rindex.rb +6 -0
- data/spec/filters/bugs/array/select.rb +3 -0
- data/spec/filters/bugs/array/shift.rb +7 -0
- data/spec/filters/bugs/array/shuffle.rb +11 -0
- data/spec/filters/bugs/array/slice.rb +7 -0
- data/spec/filters/bugs/array/take.rb +3 -0
- data/spec/filters/bugs/array/to_a.rb +3 -0
- data/spec/filters/bugs/array/try_convert.rb +7 -0
- data/spec/filters/bugs/array/uniq.rb +10 -0
- data/spec/filters/bugs/array/zip.rb +4 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_delete.rb +1 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_fetch.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_first.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_flatten.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_intersection.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/array_join.rb +0 -0
- data/spec/{rubyspec/filters → filters}/bugs/break.rb +0 -0
- data/spec/filters/bugs/case.rb +4 -0
- data/spec/{rubyspec/filters → filters}/bugs/coerce_integer.rb +0 -0
- data/spec/filters/bugs/enumerable_sort_by.rb +3 -0
- data/spec/{rubyspec/filters → filters}/bugs/kernel/instance_variables.rb +0 -0
- data/spec/filters/bugs/kernel/rand.rb +4 -0
- data/spec/filters/bugs/language/array.rb +3 -0
- data/spec/filters/bugs/language/block.rb +6 -0
- data/spec/filters/bugs/language/break.rb +3 -0
- data/spec/{rubyspec/filters → filters}/bugs/language/class.rb +3 -0
- data/spec/{rubyspec/filters → filters}/bugs/language/class_variables.rb +0 -0
- data/spec/filters/bugs/language/def.rb +27 -0
- data/spec/filters/bugs/language/defined.rb +3 -0
- data/spec/filters/bugs/language/ensure.rb +4 -0
- data/spec/filters/bugs/language/execution.rb +4 -0
- data/spec/filters/bugs/language/for.rb +18 -0
- data/spec/filters/bugs/language/if.rb +13 -0
- data/spec/filters/bugs/language/loop.rb +4 -0
- data/spec/filters/bugs/language/metaclass.rb +14 -0
- data/spec/filters/bugs/language/module.rb +6 -0
- data/spec/filters/bugs/language/next.rb +3 -0
- data/spec/filters/bugs/language/or.rb +3 -0
- data/spec/filters/bugs/language/order.rb +4 -0
- data/spec/filters/bugs/language/precedence.rb +10 -0
- data/spec/filters/bugs/language/proc.rb +24 -0
- data/spec/filters/bugs/language/redo.rb +5 -0
- data/spec/filters/bugs/language/rescue.rb +9 -0
- data/spec/filters/bugs/language/retry.rb +5 -0
- data/spec/filters/bugs/language/send.rb +10 -0
- data/spec/filters/bugs/language/super.rb +9 -0
- data/spec/filters/bugs/language/until.rb +8 -0
- data/spec/filters/bugs/language/variables.rb +37 -0
- data/spec/filters/bugs/language/while.rb +6 -0
- data/spec/filters/bugs/language/yield.rb +5 -0
- data/spec/{rubyspec/filters → filters}/bugs/module/class_variables.rb +0 -0
- data/spec/filters/bugs/module/method_defined.rb +6 -0
- data/spec/filters/bugs/parser.rb +10 -0
- data/spec/{rubyspec/filters → filters}/bugs/public_methods.rb +1 -0
- data/spec/filters/bugs/return.rb +7 -0
- data/spec/filters/bugs/singleton/instance.rb +4 -0
- data/spec/filters/bugs/source_map.rb +3 -0
- data/spec/filters/bugs/string/center.rb +4 -0
- data/spec/filters/bugs/string/lines.rb +3 -0
- data/spec/{rubyspec/filters → filters}/mspec/mocks.rb +0 -0
- data/spec/{rubyspec/filters → filters}/mspec/ruby_exe.rb +0 -0
- data/spec/{rubyspec/filters → filters}/mspec/should_receive.rb +0 -0
- data/spec/{rubyspec/filters → filters}/parser/block_args.rb +0 -0
- data/spec/{rubyspec/filters → filters}/unsupported/array_subclasses.rb +1 -0
- data/spec/filters/unsupported/frozen.rb +32 -0
- data/spec/filters/unsupported/immutable_strings.rb +3 -0
- data/spec/filters/unsupported/tainted.rb +17 -0
- data/spec/filters/unsupported/trusted.rb +15 -0
- data/spec/opal/class/constants_spec.rb +7 -0
- data/spec/opal/erb/erb_spec.rb +7 -1
- data/spec/opal/erb/inline_block.opalerb +3 -0
- data/spec/opal/hash/allocate_spec.rb +16 -0
- data/spec/opal/hash/new_spec.rb +10 -0
- data/spec/opal/hash/to_s_spec.rb +9 -0
- data/spec/opal/kernel/instance_variable_defined_spec.rb +15 -0
- data/spec/opal/kernel/rand_spec.rb +5 -5
- data/spec/opal/kernel/respond_to_spec.rb +14 -1
- data/spec/opal/language/block_spec.rb +13 -0
- data/spec/opal/language/rescue_spec.rb +27 -0
- data/spec/opal/language/return_spec.rb +38 -0
- data/spec/opal/language/singleton_class_spec.rb +13 -0
- data/spec/opal/language/super_spec.rb +99 -0
- data/spec/opal/language/variables_spec.rb +20 -0
- data/spec/opal/module/attr_accessor_spec.rb +8 -0
- data/spec/opal/module/constants_spec.rb +2 -2
- data/spec/opal/native/alias_native_spec.rb +18 -0
- data/spec/opal/native/each_spec.rb +14 -0
- data/spec/opal/native/element_reference_spec.rb +14 -0
- data/spec/opal/native/method_missing_spec.rb +39 -0
- data/spec/opal/native/new_spec.rb +19 -0
- data/spec/opal/native/nil_spec.rb +14 -0
- data/spec/opal/runtime2/class_hierarchy_spec.rb +2 -2
- data/spec/opal/source_map_spec.rb +3 -7
- data/spec/ospec/main.rb.erb +2 -5
- data/spec/parser/alias_spec.rb +4 -4
- data/spec/parser/and_spec.rb +2 -2
- data/spec/parser/array_spec.rb +6 -6
- data/spec/parser/attrasgn_spec.rb +8 -8
- data/spec/parser/begin_spec.rb +11 -11
- data/spec/parser/block_spec.rb +3 -3
- data/spec/parser/break_spec.rb +4 -4
- data/spec/parser/call_spec.rb +50 -48
- data/spec/parser/class_spec.rb +2 -2
- data/spec/parser/const_spec.rb +1 -1
- data/spec/parser/cvar_spec.rb +1 -1
- data/spec/parser/def_spec.rb +5 -5
- data/spec/parser/gvar_spec.rb +2 -2
- data/spec/parser/hash_spec.rb +4 -4
- data/spec/parser/iasgn_spec.rb +3 -3
- data/spec/parser/if_spec.rb +6 -6
- data/spec/parser/iter_spec.rb +6 -6
- data/spec/parser/lambda_spec.rb +5 -5
- data/spec/parser/lasgn_spec.rb +2 -2
- data/spec/parser/line_spec.rb +2 -2
- data/spec/parser/lvar_spec.rb +5 -5
- data/spec/parser/masgn_spec.rb +1 -1
- data/spec/parser/module_spec.rb +2 -2
- data/spec/parser/not_spec.rb +4 -4
- data/spec/parser/op_asgn1_spec.rb +2 -2
- data/spec/parser/op_asgn2_spec.rb +2 -2
- data/spec/parser/or_spec.rb +2 -2
- data/spec/parser/parse_spec.rb +66 -0
- data/spec/parser/parser_spec.rb +32 -38
- data/spec/parser/regexp_spec.rb +4 -4
- data/spec/parser/return_spec.rb +4 -4
- data/spec/parser/sclass_spec.rb +4 -4
- data/spec/parser/str_spec.rb +3 -3
- data/spec/parser/super_spec.rb +6 -6
- data/spec/parser/undef_spec.rb +3 -3
- data/spec/parser/unless_spec.rb +4 -4
- data/spec/parser/while_spec.rb +3 -3
- data/spec/parser/xstr_spec.rb +3 -3
- data/spec/parser/yield_spec.rb +6 -6
- data/spec/rubyspec/core/array/drop_spec.rb +1 -1
- data/spec/rubyspec/core/array/keep_if_spec.rb +1 -3
- data/spec/rubyspec/core/array/length_spec.rb +1 -3
- data/spec/rubyspec/core/array/map_spec.rb +2 -6
- data/spec/rubyspec/core/array/minus_spec.rb +3 -3
- data/spec/rubyspec/core/array/multiply_spec.rb +14 -16
- data/spec/rubyspec/core/array/new_spec.rb +3 -5
- data/spec/rubyspec/core/array/plus_spec.rb +2 -2
- data/spec/rubyspec/core/array/pop_spec.rb +4 -4
- data/spec/rubyspec/core/array/rassoc_spec.rb +2 -2
- data/spec/rubyspec/core/array/reject_spec.rb +2 -6
- data/spec/rubyspec/core/array/replace_spec.rb +1 -3
- data/spec/rubyspec/core/array/reverse_each_spec.rb +1 -3
- data/spec/rubyspec/core/array/reverse_spec.rb +4 -4
- data/spec/rubyspec/core/array/rindex_spec.rb +1 -1
- data/spec/rubyspec/core/array/select_spec.rb +3 -7
- data/spec/rubyspec/core/array/shared/collect.rb +7 -0
- data/spec/rubyspec/core/array/shared/index.rb +1 -1
- data/spec/rubyspec/core/array/shared/keep_if.rb +3 -0
- data/spec/rubyspec/core/array/shared/length.rb +3 -0
- data/spec/rubyspec/core/array/shared/replace.rb +3 -0
- data/spec/rubyspec/core/array/shared/slice.rb +3 -0
- data/spec/rubyspec/core/array/shuffle_spec.rb +1 -1
- data/spec/rubyspec/core/array/size_spec.rb +1 -3
- data/spec/rubyspec/core/array/slice_spec.rb +4 -6
- data/spec/rubyspec/core/array/sort_spec.rb +2 -2
- data/spec/rubyspec/core/array/to_a_spec.rb +1 -1
- data/spec/rubyspec/core/array/try_convert_spec.rb +7 -7
- data/spec/rubyspec/core/array/uniq_spec.rb +7 -7
- data/spec/rubyspec/core/array/zip_spec.rb +1 -1
- data/spec/rubyspec/core/enumerable/collect_spec.rb +24 -0
- data/spec/rubyspec/core/enumerable/count_spec.rb +35 -19
- data/spec/rubyspec/core/enumerable/find_spec.rb +5 -0
- data/spec/rubyspec/core/hash/each_pair_spec.rb +7 -7
- data/spec/rubyspec/core/hash/each_spec.rb +13 -7
- data/spec/rubyspec/core/module/method_defined_spec.rb +4 -4
- data/spec/rubyspec/core/module/public_method_defined_spec.rb +19 -0
- data/spec/rubyspec/core/module/remove_const_spec.rb +23 -0
- data/spec/rubyspec/core/numeric/step_spec.rb +14 -0
- data/spec/rubyspec/core/string/center_spec.rb +43 -65
- data/spec/rubyspec/core/string/lines_spec.rb +1 -1
- data/spec/rubyspec/core/string/ljust_spec.rb +25 -9
- data/spec/rubyspec/core/string/rjust_spec.rb +26 -10
- data/spec/rubyspec/core/struct/fixtures/classes.rb +26 -0
- data/spec/rubyspec/core/struct/initialize_spec.rb +11 -0
- data/spec/rubyspec/core/struct/new_spec.rb +24 -0
- data/spec/rubyspec/fixtures/constants.rb +7 -0
- data/spec/rubyspec/language/break_spec.rb +1 -1
- data/spec/rubyspec/language/case_spec.rb +30 -30
- data/spec/rubyspec/language/def_spec.rb +34 -34
- data/spec/rubyspec/language/defined_spec.rb +2 -2
- data/spec/rubyspec/language/ensure_spec.rb +2 -2
- data/spec/rubyspec/language/execution_spec.rb +2 -2
- data/spec/rubyspec/language/for_spec.rb +17 -17
- data/spec/rubyspec/language/hash_spec.rb +3 -3
- data/spec/rubyspec/language/if_spec.rb +11 -11
- data/spec/rubyspec/language/loop_spec.rb +3 -3
- data/spec/rubyspec/language/metaclass_spec.rb +14 -14
- data/spec/rubyspec/language/module_spec.rb +6 -6
- data/spec/rubyspec/language/next_spec.rb +5 -5
- data/spec/rubyspec/language/not_spec.rb +1 -1
- data/spec/rubyspec/language/or_spec.rb +1 -1
- data/spec/rubyspec/language/order_spec.rb +3 -5
- data/spec/rubyspec/language/precedence_spec.rb +19 -19
- data/spec/rubyspec/language/proc_spec.rb +29 -29
- data/spec/rubyspec/language/redo_spec.rb +3 -5
- data/spec/rubyspec/language/rescue_spec.rb +7 -7
- data/spec/rubyspec/language/retry_spec.rb +2 -2
- data/spec/rubyspec/language/return_spec.rb +12 -12
- data/spec/rubyspec/language/send_spec.rb +9 -9
- data/spec/rubyspec/language/singleton_class_spec.rb +3 -4
- data/spec/rubyspec/language/super_spec.rb +7 -11
- data/spec/rubyspec/language/until_spec.rb +10 -10
- data/spec/rubyspec/language/variables_spec.rb +59 -67
- data/spec/rubyspec/language/versions/array_1.9.rb +1 -1
- data/spec/rubyspec/language/versions/block_1.9.rb +0 -0
- data/spec/rubyspec/language/versions/break_1.9.rb +0 -0
- data/spec/rubyspec/language/versions/literal_lambda_1.9.rb +12 -12
- data/spec/rubyspec/language/versions/send_1.9.rb +23 -23
- data/spec/rubyspec/language/versions/symbol_1.9.rb +2 -2
- data/spec/rubyspec/language/versions/variables_1.9.rb +1 -1
- data/spec/rubyspec/language/while_spec.rb +4 -4
- data/spec/rubyspec/language/yield_spec.rb +3 -3
- data/spec/rubyspec/library/erb/util/html_escape_spec.rb +10 -0
- data/spec/rubyspec/library/singleton/clone_spec.rb +8 -0
- data/spec/rubyspec/library/singleton/dup_spec.rb +8 -0
- data/spec/rubyspec/library/singleton/fixtures/classes.rb +18 -0
- data/spec/rubyspec/library/singleton/instance_spec.rb +30 -0
- data/spec/spec_helper.rb +214 -0
- data/stdlib/buffer.rb +40 -0
- data/stdlib/buffer/array.rb +66 -0
- data/stdlib/buffer/view.rb +70 -0
- data/stdlib/erb.rb +11 -20
- data/stdlib/forwardable.rb +71 -0
- data/stdlib/json.rb +78 -0
- data/stdlib/ostruct.rb +69 -0
- data/stdlib/rbconfig.rb +1 -0
- data/stdlib/singleton.rb +40 -0
- data/stdlib/stringio.rb +173 -0
- data/stdlib/template.rb +44 -0
- metadata +285 -79
- data/corelib/opal/native.rb +0 -31
- data/spec/opal/class/bridge_class_spec.rb +0 -39
- data/spec/opal/native_spec.rb +0 -209
- data/spec/ospec/runner.rb +0 -223
- data/spec/rubyspec/filters/bugs/block_args.rb +0 -3
- data/spec/rubyspec/filters/bugs/case.rb +0 -8
- data/spec/rubyspec/filters/bugs/language/module.rb +0 -3
- data/spec/rubyspec/filters/unsupported/frozen.rb +0 -4
- data/spec/rubyspec/filters/unsupported/tainted.rb +0 -7
data/lib/opal/parser.rb
CHANGED
@@ -6,15 +6,21 @@ require 'opal/version'
|
|
6
6
|
module Opal
|
7
7
|
class Parser
|
8
8
|
|
9
|
+
# A fragment holds a string of generated javascript that will be written
|
10
|
+
# to the destination. It also keeps hold of the original sexp from which
|
11
|
+
# it was generated. Using this sexp, when writing fragments in order, a
|
12
|
+
# mapping can be created of the original location => target location,
|
13
|
+
# aka, source-maps!
|
9
14
|
class Fragment
|
10
|
-
|
15
|
+
# String of javascript this fragment holds
|
11
16
|
attr_reader :code
|
12
17
|
|
13
18
|
def initialize(code, sexp = nil)
|
14
|
-
@code = code
|
19
|
+
@code = code.to_s
|
15
20
|
@sexp = sexp
|
16
21
|
end
|
17
22
|
|
23
|
+
# In debug mode we may wish to include the original line as a comment
|
18
24
|
def to_code
|
19
25
|
if @sexp
|
20
26
|
"/*:#{@sexp.line}*/#{@code}"
|
@@ -23,8 +29,13 @@ module Opal
|
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
32
|
+
# inspect the contents of this fragment, f("fooo")
|
26
33
|
def inspect
|
27
|
-
"
|
34
|
+
"f(#{@code.inspect})"
|
35
|
+
end
|
36
|
+
|
37
|
+
def line
|
38
|
+
@sexp.line if @sexp
|
28
39
|
end
|
29
40
|
end
|
30
41
|
|
@@ -51,8 +62,16 @@ module Opal
|
|
51
62
|
# Statements which should not have ';' added to them.
|
52
63
|
STATEMENTS = [:xstr, :dxstr]
|
53
64
|
|
65
|
+
# Final generated javascript for this parser
|
54
66
|
attr_reader :result
|
55
67
|
|
68
|
+
# generated fragments as an array
|
69
|
+
attr_reader :fragments
|
70
|
+
|
71
|
+
# Parse some ruby code to a string.
|
72
|
+
#
|
73
|
+
# Opal::Parser.new.parse("1 + 2")
|
74
|
+
# # => "(function() {....})()"
|
56
75
|
def parse(source, options = {})
|
57
76
|
@sexp = Grammar.new.parse(source, options[:file])
|
58
77
|
@line = 1
|
@@ -68,29 +87,45 @@ module Opal
|
|
68
87
|
@file = options[:file] || '(file)'
|
69
88
|
@source_file = options[:source_file] || @file
|
70
89
|
@method_missing = (options[:method_missing] != false)
|
71
|
-
@optimized_operators = (options[:optimized_operators] != false)
|
72
90
|
@arity_check = options[:arity_check]
|
73
91
|
@const_missing = (options[:const_missing] != false)
|
74
92
|
@irb_vars = (options[:irb] == true)
|
75
|
-
@source_map = (options[:source_map_enabled] != false)
|
76
93
|
|
77
|
-
|
94
|
+
@method_calls = {}
|
78
95
|
|
79
|
-
|
96
|
+
@fragments = self.top(@sexp).flatten
|
80
97
|
|
81
|
-
@
|
98
|
+
@fragments.unshift f(version_comment)
|
99
|
+
|
100
|
+
@result = @fragments.map(&:code).join('')
|
82
101
|
end
|
83
102
|
|
103
|
+
# Always at top of generated file to show current opal version
|
84
104
|
def version_comment
|
85
105
|
"/* Generated by Opal #{Opal::VERSION} */\n"
|
86
106
|
end
|
87
107
|
|
88
|
-
def
|
89
|
-
@
|
108
|
+
def source_map
|
109
|
+
Opal::SourceMap.new(@fragments, '(file)')
|
90
110
|
end
|
91
111
|
|
92
|
-
def
|
93
|
-
|
112
|
+
def extract_parser_options(content)
|
113
|
+
result = {}
|
114
|
+
|
115
|
+
if /^#\ opal\:(.*)/ =~ content
|
116
|
+
$~[1].split(',').map(&:strip).each do |opt|
|
117
|
+
next if opt == ""
|
118
|
+
opt = opt.gsub('-', '_')
|
119
|
+
|
120
|
+
if opt =~ /no_/
|
121
|
+
result[opt.sub(/no_/, '').to_sym] = false
|
122
|
+
else
|
123
|
+
result[opt.to_sym] = true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
result
|
94
129
|
end
|
95
130
|
|
96
131
|
# This is called when a parsing/processing error occurs. This
|
@@ -139,10 +174,12 @@ module Opal
|
|
139
174
|
|
140
175
|
# @param [String] code the string of code
|
141
176
|
# @return [Fragment]
|
142
|
-
def
|
177
|
+
def f(code, sexp = nil)
|
143
178
|
Fragment.new(code, sexp)
|
144
179
|
end
|
145
180
|
|
181
|
+
alias_method :fragment, :f
|
182
|
+
|
146
183
|
# Converts a ruby method name into its javascript equivalent for
|
147
184
|
# a method/function call. All ruby method names get prefixed with
|
148
185
|
# a '$', and if the name is a valid javascript identifier, it will
|
@@ -164,6 +201,13 @@ module Opal
|
|
164
201
|
end
|
165
202
|
end
|
166
203
|
|
204
|
+
# Converts a ruby lvar/arg name to a js identifier. Not all ruby names
|
205
|
+
# are valid in javascript. A $ suffix is added to non-valid names.
|
206
|
+
def lvar_to_js(var)
|
207
|
+
var = "#{var}$" if RESERVED.include? var.to_s
|
208
|
+
var.to_sym
|
209
|
+
end
|
210
|
+
|
167
211
|
# Used to generate a unique id name per file. These are used
|
168
212
|
# mainly to name method bodies for methods that use blocks.
|
169
213
|
#
|
@@ -192,24 +236,29 @@ module Opal
|
|
192
236
|
|
193
237
|
code = process(scope, :stmt)
|
194
238
|
code = [code] unless code.is_a? Array
|
195
|
-
code.unshift
|
239
|
+
code.unshift f(@indent, sexp)
|
196
240
|
}
|
197
241
|
|
198
|
-
@scope.add_temp "self =
|
199
|
-
@scope.add_temp "
|
200
|
-
@scope.add_temp "
|
201
|
-
@scope.add_temp "
|
202
|
-
@scope.add_temp "
|
203
|
-
@helpers.keys.each { |h| @scope.add_temp "__#{h} = __opal.#{h}" }
|
242
|
+
@scope.add_temp "self = $opal.top"
|
243
|
+
@scope.add_temp "$scope = $opal"
|
244
|
+
@scope.add_temp "nil = $opal.nil"
|
245
|
+
@scope.add_temp "def = $opal.Object._proto" if @scope.defines_defn
|
246
|
+
@helpers.keys.each { |h| @scope.add_temp "$#{h} = $opal.#{h}" }
|
204
247
|
|
205
|
-
vars = [
|
248
|
+
vars = [f(INDENT, sexp), @scope.to_vars, f("\n", sexp)]
|
206
249
|
|
207
250
|
if @irb_vars
|
208
|
-
code.unshift
|
251
|
+
code.unshift f("if (!$opal.irb_vars) { $opal.irb_vars = {}; }\n", sexp)
|
209
252
|
end
|
210
253
|
end
|
211
254
|
|
212
|
-
|
255
|
+
if @method_missing
|
256
|
+
stubs = f("\n#{INDENT}$opal.add_stubs([" + @method_calls.keys.map { |k| "'$#{k}'" }.join(", ") + "]);\n", sexp)
|
257
|
+
else
|
258
|
+
stubs = []
|
259
|
+
end
|
260
|
+
|
261
|
+
[f("(function($opal) {\n", sexp), vars, stubs, code, f("\n})(Opal);\n", sexp)]
|
213
262
|
end
|
214
263
|
|
215
264
|
# Every time the parser enters a new scope, this is called with
|
@@ -296,6 +345,14 @@ module Opal
|
|
296
345
|
result
|
297
346
|
end
|
298
347
|
|
348
|
+
def in_case
|
349
|
+
return unless block_given?
|
350
|
+
old = @case_stmt
|
351
|
+
@case_stmt = {}
|
352
|
+
yield
|
353
|
+
@case_stmt = old
|
354
|
+
end
|
355
|
+
|
299
356
|
# Returns true if the parser is curently handling a while sexp,
|
300
357
|
# false otherwise.
|
301
358
|
#
|
@@ -318,7 +375,7 @@ module Opal
|
|
318
375
|
# @param [Array] sexp the sexp to process
|
319
376
|
# @param [Symbol] level the level to process (see `LEVEL`)
|
320
377
|
# @return [String]
|
321
|
-
def process(sexp, level)
|
378
|
+
def process(sexp, level = :expr)
|
322
379
|
type = sexp.shift
|
323
380
|
meth = "process_#{type}"
|
324
381
|
raise "Unsupported sexp: #{type}" unless respond_to? meth
|
@@ -373,6 +430,10 @@ module Opal
|
|
373
430
|
sexp
|
374
431
|
when :rescue
|
375
432
|
sexp[1] = returns sexp[1]
|
433
|
+
|
434
|
+
if sexp[2] and sexp[2][0] == :resbody and sexp[2][2]
|
435
|
+
sexp[2][2] = returns sexp[2][2]
|
436
|
+
end
|
376
437
|
sexp
|
377
438
|
when :ensure
|
378
439
|
sexp[1] = returns sexp[1]
|
@@ -422,30 +483,23 @@ module Opal
|
|
422
483
|
#
|
423
484
|
# @return [String]
|
424
485
|
def process_block(sexp, level)
|
425
|
-
|
426
|
-
sexp << s(:nil) if sexp.empty?
|
486
|
+
return process s(:nil) if sexp.empty?
|
427
487
|
|
488
|
+
result = []
|
428
489
|
join = (@scope.class_scope? ? "\n\n#@indent" : "\n#@indent")
|
429
490
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
result << fragment(join, sexp) unless result.empty?
|
491
|
+
sexp.each do |stmt|
|
492
|
+
result << f(join, sexp) unless result.empty?
|
434
493
|
|
435
494
|
# find any inline yield statements
|
436
495
|
if yasgn = find_inline_yield(stmt)
|
437
|
-
result << process(yasgn, level)
|
438
|
-
result << fragment(";", yasgn)
|
496
|
+
result << process(yasgn, level) << f(";", yasgn)
|
439
497
|
end
|
440
498
|
|
441
499
|
expr = expression?(stmt) and LEVEL.index(level) < LEVEL.index(:list)
|
442
500
|
|
443
|
-
|
444
|
-
|
445
|
-
result << code
|
446
|
-
if expr
|
447
|
-
result << fragment(";", stmt)
|
448
|
-
end
|
501
|
+
result << process(stmt, level)
|
502
|
+
result << f(";", stmt) if expr
|
449
503
|
end
|
450
504
|
|
451
505
|
result
|
@@ -476,12 +530,14 @@ module Opal
|
|
476
530
|
found = nil
|
477
531
|
case stmt.first
|
478
532
|
when :js_return
|
479
|
-
found = find_inline_yield
|
533
|
+
if found = find_inline_yield(stmt[1])
|
534
|
+
found = found[2]
|
535
|
+
end
|
480
536
|
when :array
|
481
537
|
stmt[1..-1].each_with_index do |el, idx|
|
482
538
|
if el.first == :yield
|
483
539
|
found = el
|
484
|
-
stmt[idx+1] = s(:js_tmp, '
|
540
|
+
stmt[idx+1] = s(:js_tmp, '$yielded')
|
485
541
|
end
|
486
542
|
end
|
487
543
|
when :call
|
@@ -489,72 +545,42 @@ module Opal
|
|
489
545
|
arglist[1..-1].each_with_index do |el, idx|
|
490
546
|
if el.first == :yield
|
491
547
|
found = el
|
492
|
-
arglist[idx+1] = s(:js_tmp, '
|
548
|
+
arglist[idx+1] = s(:js_tmp, '$yielded')
|
493
549
|
end
|
494
550
|
end
|
495
551
|
end
|
496
552
|
|
497
553
|
if found
|
498
|
-
@scope.add_temp '
|
499
|
-
s(:yasgn, '
|
554
|
+
@scope.add_temp '$yielded' unless @scope.has_temp? '$yielded'
|
555
|
+
s(:yasgn, '$yielded', found)
|
500
556
|
end
|
501
557
|
end
|
502
558
|
|
503
559
|
def process_scope(sexp, level)
|
504
|
-
stmt = sexp
|
505
|
-
|
506
|
-
unless @scope.class_scope?
|
507
|
-
stmt = returns stmt
|
508
|
-
end
|
560
|
+
stmt = sexp[0] || s(:nil)
|
561
|
+
stmt = returns stmt unless @scope.class_scope?
|
509
562
|
|
510
|
-
|
511
|
-
else
|
512
|
-
fragment("nil", sexp)
|
513
|
-
end
|
563
|
+
process stmt, :stmt
|
514
564
|
end
|
515
565
|
|
516
566
|
# s(:js_return, sexp)
|
517
567
|
def process_js_return(sexp, level)
|
518
|
-
[
|
568
|
+
[f("return ", sexp), process(sexp[0])]
|
519
569
|
end
|
520
570
|
|
521
571
|
# s(:js_tmp, str)
|
522
572
|
def process_js_tmp(sexp, level)
|
523
|
-
|
524
|
-
end
|
525
|
-
|
526
|
-
def process_operator(sexp, level)
|
527
|
-
meth, recv, arg = sexp
|
528
|
-
mid = mid_to_jsid meth.to_s
|
529
|
-
result = []
|
530
|
-
|
531
|
-
if @optimized_operators
|
532
|
-
with_temp do |a|
|
533
|
-
with_temp do |b|
|
534
|
-
l = process recv, :expr
|
535
|
-
r = process arg, :expr
|
536
|
-
|
537
|
-
result << fragment("(#{a} = ", sexp)
|
538
|
-
result << l
|
539
|
-
result << fragment(", #{b} = ", sexp)
|
540
|
-
result << r
|
541
|
-
result << fragment(", typeof(#{a}) === 'number' ? #{a} #{meth} #{b} ", sexp)
|
542
|
-
result << fragment(": #{a}#{mid}(#{b}))", sexp)
|
543
|
-
end
|
544
|
-
end
|
545
|
-
else
|
546
|
-
"#{process recv, :recv}#{mid}(#{process arg, :expr})"
|
547
|
-
end
|
548
|
-
|
549
|
-
result
|
573
|
+
f(sexp[0].to_s, sexp)
|
550
574
|
end
|
551
575
|
|
552
576
|
def js_block_given(sexp, level)
|
553
577
|
@scope.uses_block!
|
554
578
|
if @scope.block_name
|
555
|
-
|
579
|
+
f("(#{@scope.block_name} !== nil)", sexp)
|
580
|
+
elsif scope = @scope.find_parent_def and scope.block_name
|
581
|
+
f("(#{scope.block_name} !== nil)", sexp)
|
556
582
|
else
|
557
|
-
|
583
|
+
f("false", sexp)
|
558
584
|
end
|
559
585
|
end
|
560
586
|
|
@@ -562,127 +588,124 @@ module Opal
|
|
562
588
|
@scope.uses_block!
|
563
589
|
name = @scope.block_name
|
564
590
|
|
565
|
-
|
591
|
+
f((reverse ? "#{ name } === nil" : "#{ name } !== nil"), sexp)
|
566
592
|
end
|
567
593
|
|
568
594
|
def process_sym(sexp, level)
|
569
|
-
|
595
|
+
f(sexp[0].to_s.inspect, sexp)
|
570
596
|
end
|
571
597
|
|
598
|
+
# Process integers. Wrap in parens if a receiver of method call
|
572
599
|
def process_int(sexp, level)
|
573
|
-
|
600
|
+
f((level == :recv ? "(#{sexp[0]})" : sexp[0].to_s), sexp)
|
574
601
|
end
|
575
602
|
|
576
|
-
|
577
|
-
|
578
|
-
end
|
579
|
-
|
580
|
-
def handle_number(sexp, level)
|
581
|
-
if level == :recv
|
582
|
-
fragment("(#{sexp[0]})", sexp)
|
583
|
-
else
|
584
|
-
fragment(sexp[0].to_s, sexp)
|
585
|
-
end
|
586
|
-
end
|
603
|
+
# Floats generated just like integers
|
604
|
+
alias_method :process_float, :process_int
|
587
605
|
|
606
|
+
# Regexp literals. Convert to empty js regexp if empty (not compatible)
|
588
607
|
def process_regexp(sexp, level)
|
589
608
|
val = sexp[0]
|
590
|
-
|
609
|
+
f((val == // ? /^/.inspect : val.inspect), sexp)
|
591
610
|
end
|
592
611
|
|
612
|
+
# Dynamic regexps with interpolation
|
613
|
+
# s(:dregx, parts...) => new Regexp("...")
|
593
614
|
def process_dregx(sexp, level)
|
594
615
|
result = []
|
595
616
|
|
596
617
|
sexp.each do |part|
|
597
|
-
result <<
|
618
|
+
result << f(" + ", sexp) unless result.empty?
|
598
619
|
|
599
620
|
if String === part
|
600
|
-
result <<
|
621
|
+
result << f(part.inspect, sexp)
|
601
622
|
elsif part[0] == :str
|
602
|
-
result << process(part
|
623
|
+
result << process(part)
|
603
624
|
else
|
604
|
-
result << process(part[1]
|
625
|
+
result << process(part[1])
|
605
626
|
end
|
606
627
|
end
|
607
628
|
|
608
|
-
[
|
629
|
+
[f("(new RegExp(", sexp), result, f("))", sexp)]
|
609
630
|
end
|
610
631
|
|
632
|
+
# Exclusive range, uses opal __range helper.
|
633
|
+
# s(:dot3, start, end) => __range(start, end, false)
|
611
634
|
def process_dot2(sexp, level)
|
612
|
-
lhs = process sexp[0], :expr
|
613
|
-
rhs = process sexp[1], :expr
|
614
635
|
@helpers[:range] = true
|
615
636
|
|
616
|
-
[
|
637
|
+
[f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", false)", sexp)]
|
617
638
|
end
|
618
639
|
|
640
|
+
# Inclusive range, uses __range helper
|
641
|
+
# s(:dot3, start, end) => __range(start, end, true)
|
619
642
|
def process_dot3(sexp, level)
|
620
|
-
lhs = process sexp[0], :expr
|
621
|
-
rhs = process sexp[1], :expr
|
622
643
|
@helpers[:range] = true
|
623
644
|
|
624
|
-
[
|
645
|
+
[f("$range(", sexp), process(sexp[0]), f(", ", sexp), process(sexp[1]), f(", true)", sexp)]
|
625
646
|
end
|
626
647
|
|
627
|
-
#
|
648
|
+
# Simple strings, no interpolation.
|
649
|
+
# s(:str, "string") => "string"
|
628
650
|
def process_str(sexp, level)
|
629
|
-
|
630
|
-
if str == @file
|
631
|
-
@uses_file = true
|
632
|
-
fragment(@file.inspect, sexp)
|
633
|
-
else
|
634
|
-
fragment(str.inspect, sexp)
|
635
|
-
end
|
651
|
+
f sexp[0].inspect, sexp
|
636
652
|
end
|
637
653
|
|
654
|
+
# defined?(x) => various
|
638
655
|
def process_defined(sexp, level)
|
639
656
|
part = sexp[0]
|
640
657
|
case part[0]
|
641
658
|
when :self
|
642
|
-
|
659
|
+
f("'self'", sexp)
|
643
660
|
when :nil
|
644
|
-
|
661
|
+
f("'nil'", sexp)
|
645
662
|
when :true
|
646
|
-
|
663
|
+
f("'true'", sexp)
|
647
664
|
when :false
|
648
|
-
|
665
|
+
f("'false'", sexp)
|
649
666
|
when :call
|
650
667
|
mid = mid_to_jsid part[2].to_s
|
651
|
-
recv = part[1] ? process(part[1]
|
652
|
-
[
|
653
|
-
when :xstr
|
654
|
-
[
|
668
|
+
recv = part[1] ? process(part[1]) : f(current_self, sexp)
|
669
|
+
[f("(", sexp), recv, f("#{mid} ? 'method' : nil)", sexp)]
|
670
|
+
when :xstr, :dxstr
|
671
|
+
[f("(typeof(", sexp), process(part), f(") !== 'undefined')", sexp)]
|
655
672
|
when :const
|
656
|
-
|
673
|
+
f("($scope.#{part[1].to_s} != null)", sexp)
|
674
|
+
when :cvar
|
675
|
+
f("($opal.cvars[#{part[1].to_s.inspect}] != null ? 'class-variable' : nil)", sexp)
|
657
676
|
when :colon2
|
658
|
-
|
677
|
+
f("false", sexp)
|
659
678
|
when :colon3
|
660
|
-
|
679
|
+
f("($opal.Object._scope.#{sexp[0][1]} == null ? nil : 'constant')", sexp)
|
661
680
|
when :ivar
|
662
681
|
ivar_name = part[1].to_s[1..-1]
|
663
682
|
with_temp do |t|
|
664
|
-
|
683
|
+
f("((#{t} = #{current_self}[#{ivar_name.inspect}], #{t} != null && #{t} !== nil) ? 'instance-variable' : nil)", sexp)
|
665
684
|
end
|
666
685
|
when :lvar
|
667
|
-
|
686
|
+
f("local-variable", sexp)
|
668
687
|
else
|
669
688
|
raise "bad defined? part: #{part[0]}"
|
670
689
|
end
|
671
690
|
end
|
672
691
|
|
673
|
-
#
|
692
|
+
# not keyword or '!' operand
|
693
|
+
# s(:not, value) => (tmp = value, (tmp === nil || tmp === false))
|
674
694
|
def process_not(sexp, level)
|
675
695
|
with_temp do |tmp|
|
676
|
-
expr = sexp
|
677
|
-
[
|
696
|
+
expr = sexp[0]
|
697
|
+
[f("(#{tmp} = ", sexp), process(expr), f(", (#{tmp} === nil || #{tmp} === false))", sexp)]
|
678
698
|
end
|
679
699
|
end
|
680
700
|
|
701
|
+
# A block pass '&foo' syntax
|
702
|
+
# s(:block_pass, value) => value.$to_proc()
|
681
703
|
def process_block_pass(exp, level)
|
682
|
-
process
|
704
|
+
process s(:call, exp[0], :to_proc, s(:arglist))
|
683
705
|
end
|
684
706
|
|
685
|
-
#
|
707
|
+
# A block/iter with embeded call. Compiles into function
|
708
|
+
# s(:iter, call, block_args [, body) => (function() { ... })
|
686
709
|
def process_iter(sexp, level)
|
687
710
|
call, args, body = sexp
|
688
711
|
|
@@ -698,6 +721,12 @@ module Opal
|
|
698
721
|
args ||= s(:masgn, s(:array))
|
699
722
|
args = args.first == :lasgn ? s(:array, args) : args[1]
|
700
723
|
|
724
|
+
# opt args are last, if present, and are a [:block]
|
725
|
+
if args.last.is_a?(Array) and args.last[0] == :block
|
726
|
+
opt_args = args.pop
|
727
|
+
opt_args.shift
|
728
|
+
end
|
729
|
+
|
701
730
|
if args.last.is_a?(Array) and args.last[0] == :block_pass
|
702
731
|
block_arg = args.pop
|
703
732
|
block_arg = block_arg[1][1].to_sym
|
@@ -717,7 +746,12 @@ module Opal
|
|
717
746
|
args[1..-1].each do |arg|
|
718
747
|
arg = arg[1]
|
719
748
|
arg = "#{arg}$" if RESERVED.include? arg.to_s
|
720
|
-
|
749
|
+
|
750
|
+
if opt_args and current_opt = opt_args.find { |s| s[1] == arg.to_sym }
|
751
|
+
code << [f("if (#{arg} == null) #{arg} = ", sexp), process(current_opt[2]), f(";\n", sexp)]
|
752
|
+
else
|
753
|
+
code << f("if (#{arg} == null) #{arg} = nil;\n", sexp)
|
754
|
+
end
|
721
755
|
end
|
722
756
|
|
723
757
|
params = js_block_args(args[1..-1])
|
@@ -725,47 +759,47 @@ module Opal
|
|
725
759
|
if splat
|
726
760
|
@scope.add_arg splat
|
727
761
|
params << splat
|
728
|
-
code <<
|
762
|
+
code << f("#{splat} = $slice.call(arguments, #{len - 1});", sexp)
|
729
763
|
end
|
730
764
|
|
731
765
|
if block_arg
|
732
766
|
@scope.block_name = block_arg
|
733
767
|
@scope.add_temp block_arg
|
734
|
-
@scope.add_temp '__context'
|
735
768
|
scope_name = @scope.identify!
|
736
769
|
|
737
770
|
blk = []
|
738
|
-
blk <<
|
771
|
+
blk << f("\n#@indent#{block_arg} = #{scope_name}._p || nil, #{scope_name}.p = null;\n#@indent", sexp)
|
739
772
|
|
740
773
|
code.unshift blk
|
741
774
|
end
|
742
775
|
|
743
|
-
code <<
|
776
|
+
code << f("\n#@indent", sexp)
|
744
777
|
code << process(body, :stmt)
|
745
778
|
|
746
779
|
if @scope.defines_defn
|
747
780
|
@scope.add_temp "def = ((#{current_self}._isClass) ? #{current_self}._proto : #{current_self})"
|
748
781
|
end
|
749
782
|
|
750
|
-
to_vars = [
|
783
|
+
to_vars = [f("\n#@indent", sexp), @scope.to_vars, f("\n#@indent", sexp)]
|
751
784
|
end
|
752
785
|
end
|
753
786
|
|
754
|
-
itercode = [
|
787
|
+
itercode = [f("function(#{params.join ', '}) {\n", sexp), to_vars, code, f("\n#@indent}", sexp)]
|
755
788
|
|
756
|
-
itercode.unshift
|
757
|
-
itercode <<
|
789
|
+
itercode.unshift f("(#{identity} = ", sexp)
|
790
|
+
itercode << f(", #{identity}._s = #{current_self}, #{identity})", sexp)
|
758
791
|
|
759
792
|
call << itercode
|
760
793
|
process call, level
|
761
794
|
end
|
762
795
|
|
796
|
+
# Maps block args into array of jsid. Adds $ suffix to invalid js
|
797
|
+
# identifiers.
|
798
|
+
#
|
799
|
+
# s(:args, parts...) => ["a", "b", "break$"]
|
763
800
|
def js_block_args(sexp)
|
764
801
|
sexp.map do |arg|
|
765
|
-
|
766
|
-
a = "#{a}$".to_sym if RESERVED.include? a.to_s
|
767
|
-
@scope.add_arg a
|
768
|
-
a
|
802
|
+
@scope.add_arg lvar_to_js(arg[1])
|
769
803
|
end
|
770
804
|
end
|
771
805
|
|
@@ -778,60 +812,25 @@ module Opal
|
|
778
812
|
process s(:call, recv, mid, arglist), level
|
779
813
|
end
|
780
814
|
|
781
|
-
# Used to generate optimized attr_reader, attr_writer and
|
782
|
-
# attr_accessor methods. These are optimized to avoid the added
|
783
|
-
# cost of converting the method id's into jsid's at runtime.
|
784
|
-
#
|
785
|
-
# This method will only be called if all the given ids are strings
|
786
|
-
# or symbols. Any dynamic arguments will default to being called
|
787
|
-
# using the Module#attr_* methods as expected.
|
788
|
-
#
|
789
|
-
# @param [Symbol] meth :attr_{reader,writer,accessor}
|
790
|
-
# @param [Array<Sexp>] attrs array of s(:sym) or s(:str)
|
791
|
-
# @return [String] precompiled attr methods
|
792
|
-
def handle_attr_optimize(meth, attrs)
|
793
|
-
out = []
|
794
|
-
|
795
|
-
attrs.each do |attr|
|
796
|
-
mid = attr[1]
|
797
|
-
ivar = "@#{mid}".to_sym
|
798
|
-
|
799
|
-
unless meth == :attr_writer
|
800
|
-
out << fragment(", \n#@indent") unless out.empty?
|
801
|
-
out << process(s(:defn, mid, s(:args), s(:scope, s(:ivar, ivar))), :stmt)
|
802
|
-
end
|
803
|
-
|
804
|
-
unless meth == :attr_reader
|
805
|
-
out << fragment(", \n#@indent") unless out.empty?
|
806
|
-
mid = "#{mid}=".to_sym
|
807
|
-
out << process(s(:defn, mid, s(:args, :val), s(:scope,
|
808
|
-
s(:iasgn, ivar, s(:lvar, :val)))), :stmt)
|
809
|
-
end
|
810
|
-
end
|
811
|
-
|
812
|
-
out << fragment(", nil")
|
813
|
-
out
|
814
|
-
end
|
815
|
-
|
816
815
|
# s(:call, recv, :mid, s(:arglist))
|
817
816
|
# s(:call, nil, :mid, s(:arglist))
|
818
817
|
def process_call(sexp, level)
|
819
818
|
recv, meth, arglist, iter = sexp
|
820
819
|
mid = mid_to_jsid meth.to_s
|
821
820
|
|
821
|
+
@method_calls[meth.to_sym] = true
|
822
|
+
|
822
823
|
# we are trying to access a lvar in irb mode
|
823
824
|
if @irb_vars and @scope.top? and arglist == s(:arglist) and recv == nil
|
824
825
|
return with_temp { |t|
|
825
826
|
lvar = meth.intern
|
826
827
|
lvar = "#{lvar}$" if RESERVED.include? lvar
|
827
828
|
call = s(:call, s(:self), meth.intern, s(:arglist))
|
828
|
-
[
|
829
|
+
[f("((#{t} = $opal.irb_vars.#{lvar}) == null ? ", sexp), process(call), f(" : #{t})", sexp)]
|
829
830
|
}
|
830
831
|
end
|
831
832
|
|
832
833
|
case meth
|
833
|
-
when :attr_reader, :attr_writer, :attr_accessor
|
834
|
-
return handle_attr_optimize(meth, arglist[1..-1]) if @scope.class_scope?
|
835
834
|
when :block_given?
|
836
835
|
return js_block_given(sexp, level)
|
837
836
|
end
|
@@ -839,7 +838,7 @@ module Opal
|
|
839
838
|
splat = arglist[1..-1].any? { |a| a.first == :splat }
|
840
839
|
|
841
840
|
if Array === arglist.last and arglist.last.first == :block_pass
|
842
|
-
block = process(arglist.pop
|
841
|
+
block = process(arglist.pop)
|
843
842
|
elsif iter
|
844
843
|
block = iter
|
845
844
|
end
|
@@ -850,54 +849,35 @@ module Opal
|
|
850
849
|
tmpfunc = @scope.new_temp
|
851
850
|
end
|
852
851
|
|
853
|
-
tmprecv = @scope.new_temp
|
852
|
+
tmprecv = @scope.new_temp if splat || tmpfunc
|
854
853
|
args = ""
|
855
854
|
|
856
855
|
recv_code = process recv, :recv
|
857
856
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
args = process arglist, :expr
|
862
|
-
|
863
|
-
dispatch = "((#{tmprecv} = #{recv_code})#{mid} || $mm('#{meth.to_s}'))"
|
864
|
-
dispatch = [fragment("((#{tmprecv} = ", sexp), recv_code, fragment(")#{mid} || $mm('#{meth.to_s}'))", sexp)]
|
865
|
-
|
866
|
-
if tmpfunc
|
867
|
-
dispatch.unshift fragment("(#{tmpfunc} = ", sexp)
|
868
|
-
dispatch << fragment(", #{tmpfunc}._p = ", sexp)
|
869
|
-
dispatch << block
|
870
|
-
dispatch << fragment(", #{tmpfunc})", sexp)
|
871
|
-
end
|
857
|
+
call_recv = s(:js_tmp, tmprecv || recv_code)
|
858
|
+
arglist.insert 1, call_recv if tmpfunc and !splat
|
859
|
+
args = process arglist
|
872
860
|
|
873
|
-
|
874
|
-
|
875
|
-
dispatch << process(call_recv, :expr)
|
876
|
-
dispatch << fragment(", ", sexp)
|
877
|
-
dispatch << args
|
878
|
-
dispatch << fragment(")", sexp)
|
879
|
-
else
|
880
|
-
dispatch << fragment(".call(", sexp)
|
881
|
-
dispatch.push(*args)
|
882
|
-
dispatch << fragment(")", sexp)
|
883
|
-
end
|
884
|
-
|
885
|
-
result = dispatch
|
861
|
+
dispatch = if tmprecv
|
862
|
+
[f("(#{tmprecv} = "), recv_code, f(")#{mid}")]
|
886
863
|
else
|
887
|
-
|
864
|
+
[recv_code, f(mid)]
|
865
|
+
end
|
888
866
|
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
867
|
+
if tmpfunc
|
868
|
+
dispatch.unshift f("(#{tmpfunc} = ")
|
869
|
+
dispatch << f(", #{tmpfunc}._p = ")
|
870
|
+
dispatch << block
|
871
|
+
dispatch << f(", #{tmpfunc})")
|
872
|
+
end
|
894
873
|
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
874
|
+
result = if splat
|
875
|
+
[dispatch, f(".apply("), (tmprecv ? f(tmprecv) : recv_code),
|
876
|
+
f(", "), args, f(")")]
|
877
|
+
elsif tmpfunc
|
878
|
+
[dispatch, f(".call("), args, f(")")]
|
879
|
+
else
|
880
|
+
[dispatch, f("("), args, f(")")]
|
901
881
|
end
|
902
882
|
|
903
883
|
@scope.queue_temp tmpfunc if tmpfunc
|
@@ -906,37 +886,35 @@ module Opal
|
|
906
886
|
|
907
887
|
# s(:arglist, [arg [, arg ..]])
|
908
888
|
def process_arglist(sexp, level)
|
909
|
-
code = []
|
910
|
-
work = []
|
889
|
+
code, work = [], []
|
911
890
|
|
912
|
-
|
913
|
-
current = sexp.shift
|
891
|
+
sexp.each do |current|
|
914
892
|
splat = current.first == :splat
|
915
|
-
arg = process current
|
893
|
+
arg = process current
|
916
894
|
|
917
895
|
if splat
|
918
896
|
if work.empty?
|
919
897
|
if code.empty?
|
920
|
-
code <<
|
898
|
+
code << f("[].concat(", sexp)
|
921
899
|
code << arg
|
922
|
-
code <<
|
900
|
+
code << f(")")
|
923
901
|
else
|
924
902
|
code += ".concat(#{arg})"
|
925
903
|
end
|
926
904
|
else
|
927
905
|
if code.empty?
|
928
|
-
code << [
|
906
|
+
code << [f("["), work, f("]")]
|
929
907
|
else
|
930
|
-
code << [
|
908
|
+
code << [f(".concat(["), work, f("])")]
|
931
909
|
end
|
932
910
|
|
933
|
-
code << [
|
911
|
+
code << [f(".concat("), arg, f(")")]
|
934
912
|
end
|
935
913
|
|
936
914
|
work = []
|
937
915
|
else
|
938
|
-
work <<
|
939
|
-
work
|
916
|
+
work << f(", ") unless work.empty?
|
917
|
+
work << arg
|
940
918
|
end
|
941
919
|
end
|
942
920
|
|
@@ -946,7 +924,7 @@ module Opal
|
|
946
924
|
if code.empty?
|
947
925
|
code = join
|
948
926
|
else
|
949
|
-
code <<
|
927
|
+
code << f(".concat(") << join << f(")")
|
950
928
|
end
|
951
929
|
end
|
952
930
|
|
@@ -956,9 +934,9 @@ module Opal
|
|
956
934
|
# s(:splat, sexp)
|
957
935
|
def process_splat(sexp, level)
|
958
936
|
if sexp.first == [:nil]
|
959
|
-
[
|
937
|
+
[f("[]")]
|
960
938
|
elsif sexp.first.first == :sym
|
961
|
-
[
|
939
|
+
[f("["), process(sexp[0]), f("]")]
|
962
940
|
else
|
963
941
|
process sexp.first, :recv
|
964
942
|
end
|
@@ -974,24 +952,24 @@ module Opal
|
|
974
952
|
@helpers[:klass] = true
|
975
953
|
|
976
954
|
if Symbol === cid or String === cid
|
977
|
-
base = process
|
955
|
+
base = process s(:self)
|
978
956
|
name = cid.to_s
|
979
957
|
elsif cid[0] == :colon2
|
980
|
-
base = process(cid[1]
|
958
|
+
base = process(cid[1])
|
981
959
|
name = cid[2].to_s
|
982
960
|
elsif cid[0] == :colon3
|
983
|
-
base = process(s(:js_tmp, '
|
961
|
+
base = process(s(:js_tmp, '$opal.Object'))
|
984
962
|
name = cid[1].to_s
|
985
963
|
else
|
986
964
|
raise "Bad receiver in class"
|
987
965
|
end
|
988
966
|
|
989
|
-
sup = sup ? process(sup
|
967
|
+
sup = sup ? process(sup) : process(s(:js_tmp, 'null'))
|
990
968
|
|
991
969
|
indent do
|
992
970
|
in_scope(:class) do
|
993
971
|
@scope.name = name
|
994
|
-
@scope.add_temp "#{ @scope.proto } = #{name}._proto", "
|
972
|
+
@scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
|
995
973
|
|
996
974
|
if Array === body.last
|
997
975
|
# A single statement will need a block
|
@@ -1007,62 +985,54 @@ module Opal
|
|
1007
985
|
end
|
1008
986
|
end
|
1009
987
|
|
1010
|
-
body = returns(body)
|
1011
|
-
|
1012
|
-
code << fragment("\n", sexp)
|
988
|
+
body = process(returns(body), :stmt)
|
989
|
+
code << f("\n")
|
1013
990
|
code << @scope.to_donate_methods
|
1014
991
|
|
1015
|
-
code <<
|
992
|
+
code << f(@indent)
|
1016
993
|
code << @scope.to_vars
|
1017
|
-
code <<
|
994
|
+
code << f("\n\n#@indent")
|
1018
995
|
code << body
|
1019
996
|
end
|
1020
997
|
end
|
1021
998
|
|
1022
999
|
spacer = "\n#{@indent}#{INDENT}"
|
1023
1000
|
cls = "function #{name}() {};"
|
1024
|
-
boot = "#{name} =
|
1001
|
+
boot = "#{name} = $klass($base, $super, #{name.inspect}, #{name});"
|
1025
1002
|
|
1026
|
-
[
|
1027
|
-
code,
|
1003
|
+
[f("(function($base, $super){#{spacer}#{cls}#{spacer}#{boot}\n", sexp),
|
1004
|
+
code, f("\n#@indent})", sexp), f("(", sexp), base, f(", ", sexp), sup, f(")", sexp)]
|
1028
1005
|
end
|
1029
1006
|
|
1030
|
-
#
|
1007
|
+
# Singleton class syntax. Runs body in context of singleton_class.
|
1008
|
+
# s(:sclass, recv, body) => (function() { ... }).call(recv.$singleton_class())
|
1031
1009
|
def process_sclass(sexp, level)
|
1032
|
-
recv = sexp[0]
|
1033
|
-
body = sexp[1]
|
1034
|
-
code = []
|
1010
|
+
recv, body, code = sexp[0], sexp[1], []
|
1035
1011
|
|
1036
1012
|
in_scope(:sclass) do
|
1037
|
-
@scope.add_temp "
|
1013
|
+
@scope.add_temp "$scope = #{current_self}._scope"
|
1038
1014
|
@scope.add_temp "def = #{current_self}._proto"
|
1039
1015
|
|
1040
|
-
|
1041
|
-
code << @scope.to_vars << body
|
1016
|
+
code << @scope.to_vars << process(body, :stmt)
|
1042
1017
|
end
|
1043
1018
|
|
1044
|
-
|
1045
|
-
result << fragment("(function(){", sexp) << code
|
1046
|
-
result << fragment("}).call(__opal.singleton(", sexp)
|
1047
|
-
result << process(recv, :expr) << fragment("))", sexp)
|
1048
|
-
result
|
1019
|
+
[f("(function(){"), code, f("}).call("), process(recv, :recv), f(".$singleton_class())")]
|
1049
1020
|
end
|
1050
1021
|
|
1051
1022
|
# s(:module, cid, body)
|
1052
1023
|
def process_module(sexp, level)
|
1053
|
-
cid = sexp
|
1054
|
-
body = sexp[1]
|
1024
|
+
cid, body = sexp
|
1055
1025
|
code = []
|
1056
1026
|
@helpers[:module] = true
|
1057
1027
|
|
1058
1028
|
if Symbol === cid or String === cid
|
1059
|
-
base = process(s(:self)
|
1029
|
+
base = process(s(:self))
|
1060
1030
|
name = cid.to_s
|
1061
1031
|
elsif cid[0] == :colon2
|
1062
|
-
base = process(cid[1]
|
1032
|
+
base = process(cid[1])
|
1063
1033
|
name = cid[2].to_s
|
1064
1034
|
elsif cid[0] == :colon3
|
1065
|
-
base =
|
1035
|
+
base = f('$opal.Object', sexp)
|
1066
1036
|
name = cid[1].to_s
|
1067
1037
|
else
|
1068
1038
|
raise "Bad receiver in class"
|
@@ -1071,34 +1041,35 @@ module Opal
|
|
1071
1041
|
indent do
|
1072
1042
|
in_scope(:module) do
|
1073
1043
|
@scope.name = name
|
1074
|
-
@scope.add_temp "#{ @scope.proto } = #{name}._proto", "
|
1044
|
+
@scope.add_temp "#{ @scope.proto } = #{name}._proto", "$scope = #{name}._scope"
|
1075
1045
|
body = process body, :stmt
|
1076
1046
|
|
1077
|
-
code <<
|
1078
|
-
code
|
1079
|
-
code <<
|
1080
|
-
code
|
1081
|
-
code <<
|
1082
|
-
code
|
1047
|
+
code << f(@indent)
|
1048
|
+
code << @scope.to_vars
|
1049
|
+
code << f("\n\n#@indent")
|
1050
|
+
code << body
|
1051
|
+
code << f("\n#@ident")
|
1052
|
+
code << @scope.to_donate_methods
|
1083
1053
|
end
|
1084
1054
|
end
|
1085
1055
|
|
1086
1056
|
spacer = "\n#{@indent}#{INDENT}"
|
1087
1057
|
cls = "function #{name}() {};"
|
1088
|
-
boot = "#{name} =
|
1058
|
+
boot = "#{name} = $module($base, #{name.inspect}, #{name});"
|
1089
1059
|
|
1090
|
-
code.unshift
|
1091
|
-
code <<
|
1092
|
-
code
|
1093
|
-
code <<
|
1060
|
+
code.unshift f("(function($base){#{spacer}#{cls}#{spacer}#{boot}\n", sexp)
|
1061
|
+
code << f("\n#@indent})(")
|
1062
|
+
code << base
|
1063
|
+
code << f(")")
|
1094
1064
|
|
1095
1065
|
code
|
1096
1066
|
end
|
1097
1067
|
|
1098
1068
|
# undef :foo
|
1099
1069
|
# => delete MyClass.prototype.$foo
|
1070
|
+
# FIXME: we should be setting method to a stub method here
|
1100
1071
|
def process_undef(sexp, level)
|
1101
|
-
|
1072
|
+
f("delete #{ @scope.proto }#{ mid_to_jsid sexp[0][1].to_s }", sexp)
|
1102
1073
|
end
|
1103
1074
|
|
1104
1075
|
# s(:defn, mid, s(:args), s(:scope))
|
@@ -1121,7 +1092,7 @@ module Opal
|
|
1121
1092
|
if recvr
|
1122
1093
|
@scope.defines_defs = true
|
1123
1094
|
smethod = true if @scope.class_scope? && recvr.first == :self
|
1124
|
-
recv = process(recvr
|
1095
|
+
recv = process(recvr)
|
1125
1096
|
else
|
1126
1097
|
@scope.defines_defn = true
|
1127
1098
|
recv = current_self
|
@@ -1167,54 +1138,64 @@ module Opal
|
|
1167
1138
|
|
1168
1139
|
if block_name
|
1169
1140
|
@scope.uses_block!
|
1141
|
+
@scope.add_arg block_name
|
1170
1142
|
end
|
1171
1143
|
|
1172
|
-
yielder = block_name || '
|
1144
|
+
yielder = block_name || '$yield'
|
1173
1145
|
@scope.block_name = yielder
|
1174
1146
|
|
1175
|
-
params = process args
|
1176
|
-
stmt_code = [
|
1147
|
+
params = process args
|
1148
|
+
stmt_code = [f("\n#@indent"), process(stmts, :stmt)]
|
1177
1149
|
|
1178
1150
|
opt[1..-1].each do |o|
|
1179
1151
|
next if o[2][2] == :undefined
|
1180
|
-
code <<
|
1181
|
-
code << process(o
|
1182
|
-
code <<
|
1152
|
+
code << f("if (#{o[1]} == null) {\n#{@indent + INDENT}", o)
|
1153
|
+
code << process(o)
|
1154
|
+
code << f("\n#{@indent}}", o)
|
1183
1155
|
end if opt
|
1184
1156
|
|
1185
|
-
code <<
|
1157
|
+
code << f("#{splat} = $slice.call(arguments, #{argc});", sexp) if splat
|
1186
1158
|
|
1187
1159
|
scope_name = @scope.identity
|
1188
1160
|
|
1189
1161
|
if @scope.uses_block?
|
1190
|
-
@scope.add_temp
|
1191
|
-
|
1192
|
-
|
1162
|
+
@scope.add_temp "$iter = #{scope_name}._p"
|
1163
|
+
@scope.add_temp "#{yielder} = $iter || nil"
|
1164
|
+
|
1165
|
+
code.unshift f("#{scope_name}._p = null;", sexp)
|
1193
1166
|
end
|
1194
1167
|
|
1195
1168
|
code.push(*stmt_code)
|
1196
|
-
code.unshift blk if blk
|
1197
1169
|
|
1198
1170
|
uses_super = @scope.uses_super
|
1199
1171
|
|
1200
|
-
code = [
|
1172
|
+
code = [f("#{arity_code}#@indent", sexp), @scope.to_vars, code]
|
1173
|
+
|
1174
|
+
if @scope.uses_zuper
|
1175
|
+
code.unshift f("var $zuper = $slice.call(arguments, 0);", sexp)
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
if @scope.catch_return
|
1179
|
+
code.unshift f("try {\n", sexp)
|
1180
|
+
code.push f("\n} catch($returner) { if ($returner === $opal.returner) { return $returner.$v; } throw $returner; }", sexp)
|
1181
|
+
end
|
1201
1182
|
end
|
1202
1183
|
end
|
1203
1184
|
|
1204
|
-
result = [
|
1185
|
+
result = [f("#{"#{scope_name} = " if scope_name}function(", sexp)]
|
1205
1186
|
result.push(*params)
|
1206
|
-
result <<
|
1187
|
+
result << f(") {\n", sexp)
|
1207
1188
|
result.push(*code)
|
1208
|
-
result <<
|
1189
|
+
result << f("\n#@indent}", sexp)
|
1209
1190
|
|
1210
1191
|
if recvr
|
1211
1192
|
if smethod
|
1212
|
-
[
|
1193
|
+
[f("#{@scope.name}.constructor.prototype['$#{mid}'] = ", sexp), result]
|
1213
1194
|
else
|
1214
|
-
[recv,
|
1195
|
+
[recv, f("#{jsid} = ", sexp), result]
|
1215
1196
|
end
|
1216
1197
|
elsif @scope.class? and @scope.name == 'Object'
|
1217
|
-
[
|
1198
|
+
[f("#{current_self}._defn('$#{mid}', ", sexp), result, f(")", sexp)]
|
1218
1199
|
elsif @scope.class_scope?
|
1219
1200
|
@scope.methods << "$#{mid}"
|
1220
1201
|
if uses_super
|
@@ -1222,13 +1203,9 @@ module Opal
|
|
1222
1203
|
uses_super = "#{uses_super} = #{@scope.proto}#{jsid};\n#@indent"
|
1223
1204
|
end
|
1224
1205
|
|
1225
|
-
[
|
1226
|
-
|
1227
|
-
[
|
1228
|
-
elsif @scope.type == :top
|
1229
|
-
[fragment("def#{ jsid } = ", sexp), *result]
|
1230
|
-
else
|
1231
|
-
[fragment("def#{jsid} = ", sexp), result]
|
1206
|
+
[f("#{uses_super}#{@scope.proto}#{jsid} = ", sexp), result]
|
1207
|
+
else # :top, :iter
|
1208
|
+
[f("def#{jsid} = ", sexp), result]
|
1232
1209
|
end
|
1233
1210
|
end
|
1234
1211
|
|
@@ -1246,34 +1223,35 @@ module Opal
|
|
1246
1223
|
aritycode = "var $arity = arguments.length;"
|
1247
1224
|
|
1248
1225
|
if arity < 0 # splat or opt args
|
1249
|
-
aritycode + "if ($arity < #{-(arity + 1)}) {
|
1226
|
+
aritycode + "if ($arity < #{-(arity + 1)}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
|
1250
1227
|
else
|
1251
|
-
aritycode + "if ($arity !== #{arity}) {
|
1228
|
+
aritycode + "if ($arity !== #{arity}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
|
1252
1229
|
end
|
1253
1230
|
end
|
1254
1231
|
|
1255
1232
|
def process_args(exp, level)
|
1256
1233
|
args = []
|
1257
1234
|
|
1258
|
-
|
1259
|
-
a =
|
1235
|
+
exp.each do |a|
|
1236
|
+
a = a.to_sym
|
1260
1237
|
next if a.to_s == '*'
|
1261
|
-
a =
|
1238
|
+
a = lvar_to_js a
|
1262
1239
|
@scope.add_arg a
|
1263
1240
|
args << a
|
1264
1241
|
end
|
1265
1242
|
|
1266
|
-
|
1243
|
+
f(args.join(', '), exp)
|
1267
1244
|
end
|
1268
1245
|
|
1269
1246
|
# s(:self) # => this
|
1270
1247
|
def process_self(sexp, level)
|
1271
|
-
|
1248
|
+
f(current_self, sexp)
|
1272
1249
|
end
|
1273
1250
|
|
1274
1251
|
# Returns the current value for 'self'. This will be native
|
1275
1252
|
# 'this' for methods and blocks, and the class name for class
|
1276
1253
|
# and module bodies.
|
1254
|
+
# s(:self) => self or this or class name
|
1277
1255
|
def current_self
|
1278
1256
|
if @scope.class_scope?
|
1279
1257
|
@scope.name
|
@@ -1284,60 +1262,64 @@ module Opal
|
|
1284
1262
|
end
|
1285
1263
|
end
|
1286
1264
|
|
1265
|
+
# true literal
|
1266
|
+
# s(:true) => true
|
1287
1267
|
def process_true(sexp, level)
|
1288
|
-
|
1268
|
+
f "true", sexp
|
1289
1269
|
end
|
1290
1270
|
|
1271
|
+
# false literal
|
1272
|
+
# s(:false) => false
|
1291
1273
|
def process_false(sexp, level)
|
1292
|
-
|
1274
|
+
f "false", sexp
|
1293
1275
|
end
|
1294
1276
|
|
1277
|
+
# nil literal
|
1278
|
+
# s(:nil) => nil
|
1295
1279
|
def process_nil(sexp, level)
|
1296
|
-
|
1280
|
+
f "nil", sexp
|
1297
1281
|
end
|
1298
1282
|
|
1299
|
-
# s(:array [, sexp [, sexp]])
|
1283
|
+
# s(:array [, sexp [, sexp]]) => [...]
|
1300
1284
|
def process_array(sexp, level)
|
1301
|
-
return [
|
1285
|
+
return [f("[]", sexp)] if sexp.empty?
|
1302
1286
|
|
1303
|
-
code = []
|
1304
|
-
work = []
|
1287
|
+
code, work = [], []
|
1305
1288
|
|
1306
|
-
|
1307
|
-
current = sexp.shift
|
1289
|
+
sexp.each do |current|
|
1308
1290
|
splat = current.first == :splat
|
1309
|
-
part = process current
|
1291
|
+
part = process current
|
1310
1292
|
|
1311
1293
|
if splat
|
1312
1294
|
if work.empty?
|
1313
1295
|
if code.empty?
|
1314
|
-
code <<
|
1296
|
+
code << f("[].concat(", sexp) << part << f(")", sexp)
|
1315
1297
|
else
|
1316
|
-
code <<
|
1298
|
+
code << f(".concat(", sexp) << part << f(")", sexp)
|
1317
1299
|
end
|
1318
1300
|
else
|
1319
1301
|
if code.empty?
|
1320
|
-
code <<
|
1302
|
+
code << f("[", sexp) << work << f("]", sexp)
|
1321
1303
|
else
|
1322
|
-
code <<
|
1304
|
+
code << f(".concat([", sexp) << work << f("])", sexp)
|
1323
1305
|
end
|
1324
1306
|
|
1325
|
-
code <<
|
1307
|
+
code << f(".concat(", sexp) << part << f(")", sexp)
|
1326
1308
|
end
|
1327
1309
|
work = []
|
1328
1310
|
else
|
1329
|
-
work <<
|
1311
|
+
work << f(", ", current) unless work.empty?
|
1330
1312
|
work << part
|
1331
1313
|
end
|
1332
1314
|
end
|
1333
1315
|
|
1334
1316
|
unless work.empty?
|
1335
|
-
join = [
|
1317
|
+
join = [f("[", sexp), work, f("]", sexp)]
|
1336
1318
|
|
1337
1319
|
if code.empty?
|
1338
1320
|
code = join
|
1339
1321
|
else
|
1340
|
-
code.push([
|
1322
|
+
code.push([f(".concat(", sexp), join, f(")", sexp)])
|
1341
1323
|
end
|
1342
1324
|
end
|
1343
1325
|
|
@@ -1363,29 +1345,29 @@ module Opal
|
|
1363
1345
|
keys.size.times do |i|
|
1364
1346
|
k = keys[i][1].to_s.inspect
|
1365
1347
|
hash_keys << k unless hash_obj.include? k
|
1366
|
-
hash_obj[k] = process(vals[i]
|
1348
|
+
hash_obj[k] = process(vals[i])
|
1367
1349
|
end
|
1368
1350
|
|
1369
1351
|
result = []
|
1370
1352
|
@helpers[:hash2] = true
|
1371
1353
|
|
1372
1354
|
hash_keys.each do |k|
|
1373
|
-
result <<
|
1374
|
-
result <<
|
1355
|
+
result << f(", ", sexp) unless result.empty?
|
1356
|
+
result << f("#{k}: ", sexp)
|
1375
1357
|
result << hash_obj[k]
|
1376
1358
|
end
|
1377
1359
|
|
1378
|
-
[
|
1360
|
+
[f("$hash2([#{hash_keys.join ', '}], {", sexp), result, f("})", sexp)]
|
1379
1361
|
else
|
1380
1362
|
@helpers[:hash] = true
|
1381
1363
|
result = []
|
1382
1364
|
|
1383
1365
|
sexp.each do |p|
|
1384
|
-
result <<
|
1385
|
-
result << process(p
|
1366
|
+
result << f(", ", p) unless result.empty?
|
1367
|
+
result << process(p)
|
1386
1368
|
end
|
1387
1369
|
|
1388
|
-
[
|
1370
|
+
[f("$hash(", sexp), result, f(")", sexp)]
|
1389
1371
|
end
|
1390
1372
|
end
|
1391
1373
|
|
@@ -1401,7 +1383,7 @@ module Opal
|
|
1401
1383
|
:stmt
|
1402
1384
|
end
|
1403
1385
|
|
1404
|
-
code << js_truthy(expr) <<
|
1386
|
+
code << js_truthy(expr) << f("){", sexp)
|
1405
1387
|
pre = "while ("
|
1406
1388
|
|
1407
1389
|
in_while do
|
@@ -1411,27 +1393,26 @@ module Opal
|
|
1411
1393
|
|
1412
1394
|
if @while_loop[:use_redo]
|
1413
1395
|
pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
|
1414
|
-
code <<
|
1396
|
+
code << f("#{redo_var}=false;", sexp)
|
1415
1397
|
end
|
1416
1398
|
|
1417
1399
|
code << body
|
1418
1400
|
end
|
1419
1401
|
|
1420
|
-
code <<
|
1421
|
-
code.unshift
|
1402
|
+
code << f("}", sexp)
|
1403
|
+
code.unshift f(pre, sexp)
|
1422
1404
|
@scope.queue_temp redo_var
|
1423
1405
|
|
1424
1406
|
if stmt_level == :stmt_closure
|
1425
|
-
code.unshift
|
1426
|
-
code.push
|
1407
|
+
code.unshift f("(function() {", sexp)
|
1408
|
+
code.push f("; return nil; }).call(#{current_self})", sexp)
|
1427
1409
|
end
|
1428
1410
|
|
1429
1411
|
code
|
1430
1412
|
end
|
1431
1413
|
|
1432
1414
|
def process_until(exp, level)
|
1433
|
-
expr = exp
|
1434
|
-
stmt = exp[1]
|
1415
|
+
expr, stmt = exp
|
1435
1416
|
redo_var = @scope.new_temp
|
1436
1417
|
stmt_level = if level == :expr or level == :recv
|
1437
1418
|
:stmt_closure
|
@@ -1441,7 +1422,7 @@ module Opal
|
|
1441
1422
|
|
1442
1423
|
code = []
|
1443
1424
|
pre = "while (!("
|
1444
|
-
code << js_truthy(expr) <<
|
1425
|
+
code << js_truthy(expr) << f(")) {", exp)
|
1445
1426
|
|
1446
1427
|
in_while do
|
1447
1428
|
@while_loop[:closure] = true if stmt_level == :stmt_closure
|
@@ -1450,19 +1431,19 @@ module Opal
|
|
1450
1431
|
|
1451
1432
|
if @while_loop[:use_redo]
|
1452
1433
|
pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
|
1453
|
-
code <<
|
1434
|
+
code << f("#{redo_var}=false;", exp)
|
1454
1435
|
end
|
1455
1436
|
|
1456
1437
|
code << body
|
1457
1438
|
end
|
1458
1439
|
|
1459
|
-
code <<
|
1460
|
-
code.unshift
|
1440
|
+
code << f("}", exp)
|
1441
|
+
code.unshift f(pre, exp)
|
1461
1442
|
@scope.queue_temp redo_var
|
1462
1443
|
|
1463
1444
|
if stmt_level == :stmt_closure
|
1464
|
-
code.unshift
|
1465
|
-
code <<
|
1445
|
+
code.unshift f("(function() {", exp)
|
1446
|
+
code << f("; return nil; }).call(#{current_self})", exp)
|
1466
1447
|
end
|
1467
1448
|
|
1468
1449
|
code
|
@@ -1477,50 +1458,59 @@ module Opal
|
|
1477
1458
|
|
1478
1459
|
if [:class, :module].include? @scope.type
|
1479
1460
|
@scope.methods << "$#{exp[0][1].to_s}"
|
1480
|
-
|
1461
|
+
f("%s%s = %s%s" % [@scope.proto, new, @scope.proto, old], exp)
|
1481
1462
|
else
|
1482
1463
|
current = current_self
|
1483
|
-
|
1464
|
+
f("%s._proto%s = %s._proto%s" % [current, new, current, old], exp)
|
1484
1465
|
end
|
1485
1466
|
end
|
1486
1467
|
|
1487
1468
|
def process_masgn(sexp, level)
|
1488
|
-
lhs = sexp
|
1489
|
-
rhs = sexp[1]
|
1469
|
+
lhs, rhs = sexp
|
1490
1470
|
tmp = @scope.new_temp
|
1491
1471
|
len = 0
|
1492
1472
|
code = []
|
1493
1473
|
|
1494
|
-
# remote :array part
|
1495
|
-
lhs.shift
|
1496
1474
|
if rhs[0] == :array
|
1497
1475
|
len = rhs.length - 1 # we are guaranteed an array of this length
|
1498
|
-
code <<
|
1476
|
+
code << f("#{tmp} = ", sexp) << process(rhs)
|
1499
1477
|
elsif rhs[0] == :to_ary
|
1500
|
-
code <<
|
1501
|
-
code <<
|
1478
|
+
code << f("((#{tmp} = ", sexp) << process(rhs[1])
|
1479
|
+
code << f(")._isArray ? #{tmp} : (#{tmp} = [#{tmp}]))", sexp)
|
1502
1480
|
elsif rhs[0] == :splat
|
1503
|
-
code <<
|
1504
|
-
code <<
|
1481
|
+
code << f("(#{tmp} = ", sexp) << process(rhs[1])
|
1482
|
+
code << f(")['$to_a'] ? (#{tmp} = #{tmp}['$to_a']()) : (#{tmp})._isArray ? #{tmp} : (#{tmp} = [#{tmp}])", sexp)
|
1505
1483
|
else
|
1506
1484
|
raise "Unsupported mlhs type"
|
1507
1485
|
end
|
1508
1486
|
|
1509
|
-
lhs.each_with_index do |l, idx|
|
1510
|
-
code <<
|
1487
|
+
lhs[1..-1].each_with_index do |l, idx|
|
1488
|
+
code << f(", ", sexp) unless code.empty?
|
1511
1489
|
|
1512
1490
|
if l.first == :splat
|
1513
1491
|
if s = l[1]
|
1514
|
-
s << s(:js_tmp, "
|
1515
|
-
code << process(s
|
1492
|
+
s << s(:js_tmp, "$slice.call(#{tmp}, #{idx})")
|
1493
|
+
code << process(s)
|
1516
1494
|
end
|
1517
1495
|
else
|
1518
1496
|
if idx >= len
|
1519
|
-
|
1497
|
+
assign = s(:js_tmp, "(#{tmp}[#{idx}] == null ? nil : #{tmp}[#{idx}])")
|
1498
|
+
else
|
1499
|
+
assign = s(:js_tmp, "#{tmp}[#{idx}]")
|
1500
|
+
end
|
1501
|
+
|
1502
|
+
if l[0] == :lasgn or l[0] == :iasgn or l[0] == :lvar
|
1503
|
+
l << assign
|
1504
|
+
elsif l[0] == :call
|
1505
|
+
l[2] = "#{l[2]}=".to_sym
|
1506
|
+
l.last << assign
|
1507
|
+
elsif l[0] == :attrasgn
|
1508
|
+
l.last << assign
|
1520
1509
|
else
|
1521
|
-
|
1510
|
+
raise "bad lhs for masgn: #{l.inspect}"
|
1522
1511
|
end
|
1523
|
-
|
1512
|
+
|
1513
|
+
code << process(l)
|
1524
1514
|
end
|
1525
1515
|
end
|
1526
1516
|
|
@@ -1529,7 +1519,7 @@ module Opal
|
|
1529
1519
|
end
|
1530
1520
|
|
1531
1521
|
def process_svalue(sexp, level)
|
1532
|
-
process sexp
|
1522
|
+
process sexp[0], level
|
1533
1523
|
end
|
1534
1524
|
|
1535
1525
|
# s(:lasgn, :lvar, rhs)
|
@@ -1539,15 +1529,15 @@ module Opal
|
|
1539
1529
|
lvar = "#{lvar}$".to_sym if RESERVED.include? lvar.to_s
|
1540
1530
|
|
1541
1531
|
if @irb_vars and @scope.top?
|
1542
|
-
[
|
1532
|
+
[f("$opal.irb_vars.#{lvar} = ", sexp), process(rhs)]
|
1543
1533
|
else
|
1544
1534
|
@scope.add_local lvar
|
1545
|
-
rhs = process(rhs
|
1546
|
-
result = [
|
1535
|
+
rhs = process(rhs)
|
1536
|
+
result = [f(lvar, sexp), f(" = ", sexp), rhs]
|
1547
1537
|
|
1548
1538
|
if level == :recv
|
1549
|
-
result.unshift
|
1550
|
-
result.push
|
1539
|
+
result.unshift f("(", sexp)
|
1540
|
+
result.push f(")", sexp)
|
1551
1541
|
end
|
1552
1542
|
|
1553
1543
|
result
|
@@ -1556,42 +1546,41 @@ module Opal
|
|
1556
1546
|
|
1557
1547
|
# s(:lvar, :lvar)
|
1558
1548
|
def process_lvar(sexp, level)
|
1559
|
-
lvar = sexp.
|
1549
|
+
lvar = sexp[0].to_s
|
1560
1550
|
lvar = "#{lvar}$" if RESERVED.include? lvar
|
1561
1551
|
|
1562
1552
|
if @irb_vars and @scope.top?
|
1563
|
-
with_temp { |t|
|
1553
|
+
with_temp { |t| f("((#{t} = $opal.irb_vars.#{lvar}) == null ? nil : #{t})", sexp) }
|
1564
1554
|
else
|
1565
|
-
|
1555
|
+
f(lvar, sexp)
|
1566
1556
|
end
|
1567
1557
|
end
|
1568
1558
|
|
1569
1559
|
# s(:iasgn, :ivar, rhs)
|
1570
1560
|
def process_iasgn(exp, level)
|
1571
|
-
ivar = exp
|
1572
|
-
rhs = exp[1]
|
1561
|
+
ivar, rhs = exp
|
1573
1562
|
ivar = ivar.to_s[1..-1]
|
1574
1563
|
lhs = RESERVED.include?(ivar) ? "#{current_self}['#{ivar}']" : "#{current_self}.#{ivar}"
|
1575
|
-
[
|
1564
|
+
[f(lhs, exp), f(" = ", exp), process(rhs)]
|
1576
1565
|
end
|
1577
1566
|
|
1578
1567
|
# s(:ivar, :ivar)
|
1579
1568
|
def process_ivar(exp, level)
|
1580
|
-
ivar = exp.
|
1569
|
+
ivar = exp[0].to_s[1..-1]
|
1581
1570
|
part = RESERVED.include?(ivar) ? "['#{ivar}']" : ".#{ivar}"
|
1582
1571
|
@scope.add_ivar part
|
1583
|
-
|
1572
|
+
f("#{current_self}#{part}", exp)
|
1584
1573
|
end
|
1585
1574
|
|
1586
1575
|
# s(:gvar, gvar)
|
1587
1576
|
def process_gvar(sexp, level)
|
1588
|
-
gvar = sexp.
|
1577
|
+
gvar = sexp[0].to_s[1..-1]
|
1589
1578
|
@helpers['gvars'] = true
|
1590
|
-
|
1579
|
+
f("$gvars[#{gvar.inspect}]", sexp)
|
1591
1580
|
end
|
1592
1581
|
|
1593
1582
|
def process_nth_ref(sexp, level)
|
1594
|
-
|
1583
|
+
f("nil", sexp)
|
1595
1584
|
end
|
1596
1585
|
|
1597
1586
|
# s(:gasgn, :gvar, rhs)
|
@@ -1599,34 +1588,53 @@ module Opal
|
|
1599
1588
|
gvar = sexp[0].to_s[1..-1]
|
1600
1589
|
rhs = sexp[1]
|
1601
1590
|
@helpers['gvars'] = true
|
1602
|
-
[
|
1591
|
+
[f("$gvars[#{gvar.to_s.inspect}] = ", sexp), process(rhs)]
|
1603
1592
|
end
|
1604
1593
|
|
1605
1594
|
# s(:const, :const)
|
1606
1595
|
def process_const(sexp, level)
|
1607
|
-
cname = sexp.
|
1596
|
+
cname = sexp[0].to_s
|
1608
1597
|
|
1609
1598
|
if @const_missing
|
1610
1599
|
with_temp do |t|
|
1611
|
-
|
1600
|
+
f("((#{t} = $scope.#{cname}) == null ? $opal.cm(#{cname.inspect}) : #{t})", sexp)
|
1612
1601
|
end
|
1613
1602
|
else
|
1614
|
-
|
1603
|
+
f("$scope.#{cname}", sexp)
|
1615
1604
|
end
|
1616
1605
|
end
|
1617
1606
|
|
1618
1607
|
# s(:cdecl, :const, rhs)
|
1619
1608
|
def process_cdecl(sexp, level)
|
1620
1609
|
const, rhs = sexp
|
1621
|
-
[
|
1610
|
+
[f("$scope.#{const} = ", sexp), process(rhs)]
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
# s(:casgn, s(:const, ::A), :B, val)
|
1614
|
+
# A::B = 100
|
1615
|
+
def process_casgn(sexp, level)
|
1616
|
+
lhs, const, rhs = sexp
|
1617
|
+
[process(lhs), f("._scope.#{const} = ", sexp), process(rhs)]
|
1622
1618
|
end
|
1623
1619
|
|
1624
1620
|
# s(:return [val])
|
1625
1621
|
def process_return(sexp, level)
|
1626
|
-
val = process(sexp
|
1622
|
+
val = process(sexp[0] || s(:nil))
|
1623
|
+
|
1624
|
+
if @scope.iter? and parent_def = @scope.find_parent_def
|
1625
|
+
parent_def.catch_return = true
|
1626
|
+
[f("$opal.$return(", sexp), val, f(")", sexp)]
|
1627
1627
|
|
1628
|
-
|
1629
|
-
|
1628
|
+
elsif level == :expr and @scope.def?
|
1629
|
+
@scope.catch_return = true
|
1630
|
+
[f("$opal.$return(", sexp), val, f(")", sexp)]
|
1631
|
+
|
1632
|
+
elsif level == :stmt
|
1633
|
+
[f("return ", sexp), val]
|
1634
|
+
|
1635
|
+
else
|
1636
|
+
raise SyntaxError, "void value expression: cannot return as an expression"
|
1637
|
+
end
|
1630
1638
|
end
|
1631
1639
|
|
1632
1640
|
# s(:xstr, content)
|
@@ -1634,9 +1642,9 @@ module Opal
|
|
1634
1642
|
code = sexp.first.to_s
|
1635
1643
|
code += ";" if level == :stmt and !code.include?(';')
|
1636
1644
|
|
1637
|
-
result =
|
1645
|
+
result = f(code, sexp)
|
1638
1646
|
|
1639
|
-
level == :recv ? [
|
1647
|
+
level == :recv ? [f("(", sexp), result, f(")", sexp)] : result
|
1640
1648
|
end
|
1641
1649
|
|
1642
1650
|
# s(:dxstr, parts...)
|
@@ -1646,22 +1654,22 @@ module Opal
|
|
1646
1654
|
|
1647
1655
|
sexp.each do |p|
|
1648
1656
|
if String === p
|
1649
|
-
result <<
|
1657
|
+
result << f(p.to_s, sexp)
|
1650
1658
|
needs_sc = true if level == :stmt and !p.to_s.include?(';')
|
1651
1659
|
elsif p.first == :evstr
|
1652
1660
|
result.push(*process(p.last, :stmt))
|
1653
1661
|
elsif p.first == :str
|
1654
|
-
result <<
|
1662
|
+
result << f(p.last.to_s, p)
|
1655
1663
|
needs_sc = true if level == :stmt and !p.last.to_s.include?(';')
|
1656
1664
|
else
|
1657
1665
|
raise "Bad dxstr part"
|
1658
1666
|
end
|
1659
1667
|
end
|
1660
1668
|
|
1661
|
-
result <<
|
1669
|
+
result << f(";", sexp) if needs_sc
|
1662
1670
|
|
1663
1671
|
if level == :recv
|
1664
|
-
[
|
1672
|
+
[f("(", sexp), result, f(")", sexp)]
|
1665
1673
|
else
|
1666
1674
|
result
|
1667
1675
|
end
|
@@ -1672,22 +1680,22 @@ module Opal
|
|
1672
1680
|
result = []
|
1673
1681
|
|
1674
1682
|
sexp.each do |p|
|
1675
|
-
result <<
|
1683
|
+
result << f(" + ", sexp) unless result.empty?
|
1676
1684
|
if String === p
|
1677
|
-
result <<
|
1685
|
+
result << f(p.inspect, sexp)
|
1678
1686
|
elsif p.first == :evstr
|
1679
|
-
result <<
|
1680
|
-
result << process(p.last
|
1681
|
-
result <<
|
1687
|
+
result << f("(", p)
|
1688
|
+
result << process(p.last)
|
1689
|
+
result << f(")", p)
|
1682
1690
|
elsif p.first == :str
|
1683
|
-
result <<
|
1691
|
+
result << f(p.last.inspect, p)
|
1684
1692
|
else
|
1685
1693
|
raise "Bad dstr part"
|
1686
1694
|
end
|
1687
1695
|
end
|
1688
1696
|
|
1689
1697
|
if level == :recv
|
1690
|
-
[
|
1698
|
+
[f("(", sexp), result, f(")", sexp)]
|
1691
1699
|
else
|
1692
1700
|
result
|
1693
1701
|
end
|
@@ -1697,20 +1705,20 @@ module Opal
|
|
1697
1705
|
result = []
|
1698
1706
|
|
1699
1707
|
sexp.each do |p|
|
1700
|
-
result <<
|
1708
|
+
result << f(" + ", sexp) unless result.empty?
|
1701
1709
|
|
1702
1710
|
if String === p
|
1703
|
-
result <<
|
1711
|
+
result << f(p.inspect, sexp)
|
1704
1712
|
elsif p.first == :evstr
|
1705
|
-
result << process(s(:call, p.last, :to_s, s(:arglist))
|
1713
|
+
result << process(s(:call, p.last, :to_s, s(:arglist)))
|
1706
1714
|
elsif p.first == :str
|
1707
|
-
result <<
|
1715
|
+
result << f(p.last.inspect, sexp)
|
1708
1716
|
else
|
1709
1717
|
raise "Bad dsym part"
|
1710
1718
|
end
|
1711
1719
|
end
|
1712
1720
|
|
1713
|
-
[
|
1721
|
+
[f("(", sexp), result, f(")", sexp)]
|
1714
1722
|
end
|
1715
1723
|
|
1716
1724
|
# s(:if, test, truthy, falsy)
|
@@ -1732,18 +1740,18 @@ module Opal
|
|
1732
1740
|
check = js_truthy test
|
1733
1741
|
end
|
1734
1742
|
|
1735
|
-
result = [
|
1743
|
+
result = [f("if (", sexp), check, f(") {\n", sexp)]
|
1736
1744
|
|
1737
|
-
indent { result.push(
|
1745
|
+
indent { result.push(f(@indent, sexp), process(truthy, :stmt)) } if truthy
|
1738
1746
|
|
1739
1747
|
outdent = @indent
|
1740
|
-
indent { result.push(
|
1748
|
+
indent { result.push(f("\n#{outdent}} else {\n#@indent", sexp), process(falsy, :stmt)) } if falsy
|
1741
1749
|
|
1742
|
-
result <<
|
1750
|
+
result << f("\n#@indent}", sexp)
|
1743
1751
|
|
1744
1752
|
if returnable
|
1745
|
-
result.unshift
|
1746
|
-
result.push
|
1753
|
+
result.unshift f("(function() { ", sexp)
|
1754
|
+
result.push f("; return nil; }).call(#{current_self})", sexp)
|
1747
1755
|
end
|
1748
1756
|
|
1749
1757
|
result
|
@@ -1753,14 +1761,14 @@ module Opal
|
|
1753
1761
|
if sexp.first == :call
|
1754
1762
|
mid = sexp[2]
|
1755
1763
|
if mid == :block_given?
|
1756
|
-
return process sexp
|
1764
|
+
return process sexp
|
1757
1765
|
elsif COMPARE.include? mid.to_s
|
1758
|
-
return process sexp
|
1766
|
+
return process sexp
|
1759
1767
|
elsif mid == :"=="
|
1760
|
-
return process sexp
|
1768
|
+
return process sexp
|
1761
1769
|
end
|
1762
1770
|
elsif [:lvar, :self].include? sexp.first
|
1763
|
-
[process(sexp.dup
|
1771
|
+
[process(sexp.dup), f(" !== false && ", sexp), process(sexp.dup), f(" !== nil", sexp)]
|
1764
1772
|
end
|
1765
1773
|
end
|
1766
1774
|
|
@@ -1770,7 +1778,7 @@ module Opal
|
|
1770
1778
|
end
|
1771
1779
|
|
1772
1780
|
with_temp do |tmp|
|
1773
|
-
[
|
1781
|
+
[f("(#{tmp} = ", sexp), process(sexp), f(") !== false && #{tmp} !== nil", sexp)]
|
1774
1782
|
end
|
1775
1783
|
end
|
1776
1784
|
|
@@ -1784,9 +1792,9 @@ module Opal
|
|
1784
1792
|
|
1785
1793
|
with_temp do |tmp|
|
1786
1794
|
result = []
|
1787
|
-
result <<
|
1788
|
-
result << process(sexp
|
1789
|
-
result <<
|
1795
|
+
result << f("(#{tmp} = ", sexp)
|
1796
|
+
result << process(sexp)
|
1797
|
+
result << f(") === false || #{tmp} === nil", sexp)
|
1790
1798
|
result
|
1791
1799
|
end
|
1792
1800
|
end
|
@@ -1799,9 +1807,9 @@ module Opal
|
|
1799
1807
|
|
1800
1808
|
if t = js_truthy_optimize(lhs)
|
1801
1809
|
result = []
|
1802
|
-
result <<
|
1803
|
-
result <<
|
1804
|
-
result <<
|
1810
|
+
result << f("((#{tmp} = ", sexp) << t
|
1811
|
+
result << f(") ? ", sexp) << process(rhs)
|
1812
|
+
result << f(" : #{tmp})", sexp)
|
1805
1813
|
@scope.queue_temp tmp
|
1806
1814
|
|
1807
1815
|
return result
|
@@ -1809,19 +1817,18 @@ module Opal
|
|
1809
1817
|
|
1810
1818
|
@scope.queue_temp tmp
|
1811
1819
|
|
1812
|
-
[
|
1820
|
+
[f("(#{tmp} = ", sexp), process(lhs), f(", #{tmp} !== false && #{tmp} !== nil ? ", sexp), process(rhs), f(" : #{tmp})", sexp)]
|
1813
1821
|
|
1814
1822
|
end
|
1815
1823
|
|
1816
1824
|
# s(:or, lhs, rhs)
|
1817
1825
|
def process_or(sexp, level)
|
1818
|
-
lhs = sexp
|
1819
|
-
rhs = sexp[1]
|
1826
|
+
lhs, rhs = sexp
|
1820
1827
|
|
1821
1828
|
with_temp do |tmp|
|
1822
|
-
lhs = process lhs
|
1823
|
-
rhs = process rhs
|
1824
|
-
[
|
1829
|
+
lhs = process lhs
|
1830
|
+
rhs = process rhs
|
1831
|
+
[f("(((#{tmp} = ", sexp), lhs, f(") !== false && #{tmp} !== nil) ? #{tmp} : ", sexp), rhs, f(")", sexp)]
|
1825
1832
|
end
|
1826
1833
|
end
|
1827
1834
|
|
@@ -1830,10 +1837,10 @@ module Opal
|
|
1830
1837
|
call = handle_yield_call sexp, level
|
1831
1838
|
|
1832
1839
|
if level == :stmt
|
1833
|
-
[
|
1840
|
+
[f("if (", sexp), call, f(" === $breaker) return $breaker.$v")]
|
1834
1841
|
else
|
1835
1842
|
with_temp do |tmp|
|
1836
|
-
[
|
1843
|
+
[f("(((#{tmp} = ", sexp), call, f(") === $breaker) ? $breaker.$v : #{tmp})", sexp)]
|
1837
1844
|
end
|
1838
1845
|
end
|
1839
1846
|
end
|
@@ -1847,7 +1854,7 @@ module Opal
|
|
1847
1854
|
def process_yasgn(sexp, level)
|
1848
1855
|
call = handle_yield_call s(*sexp[1][1..-1]), :stmt
|
1849
1856
|
|
1850
|
-
[
|
1857
|
+
[f("if ((#{sexp[0]} = ", sexp), call, f(") === $breaker) return $breaker.$v", sexp)]
|
1851
1858
|
end
|
1852
1859
|
|
1853
1860
|
# Created by `#returns()` for when a yield statement should return
|
@@ -1856,8 +1863,8 @@ module Opal
|
|
1856
1863
|
call = handle_yield_call sexp, level
|
1857
1864
|
|
1858
1865
|
with_temp do |tmp|
|
1859
|
-
[
|
1860
|
-
|
1866
|
+
[f("return #{tmp} = ", sexp), call,
|
1867
|
+
f(", #{tmp} === $breaker ? #{tmp} : #{tmp}")]
|
1861
1868
|
end
|
1862
1869
|
end
|
1863
1870
|
|
@@ -1865,25 +1872,28 @@ module Opal
|
|
1865
1872
|
@scope.uses_block!
|
1866
1873
|
|
1867
1874
|
splat = sexp.any? { |s| s.first == :splat }
|
1868
|
-
sexp.unshift s(:js_tmp, 'null') unless splat # self
|
1869
|
-
args = process_arglist sexp, level
|
1870
1875
|
|
1871
|
-
|
1876
|
+
if !splat and sexp.size == 1
|
1877
|
+
return [f("$opal.$yield1(#{@scope.block_name || '$yield'}, "), process(sexp[0]), f(")")]
|
1878
|
+
end
|
1879
|
+
|
1880
|
+
args = process_arglist sexp, level
|
1881
|
+
y = @scope.block_name || '$yield'
|
1872
1882
|
|
1873
1883
|
if splat
|
1874
|
-
[
|
1884
|
+
[f("$opal.$yieldX(#{y}, ", sexp), args, f(")")]
|
1875
1885
|
else
|
1876
|
-
[
|
1886
|
+
[f("$opal.$yieldX(#{y}, [", sexp), args, f("])")]
|
1877
1887
|
end
|
1878
1888
|
end
|
1879
1889
|
|
1880
1890
|
def process_break(sexp, level)
|
1881
|
-
val = sexp.empty? ?
|
1891
|
+
val = sexp.empty? ? f('nil', sexp) : process(sexp[0])
|
1882
1892
|
if in_while?
|
1883
|
-
@while_loop[:closure] ? [
|
1893
|
+
@while_loop[:closure] ? [f("return ", sexp), val, f("", sexp)] : f("break;", sexp)
|
1884
1894
|
elsif @scope.iter?
|
1885
1895
|
error "break must be used as a statement" unless level == :stmt
|
1886
|
-
[
|
1896
|
+
[f("return ($breaker.$v = ", sexp), val, f(", $breaker)", sexp)]
|
1887
1897
|
else
|
1888
1898
|
error "void value expression: cannot use break outside of iter/while"
|
1889
1899
|
end
|
@@ -1891,37 +1901,41 @@ module Opal
|
|
1891
1901
|
|
1892
1902
|
# s(:case, expr, when1, when2, ..)
|
1893
1903
|
def process_case(exp, level)
|
1894
|
-
pre = []
|
1895
|
-
|
1896
|
-
@scope.add_local "$case"
|
1897
|
-
expr = process exp.shift, :expr
|
1904
|
+
pre, code = [], []
|
1905
|
+
|
1898
1906
|
# are we inside a statement_closure
|
1899
1907
|
returnable = level != :stmt
|
1900
1908
|
done_else = false
|
1901
1909
|
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1910
|
+
in_case do
|
1911
|
+
if cond = exp[0]
|
1912
|
+
@case_stmt[:cond] = true
|
1913
|
+
@scope.add_local "$case"
|
1914
|
+
expr = process cond
|
1915
|
+
pre << f("$case = ", exp) << expr << f(";", exp)
|
1916
|
+
end
|
1917
|
+
|
1918
|
+
exp[1..-1].each do |wen|
|
1919
|
+
if wen and wen.first == :when
|
1920
|
+
returns(wen) if returnable
|
1921
|
+
wen = process(wen, :stmt)
|
1922
|
+
code << f("else ", exp) unless code.empty?
|
1923
|
+
code << wen
|
1924
|
+
elsif wen # s(:else)
|
1925
|
+
done_else = true
|
1926
|
+
wen = returns(wen) if returnable
|
1927
|
+
code << f("else {", exp) << process(wen, :stmt) << f("}", exp)
|
1928
|
+
end
|
1915
1929
|
end
|
1916
1930
|
end
|
1917
1931
|
|
1918
|
-
code <<
|
1932
|
+
code << f("else { return nil }", exp) if returnable and !done_else
|
1919
1933
|
|
1920
1934
|
code.unshift pre
|
1921
1935
|
|
1922
1936
|
if returnable
|
1923
|
-
code.unshift
|
1924
|
-
code <<
|
1937
|
+
code.unshift f("(function() { ", exp)
|
1938
|
+
code << f(" }).call(#{current_self})", exp)
|
1925
1939
|
end
|
1926
1940
|
|
1927
1941
|
code
|
@@ -1932,43 +1946,41 @@ module Opal
|
|
1932
1946
|
#
|
1933
1947
|
# s(:when, s(:array, foo), bar)
|
1934
1948
|
def process_when(exp, level)
|
1935
|
-
arg = exp
|
1936
|
-
body = exp
|
1937
|
-
#body = process body, level if body
|
1949
|
+
arg = exp[0][1..-1]
|
1950
|
+
body = exp[1] || s(:nil)
|
1938
1951
|
body = process body, level
|
1939
1952
|
|
1940
1953
|
test = []
|
1941
|
-
|
1942
|
-
test <<
|
1943
|
-
a = arg.shift
|
1954
|
+
arg.each do |a|
|
1955
|
+
test << f(" || ") unless test.empty?
|
1944
1956
|
|
1945
1957
|
if a.first == :splat # when inside another when means a splat of values
|
1946
|
-
call =
|
1947
|
-
|
1948
|
-
splt
|
1949
|
-
splt <<
|
1950
|
-
splt <<
|
1958
|
+
call = f("$splt[i]['$===']($case)", a)
|
1959
|
+
|
1960
|
+
splt = [f("(function($splt) { for(var i = 0; i < $splt.length; i++) {", exp)]
|
1961
|
+
splt << f("if (") << call << f(") { return true; }", exp)
|
1962
|
+
splt << f("} return false; }).call(#{current_self}, ", exp)
|
1963
|
+
splt << process(a[1]) << f(")")
|
1951
1964
|
|
1952
1965
|
test << splt
|
1953
1966
|
else
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1967
|
+
if @case_stmt[:cond]
|
1968
|
+
call = s(:call, a, :===, s(:arglist, s(:js_tmp, "$case")))
|
1969
|
+
test << process(call)
|
1970
|
+
else
|
1971
|
+
test << js_truthy(a)
|
1972
|
+
end
|
1958
1973
|
end
|
1959
1974
|
end
|
1960
1975
|
|
1961
|
-
[
|
1976
|
+
[f("if ("), test, f(") {#@space"), body, f("#@space}")]
|
1962
1977
|
end
|
1963
1978
|
|
1964
1979
|
# lhs =~ rhs
|
1965
1980
|
#
|
1966
|
-
# s(:match3, lhs, rhs)
|
1981
|
+
# s(:match3, lhs, rhs) # => s(:call, lhs, :=~, s(:arglist, rhs))
|
1967
1982
|
def process_match3(sexp, level)
|
1968
|
-
|
1969
|
-
rhs = sexp[1]
|
1970
|
-
call = s(:call, lhs, :=~, s(:arglist, rhs))
|
1971
|
-
process call, level
|
1983
|
+
process s(:call, sexp[0], :=~, s(:arglist, sexp[1])), level
|
1972
1984
|
end
|
1973
1985
|
|
1974
1986
|
# @@class_variable
|
@@ -1976,8 +1988,7 @@ module Opal
|
|
1976
1988
|
# s(:cvar, name)
|
1977
1989
|
def process_cvar(exp, level)
|
1978
1990
|
with_temp do |tmp|
|
1979
|
-
|
1980
|
-
[tmp, exp.shift.to_s.inspect, tmp]), exp)
|
1991
|
+
f("((#{tmp} = $opal.cvars['#{exp[0]}']) == null ? nil : #{tmp})", exp)
|
1981
1992
|
end
|
1982
1993
|
end
|
1983
1994
|
|
@@ -1985,41 +1996,39 @@ module Opal
|
|
1985
1996
|
#
|
1986
1997
|
# s(:cvasgn, :@@name, rhs)
|
1987
1998
|
def process_cvasgn(exp, level)
|
1988
|
-
"(
|
1999
|
+
"($opal.cvars['#{exp[0]}'] = #{process exp[1]})"
|
1989
2000
|
end
|
1990
2001
|
|
2002
|
+
# s(:cvdecl, :@@foo, value) # => ($opal.cvars['@@foo'] = value)
|
1991
2003
|
def process_cvdecl(exp, level)
|
1992
|
-
[
|
2004
|
+
[f("($opal.cvars['#{exp[0]}'] = ", exp), process(exp[1]), f(")", exp)]
|
1993
2005
|
end
|
1994
2006
|
|
1995
2007
|
# BASE::NAME
|
1996
2008
|
#
|
1997
2009
|
# s(:colon2, base, :NAME)
|
1998
2010
|
def process_colon2(sexp, level)
|
1999
|
-
base = sexp
|
2000
|
-
cname = sexp[1].to_s
|
2011
|
+
base, cname = sexp
|
2001
2012
|
result = []
|
2002
2013
|
|
2003
2014
|
if @const_missing
|
2004
2015
|
with_temp do |t|
|
2005
|
-
base = process base
|
2016
|
+
base = process base
|
2006
2017
|
|
2007
|
-
result <<
|
2008
|
-
result <<
|
2018
|
+
result << f("((#{t} = (", sexp) << base << f(")._scope).", sexp)
|
2019
|
+
result << f("#{cname} == null ? #{t}.cm('#{cname}') : #{t}.#{cname})", sexp)
|
2009
2020
|
end
|
2010
2021
|
else
|
2011
|
-
|
2012
|
-
|
2013
|
-
result << fragment("(", sexp) << base << fragment(")._scope.#{cname}", sexp)
|
2022
|
+
result << f("(", sexp) << process(base) << f(")._scope.#{cname}", sexp)
|
2014
2023
|
end
|
2015
2024
|
|
2016
2025
|
result
|
2017
2026
|
end
|
2018
2027
|
|
2028
|
+
# s(:colon3, :CONST_NAME) # => $opal.Object._scope.CONST_NAME
|
2019
2029
|
def process_colon3(exp, level)
|
2020
2030
|
with_temp do |t|
|
2021
|
-
|
2022
|
-
fragment("((#{t} = __opal.Object._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})", exp)
|
2031
|
+
f("((#{t} = $opal.Object._scope.#{exp[0]}) == null ? $opal.cm('#{exp[0]}') : #{t})", exp)
|
2023
2032
|
end
|
2024
2033
|
end
|
2025
2034
|
|
@@ -2028,46 +2037,68 @@ module Opal
|
|
2028
2037
|
# s(:super, arg1, arg2, ...)
|
2029
2038
|
def process_super(sexp, level)
|
2030
2039
|
args = []
|
2031
|
-
|
2032
|
-
args <<
|
2033
|
-
args << process(
|
2040
|
+
sexp.each do |part|
|
2041
|
+
args << f(", ", sexp) unless args.empty?
|
2042
|
+
args << process(part)
|
2034
2043
|
end
|
2035
2044
|
|
2036
|
-
js_super [
|
2045
|
+
js_super [f("[", sexp), args, f("]", sexp)], false, sexp
|
2037
2046
|
end
|
2038
2047
|
|
2039
2048
|
# super
|
2040
2049
|
#
|
2041
2050
|
# s(:zsuper)
|
2042
2051
|
def process_zsuper(exp, level)
|
2043
|
-
|
2052
|
+
if @scope.def?
|
2053
|
+
@scope.uses_zuper = true
|
2054
|
+
js_super f("$zuper", exp), true, exp
|
2055
|
+
else
|
2056
|
+
js_super f("$slice.call(arguments)", exp), true, exp
|
2057
|
+
end
|
2044
2058
|
end
|
2045
2059
|
|
2046
|
-
def js_super args, sexp
|
2060
|
+
def js_super args, pass_block, sexp
|
2047
2061
|
if @scope.def_in_class?
|
2062
|
+
@scope.uses_block!
|
2048
2063
|
mid = @scope.mid.to_s
|
2049
|
-
sid = "super_#{unique_temp}"
|
2050
2064
|
|
2051
|
-
@scope.uses_super
|
2065
|
+
if @scope.uses_super
|
2066
|
+
sid = @scope.uses_super
|
2067
|
+
else
|
2068
|
+
sid = @scope.uses_super = "super_#{unique_temp}"
|
2069
|
+
end
|
2052
2070
|
|
2071
|
+
if pass_block
|
2072
|
+
@scope.uses_block!
|
2073
|
+
[f("(#{sid}._p = $iter, #{sid}.apply(#{current_self}, ", sexp), args, f("))", sexp)]
|
2074
|
+
else
|
2075
|
+
[f("#{sid}.apply(#{current_self}, ", sexp), args, f(")", sexp)]
|
2076
|
+
end
|
2053
2077
|
|
2054
|
-
[fragment("#{sid}.apply(#{current_self}, ", sexp), args, fragment(")", sexp)]
|
2055
2078
|
|
2056
2079
|
elsif @scope.type == :def
|
2080
|
+
@scope.uses_block!
|
2057
2081
|
@scope.identify!
|
2058
2082
|
cls_name = @scope.parent.name || "#{current_self}._klass._proto"
|
2059
2083
|
jsid = mid_to_jsid @scope.mid.to_s
|
2060
2084
|
|
2085
|
+
if pass_block
|
2086
|
+
@scope.uses_block!
|
2087
|
+
iter = "$iter"
|
2088
|
+
else
|
2089
|
+
iter = "null"
|
2090
|
+
end
|
2091
|
+
|
2061
2092
|
if @scope.defs
|
2062
|
-
[
|
2093
|
+
[f("$opal.dispatch_super(this, #{@scope.mid.to_s.inspect},", sexp), args, f(", #{iter}, #{cls_name})", sexp)]
|
2063
2094
|
else
|
2064
|
-
[
|
2095
|
+
[f("$opal.dispatch_super(#{current_self}, #{@scope.mid.to_s.inspect}, ", sexp), args, f(", #{iter})", sexp)]
|
2065
2096
|
end
|
2066
2097
|
|
2067
2098
|
elsif @scope.type == :iter
|
2068
2099
|
chain, defn, mid = @scope.get_super_chain
|
2069
2100
|
trys = chain.map { |c| "#{c}._sup" }.join ' || '
|
2070
|
-
[
|
2101
|
+
[f("(#{trys} || #{current_self}._klass._super._proto[#{mid}]).apply(#{current_self}, ", sexp), args, f(")", sexp)]
|
2071
2102
|
else
|
2072
2103
|
raise "Cannot call super() from outside a method block"
|
2073
2104
|
end
|
@@ -2077,14 +2108,14 @@ module Opal
|
|
2077
2108
|
#
|
2078
2109
|
# s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, rhs))
|
2079
2110
|
def process_op_asgn_or(exp, level)
|
2080
|
-
process s(:or, exp
|
2111
|
+
process s(:or, exp[0], exp[1])
|
2081
2112
|
end
|
2082
2113
|
|
2083
2114
|
# a &&= rhs
|
2084
2115
|
#
|
2085
2116
|
# s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, rhs))
|
2086
2117
|
def process_op_asgn_and(sexp, level)
|
2087
|
-
process s(:and, sexp
|
2118
|
+
process s(:and, sexp[0], sexp[1])
|
2088
2119
|
end
|
2089
2120
|
|
2090
2121
|
# lhs[args] ||= rhs
|
@@ -2095,17 +2126,17 @@ module Opal
|
|
2095
2126
|
|
2096
2127
|
with_temp do |a| # args
|
2097
2128
|
with_temp do |r| # recv
|
2098
|
-
args = process arglist[1]
|
2099
|
-
recv = process lhs
|
2129
|
+
args = process arglist[1]
|
2130
|
+
recv = process lhs
|
2100
2131
|
|
2101
2132
|
aref = s(:call, s(:js_tmp, r), :[], s(:arglist, s(:js_tmp, a)))
|
2102
2133
|
aset = s(:call, s(:js_tmp, r), :[]=, s(:arglist, s(:js_tmp, a), rhs))
|
2103
2134
|
orop = s(:or, aref, aset)
|
2104
2135
|
|
2105
2136
|
result = []
|
2106
|
-
result <<
|
2107
|
-
result << recv <<
|
2108
|
-
result <<
|
2137
|
+
result << f("(#{a} = ", sexp) << args << f(", #{r} = ", sexp)
|
2138
|
+
result << recv << f(", ", sexp) << process(orop)
|
2139
|
+
result << f(")", sexp)
|
2109
2140
|
result
|
2110
2141
|
end
|
2111
2142
|
end
|
@@ -2115,10 +2146,10 @@ module Opal
|
|
2115
2146
|
#
|
2116
2147
|
# s(:op_asgn2, lhs, :b=, :+, rhs)
|
2117
2148
|
def process_op_asgn2(sexp, level)
|
2118
|
-
lhs = process sexp
|
2119
|
-
mid = sexp.
|
2120
|
-
op = sexp
|
2121
|
-
rhs = sexp
|
2149
|
+
lhs = process sexp[0]
|
2150
|
+
mid = sexp[1].to_s[0..-2]
|
2151
|
+
op = sexp[2]
|
2152
|
+
rhs = sexp[3]
|
2122
2153
|
|
2123
2154
|
if op.to_s == "||"
|
2124
2155
|
with_temp do |temp|
|
@@ -2126,7 +2157,7 @@ module Opal
|
|
2126
2157
|
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
|
2127
2158
|
orop = s(:or, getr, asgn)
|
2128
2159
|
|
2129
|
-
[
|
2160
|
+
[f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(orop), f(")", sexp)]
|
2130
2161
|
end
|
2131
2162
|
elsif op.to_s == '&&'
|
2132
2163
|
with_temp do |temp|
|
@@ -2134,7 +2165,7 @@ module Opal
|
|
2134
2165
|
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
|
2135
2166
|
andop = s(:and, getr, asgn)
|
2136
2167
|
|
2137
|
-
[
|
2168
|
+
[f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(andop), f(")", sexp)]
|
2138
2169
|
end
|
2139
2170
|
else
|
2140
2171
|
with_temp do |temp|
|
@@ -2142,14 +2173,14 @@ module Opal
|
|
2142
2173
|
oper = s(:call, getr, op, s(:arglist, rhs))
|
2143
2174
|
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, oper))
|
2144
2175
|
|
2145
|
-
[
|
2176
|
+
[f("(#{temp} = ", sexp), lhs, f(", ", sexp), process(asgn), f(")", sexp)]
|
2146
2177
|
end
|
2147
2178
|
end
|
2148
2179
|
end
|
2149
2180
|
|
2150
2181
|
# s(:ensure, body, ensure)
|
2151
2182
|
def process_ensure(exp, level)
|
2152
|
-
begn = exp
|
2183
|
+
begn = exp[0]
|
2153
2184
|
if level == :recv || level == :expr
|
2154
2185
|
retn = true
|
2155
2186
|
begn = returns begn
|
@@ -2157,49 +2188,49 @@ module Opal
|
|
2157
2188
|
|
2158
2189
|
result = []
|
2159
2190
|
body = process begn, level
|
2160
|
-
ensr = exp
|
2191
|
+
ensr = exp[1] || s(:nil)
|
2161
2192
|
ensr = process ensr, level
|
2162
2193
|
|
2163
|
-
body = [
|
2194
|
+
body = [f("try {\n", exp), body, f("}", exp)]
|
2164
2195
|
|
2165
|
-
result << body <<
|
2196
|
+
result << body << f("#{@space}finally {#@space", exp) << ensr << f("}", exp)
|
2166
2197
|
|
2167
2198
|
if retn
|
2168
|
-
[
|
2199
|
+
[f("(function() { ", exp), result, f("; }).call(#{current_self})", exp)]
|
2169
2200
|
else
|
2170
2201
|
result
|
2171
2202
|
end
|
2172
2203
|
end
|
2173
2204
|
|
2174
2205
|
def process_rescue(exp, level)
|
2175
|
-
body = exp.first.first == :resbody ? s(:nil) : exp
|
2206
|
+
body = exp.first.first == :resbody ? s(:nil) : exp[0]
|
2176
2207
|
body = indent { process body, level }
|
2177
2208
|
handled_else = false
|
2178
2209
|
|
2179
2210
|
parts = []
|
2180
|
-
|
2181
|
-
handled_else = true unless
|
2182
|
-
part = indent { process
|
2211
|
+
exp[1..-1].each do |a|
|
2212
|
+
handled_else = true unless a.first == :resbody
|
2213
|
+
part = indent { process a, level }
|
2183
2214
|
|
2184
2215
|
unless parts.empty?
|
2185
|
-
parts <<
|
2216
|
+
parts << f("else ", exp)
|
2186
2217
|
end
|
2187
2218
|
|
2188
2219
|
parts << part
|
2189
2220
|
end
|
2190
2221
|
# if no rescue statement captures our error, we should rethrow
|
2191
|
-
parts << indent {
|
2222
|
+
parts << indent { f("else { throw $err; }", exp) } unless handled_else
|
2192
2223
|
|
2193
2224
|
code = []
|
2194
|
-
code <<
|
2225
|
+
code << f("try {#@space#{INDENT}", exp)
|
2195
2226
|
code << body
|
2196
|
-
code <<
|
2227
|
+
code << f("#@space} catch ($err) {#@space", exp)
|
2197
2228
|
code << parts
|
2198
|
-
code <<
|
2229
|
+
code << f("#@space}", exp)
|
2199
2230
|
|
2200
2231
|
if level == :expr
|
2201
|
-
code.unshift
|
2202
|
-
code <<
|
2232
|
+
code.unshift f("(function() { ", exp)
|
2233
|
+
code << f(" }).call(#{current_self})", exp)
|
2203
2234
|
end
|
2204
2235
|
|
2205
2236
|
code
|
@@ -2215,49 +2246,52 @@ module Opal
|
|
2215
2246
|
|
2216
2247
|
err = []
|
2217
2248
|
types.each do |t|
|
2218
|
-
err <<
|
2249
|
+
err << f(", ", exp) unless err.empty?
|
2219
2250
|
call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
|
2220
|
-
a = process call
|
2251
|
+
a = process call
|
2221
2252
|
err << a
|
2222
2253
|
end
|
2223
|
-
err <<
|
2254
|
+
err << f("true", exp) if err.empty?
|
2224
2255
|
|
2225
2256
|
if Array === args.last and [:lasgn, :iasgn].include? args.last.first
|
2226
2257
|
val = args.last
|
2227
2258
|
val[2] = s(:js_tmp, "$err")
|
2228
|
-
val = [process(val
|
2259
|
+
val = [process(val) , f(";", exp)]
|
2229
2260
|
end
|
2230
2261
|
|
2231
2262
|
val = [] unless val
|
2232
2263
|
|
2233
|
-
[
|
2264
|
+
[f("if (", exp), err, f("){#@space", exp), val, body, f("}", exp)]
|
2234
2265
|
end
|
2235
2266
|
|
2236
2267
|
# FIXME: Hack.. grammar should remove top level begin.
|
2237
2268
|
def process_begin(exp, level)
|
2238
|
-
|
2269
|
+
process exp[0], level
|
2239
2270
|
end
|
2240
2271
|
|
2241
2272
|
def process_next(exp, level)
|
2242
2273
|
if in_while?
|
2243
|
-
|
2274
|
+
f("continue;", exp)
|
2244
2275
|
else
|
2245
2276
|
result = []
|
2246
|
-
result <<
|
2277
|
+
result << f("return ", exp)
|
2247
2278
|
|
2248
|
-
result << (exp.empty? ?
|
2249
|
-
result <<
|
2279
|
+
result << (exp.empty? ? f('nil', exp) : process(exp[0]))
|
2280
|
+
result << f(";", exp)
|
2250
2281
|
|
2251
2282
|
result
|
2252
2283
|
end
|
2253
2284
|
end
|
2254
2285
|
|
2286
|
+
# s(:redo) # => $redo_var = true
|
2287
|
+
# Only currently supported inside while loops. Simply sets the redo variable
|
2288
|
+
# for the loop to true.
|
2255
2289
|
def process_redo(exp, level)
|
2256
2290
|
if in_while?
|
2257
2291
|
@while_loop[:use_redo] = true
|
2258
|
-
|
2292
|
+
f("#{@while_loop[:redo_var]} = true", exp)
|
2259
2293
|
else
|
2260
|
-
|
2294
|
+
f("REDO()", exp)
|
2261
2295
|
end
|
2262
2296
|
end
|
2263
2297
|
end
|