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.



1395
1396
1397
1398
# File 'lib/syntax_tree/yarv/instructions.rb', line 1395

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

Instance Attribute Details

#flagsObject (readonly)

Returns the value of attribute flags.



1393
1394
1395
# File 'lib/syntax_tree/yarv/instructions.rb', line 1393

def flags
  @flags
end

#numberObject (readonly)

Returns the value of attribute number.



1393
1394
1395
# File 'lib/syntax_tree/yarv/instructions.rb', line 1393

def number
  @number
end

Instance Method Details

#==(other) ⇒ Object



1412
1413
1414
1415
# File 'lib/syntax_tree/yarv/instructions.rb', line 1412

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

#call(vm) ⇒ Object



1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
# File 'lib/syntax_tree/yarv/instructions.rb', line 1429

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



1408
1409
1410
# File 'lib/syntax_tree/yarv/instructions.rb', line 1408

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

#disasm(fmt) ⇒ Object



1400
1401
1402
# File 'lib/syntax_tree/yarv/instructions.rb', line 1400

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

#lengthObject



1417
1418
1419
# File 'lib/syntax_tree/yarv/instructions.rb', line 1417

def length
  3
end

#popsObject



1421
1422
1423
# File 'lib/syntax_tree/yarv/instructions.rb', line 1421

def pops
  1
end

#pushesObject



1425
1426
1427
# File 'lib/syntax_tree/yarv/instructions.rb', line 1425

def pushes
  number
end

#to_a(_iseq) ⇒ Object



1404
1405
1406
# File 'lib/syntax_tree/yarv/instructions.rb', line 1404

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