sass 3.2.0.alpha.278 → 3.2.0.alpha.291
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/REVISION +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass/engine.rb +15 -9
- data/lib/sass/script/arg_list.rb +52 -0
- data/lib/sass/script/funcall.rb +45 -38
- data/lib/sass/script/lexer.rb +1 -0
- data/lib/sass/script/list.rb +1 -1
- data/lib/sass/script/literal.rb +1 -0
- data/lib/sass/script/number.rb +7 -6
- data/lib/sass/script/parser.rb +32 -34
- data/lib/sass/scss/parser.rb +6 -6
- data/lib/sass/tree/function_node.rb +8 -1
- data/lib/sass/tree/mixin_def_node.rb +8 -1
- data/lib/sass/tree/mixin_node.rb +8 -1
- data/lib/sass/tree/visitors/convert.rb +22 -6
- data/lib/sass/tree/visitors/perform.rb +88 -33
- data/test/sass/conversion_test.rb +54 -0
- data/test/sass/engine_test.rb +15 -13
- data/test/sass/functions_test.rb +3 -2
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +1 -1
- data/test/sass/script_test.rb +2 -1
- data/test/sass/scss/scss_test.rb +359 -1
- metadata +21 -20
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
b79252d738656e1cea492c2c09624ae1581681f6
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.291
|
data/VERSION_DATE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
10 August 2012 23:31:56 GMT
|
data/lib/sass/engine.rb
CHANGED
@@ -52,11 +52,14 @@ module Sass
|
|
52
52
|
# `name`: `String`
|
53
53
|
# : The name of the mixin/function.
|
54
54
|
#
|
55
|
-
# `args`: `Array<(
|
55
|
+
# `args`: `Array<(Script::Node, Script::Node)>`
|
56
56
|
# : The arguments for the mixin/function.
|
57
|
-
# Each element is a tuple containing the
|
57
|
+
# Each element is a tuple containing the variable node of the argument
|
58
58
|
# and the parse tree for the default value of the argument.
|
59
59
|
#
|
60
|
+
# `splat`: `Script::Node?`
|
61
|
+
# : The variable node of the splat argument for this callable, or null.
|
62
|
+
#
|
60
63
|
# `environment`: {Sass::Environment}
|
61
64
|
# : The environment in which the mixin/function was defined.
|
62
65
|
# This is captured so that the mixin/function can have access
|
@@ -67,7 +70,10 @@ module Sass
|
|
67
70
|
#
|
68
71
|
# `has_content`: `Boolean`
|
69
72
|
# : Whether the callable accepts a content block.
|
70
|
-
|
73
|
+
#
|
74
|
+
# `type`: `String`
|
75
|
+
# : The user-friendly name of the type of the callable.
|
76
|
+
Callable = Struct.new(:name, :args, :splat, :environment, :tree, :has_content, :type)
|
71
77
|
|
72
78
|
# This class handles the parsing and compilation of the Sass template.
|
73
79
|
# Example usage:
|
@@ -827,9 +833,9 @@ WARNING
|
|
827
833
|
raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".") if name.nil?
|
828
834
|
|
829
835
|
offset = line.offset + line.text.size - arg_string.size
|
830
|
-
args = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
836
|
+
args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
831
837
|
parse_mixin_definition_arglist
|
832
|
-
Tree::MixinDefNode.new(name, args)
|
838
|
+
Tree::MixinDefNode.new(name, args, splat)
|
833
839
|
end
|
834
840
|
|
835
841
|
CONTENT_RE = /^@content\s*(.+)?$/
|
@@ -847,9 +853,9 @@ WARNING
|
|
847
853
|
raise SyntaxError.new("Invalid mixin include \"#{line.text}\".") if name.nil?
|
848
854
|
|
849
855
|
offset = line.offset + line.text.size - arg_string.size
|
850
|
-
args, keywords = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
856
|
+
args, keywords, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
851
857
|
parse_mixin_include_arglist
|
852
|
-
Tree::MixinNode.new(name, args, keywords)
|
858
|
+
Tree::MixinNode.new(name, args, keywords, splat)
|
853
859
|
end
|
854
860
|
|
855
861
|
FUNCTION_RE = /^@function\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
|
@@ -858,9 +864,9 @@ WARNING
|
|
858
864
|
raise SyntaxError.new("Invalid function definition \"#{line.text}\".") if name.nil?
|
859
865
|
|
860
866
|
offset = line.offset + line.text.size - arg_string.size
|
861
|
-
args = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
867
|
+
args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
|
862
868
|
parse_function_definition_arglist
|
863
|
-
Tree::FunctionNode.new(name, args)
|
869
|
+
Tree::FunctionNode.new(name, args, splat)
|
864
870
|
end
|
865
871
|
|
866
872
|
def parse_script(script, options = {})
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Sass::Script
|
2
|
+
# A SassScript object representing a variable argument list. This works just
|
3
|
+
# like a normal list, but can also contain keyword arguments.
|
4
|
+
#
|
5
|
+
# The keyword arguments attached to this list are unused except when this is
|
6
|
+
# passed as a glob argument to a function or mixin.
|
7
|
+
class ArgList < List
|
8
|
+
# Whether \{#keywords} has been accessed. If so, we assume that all keywords
|
9
|
+
# were valid for the function that created this ArgList.
|
10
|
+
#
|
11
|
+
# @return [Boolean]
|
12
|
+
attr_accessor :keywords_accessed
|
13
|
+
|
14
|
+
# Creates a new argument list.
|
15
|
+
#
|
16
|
+
# @param value [Array<Literal>] See \{List#value}.
|
17
|
+
# @param keywords [Hash<String, Literal>] See \{#keywords}
|
18
|
+
# @param separator [String] See \{List#separator}.
|
19
|
+
def initialize(value, keywords, separator)
|
20
|
+
super(value, separator)
|
21
|
+
@keywords = keywords
|
22
|
+
end
|
23
|
+
|
24
|
+
# The keyword arguments attached to this list.
|
25
|
+
#
|
26
|
+
# @return [Hash<String, Literal>]
|
27
|
+
def keywords
|
28
|
+
@keywords_accessed = true
|
29
|
+
@keywords
|
30
|
+
end
|
31
|
+
|
32
|
+
# @see Node#children
|
33
|
+
def children
|
34
|
+
super + @keywords.values
|
35
|
+
end
|
36
|
+
|
37
|
+
# @see Node#deep_copy
|
38
|
+
def deep_copy
|
39
|
+
node = super
|
40
|
+
node.instance_variable_set('@keywords',
|
41
|
+
Sass::Util.map_hash(@keywords) {|k, v| [k, v.deep_copy]})
|
42
|
+
node
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
# @see Node#_perform
|
48
|
+
def _perform(environment)
|
49
|
+
self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/sass/script/funcall.rb
CHANGED
@@ -23,13 +23,20 @@ module Sass
|
|
23
23
|
# @return [{String => Script::Node}]
|
24
24
|
attr_reader :keywords
|
25
25
|
|
26
|
+
# The splat argument for this function, if one exists.
|
27
|
+
#
|
28
|
+
# @return [Script::Node?]
|
29
|
+
attr_accessor :splat
|
30
|
+
|
26
31
|
# @param name [String] See \{#name}
|
27
32
|
# @param args [Array<Script::Node>] See \{#args}
|
33
|
+
# @param splat [Script::Node] See \{#splat}
|
28
34
|
# @param keywords [{String => Script::Node}] See \{#keywords}
|
29
|
-
def initialize(name, args, keywords)
|
35
|
+
def initialize(name, args, keywords, splat)
|
30
36
|
@name = name
|
31
37
|
@args = args
|
32
38
|
@keywords = keywords
|
39
|
+
@splat = splat
|
33
40
|
super()
|
34
41
|
end
|
35
42
|
|
@@ -38,7 +45,11 @@ module Sass
|
|
38
45
|
args = @args.map {|a| a.inspect}.join(', ')
|
39
46
|
keywords = Sass::Util.hash_to_a(@keywords).
|
40
47
|
map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
|
41
|
-
|
48
|
+
if self.splat
|
49
|
+
splat = (args.empty? && keywords.empty?) ? "" : ", "
|
50
|
+
splat = "#{splat}#{self.splat.inspect}..."
|
51
|
+
end
|
52
|
+
"#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
|
42
53
|
end
|
43
54
|
|
44
55
|
# @see Node#to_sass
|
@@ -46,7 +57,11 @@ module Sass
|
|
46
57
|
args = @args.map {|a| a.to_sass(opts)}.join(', ')
|
47
58
|
keywords = Sass::Util.hash_to_a(@keywords).
|
48
59
|
map {|k, v| "$#{dasherize(k, opts)}: #{v.to_sass(opts)}"}.join(', ')
|
49
|
-
|
60
|
+
if self.splat
|
61
|
+
splat = (args.empty? && keywords.empty?) ? "" : ", "
|
62
|
+
splat = "#{splat}#{self.splat.inspect}..."
|
63
|
+
end
|
64
|
+
"#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
|
50
65
|
end
|
51
66
|
|
52
67
|
# Returns the arguments to the function.
|
@@ -54,7 +69,9 @@ module Sass
|
|
54
69
|
# @return [Array<Node>]
|
55
70
|
# @see Node#children
|
56
71
|
def children
|
57
|
-
@args + @keywords.values
|
72
|
+
res = @args + @keywords.values
|
73
|
+
res << @splat if @splat
|
74
|
+
res
|
58
75
|
end
|
59
76
|
|
60
77
|
# @see Node#deep_copy
|
@@ -74,13 +91,14 @@ module Sass
|
|
74
91
|
# @raise [Sass::SyntaxError] if the function call raises an ArgumentError
|
75
92
|
def _perform(environment)
|
76
93
|
args = @args.map {|a| a.perform(environment)}
|
94
|
+
splat = @splat.perform(environment) if @splat
|
77
95
|
if fn = environment.function(@name)
|
78
96
|
keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
|
79
|
-
return perform_sass_fn(fn, args, keywords)
|
97
|
+
return perform_sass_fn(fn, args, keywords, splat)
|
80
98
|
end
|
81
99
|
|
82
100
|
ruby_name = @name.tr('-', '_')
|
83
|
-
args = construct_ruby_args(ruby_name, args, environment)
|
101
|
+
args = construct_ruby_args(ruby_name, args, splat, environment)
|
84
102
|
|
85
103
|
unless Functions.callable?(ruby_name)
|
86
104
|
opts(to_literal(args))
|
@@ -106,12 +124,23 @@ module Sass
|
|
106
124
|
|
107
125
|
private
|
108
126
|
|
109
|
-
def construct_ruby_args(name, args, environment)
|
110
|
-
|
111
|
-
|
127
|
+
def construct_ruby_args(name, args, splat, environment)
|
128
|
+
args += splat.to_a if splat
|
129
|
+
|
130
|
+
# If variable arguments were passed, there won't be any explicit keywords.
|
131
|
+
if splat.is_a?(Sass::Script::ArgList)
|
132
|
+
kwargs_size = splat.keywords.size
|
133
|
+
splat.keywords_accessed = false
|
134
|
+
else
|
135
|
+
kwargs_size = @keywords.size
|
136
|
+
end
|
137
|
+
|
138
|
+
unless signature = Functions.signature(name.to_sym, args.size, kwargs_size)
|
139
|
+
return args if @keywords.empty?
|
112
140
|
raise Sass::SyntaxError.new("Function #{name} doesn't support keyword arguments")
|
113
141
|
end
|
114
|
-
keywords = Sass::
|
142
|
+
keywords = splat.is_a?(Sass::Script::ArgList) ? splat.keywords :
|
143
|
+
Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
|
115
144
|
|
116
145
|
# If the user passes more non-keyword args than the function expects,
|
117
146
|
# but it does expect keyword args, Ruby's arg handling won't raise an error.
|
@@ -148,36 +177,14 @@ module Sass
|
|
148
177
|
args
|
149
178
|
end
|
150
179
|
|
151
|
-
def perform_sass_fn(function, args, keywords)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
raise Sass::SyntaxError.new("Function #{@name} doesn't have #{unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'} #{unknown_args.map{|name| "$#{name}"}.join ', '}")
|
180
|
+
def perform_sass_fn(function, args, keywords, splat)
|
181
|
+
Sass::Tree::Visitors::Perform.perform_arguments(function, args, keywords, splat) do |env|
|
182
|
+
val = catch :_sass_return do
|
183
|
+
function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, env)}
|
184
|
+
raise Sass::SyntaxError.new("Function #{@name} finished without @return")
|
157
185
|
end
|
186
|
+
val
|
158
187
|
end
|
159
|
-
|
160
|
-
if args.size > function.args.size
|
161
|
-
raise ArgumentError.new("Wrong number of arguments (#{args.size} for #{function.args.size})")
|
162
|
-
end
|
163
|
-
|
164
|
-
environment = function.args.zip(args).
|
165
|
-
inject(Sass::Environment.new(function.environment)) do |env, ((var, default), value)|
|
166
|
-
if value && keywords.include?(var.underscored_name)
|
167
|
-
raise Sass::SyntaxError.new("Function #{@name} was passed argument $#{var.name} both by position and by name")
|
168
|
-
end
|
169
|
-
|
170
|
-
env.set_local_var(var.name,
|
171
|
-
value || keywords[var.underscored_name] || (default && default.perform(env)))
|
172
|
-
raise Sass::SyntaxError.new("Function #{@name} is missing argument #{var.inspect}") unless env.var(var.name)
|
173
|
-
env
|
174
|
-
end
|
175
|
-
|
176
|
-
val = catch :_sass_return do
|
177
|
-
function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, environment)}
|
178
|
-
raise Sass::SyntaxError.new("Function #{@name} finished without @return")
|
179
|
-
end
|
180
|
-
val
|
181
188
|
end
|
182
189
|
end
|
183
190
|
end
|
data/lib/sass/script/lexer.rb
CHANGED
data/lib/sass/script/list.rb
CHANGED
data/lib/sass/script/literal.rb
CHANGED
data/lib/sass/script/number.rb
CHANGED
@@ -422,12 +422,13 @@ module Sass::Script
|
|
422
422
|
end
|
423
423
|
|
424
424
|
# A hash of unit names to their index in the conversion table
|
425
|
-
CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
|
426
|
-
CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
|
427
|
-
[ nil, 1, 2.36220473, 10, 28.3464567], # cm
|
428
|
-
[ nil, nil, 1, 4.23333333, 12 ], # pc
|
429
|
-
[ nil, nil, nil, 1, 2.83464567], # mm
|
430
|
-
[ nil, nil, nil, nil, 1 ]
|
425
|
+
CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4, "px" => 5 }
|
426
|
+
CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 , 96 ], # in
|
427
|
+
[ nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
|
428
|
+
[ nil, nil, 1, 4.23333333, 12 , 16 ], # pc
|
429
|
+
[ nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
|
430
|
+
[ nil, nil, nil, nil, 1 , 1.3333333333], # pt
|
431
|
+
[ nil, nil, nil, nil, nil , 1 ]] # px
|
431
432
|
|
432
433
|
def conversion_factor(from_unit, to_unit)
|
433
434
|
res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
|
data/lib/sass/script/parser.rb
CHANGED
@@ -74,21 +74,22 @@ module Sass
|
|
74
74
|
|
75
75
|
# Parses the argument list for a mixin include.
|
76
76
|
#
|
77
|
-
# @return [(Array<Script::Node>, {String => Script::
|
78
|
-
# The root nodes of the arguments
|
79
|
-
# Keyword arguments are in a hash from names to values.
|
77
|
+
# @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
|
78
|
+
# The root nodes of the positional arguments, keyword arguments, and
|
79
|
+
# splat argument. Keyword arguments are in a hash from names to values.
|
80
80
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
81
81
|
def parse_mixin_include_arglist
|
82
82
|
args, keywords = [], {}
|
83
83
|
if try_tok(:lparen)
|
84
|
-
args, keywords = mixin_arglist || [[], {}]
|
84
|
+
args, keywords, splat = mixin_arglist || [[], {}]
|
85
85
|
assert_tok(:rparen)
|
86
86
|
end
|
87
87
|
assert_done
|
88
88
|
|
89
89
|
args.each {|a| a.options = @options}
|
90
90
|
keywords.each {|k, v| v.options = @options}
|
91
|
-
|
91
|
+
splat.options = @options if splat
|
92
|
+
return args, keywords, splat
|
92
93
|
rescue Sass::SyntaxError => e
|
93
94
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
94
95
|
raise e
|
@@ -96,17 +97,19 @@ module Sass
|
|
96
97
|
|
97
98
|
# Parses the argument list for a mixin definition.
|
98
99
|
#
|
99
|
-
# @return [Array<Script::Node
|
100
|
+
# @return [(Array<Script::Node>, Script::Node)]
|
101
|
+
# The root nodes of the arguments, and the splat argument.
|
100
102
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
101
103
|
def parse_mixin_definition_arglist
|
102
|
-
args = defn_arglist!(false)
|
104
|
+
args, splat = defn_arglist!(false)
|
103
105
|
assert_done
|
104
106
|
|
105
107
|
args.each do |k, v|
|
106
108
|
k.options = @options
|
107
109
|
v.options = @options if v
|
108
110
|
end
|
109
|
-
|
111
|
+
splat.options = @options if splat
|
112
|
+
return args, splat
|
110
113
|
rescue Sass::SyntaxError => e
|
111
114
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
112
115
|
raise e
|
@@ -114,17 +117,19 @@ module Sass
|
|
114
117
|
|
115
118
|
# Parses the argument list for a function definition.
|
116
119
|
#
|
117
|
-
# @return [Array<Script::Node
|
120
|
+
# @return [(Array<Script::Node>, Script::Node)]
|
121
|
+
# The root nodes of the arguments, and the splat argument.
|
118
122
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
119
123
|
def parse_function_definition_arglist
|
120
|
-
args = defn_arglist!(true)
|
124
|
+
args, splat = defn_arglist!(true)
|
121
125
|
assert_done
|
122
126
|
|
123
127
|
args.each do |k, v|
|
124
128
|
k.options = @options
|
125
129
|
v.options = @options if v
|
126
130
|
end
|
127
|
-
|
131
|
+
splat.options = @options if splat
|
132
|
+
return args, splat
|
128
133
|
rescue Sass::SyntaxError => e
|
129
134
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
130
135
|
raise e
|
@@ -324,37 +329,41 @@ RUBY
|
|
324
329
|
|
325
330
|
def funcall
|
326
331
|
return raw unless tok = try_tok(:funcall)
|
327
|
-
args, keywords = fn_arglist || [[], {}]
|
332
|
+
args, keywords, splat = fn_arglist || [[], {}]
|
328
333
|
assert_tok(:rparen)
|
329
|
-
node(Script::Funcall.new(tok.value, args, keywords))
|
334
|
+
node(Script::Funcall.new(tok.value, args, keywords, splat))
|
330
335
|
end
|
331
336
|
|
332
337
|
def defn_arglist!(must_have_parens)
|
333
338
|
if must_have_parens
|
334
339
|
assert_tok(:lparen)
|
335
340
|
else
|
336
|
-
return [] unless try_tok(:lparen)
|
341
|
+
return [], nil unless try_tok(:lparen)
|
337
342
|
end
|
338
|
-
return [] if try_tok(:rparen)
|
343
|
+
return [], nil if try_tok(:rparen)
|
339
344
|
|
340
345
|
res = []
|
346
|
+
splat = nil
|
341
347
|
must_have_default = false
|
342
348
|
loop do
|
343
349
|
line = @lexer.line
|
344
350
|
offset = @lexer.offset + 1
|
345
351
|
c = assert_tok(:const)
|
346
352
|
var = Script::Variable.new(c.value)
|
347
|
-
if
|
353
|
+
if try_tok(:colon)
|
348
354
|
val = assert_expr(:space)
|
349
355
|
must_have_default = true
|
350
356
|
elsif must_have_default
|
351
357
|
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.")
|
358
|
+
elsif try_tok(:splat)
|
359
|
+
splat = var
|
360
|
+
break
|
352
361
|
end
|
353
362
|
res << [var, val]
|
354
363
|
break unless try_tok(:comma)
|
355
364
|
end
|
356
365
|
assert_tok(:rparen)
|
357
|
-
res
|
366
|
+
return res, splat
|
358
367
|
end
|
359
368
|
|
360
369
|
def fn_arglist
|
@@ -376,34 +385,23 @@ RUBY
|
|
376
385
|
|
377
386
|
unless try_tok(:comma)
|
378
387
|
return [], keywords if keywords
|
388
|
+
return [], {}, e if try_tok(:splat)
|
379
389
|
return [e], {}
|
380
390
|
end
|
381
391
|
|
382
|
-
other_args, other_keywords = assert_expr(type)
|
392
|
+
other_args, other_keywords, splat = assert_expr(type)
|
383
393
|
if keywords
|
384
|
-
if !other_args.empty?
|
385
|
-
raise SyntaxError.new("Positional arguments must come before keyword arguments")
|
394
|
+
if !other_args.empty? || splat
|
395
|
+
raise SyntaxError.new("Positional arguments must come before keyword arguments.")
|
386
396
|
elsif other_keywords[name.underscored_name]
|
387
397
|
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
|
388
398
|
end
|
389
|
-
return other_args, keywords.merge(other_keywords)
|
399
|
+
return other_args, keywords.merge(other_keywords), splat
|
390
400
|
else
|
391
|
-
return [e, *other_args], other_keywords
|
401
|
+
return [e, *other_args], other_keywords, splat
|
392
402
|
end
|
393
403
|
end
|
394
404
|
|
395
|
-
def keyword_arglist
|
396
|
-
return unless var = try_tok(:const)
|
397
|
-
unless try_tok(:colon)
|
398
|
-
return_tok!
|
399
|
-
return
|
400
|
-
end
|
401
|
-
name = var[1]
|
402
|
-
value = interpolation
|
403
|
-
return {name => value} unless try_tok(:comma)
|
404
|
-
{name => value}.merge(assert_expr(:keyword_arglist))
|
405
|
-
end
|
406
|
-
|
407
405
|
def raw
|
408
406
|
return special_fun unless tok = try_tok(:raw)
|
409
407
|
node(Script::String.new(tok.value))
|