opal 0.3.41 → 0.3.42
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/.gitignore +2 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +14 -1
- data/Gemfile +2 -5
- data/Rakefile +41 -3
- data/bin/opal +33 -0
- data/lib/opal.rb +2 -12
- data/lib/opal/core_ext.rb +5 -0
- data/lib/opal/grammar.rb +2207 -2138
- data/lib/opal/grammar.y +21 -0
- data/lib/opal/grammar_helpers.rb +360 -0
- data/lib/opal/lexer.rb +55 -401
- data/lib/opal/lexer_scope.rb +28 -0
- data/lib/opal/parser.rb +155 -171
- data/lib/opal/target_scope.rb +257 -0
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +6 -2
- data/opal/opal-parser.js.erb +3 -2
- data/opal/opal.rb +20 -18
- data/opal/opal/array.rb +21 -12
- data/opal/opal/basic_object.rb +2 -1
- data/opal/opal/boolean.rb +3 -0
- data/opal/opal/browser_loader.js +57 -0
- data/opal/opal/class.rb +51 -13
- data/opal/opal/date.rb +1 -20
- data/opal/opal/enumerable.rb +66 -33
- data/opal/opal/error.rb +2 -0
- data/opal/opal/hash.rb +1 -1
- data/opal/opal/kernel.rb +14 -3
- data/opal/opal/nil_class.rb +4 -0
- data/opal/opal/proc.rb +9 -1
- data/opal/opal/racc.rb +2 -2
- data/opal/opal/regexp.rb +1 -1
- data/opal/opal/runtime.js +14 -4
- data/opal/opal/string.rb +21 -4
- data/opal/opal/time.rb +27 -0
- data/spec/core/array/allocate_spec.rb +7 -1
- data/spec/core/array/append_spec.rb +18 -3
- data/spec/core/array/array_spec.rb +7 -0
- data/spec/core/array/assoc_spec.rb +23 -8
- data/spec/core/array/at_spec.rb +23 -3
- data/spec/core/array/choice_spec.rb +20 -0
- data/spec/core/array/clear_spec.rb +45 -4
- data/spec/core/array/combination_spec.rb +55 -0
- data/spec/core/array/compact_spec.rb +72 -1
- data/spec/core/array/constructor_spec.rb +13 -2
- data/spec/core/array/count_spec.rb +15 -7
- data/spec/core/array/delete_at_spec.rb +44 -1
- data/spec/core/array/delete_if_spec.rb +52 -2
- data/spec/core/array/delete_spec.rb +83 -2
- data/spec/core/array/drop_spec.rb +24 -16
- data/spec/core/array/drop_while_spec.rb +17 -0
- data/spec/core/array/each_index_spec.rb +11 -1
- data/spec/core/array/each_spec.rb +20 -2
- data/spec/core/array/empty_spec.rb +4 -1
- data/spec/core/array/eql_spec.rb +14 -0
- data/spec/core/array/fetch_spec.rb +31 -2
- data/spec/core/array/find_index_spec.rb +8 -0
- data/spec/core/array/first_spec.rb +45 -8
- data/spec/core/array/fixtures/classes.rb +538 -0
- data/spec/core/array/flatten_spec.rb +200 -7
- data/spec/core/array/frozen_spec.rb +32 -0
- data/spec/core/array/include_spec.rb +16 -1
- data/spec/core/array/index_spec.rb +5 -25
- data/spec/core/array/insert_spec.rb +37 -3
- data/spec/core/array/inspect_spec.rb +6 -12
- data/spec/core/array/intersection_spec.rb +55 -4
- data/spec/core/array/join_spec.rb +29 -4
- data/spec/core/array/keep_if_spec.rb +13 -6
- data/spec/core/array/last_spec.rb +35 -1
- data/spec/core/array/length_spec.rb +7 -4
- data/spec/core/array/map_spec.rb +9 -47
- data/spec/core/array/minus_spec.rb +68 -4
- data/spec/core/array/multiply_spec.rb +138 -6
- data/spec/core/array/new_spec.rb +92 -3
- data/spec/core/array/ntimes_spec.rb +26 -0
- data/spec/core/array/plus_spec.rb +48 -2
- data/spec/core/array/pop_spec.rb +159 -39
- data/spec/core/array/push_spec.rb +29 -1
- data/spec/core/array/rassoc_spec.rb +31 -2
- data/spec/core/array/reject_spec.rb +89 -2
- data/spec/core/array/replace_spec.rb +7 -29
- data/spec/core/array/reverse_each_spec.rb +25 -1
- data/spec/core/array/reverse_spec.rb +53 -1
- data/spec/core/array/rindex_spec.rb +55 -5
- data/spec/core/array/select_spec.rb +35 -8
- data/spec/core/array/shared/collect.rb +0 -0
- data/spec/core/array/shared/enumeratorize.rb +12 -0
- data/spec/core/array/shared/eql.rb +95 -0
- data/spec/core/array/shared/index.rb +37 -0
- data/spec/core/array/shared/inspect.rb +3 -0
- data/spec/core/array/shared/join.rb +7 -0
- data/spec/core/array/shared/keep_if.rb +0 -0
- data/spec/core/array/shared/length.rb +0 -0
- data/spec/core/array/shared/replace.rb +0 -0
- data/spec/core/array/shared/slice.rb +0 -0
- data/spec/core/array/shift_spec.rb +132 -23
- data/spec/core/array/shuffle_spec.rb +82 -6
- data/spec/core/array/size_spec.rb +7 -4
- data/spec/core/array/slice_spec.rb +132 -1
- data/spec/core/array/sort_spec.rb +263 -14
- data/spec/core/array/take_spec.rb +24 -16
- data/spec/core/array/take_while_spec.rb +14 -10
- data/spec/core/array/to_a_spec.rb +18 -1
- data/spec/core/array/to_ary_spec.rb +15 -1
- data/spec/core/array/try_convert_spec.rb +39 -2
- data/spec/core/array/uniq_spec.rb +148 -3
- data/spec/core/array/unshift_spec.rb +36 -1
- data/spec/core/array/zip_spec.rb +36 -1
- data/spec/core/class/new_spec.rb +8 -6
- data/spec/core/enumerable/all_spec.rb +37 -9
- data/spec/core/enumerable/any_spec.rb +45 -7
- data/spec/core/enumerable/collect_spec.rb +4 -1
- data/spec/core/enumerable/count_spec.rb +4 -1
- data/spec/core/enumerable/detect_spec.rb +2 -2
- data/spec/core/enumerable/drop_spec.rb +4 -1
- data/spec/core/enumerable/drop_while_spec.rb +4 -1
- data/spec/core/enumerable/each_slice_spec.rb +2 -1
- data/spec/core/enumerable/each_with_index_spec.rb +4 -1
- data/spec/core/enumerable/each_with_object_spec.rb +4 -1
- data/spec/core/enumerable/entries_spec.rb +4 -1
- data/spec/core/enumerable/find_all_spec.rb +4 -1
- data/spec/core/enumerable/find_index_spec.rb +4 -1
- data/spec/core/enumerable/find_spec.rb +5 -2
- data/spec/core/enumerable/first_spec.rb +4 -1
- data/spec/core/enumerable/fixtures/classes.rb +198 -2
- data/spec/core/enumerable/grep_spec.rb +4 -1
- data/spec/core/enumerable/take_spec.rb +4 -1
- data/spec/core/enumerable/to_a_spec.rb +4 -1
- data/spec/core/false/and_spec.rb +11 -0
- data/spec/core/false/inspect_spec.rb +7 -0
- data/spec/core/false/or_spec.rb +11 -0
- data/spec/core/false/to_s_spec.rb +7 -0
- data/spec/core/false/xor_spec.rb +11 -0
- data/spec/core/kernel/rand_spec.rb +5 -5
- data/spec/core/module/const_get_spec.rb +4 -4
- data/spec/core/module/fixtures/classes.rb +434 -0
- data/spec/core/module/method_defined_spec.rb +49 -0
- data/spec/core/module/module_function_spec.rb +28 -0
- data/spec/core/nil/and_spec.rb +3 -1
- data/spec/core/nil/dup_spec.rb +7 -0
- data/spec/core/nil/inspect_spec.rb +3 -1
- data/spec/core/nil/nil_spec.rb +3 -1
- data/spec/core/nil/or_spec.rb +4 -2
- data/spec/core/nil/to_a_spec.rb +3 -1
- data/spec/core/nil/to_f_spec.rb +3 -1
- data/spec/core/nil/to_i_spec.rb +3 -1
- data/spec/core/nil/to_s_spec.rb +3 -1
- data/spec/core/nil/xor_spec.rb +4 -2
- data/spec/core/string/element_reference_spec.rb +14 -1
- data/spec/core/string/fixtures/classes.rb +0 -0
- data/spec/core/true/and_spec.rb +11 -0
- data/spec/core/true/inspect_spec.rb +7 -0
- data/spec/core/true/or_spec.rb +11 -0
- data/spec/core/true/to_s_spec.rb +7 -0
- data/spec/core/true/xor_spec.rb +11 -0
- data/spec/{core → core_ext}/array/element_reference_spec.rb +0 -0
- data/spec/{core → core_ext}/array/equal_value_spec.rb +0 -0
- data/spec/{core → core_ext}/array/fill_spec.rb +0 -0
- data/spec/{core → core_ext}/array/reduce_spec.rb +0 -0
- data/spec/core_ext/basic_object/send_spec.rb +3 -3
- data/spec/{core → core_ext}/boolean/singleton_class_spec.rb +0 -0
- data/spec/{core → core_ext}/boolean/to_json_spec.rb +0 -0
- data/spec/core_ext/class/_inherited_spec.rb +3 -3
- data/spec/core_ext/class/proc_methods_spec.rb +2 -2
- data/spec/core_ext/class/singleton_methods_spec.rb +8 -8
- data/spec/core_ext/method_missing_spec.rb +3 -3
- data/spec/core_ext/native/method_missing_spec.rb +3 -2
- data/spec/core_ext/native/to_native_spec.rb +3 -2
- data/spec/{core → core_ext}/nil/to_json_spec.rb +0 -0
- data/spec/date.rb +0 -0
- data/spec/fileutils.rb +0 -0
- data/spec/filters/ancestors.rb +4 -0
- data/spec/filters/array_delete.rb +3 -0
- data/spec/filters/array_fetch.rb +3 -0
- data/spec/filters/array_first.rb +3 -0
- data/spec/filters/array_flatten.rb +14 -0
- data/spec/filters/array_intersection.rb +5 -0
- data/spec/filters/array_join.rb +6 -0
- data/spec/filters/array_subclasses.rb +4 -0
- data/spec/filters/block_args.rb +3 -0
- data/spec/filters/coerce_integer.rb +9 -0
- data/spec/filters/frozen.rb +4 -0
- data/spec/filters/mocks.rb +3 -0
- data/spec/filters/should_receive.rb +4 -0
- data/spec/filters/tainted.rb +7 -0
- data/spec/fixtures/class.rb +124 -0
- data/spec/fixtures/class_variables.rb +0 -0
- data/spec/fixtures/constants.rb +0 -0
- data/spec/grammar/alias_spec.rb +1 -1
- data/spec/grammar/def_spec.rb +1 -0
- data/spec/grammar/lvar_spec.rb +1 -2
- data/spec/grammar/nth_ref_spec.rb +13 -0
- data/spec/grammar/sclass_spec.rb +6 -7
- data/spec/grammar/str_spec.rb +4 -4
- data/spec/grammar/string_spec.rb +8 -0
- data/spec/grammar/xstr_spec.rb +4 -4
- data/spec/iconv.rb +0 -0
- data/spec/language/alias_spec.rb +140 -3
- data/spec/language/and_spec.rb +14 -7
- data/spec/language/array_spec.rb +57 -5
- data/spec/language/block_spec.rb +466 -49
- data/spec/language/break_spec.rb +294 -44
- data/spec/language/case_spec.rb +151 -3
- data/spec/language/class_spec.rb +196 -0
- data/spec/language/class_variable_spec.rb +56 -0
- data/spec/language/def_spec.rb +507 -4
- data/spec/language/defined_spec.rb +19 -7
- data/spec/language/ensure_spec.rb +26 -39
- data/spec/language/execution_spec.rb +15 -0
- data/spec/language/fixtures/array.rb +11 -0
- data/spec/language/fixtures/block.rb +57 -0
- data/spec/language/fixtures/break.rb +240 -0
- data/spec/language/fixtures/ensure.rb +72 -0
- data/spec/language/fixtures/literal_lambda.rb +7 -0
- data/spec/language/fixtures/metaclass.rb +33 -0
- data/spec/language/fixtures/module.rb +24 -0
- data/spec/language/fixtures/next.rb +78 -12
- data/spec/language/fixtures/return.rb +118 -0
- data/spec/language/fixtures/send.rb +110 -0
- data/spec/language/fixtures/send_1.9.rb +22 -0
- data/spec/language/fixtures/super.rb +308 -0
- data/spec/language/fixtures/variables.rb +58 -0
- data/spec/language/fixtures/yield.rb +5 -0
- data/spec/language/for_spec.rb +192 -0
- data/spec/language/hash_spec.rb +29 -5
- data/spec/language/if_spec.rb +90 -9
- data/spec/language/literal_lambda_spec.rb +1 -47
- data/spec/language/loop_spec.rb +39 -2
- data/spec/language/metaclass_spec.rb +151 -5
- data/spec/language/module_spec.rb +56 -0
- data/spec/language/next_spec.rb +370 -12
- data/spec/language/not_spec.rb +55 -0
- data/spec/language/numbers_spec.rb +56 -0
- data/spec/language/or_spec.rb +31 -3
- data/spec/language/order_spec.rb +79 -0
- data/spec/language/precedence_spec.rb +483 -0
- data/spec/language/proc_spec.rb +249 -21
- data/spec/language/redo_spec.rb +67 -0
- data/spec/language/rescue_spec.rb +121 -0
- data/spec/language/retry_spec.rb +56 -0
- data/spec/language/return_spec.rb +281 -0
- data/spec/language/send_spec.rb +141 -48
- data/spec/language/singleton_class_spec.rb +1 -1
- data/spec/language/string_spec.rb +11 -0
- data/spec/language/super_spec.rb +213 -133
- data/spec/language/symbol_spec.rb +2 -1
- data/spec/language/undef_spec.rb +3 -1
- data/spec/language/unless_spec.rb +6 -2
- data/spec/language/until_spec.rb +102 -3
- data/spec/language/variables_spec.rb +1212 -16
- data/spec/language/versions/array_1.9.rb +39 -0
- data/spec/language/versions/case_1.9.rb +20 -0
- data/spec/language/versions/hash_1.9.rb +18 -0
- data/spec/language/versions/literal_lambda_1.9.rb +143 -0
- data/spec/language/versions/not_1.9.rb +22 -0
- data/spec/language/versions/send_1.9.rb +241 -0
- data/spec/language/versions/symbol_1.9.rb +15 -0
- data/spec/language/versions/variables_1.9.rb +8 -0
- data/spec/language/while_spec.rb +70 -5
- data/spec/language/yield_spec.rb +32 -6
- data/spec/mspec/guards/block_device.rb +0 -0
- data/spec/mspec/guards/endian.rb +0 -0
- data/spec/mspec/helpers/environment.rb +0 -0
- data/spec/mspec/helpers/language_version.rb +0 -0
- data/spec/mspec/helpers/tmp.rb +0 -0
- data/spec/ospec/filter.rb +32 -0
- data/spec/ospec/main.rb.erb +18 -0
- data/spec/ospec/phantom.rb +97 -0
- data/spec/ospec/runner.rb +95 -0
- data/spec/ospec/sprockets.js +40 -0
- data/spec/pp.rb +3 -0
- data/spec/rbconfig.rb +5 -0
- data/spec/spec_helper.rb +53 -26
- data/spec/yaml.rb +0 -0
- metadata +275 -31
- data/config.ru +0 -8
- data/lib/opal/processor.rb +0 -47
- data/lib/opal/scope.rb +0 -236
- data/lib/opal/server.rb +0 -94
- data/spec/core/boolean/and_spec.rb +0 -17
- data/spec/core/boolean/inspect_spec.rb +0 -9
- data/spec/core/boolean/or_spec.rb +0 -17
- data/spec/core/boolean/to_s_spec.rb +0 -9
- data/spec/core/boolean/xor_spec.rb +0 -17
@@ -0,0 +1,28 @@
|
|
1
|
+
module Opal
|
2
|
+
# LexerScope is used during lexing to keep track of local variables
|
3
|
+
# created inside a scope. A lexer scope can be asked if it has a local
|
4
|
+
# variable defined, and it can also check its parent scope if applicable.
|
5
|
+
#
|
6
|
+
# A LexerScope is created automatically as a new scope is entered during
|
7
|
+
# the lexing stage.
|
8
|
+
class LexerScope
|
9
|
+
attr_reader :locals
|
10
|
+
attr_accessor :parent
|
11
|
+
|
12
|
+
def initialize(type)
|
13
|
+
@block = type == :block
|
14
|
+
@locals = []
|
15
|
+
@parent = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_local(local)
|
19
|
+
@locals << local
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_local?(local)
|
23
|
+
return true if @locals.include? local
|
24
|
+
return @parent.has_local?(local) if @parent and @block
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/opal/parser.rb
CHANGED
@@ -1,45 +1,10 @@
|
|
1
1
|
require 'opal/lexer'
|
2
2
|
require 'opal/grammar'
|
3
|
-
require 'opal/
|
3
|
+
require 'opal/target_scope'
|
4
4
|
|
5
5
|
module Opal
|
6
|
-
# This class is used to generate the javascript code from the given
|
7
|
-
# ruby code. First, this class will use an instance of `Opal::Grammar`
|
8
|
-
# to lex and then build up a tree of sexp statements. Once done, the
|
9
|
-
# top level sexp is passed into `#top` which recursively generates
|
10
|
-
# javascript for each sexp inside, and the result is returned as a
|
11
|
-
# string.
|
12
|
-
#
|
13
|
-
# p = Opal::Parser.new
|
14
|
-
# p.parse "puts 42"
|
15
|
-
# # => "(function() { ... })()"
|
16
|
-
#
|
17
|
-
# ## Sexps
|
18
|
-
#
|
19
|
-
# A sexp, in opal, is an array where the first value is a symbol
|
20
|
-
# identifying the type of sexp. A simple ruby string "hello" would
|
21
|
-
# be represented by the sexp:
|
22
|
-
#
|
23
|
-
# s(:str, "hello")
|
24
|
-
#
|
25
|
-
# Once that sexp is encounterd by the parser, it is handled by
|
26
|
-
# `#process` which removes the sexp type from the array, and checks
|
27
|
-
# for a method "process_str", which is used to handle specific sexps.
|
28
|
-
# Once found, that method is called with the sexp and level as
|
29
|
-
# arguments, and the returned string is the javascript to be used in
|
30
|
-
# the resulting file.
|
31
|
-
#
|
32
|
-
# ## Levels
|
33
|
-
#
|
34
|
-
# A level inside the parser is just a symbol representing what type
|
35
|
-
# of destination the code to be generated is for. For example, the
|
36
|
-
# main two levels are `:stmt` and `:expr`. Most sexps generate the
|
37
|
-
# same code for every level, but an `if` statement for example
|
38
|
-
# will change when written as an expression. Javascript cannot have
|
39
|
-
# if statements as expressions, so that sexp would wrap its result
|
40
|
-
# inside an anonymous function so the if statement can compile as
|
41
|
-
# expected.
|
42
6
|
class Parser
|
7
|
+
|
43
8
|
# Generated code gets indented with two spaces on each scope
|
44
9
|
INDENT = ' '
|
45
10
|
|
@@ -63,28 +28,14 @@ module Opal
|
|
63
28
|
# Statements which should not have ';' added to them.
|
64
29
|
STATEMENTS = [:xstr, :dxstr]
|
65
30
|
|
66
|
-
# The grammar (tree of sexps) representing this compiled code
|
67
|
-
# @return [Opal::Grammar]
|
68
|
-
attr_reader :grammar
|
69
|
-
|
70
31
|
# Holds an array of paths which this file "requires".
|
71
32
|
# @return [Array<String>]
|
72
33
|
attr_reader :requires
|
73
34
|
|
74
|
-
|
75
|
-
|
76
|
-
# process. This is then handled recursively, resulting in a
|
77
|
-
# string of javascript being returned.
|
78
|
-
#
|
79
|
-
# p = Opal::Parser.new
|
80
|
-
# p.parse "puts 'hey'"
|
81
|
-
# # => "(function() { .... })()"
|
82
|
-
#
|
83
|
-
# @param [String] source the ruby code to parse
|
84
|
-
# @param [String] file the filename representing this code
|
85
|
-
# @return [String] string of javascript code
|
35
|
+
attr_reader :result
|
36
|
+
|
86
37
|
def parse(source, options = {})
|
87
|
-
@
|
38
|
+
@sexp = Grammar.new.parse(source, options[:file])
|
88
39
|
@requires = []
|
89
40
|
@line = 1
|
90
41
|
@indent = ''
|
@@ -100,8 +51,9 @@ module Opal
|
|
100
51
|
@method_missing = (options[:method_missing] != false)
|
101
52
|
@optimized_operators = (options[:optimized_operators] != false)
|
102
53
|
@arity_check = options[:arity_check]
|
54
|
+
@const_missing = (options[:const_missing] != false)
|
103
55
|
|
104
|
-
top
|
56
|
+
@result = top(@sexp)
|
105
57
|
end
|
106
58
|
|
107
59
|
# This is called when a parsing/processing error occurs. This
|
@@ -113,7 +65,7 @@ module Opal
|
|
113
65
|
#
|
114
66
|
# @param [String] msg error message to raise
|
115
67
|
def error(msg)
|
116
|
-
raise "#{msg} :#{@file}:#{@line}"
|
68
|
+
raise SyntaxError, "#{msg} :#{@file}:#{@line}"
|
117
69
|
end
|
118
70
|
|
119
71
|
# Instances of `Scope` can use this to determine the current
|
@@ -177,7 +129,6 @@ module Opal
|
|
177
129
|
# @return [String]
|
178
130
|
def top(sexp, options = {})
|
179
131
|
code = nil
|
180
|
-
vars = []
|
181
132
|
|
182
133
|
in_scope(:top) do
|
183
134
|
indent {
|
@@ -221,7 +172,7 @@ module Opal
|
|
221
172
|
return unless block_given?
|
222
173
|
|
223
174
|
parent = @scope
|
224
|
-
@scope =
|
175
|
+
@scope = TargetScope.new(type, self).tap { |s| s.parent = parent }
|
225
176
|
yield @scope
|
226
177
|
|
227
178
|
@scope = parent
|
@@ -608,8 +559,13 @@ module Opal
|
|
608
559
|
"(#{recv}#{mid} ? 'method' : nil)"
|
609
560
|
when :xstr
|
610
561
|
"(typeof(#{process part, :expression}) !== 'undefined')"
|
562
|
+
when :const
|
563
|
+
"(__scope.#{part[1].to_s} != null)"
|
611
564
|
when :colon2
|
612
565
|
"false"
|
566
|
+
when :ivar
|
567
|
+
ivar_name = part[1].to_s[1..-1]
|
568
|
+
"(#{current_self}[#{ivar_name.inspect}] != null ? 'instance-variable' : 'nil')"
|
613
569
|
else
|
614
570
|
raise "bad defined? part: #{part[0]}"
|
615
571
|
end
|
@@ -676,8 +632,6 @@ module Opal
|
|
676
632
|
@scope.add_temp block_arg
|
677
633
|
@scope.add_temp '__context'
|
678
634
|
scope_name = @scope.identify!
|
679
|
-
# @scope.add_arg block_arg
|
680
|
-
# code += "var #{block_arg} = _$ || nil, $context = #{block_arg}.$S;"
|
681
635
|
blk = "\n%s%s = %s._p || nil, __context = %s._s, %s.p = null;\n%s" %
|
682
636
|
[@indent, block_arg, scope_name, block_arg, scope_name, @indent]
|
683
637
|
|
@@ -695,7 +649,7 @@ module Opal
|
|
695
649
|
end
|
696
650
|
|
697
651
|
itercode = "function(#{params.join ', '}) {\n#{code}\n#@indent}"
|
698
|
-
call
|
652
|
+
call << ("(%s = %s, %s._s = %s, %s)" % [identity, itercode, identity, current_self, identity])
|
699
653
|
|
700
654
|
process call, level
|
701
655
|
end
|
@@ -714,11 +668,8 @@ module Opal
|
|
714
668
|
#
|
715
669
|
# s(recv, :mid=, s(:arglist, rhs))
|
716
670
|
def process_attrasgn(exp, level)
|
717
|
-
recv = exp
|
718
|
-
mid
|
719
|
-
arglist = exp[2]
|
720
|
-
|
721
|
-
return process(s(:call, recv, mid, arglist), level)
|
671
|
+
recv, mid, arglist = exp
|
672
|
+
process s(:call, recv, mid, arglist), level
|
722
673
|
end
|
723
674
|
|
724
675
|
# Used to generate optimized attr_reader, attr_writer and
|
@@ -784,13 +735,7 @@ module Opal
|
|
784
735
|
when :alias_native
|
785
736
|
return handle_alias_native(sexp) if @scope.class_scope?
|
786
737
|
when :require
|
787
|
-
|
788
|
-
|
789
|
-
if path and path[0] == :str
|
790
|
-
@requires << path[1]
|
791
|
-
end
|
792
|
-
|
793
|
-
return ""
|
738
|
+
return handle_require arglist[1]
|
794
739
|
when :respond_to?
|
795
740
|
return handle_respond_to(sexp, level)
|
796
741
|
end
|
@@ -798,21 +743,18 @@ module Opal
|
|
798
743
|
splat = arglist[1..-1].any? { |a| a.first == :splat }
|
799
744
|
|
800
745
|
if Array === arglist.last and arglist.last.first == :block_pass
|
801
|
-
|
746
|
+
block = process s(:js_tmp, process(arglist.pop, :expr)), :expr
|
802
747
|
elsif iter
|
803
|
-
block
|
748
|
+
block = iter
|
804
749
|
end
|
805
750
|
|
806
751
|
recv ||= s(:self)
|
807
752
|
|
808
753
|
if block
|
809
|
-
|
810
|
-
elsif splat and recv != [:self] and recv[0] != :lvar
|
811
|
-
tmprecv = @scope.new_temp
|
812
|
-
else # method_missing
|
813
|
-
tmprecv = @scope.new_temp
|
754
|
+
tmpfunc = @scope.new_temp
|
814
755
|
end
|
815
756
|
|
757
|
+
tmprecv = @scope.new_temp
|
816
758
|
args = ""
|
817
759
|
|
818
760
|
recv_code = process recv, :recv
|
@@ -822,10 +764,10 @@ module Opal
|
|
822
764
|
arglist.insert 1, call_recv unless splat
|
823
765
|
args = process arglist, :expr
|
824
766
|
|
825
|
-
dispatch =
|
826
|
-
|
827
|
-
|
828
|
-
"(#{
|
767
|
+
dispatch = "((#{tmprecv} = #{recv_code})#{mid} || $mm('#{ meth.to_s }'))"
|
768
|
+
|
769
|
+
if tmpfunc
|
770
|
+
dispatch = "(#{tmpfunc} = #{dispatch}, #{tmpfunc}._p = #{block}, #{tmpfunc})"
|
829
771
|
end
|
830
772
|
|
831
773
|
result = if splat
|
@@ -839,10 +781,53 @@ module Opal
|
|
839
781
|
result = splat ? "#{dispatch}.apply(#{tmprecv || recv_code}, #{args})" : "#{dispatch}(#{args})"
|
840
782
|
end
|
841
783
|
|
842
|
-
@scope.queue_temp
|
784
|
+
@scope.queue_temp tmpfunc if tmpfunc
|
843
785
|
result
|
844
786
|
end
|
845
787
|
|
788
|
+
def handle_require(sexp)
|
789
|
+
str = handle_require_sexp sexp
|
790
|
+
@requires << str
|
791
|
+
""
|
792
|
+
end
|
793
|
+
|
794
|
+
def handle_require_sexp(sexp)
|
795
|
+
type = sexp.shift
|
796
|
+
|
797
|
+
if type == :str
|
798
|
+
return sexp[0]
|
799
|
+
elsif type == :call
|
800
|
+
recv, meth, args = sexp
|
801
|
+
parts = args[1..-1].map { |s| handle_require_sexp s }
|
802
|
+
|
803
|
+
if recv == [:const, :File]
|
804
|
+
if meth == :expand_path
|
805
|
+
return handle_expand_path(*parts)
|
806
|
+
elsif meth == :join
|
807
|
+
return handle_expand_path parts.join("/")
|
808
|
+
elsif meth == :dirname
|
809
|
+
return handle_expand_path parts[0].split("/")[0...-1].join("/")
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
error "Cannot handle dynamic require"
|
815
|
+
end
|
816
|
+
|
817
|
+
def handle_expand_path(path, base = '')
|
818
|
+
"#{base}/#{path}".split("/").inject([]) do |path, part|
|
819
|
+
if part == ''
|
820
|
+
# we had '//', so ignore
|
821
|
+
elsif part == '..'
|
822
|
+
path.pop
|
823
|
+
else
|
824
|
+
path << part
|
825
|
+
end
|
826
|
+
|
827
|
+
path
|
828
|
+
end.join "/"
|
829
|
+
end
|
830
|
+
|
846
831
|
# s(:arglist, [arg [, arg ..]])
|
847
832
|
def process_arglist(sexp, level)
|
848
833
|
code = ''
|
@@ -997,31 +982,24 @@ module Opal
|
|
997
982
|
"(function(__base){#{spacer}#{cls}#{spacer}#{boot}\n#{code}\n#{@indent}})(#{base})"
|
998
983
|
end
|
999
984
|
|
1000
|
-
def process_undef(exp, level)
|
1001
|
-
@helpers[:undef] = true
|
1002
|
-
jsid = mid_to_jsid exp[0][1].to_s
|
1003
985
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
#
|
1008
|
-
"delete #{ @scope.proto }#{jsid}"
|
986
|
+
# undef :foo
|
987
|
+
# => delete MyClass.prototype.$foo
|
988
|
+
def process_undef(sexp, level)
|
989
|
+
"delete #{ @scope.proto }#{ mid_to_jsid sexp[0][1].to_s }"
|
1009
990
|
end
|
1010
991
|
|
1011
992
|
# s(:defn, mid, s(:args), s(:scope))
|
1012
993
|
def process_defn(sexp, level)
|
1013
|
-
mid = sexp
|
1014
|
-
|
1015
|
-
stmts = sexp[2]
|
994
|
+
mid, args, stmts = sexp
|
995
|
+
|
1016
996
|
js_def nil, mid, args, stmts, sexp.line, sexp.end_line
|
1017
997
|
end
|
1018
998
|
|
1019
999
|
# s(:defs, recv, mid, s(:args), s(:scope))
|
1020
1000
|
def process_defs(sexp, level)
|
1021
|
-
recv = sexp
|
1022
|
-
|
1023
|
-
args = sexp[2]
|
1024
|
-
stmts = sexp[3]
|
1001
|
+
recv, mid, args, stmts = sexp
|
1002
|
+
|
1025
1003
|
js_def recv, mid, args, stmts, sexp.line, sexp.end_line
|
1026
1004
|
end
|
1027
1005
|
|
@@ -1058,7 +1036,6 @@ module Opal
|
|
1058
1036
|
if args.last.to_s.start_with? '*'
|
1059
1037
|
uses_splat = true
|
1060
1038
|
if args.last == :*
|
1061
|
-
#args[-1] = splat
|
1062
1039
|
argc -= 1
|
1063
1040
|
else
|
1064
1041
|
splat = args[-1].to_s[1..-1].to_sym
|
@@ -1067,8 +1044,6 @@ module Opal
|
|
1067
1044
|
end
|
1068
1045
|
end
|
1069
1046
|
|
1070
|
-
args << block_name if block_name # have to re-add incase there was a splat arg
|
1071
|
-
|
1072
1047
|
if @arity_check
|
1073
1048
|
arity_code = arity_check(args, opt, uses_splat, block_name, mid) + "\n#{INDENT}"
|
1074
1049
|
end
|
@@ -1088,55 +1063,24 @@ module Opal
|
|
1088
1063
|
params = process args, :expr
|
1089
1064
|
stmt_code = "\n#@indent" + process(stmts, :stmt)
|
1090
1065
|
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
# params = yielder
|
1096
|
-
code += "if (typeof(#{yielder}) !== 'function') { #{yielder} = nil }"
|
1097
|
-
# CASE 2: we have a splat - use argc to get splat args, then check last one
|
1098
|
-
elsif splat
|
1099
|
-
@scope.add_temp yielder
|
1100
|
-
code += "#{splat} = __slice.call(arguments, #{argc});\n#{@indent}"
|
1101
|
-
code += "if (typeof(#{splat}[#{splat}.length - 1]) === 'function') { #{yielder} = #{splat}.pop(); } else { #{yielder} = nil; }\n#{@indent}"
|
1102
|
-
# CASE 3: we have some opt args
|
1103
|
-
elsif opt
|
1104
|
-
code += "var BLOCK_IDX = arguments.length - 1;\n#{@indent}"
|
1105
|
-
code += "if (typeof(arguments[BLOCK_IDX]) === 'function' && arguments[BLOCK_IDX]._s !== undefined) { #{yielder} = arguments[BLOCK_IDX] } else { #{yielder} = nil }"
|
1106
|
-
lastopt = opt[-1][1]
|
1107
|
-
opt[1..-1].each do |o|
|
1108
|
-
id = process s(:lvar, o[1]), :expr
|
1109
|
-
if o[2][2] == :undefined
|
1110
|
-
code += ("if (%s === %s && typeof(%s) === 'function') { %s = undefined; }" % [id, yielder, id, id])
|
1111
|
-
else
|
1112
|
-
code += ("if (%s == null || %s === %s) {\n%s%s\n%s}" %
|
1113
|
-
[id, id, yielder, @indent + INDENT, process(o, :expre), @indent])
|
1114
|
-
end
|
1115
|
-
end
|
1116
|
-
|
1117
|
-
# CASE 4: normal args and block
|
1118
|
-
else
|
1119
|
-
code += "if (typeof(#{yielder}) !== 'function') { #{yielder} = nil }"
|
1120
|
-
end
|
1121
|
-
else
|
1122
|
-
opt[1..-1].each do |o|
|
1123
|
-
next if o[2][2] == :undefined
|
1124
|
-
id = process s(:lvar, o[1]), :expr
|
1125
|
-
code += ("if (%s == null) {\n%s%s\n%s}" %
|
1066
|
+
opt[1..-1].each do |o|
|
1067
|
+
next if o[2][2] == :undefined
|
1068
|
+
id = process s(:lvar, o[1]), :expr
|
1069
|
+
code += ("if (%s == null) {\n%s%s\n%s}" %
|
1126
1070
|
[id, @indent + INDENT, process(o, :expre), @indent])
|
1127
|
-
|
1071
|
+
end if opt
|
1128
1072
|
|
1129
|
-
|
1130
|
-
end
|
1073
|
+
code += "#{splat} = __slice.call(arguments, #{argc});" if splat
|
1131
1074
|
|
1132
|
-
|
1075
|
+
scope_name = @scope.identity
|
1133
1076
|
|
1134
|
-
if @scope.uses_block?
|
1135
|
-
|
1077
|
+
if @scope.uses_block?
|
1078
|
+
@scope.add_temp yielder
|
1079
|
+
blk = "\n%s%s = %s._p || nil, %s._p = null;\n%s" % [@indent, yielder, scope_name, scope_name, @indent]
|
1136
1080
|
end
|
1137
1081
|
|
1138
|
-
|
1139
|
-
|
1082
|
+
code += stmt_code
|
1083
|
+
code = "#{blk}#{code}"
|
1140
1084
|
|
1141
1085
|
uses_super = @scope.uses_super
|
1142
1086
|
|
@@ -1152,6 +1096,8 @@ module Opal
|
|
1152
1096
|
else
|
1153
1097
|
"#{ recv }#{ jsid } = #{ defcode }"
|
1154
1098
|
end
|
1099
|
+
elsif @scope.class? and @scope.name == 'Object'
|
1100
|
+
"#{current_self}._defn('$#{mid}', #{defcode})"
|
1155
1101
|
elsif @scope.class_scope?
|
1156
1102
|
@scope.methods << "$#{mid}"
|
1157
1103
|
if uses_super
|
@@ -1159,6 +1105,8 @@ module Opal
|
|
1159
1105
|
uses_super = "#{uses_super} = #{@scope.proto}#{jsid};\n#@indent"
|
1160
1106
|
end
|
1161
1107
|
"#{uses_super}#{ @scope.proto }#{jsid} = #{defcode}"
|
1108
|
+
# elsif @scope.sclass?
|
1109
|
+
# "#{ current_self }._defs('$#{mid}', #{defcode})"
|
1162
1110
|
elsif @scope.type == :iter
|
1163
1111
|
"def#{jsid} = #{defcode}"
|
1164
1112
|
elsif @scope.type == :top
|
@@ -1176,7 +1124,6 @@ module Opal
|
|
1176
1124
|
arity = args.size - 1
|
1177
1125
|
arity -= (opt.size - 1) if opt
|
1178
1126
|
arity -= 1 if splat
|
1179
|
-
arity -= 1 if block_name
|
1180
1127
|
arity = -arity - 1 if opt or splat
|
1181
1128
|
|
1182
1129
|
# $arity will point to our received arguments count
|
@@ -1185,7 +1132,7 @@ module Opal
|
|
1185
1132
|
if arity < 0 # splat or opt args
|
1186
1133
|
aritycode + "if ($arity < #{-(arity + 1)}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
|
1187
1134
|
else
|
1188
|
-
aritycode + "if ($arity !== #{arity}
|
1135
|
+
aritycode + "if ($arity !== #{arity}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
|
1189
1136
|
end
|
1190
1137
|
end
|
1191
1138
|
|
@@ -1214,13 +1161,9 @@ module Opal
|
|
1214
1161
|
def current_self
|
1215
1162
|
if @scope.class_scope?
|
1216
1163
|
@scope.name
|
1217
|
-
elsif @scope.top?
|
1164
|
+
elsif @scope.top? or @scope.iter?
|
1218
1165
|
'self'
|
1219
|
-
|
1220
|
-
'self'
|
1221
|
-
elsif @scope.iter?
|
1222
|
-
'self'
|
1223
|
-
else # def
|
1166
|
+
else # defn, defs
|
1224
1167
|
'this'
|
1225
1168
|
end
|
1226
1169
|
end
|
@@ -1301,9 +1244,9 @@ module Opal
|
|
1301
1244
|
|
1302
1245
|
# s(:while, exp, block, true)
|
1303
1246
|
def process_while(sexp, level)
|
1304
|
-
expr = sexp
|
1305
|
-
stmt = sexp[1]
|
1247
|
+
expr, stmt = sexp
|
1306
1248
|
redo_var = @scope.new_temp
|
1249
|
+
|
1307
1250
|
stmt_level = if level == :expr or level == :recv
|
1308
1251
|
:stmt_closure
|
1309
1252
|
else
|
@@ -1471,6 +1414,10 @@ module Opal
|
|
1471
1414
|
@helpers['gvars'] = true
|
1472
1415
|
"__gvars[#{gvar.inspect}]"
|
1473
1416
|
end
|
1417
|
+
|
1418
|
+
def process_nth_ref(sexp, level)
|
1419
|
+
"nil"
|
1420
|
+
end
|
1474
1421
|
|
1475
1422
|
# s(:gasgn, :gvar, rhs)
|
1476
1423
|
def process_gasgn(sexp, level)
|
@@ -1491,8 +1438,7 @@ module Opal
|
|
1491
1438
|
|
1492
1439
|
# s(:cdecl, :const, rhs)
|
1493
1440
|
def process_cdecl(sexp, level)
|
1494
|
-
const = sexp
|
1495
|
-
rhs = sexp[1]
|
1441
|
+
const, rhs = sexp
|
1496
1442
|
"__scope.#{const} = #{process rhs, :expr}"
|
1497
1443
|
end
|
1498
1444
|
|
@@ -1500,7 +1446,7 @@ module Opal
|
|
1500
1446
|
def process_return(sexp, level)
|
1501
1447
|
val = process(sexp.shift || s(:nil), :expr)
|
1502
1448
|
|
1503
|
-
raise "
|
1449
|
+
raise SyntaxError, "void value expression: cannot return as an expression" unless level == :stmt
|
1504
1450
|
"return #{val}"
|
1505
1451
|
end
|
1506
1452
|
|
@@ -1634,8 +1580,7 @@ module Opal
|
|
1634
1580
|
|
1635
1581
|
# s(:and, lhs, rhs)
|
1636
1582
|
def process_and(sexp, level)
|
1637
|
-
lhs = sexp
|
1638
|
-
rhs = sexp[1]
|
1583
|
+
lhs, rhs = sexp
|
1639
1584
|
t = nil
|
1640
1585
|
tmp = @scope.new_temp
|
1641
1586
|
|
@@ -1702,12 +1647,12 @@ module Opal
|
|
1702
1647
|
@scope.uses_block!
|
1703
1648
|
|
1704
1649
|
splat = sexp.any? { |s| s.first == :splat }
|
1705
|
-
|
1650
|
+
sexp.unshift s(:js_tmp, 'null') unless splat # self
|
1706
1651
|
args = process_arglist sexp, level
|
1707
1652
|
|
1708
1653
|
y = @scope.block_name || '__yield'
|
1709
1654
|
|
1710
|
-
splat ? "#{y}.apply(null, #{args})" : "#{y}(#{args})"
|
1655
|
+
splat ? "#{y}.apply(null, #{args})" : "#{y}.call(#{args})"
|
1711
1656
|
end
|
1712
1657
|
|
1713
1658
|
def process_break(exp, level)
|
@@ -1718,7 +1663,7 @@ module Opal
|
|
1718
1663
|
error "break must be used as a statement" unless level == :stmt
|
1719
1664
|
"return (__breaker.$v = #{ val }, __breaker)"
|
1720
1665
|
else
|
1721
|
-
error "cannot use break outside of iter/while"
|
1666
|
+
error "void value expression: cannot use break outside of iter/while"
|
1722
1667
|
end
|
1723
1668
|
end
|
1724
1669
|
|
@@ -1864,7 +1809,7 @@ module Opal
|
|
1864
1809
|
|
1865
1810
|
elsif @scope.type == :def
|
1866
1811
|
identity = @scope.identify!
|
1867
|
-
cls_name = @scope.parent.name
|
1812
|
+
cls_name = @scope.parent.name || "#{current_self}._klass.prototype"
|
1868
1813
|
jsid = mid_to_jsid @scope.mid.to_s
|
1869
1814
|
|
1870
1815
|
if @scope.defs
|
@@ -1889,8 +1834,31 @@ module Opal
|
|
1889
1834
|
process s(:or, exp.shift, exp.shift), :expr
|
1890
1835
|
end
|
1891
1836
|
|
1837
|
+
# a &&= rhs
|
1838
|
+
#
|
1839
|
+
# s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, rhs))
|
1840
|
+
def process_op_asgn_and(sexp, level)
|
1841
|
+
process s(:and, sexp.shift, sexp.shift), :expr
|
1842
|
+
end
|
1843
|
+
|
1844
|
+
# lhs[args] ||= rhs
|
1845
|
+
#
|
1846
|
+
# s(:op_asgn1, lhs, args, :||, rhs)
|
1892
1847
|
def process_op_asgn1(sexp, level)
|
1893
|
-
|
1848
|
+
lhs, arglist, op, rhs = sexp
|
1849
|
+
|
1850
|
+
with_temp do |a| # args
|
1851
|
+
with_temp do |r| # recv
|
1852
|
+
args = process arglist[1], :expr
|
1853
|
+
recv = process lhs, :expr
|
1854
|
+
|
1855
|
+
aref = s(:call, s(:js_tmp, r), :[], s(:arglist, s(:js_tmp, a)))
|
1856
|
+
aset = s(:call, s(:js_tmp, r), :[]=, s(:arglist, s(:js_tmp, a), rhs))
|
1857
|
+
orop = s(:or, aref, aset)
|
1858
|
+
|
1859
|
+
"(#{a} = #{args}, #{r} = #{recv}, #{process orop, :expr})"
|
1860
|
+
end
|
1861
|
+
end
|
1894
1862
|
end
|
1895
1863
|
|
1896
1864
|
# lhs.b += rhs
|
@@ -1903,7 +1871,21 @@ module Opal
|
|
1903
1871
|
rhs = exp.shift
|
1904
1872
|
|
1905
1873
|
if op.to_s == "||"
|
1906
|
-
|
1874
|
+
with_temp do |temp|
|
1875
|
+
getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
|
1876
|
+
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
|
1877
|
+
orop = s(:or, getr, asgn)
|
1878
|
+
|
1879
|
+
"(#{temp} = #{lhs}, #{process orop, :expr})"
|
1880
|
+
end
|
1881
|
+
elsif op.to_s == '&&'
|
1882
|
+
with_temp do |temp|
|
1883
|
+
getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
|
1884
|
+
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, rhs))
|
1885
|
+
andop = s(:and, getr, asgn)
|
1886
|
+
|
1887
|
+
"(#{temp} = #{lhs}, #{process andop, :expr})"
|
1888
|
+
end
|
1907
1889
|
else
|
1908
1890
|
with_temp do |temp|
|
1909
1891
|
getr = s(:call, s(:js_tmp, temp), mid, s(:arglist))
|
@@ -1936,15 +1918,17 @@ module Opal
|
|
1936
1918
|
def process_rescue(exp, level)
|
1937
1919
|
body = exp.first.first == :resbody ? s(:nil) : exp.shift
|
1938
1920
|
body = indent { process body, level }
|
1921
|
+
handled_else = false
|
1939
1922
|
|
1940
1923
|
parts = []
|
1941
1924
|
until exp.empty?
|
1925
|
+
handled_else = true unless exp.first.first == :resbody
|
1942
1926
|
part = indent { process exp.shift, level }
|
1943
1927
|
part = "else " + part unless parts.empty?
|
1944
1928
|
parts << part
|
1945
1929
|
end
|
1946
1930
|
# if no rescue statement captures our error, we should rethrow
|
1947
|
-
parts << indent { "else { throw $err; }" }
|
1931
|
+
parts << indent { "else { throw $err; }" } unless handled_else
|
1948
1932
|
|
1949
1933
|
code = "try {#@space#{INDENT}#{body}#@space} catch ($err) {#@space#{parts.join @space}#{@space}}"
|
1950
1934
|
code = "(function() { #{code} }).call(#{current_self})" if level == :expr
|
@@ -1957,7 +1941,8 @@ module Opal
|
|
1957
1941
|
body = exp[1]
|
1958
1942
|
|
1959
1943
|
body = process(body || s(:nil), level)
|
1960
|
-
types = args[1..-
|
1944
|
+
types = args[1..-1]
|
1945
|
+
types.pop if types.last and types.last.first != :const
|
1961
1946
|
|
1962
1947
|
err = types.map { |t|
|
1963
1948
|
call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
|
@@ -1981,11 +1966,10 @@ module Opal
|
|
1981
1966
|
end
|
1982
1967
|
|
1983
1968
|
def process_next(exp, level)
|
1984
|
-
val = exp.empty? ? 'nil' : process(exp.shift, :expr)
|
1985
1969
|
if in_while?
|
1986
1970
|
"continue;"
|
1987
1971
|
else
|
1988
|
-
"return #{
|
1972
|
+
"return #{ exp.empty? ? 'nil' : process(exp.shift, :expr) };"
|
1989
1973
|
end
|
1990
1974
|
end
|
1991
1975
|
|