opal 0.3.41 → 0.3.42
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|