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