Class: SyntaxTree::YARV::ExpandArray

Inherits:
Instruction show all
Defined in:
lib/syntax_tree/yarv/instructions.rb

Overview

### Summary

‘expandarray` looks at the top of the stack, and if the value is an array it replaces it on the stack with `number` elements of the array, or `nil` if the elements are missing.

### Usage

~~~ruby x, = [true, false, nil] ~~~

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Instruction

#branch_targets, #canonical, #falls_through?, #leaves?, #side_effects?

Constructor Details

#initialize(number, flags) ⇒ ExpandArray

Returns a new instance of ExpandArray.



1448
1449
1450
1451
# File 'lib/syntax_tree/yarv/instructions.rb', line 1448

def initialize(number, flags)
  @number = number
  @flags = flags
end

Instance Attribute Details

#flagsObject (readonly)

Returns the value of attribute flags.



1446
1447
1448
# File 'lib/syntax_tree/yarv/instructions.rb', line 1446

def flags
  @flags
end

#numberObject (readonly)

Returns the value of attribute number.



1446
1447
1448
# File 'lib/syntax_tree/yarv/instructions.rb', line 1446

def number
  @number
end

Instance Method Details

#==(other) ⇒ Object



1465
1466
1467
1468
# File 'lib/syntax_tree/yarv/instructions.rb', line 1465

def ==(other)
  other.is_a?(ExpandArray) && other.number == number &&
    other.flags == flags
end

#call(vm) ⇒ Object



1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
# File 'lib/syntax_tree/yarv/instructions.rb', line 1482

def call(vm)
  object = vm.pop
  object =
    if Array === object
      object.dup
    elsif object.respond_to?(:to_ary, true)
      object.to_ary
    else
      [object]
    end

  splat_flag = flags & 0x01 > 0
  postarg_flag = flags & 0x02 > 0

  if number == 0 && splat_flag == 0
    # no space left on stack
  elsif postarg_flag
    values = []

    if number > object.size
      (number - object.size).times { values.push(nil) }
    end
    [number, object.size].min.times { values.push(object.pop) }
    values.push(object.to_a) if splat_flag

    values.each { |item| vm.push(item) }
  else
    values = []

    [number, object.size].min.times { values.push(object.shift) }
    if number > values.size
      (number - values.size).times { values.push(nil) }
    end
    values.push(object.to_a) if splat_flag

    values.reverse_each { |item| vm.push(item) }
  end
end

#deconstruct_keys(_keys) ⇒ Object



1461
1462
1463
# File 'lib/syntax_tree/yarv/instructions.rb', line 1461

def deconstruct_keys(_keys)
  { number: number, flags: flags }
end

#disasm(fmt) ⇒ Object



1453
1454
1455
# File 'lib/syntax_tree/yarv/instructions.rb', line 1453

def disasm(fmt)
  fmt.instruction("expandarray", [fmt.object(number), fmt.object(flags)])
end

#lengthObject



1470
1471
1472
# File 'lib/syntax_tree/yarv/instructions.rb', line 1470

def length
  3
end

#popsObject



1474
1475
1476
# File 'lib/syntax_tree/yarv/instructions.rb', line 1474

def pops
  1
end

#pushesObject



1478
1479
1480
# File 'lib/syntax_tree/yarv/instructions.rb', line 1478

def pushes
  number
end

#to_a(_iseq) ⇒ Object



1457
1458
1459
# File 'lib/syntax_tree/yarv/instructions.rb', line 1457

def to_a(_iseq)
  [:expandarray, number, flags]
end