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



1337
1338
1339
1340
# File 'lib/syntax_tree/yarv/instructions.rb', line 1337

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

Instance Attribute Details

#flagsObject (readonly)

Returns the value of attribute flags.



1335
1336
1337
# File 'lib/syntax_tree/yarv/instructions.rb', line 1335

def flags
  @flags
end

#numberObject (readonly)

Returns the value of attribute number.



1335
1336
1337
# File 'lib/syntax_tree/yarv/instructions.rb', line 1335

def number
  @number
end

Instance Method Details

#==(other) ⇒ Object



1354
1355
1356
1357
# File 'lib/syntax_tree/yarv/instructions.rb', line 1354

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

#call(vm) ⇒ Object



1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
# File 'lib/syntax_tree/yarv/instructions.rb', line 1371

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



1350
1351
1352
# File 'lib/syntax_tree/yarv/instructions.rb', line 1350

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

#disasm(fmt) ⇒ Object



1342
1343
1344
# File 'lib/syntax_tree/yarv/instructions.rb', line 1342

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

#lengthObject



1359
1360
1361
# File 'lib/syntax_tree/yarv/instructions.rb', line 1359

def length
  3
end

#popsObject



1363
1364
1365
# File 'lib/syntax_tree/yarv/instructions.rb', line 1363

def pops
  1
end

#pushesObject



1367
1368
1369
# File 'lib/syntax_tree/yarv/instructions.rb', line 1367

def pushes
  number
end

#to_a(_iseq) ⇒ Object



1346
1347
1348
# File 'lib/syntax_tree/yarv/instructions.rb', line 1346

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