sass 3.2.0.alpha.278 → 3.2.0.alpha.291
Sign up to get free protection for your applications and to get access to all the features.
- 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))
|