rubinius-ast 2.1.3 → 2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc9ddee64cf9f30bf0458c2cdee3f81c509c7062
4
- data.tar.gz: 126e405ea53fa96cf9d9eac72c48931f8244a7de
3
+ metadata.gz: 446fcd824eee49fa15042e4aa39a3e802b49a4bb
4
+ data.tar.gz: b89a58a16a0ccacf3ac5e638fd29b2cefc2d5472
5
5
  SHA512:
6
- metadata.gz: 38d4c5b5fa58fa3bc5c77acb2a5db91b08ff21ac8adf95b0f93cd6756aa1510da999e56ce723e941a30bc68f4961c36b762874ee7f8485479b77e42ccef031aa
7
- data.tar.gz: 8d7e5e6b3358850059b2f338c29a8eb3fbf8bc12783e0d0a6c3246f0b2dc1bfdb494d204280bb13dd119b6b0c581dc7edb5b0d108b3311b0930bf6e0b94c044d
6
+ metadata.gz: 625a245f3487f621f66419640e446a00e4046318ec505a123c80ee27186b803f1d01f5635ae7884134cba19625e3d36468bd87348ab930fb69820706031a725d
7
+ data.tar.gz: 9ad09df099f4f9bc70476b71d144972186b0fcf8a194cb092b4af4c956609321fd3be6ca55d398a93f79e84dc289cf688efee67d33cf9cdfbed03020e4d38f7a
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
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.push_literal Compiler::Runtime
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 Rubinius::ToolSets.current::ToolSet
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.push_literal Compiler::Runtime
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.push_literal Compiler::Runtime
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.push_literal Compiler::Runtime
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
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
3
+ module CodeTools
4
4
  module AST
5
5
  class EndData < Node
6
6
  attr_accessor :data
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: us-ascii -*-
2
2
 
3
- module Rubinius::ToolSets.current::ToolSet
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 strip_arguments
83
- if @array.first.kind_of? FormalArguments
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.strip_arguments
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 FormalArguments < Node
281
- attr_accessor :names, :required, :optional, :defaults, :splat
282
- attr_reader :block_arg, :block_index
280
+ class Lambda < Node
281
+ attr_accessor :arguments, :body
283
282
 
284
- def initialize(line, args, defaults, splat)
283
+ def initialize(line, arguments, body)
285
284
  @line = line
286
- @defaults = nil
287
- @block_arg = nil
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.state.check_for_locals = false
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
- arguments
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
- sexp = [:args]
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 FormalArguments19 < FormalArguments
398
- attr_accessor :post
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, post, block)
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
- if required
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
- names << splat
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
- @post = []
443
- if post
444
- post.each do |arg|
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 MultipleAssignment
447
- @post << PatternArguments.from_masgn(arg)
369
+ when :_
370
+ var = names.include?(:_) ? local_placeholder : arg
371
+ names << arg
448
372
  when Symbol
449
- @post << arg
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
- if block
456
- @block_arg = BlockArgument.new line, block
457
- names << block
458
- @block_index = names.length - 1
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
- @splat = splat
462
- @names = names
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 map_arguments(scope)
490
- @required.each_with_index do |arg, index|
491
- case arg
492
- when PatternArguments
493
- arg.map_arguments scope
494
- when Symbol
495
- @required[index] = arg = :"_#{index}" if arg == :_ and index > 0
496
- scope.new_local arg
497
- end
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
- @defaults.map_arguments scope if @defaults
501
- scope.new_local @splat if @splat.kind_of? Symbol
446
+ if @splat or not @optional.empty? or
447
+ (@keywords and not @keywords.required?)
448
+ arity = -arity
449
+ end
502
450
 
503
- @post.each do |arg|
504
- case arg
505
- when PatternArguments
506
- arg.map_arguments scope
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 arg
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.assign_local_reference @block_arg if @block_arg
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.each do |arg|
521
- if arg.kind_of? PatternArguments
522
- arg.argument.position_bytecode(g)
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
- @block_arg.bytecode(g) if @block_arg
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? PatternArguments
531
- arg.argument.position_bytecode(g)
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
- class PatternArguments < Node
541
- attr_accessor :arguments, :argument
504
+ def to_sexp
505
+ sexp = [:args]
542
506
 
543
- def self.from_masgn(node)
544
- array = []
545
- size = 0
546
- if node.left
547
- size += node.left.body.size
548
- node.left.body.map do |n|
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 node.post
559
- idx = 0
560
- post_args = []
561
- node.post.body.map do |n|
562
- case n
563
- when MultipleAssignment
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 node.splat
574
- n = node.splat
575
- case n
576
- when EmptySplat
577
- array << SplatPatternVariable.new(n.line, :*)
578
- when SplatAssignment, SplatWrapped, SplatArray
579
- array << SplatPatternVariable.new(n.value.line, n.value.name)
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
- PatternArguments.new node.line, ArrayLiteral.new(node.line, array)
584
- end
535
+ sexp += @keywords.names if @keywords
585
536
 
586
- def initialize(line, arguments)
587
- @line = line
588
- @arguments = arguments
589
- @argument = nil
590
- end
537
+ sexp << :"&#{@block_arg.name}" if @block_arg
591
538
 
592
- # Assign the left-most, depth-first PatternVariable so that this local
593
- # will be assigned the passed argument at that position. The rest of the
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
- def bytecode(g)
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