rubinius-ast 2.1.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rubinius/ast/constants.rb +3 -2
- data/lib/rubinius/ast/control_flow.rb +7 -4
- data/lib/rubinius/ast/data.rb +1 -1
- data/lib/rubinius/ast/definitions.rb +375 -241
- data/lib/rubinius/ast/encoding.rb +3 -2
- data/lib/rubinius/ast/exceptions.rb +1 -1
- data/lib/rubinius/ast/file.rb +1 -1
- data/lib/rubinius/ast/grapher.rb +1 -1
- data/lib/rubinius/ast/literals.rb +69 -9
- data/lib/rubinius/ast/node.rb +5 -1
- data/lib/rubinius/ast/operators.rb +83 -17
- data/lib/rubinius/ast/self.rb +1 -1
- data/lib/rubinius/ast/sends.rb +84 -90
- data/lib/rubinius/ast/transforms.rb +1 -1
- data/lib/rubinius/ast/values.rb +123 -11
- data/lib/rubinius/ast/variables.rb +154 -195
- data/lib/rubinius/ast/version.rb +2 -2
- data/rubinius-ast.gemspec +1 -2
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 446fcd824eee49fa15042e4aa39a3e802b49a4bb
|
4
|
+
data.tar.gz: b89a58a16a0ccacf3ac5e638fd29b2cefc2d5472
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 625a245f3487f621f66419640e446a00e4046318ec505a123c80ee27186b803f1d01f5635ae7884134cba19625e3d36468bd87348ab930fb69820706031a725d
|
7
|
+
data.tar.gz: 9ad09df099f4f9bc70476b71d144972186b0fcf8a194cb092b4af4c956609321fd3be6ca55d398a93f79e84dc289cf688efee67d33cf9cdfbed03020e4d38f7a
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
|
6
6
|
class TypeConstant < Node
|
@@ -204,7 +204,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
204
204
|
pos(g)
|
205
205
|
|
206
206
|
if g.state.op_asgn?
|
207
|
-
g.
|
207
|
+
g.push_rubinius
|
208
|
+
g.find_const :Runtime
|
208
209
|
g.push_literal @name
|
209
210
|
g.push_scope
|
210
211
|
g.send :find_constant_for_op_asign_or, 2
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
class Case < Node
|
6
6
|
attr_accessor :whens, :else
|
@@ -209,7 +209,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
209
209
|
g.dup
|
210
210
|
@condition.bytecode(g)
|
211
211
|
g.cast_array
|
212
|
-
g.
|
212
|
+
g.push_rubinius
|
213
|
+
g.find_const :Runtime
|
213
214
|
g.rotate(3)
|
214
215
|
g.send :matches_when, 2
|
215
216
|
g.git body
|
@@ -271,14 +272,16 @@ module Rubinius::ToolSets.current::ToolSet
|
|
271
272
|
end
|
272
273
|
|
273
274
|
def get_flip_flop(g, index)
|
274
|
-
g.
|
275
|
+
g.push_rubinius
|
276
|
+
g.find_const :Runtime
|
275
277
|
g.push_scope
|
276
278
|
g.push_literal index
|
277
279
|
g.send(:get_flip_flop, 2)
|
278
280
|
end
|
279
281
|
|
280
282
|
def set_flip_flop(g, index, value)
|
281
|
-
g.
|
283
|
+
g.push_rubinius
|
284
|
+
g.find_const :Runtime
|
282
285
|
g.push_scope
|
283
286
|
g.push_literal index
|
284
287
|
g.push_literal value
|
data/lib/rubinius/ast/data.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
class Alias < Node
|
6
6
|
attr_accessor :to, :from
|
@@ -79,8 +79,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
79
79
|
@locals = nil
|
80
80
|
end
|
81
81
|
|
82
|
-
def
|
83
|
-
if @array.first.kind_of?
|
82
|
+
def extract_parameters
|
83
|
+
if @array.first.kind_of? Parameters
|
84
84
|
node = @array.shift
|
85
85
|
if @array.first.kind_of? BlockArgument
|
86
86
|
node.block_arg = @array.shift
|
@@ -191,7 +191,7 @@ module Rubinius::ToolSets.current::ToolSet
|
|
191
191
|
def initialize(line, name, block)
|
192
192
|
@line = line
|
193
193
|
@name = name
|
194
|
-
@arguments = block.
|
194
|
+
@arguments = block.extract_parameters
|
195
195
|
block.array << NilLiteral.new(line) if block.array.empty?
|
196
196
|
@body = block
|
197
197
|
end
|
@@ -277,153 +277,53 @@ module Rubinius::ToolSets.current::ToolSet
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
-
class
|
281
|
-
attr_accessor :
|
282
|
-
attr_reader :block_arg, :block_index
|
280
|
+
class Lambda < Node
|
281
|
+
attr_accessor :arguments, :body
|
283
282
|
|
284
|
-
def initialize(line,
|
283
|
+
def initialize(line, arguments, body)
|
285
284
|
@line = line
|
286
|
-
@
|
287
|
-
@
|
288
|
-
@block_index = nil
|
289
|
-
|
290
|
-
if defaults
|
291
|
-
defaults = DefaultArguments.new line, defaults
|
292
|
-
@defaults = defaults
|
293
|
-
@optional = defaults.names
|
294
|
-
|
295
|
-
stop = defaults.names.first
|
296
|
-
last = args.each_with_index { |a, i| break i if a == stop }
|
297
|
-
@required = args[0, last]
|
298
|
-
else
|
299
|
-
@required = args.dup
|
300
|
-
@optional = []
|
301
|
-
end
|
302
|
-
|
303
|
-
if splat.kind_of? Symbol
|
304
|
-
args << splat
|
305
|
-
elsif splat
|
306
|
-
splat = :*
|
307
|
-
args << splat
|
308
|
-
end
|
309
|
-
@names = args
|
310
|
-
@splat = splat
|
311
|
-
end
|
312
|
-
|
313
|
-
def block_arg=(node)
|
314
|
-
@names << node.name
|
315
|
-
|
316
|
-
@block_index = @names.length - 1
|
317
|
-
@block_arg = node
|
285
|
+
@arguments = arguments
|
286
|
+
@body = Iter.new line, arguments, body
|
318
287
|
end
|
319
288
|
|
320
289
|
def bytecode(g)
|
321
|
-
g
|
322
|
-
map_arguments g.state.scope
|
323
|
-
|
324
|
-
@defaults.bytecode(g) if @defaults
|
325
|
-
@block_arg.bytecode(g) if @block_arg
|
326
|
-
g.state.check_for_locals = true
|
327
|
-
end
|
328
|
-
|
329
|
-
def required_args
|
330
|
-
@required.size
|
331
|
-
end
|
332
|
-
|
333
|
-
alias_method :arity, :required_args
|
334
|
-
|
335
|
-
def post_args
|
336
|
-
0
|
337
|
-
end
|
338
|
-
|
339
|
-
def total_args
|
340
|
-
@required.size + @optional.size
|
341
|
-
end
|
342
|
-
|
343
|
-
def splat_index
|
344
|
-
if @splat
|
345
|
-
index = @names.size
|
346
|
-
index -= 1 if @block_arg
|
347
|
-
index -= 1 if @splat.kind_of? Symbol
|
348
|
-
index
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
def map_arguments(scope)
|
353
|
-
@required.each { |arg| scope.new_local arg }
|
354
|
-
@defaults.map_arguments scope if @defaults
|
355
|
-
scope.new_local @splat if @splat.kind_of? Symbol
|
356
|
-
scope.assign_local_reference @block_arg if @block_arg
|
357
|
-
end
|
358
|
-
|
359
|
-
def to_actual(line)
|
360
|
-
arguments = ActualArguments.new line
|
361
|
-
|
362
|
-
last = -1
|
363
|
-
last -= 1 if @block_arg and @block_arg.name == names[last]
|
364
|
-
last -= 1 if @splat == names[last]
|
365
|
-
|
366
|
-
arguments.array = @names[0..last].map { |name| LocalVariableAccess.new line, name }
|
367
|
-
|
368
|
-
if @splat.kind_of? Symbol
|
369
|
-
arguments.splat = SplatValue.new(line, LocalVariableAccess.new(line, @splat))
|
370
|
-
end
|
290
|
+
pos(g)
|
371
291
|
|
372
|
-
|
292
|
+
g.push_rubinius
|
293
|
+
@body.bytecode(g)
|
294
|
+
g.send_with_block :lambda, 0, false
|
373
295
|
end
|
374
296
|
|
375
297
|
def to_sexp
|
376
|
-
|
377
|
-
|
378
|
-
@required.each { |x| sexp << x }
|
379
|
-
sexp += @defaults.names if @defaults
|
380
|
-
|
381
|
-
if @splat == :*
|
382
|
-
sexp << :*
|
383
|
-
elsif @splat
|
384
|
-
sexp << :"*#{@splat}"
|
385
|
-
end
|
386
|
-
|
387
|
-
sexp += @post if @post
|
388
|
-
|
389
|
-
sexp << :"&#{@block_arg.name}" if @block_arg
|
390
|
-
|
391
|
-
sexp << [:block] + @defaults.to_sexp if @defaults
|
392
|
-
|
393
|
-
sexp
|
298
|
+
[:lambda, @arguments.to_sexp, [:scope, @body.body.to_sexp]]
|
394
299
|
end
|
395
300
|
end
|
396
301
|
|
397
|
-
class
|
398
|
-
attr_accessor :
|
302
|
+
class Parameters < Node
|
303
|
+
attr_accessor :names, :required, :optional, :defaults, :splat,
|
304
|
+
:post, :keywords, :kwrest
|
305
|
+
attr_reader :block_arg, :block_index
|
399
306
|
|
400
|
-
def initialize(line, required, optional, splat,
|
307
|
+
def initialize(line, required=nil, optional=nil, splat=nil,
|
308
|
+
post=nil, kwargs=nil, kwrest=nil, block=nil)
|
401
309
|
@line = line
|
402
310
|
@defaults = nil
|
311
|
+
@keywords = nil
|
403
312
|
@block_arg = nil
|
404
313
|
@splat_index = nil
|
405
314
|
@block_index = nil
|
315
|
+
@locals = []
|
316
|
+
@local_index = 0
|
406
317
|
|
407
|
-
@required = []
|
408
318
|
names = []
|
409
319
|
|
410
|
-
|
411
|
-
required.each do |arg|
|
412
|
-
case arg
|
413
|
-
when Symbol
|
414
|
-
names << arg
|
415
|
-
@required << arg
|
416
|
-
when MultipleAssignment
|
417
|
-
@required << PatternArguments.from_masgn(arg)
|
418
|
-
@splat_index = -4 if @required.size == 1
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
320
|
+
process_fixed_arguments Array(required), @required = [], names
|
422
321
|
|
423
322
|
if optional
|
424
323
|
@defaults = DefaultArguments.new line, optional
|
425
324
|
@optional = @defaults.names
|
426
325
|
names.concat @optional
|
326
|
+
@locals.concat @defaults.arguments
|
427
327
|
else
|
428
328
|
@optional = []
|
429
329
|
end
|
@@ -431,35 +331,84 @@ module Rubinius::ToolSets.current::ToolSet
|
|
431
331
|
case splat
|
432
332
|
when Symbol
|
433
333
|
names << splat
|
334
|
+
@locals << splat
|
434
335
|
when true
|
435
336
|
splat = :*
|
436
|
-
|
337
|
+
@locals << splat
|
437
338
|
when false
|
438
|
-
@splat_index = -3
|
439
339
|
splat = nil
|
340
|
+
@splat_index = -3
|
341
|
+
end
|
342
|
+
|
343
|
+
@splat = splat
|
344
|
+
|
345
|
+
process_fixed_arguments post, @post = [], names
|
346
|
+
|
347
|
+
if kwargs
|
348
|
+
@keywords = KeywordParameters.new line, kwargs, kwrest
|
349
|
+
names.concat @keywords.names
|
350
|
+
elsif kwrest
|
351
|
+
@keywords = KeywordParameters.new line, nil, kwrest
|
352
|
+
end
|
353
|
+
|
354
|
+
if @keywords
|
355
|
+
var = local_placeholder
|
356
|
+
@keywords.value = LocalVariableAccess.new line, var
|
357
|
+
@locals << var
|
440
358
|
end
|
441
359
|
|
442
|
-
@
|
443
|
-
|
444
|
-
|
360
|
+
@names = names
|
361
|
+
|
362
|
+
self.block_arg = block
|
363
|
+
end
|
364
|
+
|
365
|
+
def process_fixed_arguments(array, arguments, names)
|
366
|
+
if array
|
367
|
+
array.each do |arg|
|
445
368
|
case arg
|
446
|
-
when
|
447
|
-
|
369
|
+
when :_
|
370
|
+
var = names.include?(:_) ? local_placeholder : arg
|
371
|
+
names << arg
|
448
372
|
when Symbol
|
449
|
-
|
373
|
+
var = arg
|
450
374
|
names << arg
|
375
|
+
when MultipleAssignment
|
376
|
+
var = arg
|
377
|
+
var.right = LocalVariableAccess.new line, local_placeholder
|
378
|
+
when VariableAssignment
|
379
|
+
var = arg
|
380
|
+
names << var.name
|
451
381
|
end
|
382
|
+
|
383
|
+
arguments << var
|
384
|
+
@locals << var
|
452
385
|
end
|
453
386
|
end
|
387
|
+
end
|
454
388
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
389
|
+
def local_placeholder
|
390
|
+
:"_:#{@local_index += 1}"
|
391
|
+
end
|
392
|
+
|
393
|
+
def block_arg=(block)
|
394
|
+
case block
|
395
|
+
when BlockArgument
|
396
|
+
@block_arg = block
|
397
|
+
when nil
|
398
|
+
return
|
399
|
+
else
|
400
|
+
@block_arg = BlockArgument.new @line, block
|
459
401
|
end
|
460
402
|
|
461
|
-
@
|
462
|
-
|
403
|
+
if @locals.last.kind_of? BlockArgument
|
404
|
+
@block_index -= 1
|
405
|
+
@locals.pop
|
406
|
+
end
|
407
|
+
@names.pop if @names.last.kind_of? BlockArgument
|
408
|
+
|
409
|
+
@block_index = @locals.size
|
410
|
+
@locals << @block_arg
|
411
|
+
@names << @block_arg.name
|
463
412
|
end
|
464
413
|
|
465
414
|
def required_args
|
@@ -471,153 +420,126 @@ module Rubinius::ToolSets.current::ToolSet
|
|
471
420
|
end
|
472
421
|
|
473
422
|
def total_args
|
474
|
-
@required.size + @optional.size + @post.size
|
423
|
+
args = @required.size + @optional.size + @post.size
|
424
|
+
args += 1 if @keywords
|
425
|
+
args
|
475
426
|
end
|
476
427
|
|
477
428
|
def splat_index
|
478
429
|
return @splat_index if @splat_index
|
479
430
|
|
480
|
-
if @splat
|
481
|
-
index = @names.size
|
482
|
-
index -= 1 if @block_arg
|
483
|
-
index -= 1 if @splat.kind_of? Symbol
|
484
|
-
index -= @post.size
|
485
|
-
index
|
486
|
-
end
|
431
|
+
return @required.size + @optional.size if @splat
|
487
432
|
end
|
488
433
|
|
489
|
-
def
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
434
|
+
def arity
|
435
|
+
arity = required_args
|
436
|
+
|
437
|
+
if @keywords and @keywords.required?
|
438
|
+
arity += 1
|
439
|
+
end
|
440
|
+
|
441
|
+
if @splat or not @optional.empty? or
|
442
|
+
(@keywords and not @keywords.required?)
|
443
|
+
arity += 1
|
498
444
|
end
|
499
445
|
|
500
|
-
@
|
501
|
-
|
446
|
+
if @splat or not @optional.empty? or
|
447
|
+
(@keywords and not @keywords.required?)
|
448
|
+
arity = -arity
|
449
|
+
end
|
502
450
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
451
|
+
arity
|
452
|
+
end
|
453
|
+
|
454
|
+
def map_arguments(scope)
|
455
|
+
@locals.map do |v|
|
456
|
+
case v
|
507
457
|
when Symbol
|
508
|
-
scope.new_local
|
458
|
+
scope.new_local v
|
459
|
+
when MultipleAssignment
|
460
|
+
scope.assign_local_reference v.right
|
461
|
+
when LocalVariable
|
462
|
+
scope.assign_local_reference v
|
463
|
+
when nil
|
464
|
+
STDERR.puts @locals.inspect, self.inspect
|
509
465
|
end
|
510
466
|
end
|
511
467
|
|
512
|
-
scope
|
513
|
-
|
468
|
+
@keywords.map_arguments(scope) if @keywords
|
514
469
|
end
|
515
470
|
|
516
471
|
def bytecode(g)
|
517
472
|
g.state.check_for_locals = false
|
518
473
|
map_arguments g.state.scope
|
519
474
|
|
520
|
-
@required.
|
521
|
-
if arg.kind_of?
|
522
|
-
|
475
|
+
@required.each_with_index do |arg, index|
|
476
|
+
if arg.kind_of? MultipleAssignment
|
477
|
+
g.push_local index
|
523
478
|
arg.bytecode(g)
|
524
479
|
g.pop
|
525
480
|
end
|
526
481
|
end
|
482
|
+
|
527
483
|
@defaults.bytecode(g) if @defaults
|
528
|
-
|
484
|
+
|
485
|
+
index = @required.size + @optional.size
|
486
|
+
index += 1 if @splat_index
|
487
|
+
|
529
488
|
@post.each do |arg|
|
530
|
-
if arg.kind_of?
|
531
|
-
|
489
|
+
if arg.kind_of? MultipleAssignment
|
490
|
+
g.push_local index
|
491
|
+
index += 1
|
532
492
|
arg.bytecode(g)
|
533
493
|
g.pop
|
534
494
|
end
|
535
495
|
end
|
496
|
+
|
497
|
+
@keywords.bytecode(g) if @keywords
|
498
|
+
|
499
|
+
@block_arg.bytecode(g) if @block_arg
|
500
|
+
|
536
501
|
g.state.check_for_locals = true
|
537
502
|
end
|
538
|
-
end
|
539
503
|
|
540
|
-
|
541
|
-
|
504
|
+
def to_sexp
|
505
|
+
sexp = [:args]
|
542
506
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
case n
|
550
|
-
when MultipleAssignment
|
551
|
-
array << PatternArguments.from_masgn(n)
|
552
|
-
when LocalVariable
|
553
|
-
array << LeftPatternVariable.new(n.line, n.name)
|
554
|
-
end
|
507
|
+
@required.each do |a|
|
508
|
+
case a
|
509
|
+
when Symbol
|
510
|
+
sexp << a
|
511
|
+
when Node
|
512
|
+
sexp << a.to_sexp
|
555
513
|
end
|
556
514
|
end
|
557
515
|
|
558
|
-
if
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
post_args << PatternArguments.from_masgn(n)
|
565
|
-
when LocalVariable
|
566
|
-
post_args << PostPatternVariable.new(n.line, n.name, idx)
|
567
|
-
end
|
568
|
-
idx += 1
|
569
|
-
end
|
570
|
-
array.concat(post_args.reverse)
|
516
|
+
sexp += @defaults.names if @defaults
|
517
|
+
|
518
|
+
if @splat == :*
|
519
|
+
sexp << :*
|
520
|
+
elsif @splat
|
521
|
+
sexp << :"*#{@splat}"
|
571
522
|
end
|
572
523
|
|
573
|
-
if
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
524
|
+
if @post
|
525
|
+
@post.each do |a|
|
526
|
+
case a
|
527
|
+
when Symbol
|
528
|
+
sexp << a
|
529
|
+
when Node
|
530
|
+
sexp << a.to_sexp
|
531
|
+
end
|
580
532
|
end
|
581
533
|
end
|
582
534
|
|
583
|
-
|
584
|
-
end
|
535
|
+
sexp += @keywords.names if @keywords
|
585
536
|
|
586
|
-
|
587
|
-
@line = line
|
588
|
-
@arguments = arguments
|
589
|
-
@argument = nil
|
590
|
-
end
|
537
|
+
sexp << :"&#{@block_arg.name}" if @block_arg
|
591
538
|
|
592
|
-
|
593
|
-
|
594
|
-
# pattern will be destructured from the value of this assignment.
|
595
|
-
def map_arguments(scope)
|
596
|
-
arguments = @arguments.body
|
597
|
-
while arguments
|
598
|
-
node = arguments.first
|
599
|
-
case node
|
600
|
-
when LeftPatternVariable, PostPatternVariable, SplatPatternVariable
|
601
|
-
@argument = node
|
602
|
-
scope.new_local node.name
|
603
|
-
scope.assign_local_reference node
|
604
|
-
return
|
605
|
-
end
|
606
|
-
arguments = node.arguments.body
|
607
|
-
end
|
608
|
-
end
|
539
|
+
sexp << [:block] + @defaults.to_sexp if @defaults
|
540
|
+
sexp << @keywords.to_sexp if @keywords
|
609
541
|
|
610
|
-
|
611
|
-
@arguments.body.each do |arg|
|
612
|
-
if arg.kind_of? PatternArguments
|
613
|
-
g.shift_array
|
614
|
-
g.cast_array
|
615
|
-
arg.bytecode(g)
|
616
|
-
g.pop
|
617
|
-
else
|
618
|
-
arg.bytecode(g)
|
619
|
-
end
|
620
|
-
end
|
542
|
+
sexp
|
621
543
|
end
|
622
544
|
end
|
623
545
|
|
@@ -653,6 +575,218 @@ module Rubinius::ToolSets.current::ToolSet
|
|
653
575
|
end
|
654
576
|
end
|
655
577
|
|
578
|
+
class KeywordParameters < Node
|
579
|
+
attr_accessor :arguments, :defaults, :names, :kwrest, :value
|
580
|
+
|
581
|
+
def initialize(line, block, kwrest)
|
582
|
+
@line = line
|
583
|
+
@kwrest = kwrest
|
584
|
+
@required = []
|
585
|
+
@defaults = []
|
586
|
+
|
587
|
+
if block
|
588
|
+
array = block.array
|
589
|
+
@names = array.map { |a| a.name }
|
590
|
+
|
591
|
+
array.each do |arg|
|
592
|
+
if arg.value.value == :*
|
593
|
+
@required << arg
|
594
|
+
else
|
595
|
+
@defaults << arg
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
@arguments = array
|
600
|
+
else
|
601
|
+
@arguments = []
|
602
|
+
@names = []
|
603
|
+
end
|
604
|
+
|
605
|
+
case kwrest
|
606
|
+
when Symbol
|
607
|
+
kwrest_name = :"**#{kwrest}"
|
608
|
+
@kwrest = LocalVariableAssignment.new line, kwrest
|
609
|
+
when true
|
610
|
+
kwrest_name = :**
|
611
|
+
@kwrest = true
|
612
|
+
end
|
613
|
+
|
614
|
+
@names << kwrest_name if kwrest_name
|
615
|
+
end
|
616
|
+
|
617
|
+
def required?
|
618
|
+
not @required.empty?
|
619
|
+
end
|
620
|
+
|
621
|
+
def entries
|
622
|
+
entries = []
|
623
|
+
@required.each { |arg| entries << arg.name << true }
|
624
|
+
@defaults.each { |arg| entries << arg.name << false }
|
625
|
+
entries
|
626
|
+
end
|
627
|
+
|
628
|
+
def map_arguments(scope)
|
629
|
+
@arguments.each { |var| scope.assign_local_reference var }
|
630
|
+
|
631
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
632
|
+
scope.assign_local_reference @kwrest
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
def bytecode(g)
|
637
|
+
done = g.new_label
|
638
|
+
check_hash = g.new_label
|
639
|
+
assignments = g.new_label
|
640
|
+
|
641
|
+
@value.bytecode(g)
|
642
|
+
|
643
|
+
g.dup
|
644
|
+
g.push :nil
|
645
|
+
g.swap
|
646
|
+
g.send :equal?, 1, true
|
647
|
+
g.gif check_hash
|
648
|
+
|
649
|
+
g.pop
|
650
|
+
g.push_cpath_top
|
651
|
+
g.find_const :Hash
|
652
|
+
g.send :allocate, 0, true
|
653
|
+
g.goto assignments
|
654
|
+
|
655
|
+
check_hash.set!
|
656
|
+
kind_of_hash(g, assignments)
|
657
|
+
|
658
|
+
discard = g.new_label
|
659
|
+
|
660
|
+
g.dup
|
661
|
+
g.send :to_hash, 0, true
|
662
|
+
kind_of_hash(g, discard)
|
663
|
+
|
664
|
+
g.push_type
|
665
|
+
g.move_down 2
|
666
|
+
g.push_literal :to_hash
|
667
|
+
g.push_cpath_top
|
668
|
+
g.find_const :Hash
|
669
|
+
g.send :coerce_to_type_error, 4, true
|
670
|
+
g.goto done
|
671
|
+
|
672
|
+
discard.set!
|
673
|
+
g.swap
|
674
|
+
g.pop
|
675
|
+
|
676
|
+
missing_value = g.new_label
|
677
|
+
|
678
|
+
assignments.set!
|
679
|
+
|
680
|
+
@required.each do |arg|
|
681
|
+
g.dup
|
682
|
+
g.push_literal arg.name
|
683
|
+
g.send :find_item, 1, true
|
684
|
+
|
685
|
+
g.dup
|
686
|
+
g.gif missing_value
|
687
|
+
|
688
|
+
g.send :value, 0, true
|
689
|
+
|
690
|
+
arg.variable.set_bytecode(g)
|
691
|
+
g.pop
|
692
|
+
end
|
693
|
+
|
694
|
+
defaults = g.new_label
|
695
|
+
g.goto defaults
|
696
|
+
|
697
|
+
missing_value.set!
|
698
|
+
g.pop
|
699
|
+
g.push_rubinius
|
700
|
+
g.find_const :Runtime
|
701
|
+
g.swap
|
702
|
+
g.send :keywords_missing, 1, true
|
703
|
+
g.goto done
|
704
|
+
|
705
|
+
defaults.set!
|
706
|
+
|
707
|
+
extra_keys = g.new_label
|
708
|
+
|
709
|
+
if @defaults.empty?
|
710
|
+
g.dup
|
711
|
+
g.send :size, 0, true
|
712
|
+
g.push @arguments.size
|
713
|
+
g.swap
|
714
|
+
g.send :equal?, 1, true
|
715
|
+
g.gif extra_keys
|
716
|
+
|
717
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
718
|
+
g.push_cpath_top
|
719
|
+
g.find_const :Hash
|
720
|
+
g.send :allocate, 0, true
|
721
|
+
@kwrest.variable.set_bytecode(g)
|
722
|
+
g.pop
|
723
|
+
end
|
724
|
+
|
725
|
+
g.goto done
|
726
|
+
else
|
727
|
+
@defaults.each do |arg|
|
728
|
+
next_value = g.new_label
|
729
|
+
default_value = g.new_label
|
730
|
+
|
731
|
+
g.dup
|
732
|
+
g.push_literal arg.name
|
733
|
+
g.send :find_item, 1, true
|
734
|
+
|
735
|
+
g.dup
|
736
|
+
g.gif default_value
|
737
|
+
|
738
|
+
g.send :value, 0, true
|
739
|
+
arg.variable.set_bytecode(g)
|
740
|
+
g.goto next_value
|
741
|
+
|
742
|
+
default_value.set!
|
743
|
+
g.pop
|
744
|
+
arg.bytecode(g)
|
745
|
+
|
746
|
+
next_value.set!
|
747
|
+
g.pop
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
extra_keys.set!
|
752
|
+
|
753
|
+
g.dup
|
754
|
+
g.push_rubinius
|
755
|
+
g.find_const :Runtime
|
756
|
+
g.swap
|
757
|
+
|
758
|
+
if @kwrest
|
759
|
+
g.push :true
|
760
|
+
else
|
761
|
+
g.push :false
|
762
|
+
end
|
763
|
+
|
764
|
+
g.send :keywords_extra, 2, true
|
765
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
766
|
+
@kwrest.variable.set_bytecode(g)
|
767
|
+
end
|
768
|
+
g.pop
|
769
|
+
|
770
|
+
done.set!
|
771
|
+
end
|
772
|
+
|
773
|
+
def kind_of_hash(g, label)
|
774
|
+
g.dup
|
775
|
+
g.push_cpath_top
|
776
|
+
g.find_const :Hash
|
777
|
+
g.swap
|
778
|
+
g.kind_of
|
779
|
+
g.git label
|
780
|
+
end
|
781
|
+
|
782
|
+
def to_sexp
|
783
|
+
sexp = [:kwargs]
|
784
|
+
sexp << @names unless @names.empty?
|
785
|
+
sexp << @defaults.map { |x| x.to_sexp } unless @defaults.empty?
|
786
|
+
sexp
|
787
|
+
end
|
788
|
+
end
|
789
|
+
|
656
790
|
module LocalVariable
|
657
791
|
attr_accessor :variable
|
658
792
|
end
|