Skip to content

Commit 074b286

Browse files
authored
Merge pull request #165 from php-java/add-mnemonic-multianewarray
Add mnemonic multianewarray
2 parents bd2010f + edfcd7b commit 074b286

6 files changed

Lines changed: 106 additions & 7 deletions

File tree

src/Kernel/Mnemonics/_arraylength.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ final class _arraylength implements OperationInterface
99
public function execute(): void
1010
{
1111
$arrayref = $this->popFromOperandStack();
12-
$this->pushToOperandStack(count($arrayref->toArray()));
12+
$this->pushToOperandStack(
13+
count($arrayref)
14+
);
1315
}
1416
}

src/Kernel/Mnemonics/_getstatic.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace PHPJava\Kernel\Mnemonics;
33

4+
use PHPJava\Exceptions\NotImplementedException;
45
use PHPJava\Kernel\Structures\_Fieldref;
56
use PHPJava\Utilities\ClassResolver;
67
use PHPJava\Utilities\Formatter;
@@ -36,6 +37,9 @@ public function execute(): void
3637
/**
3738
* @var \PHPJava\Core\JavaClass $className
3839
*/
40+
throw new NotImplementedException(
41+
'Not implemented operation.'
42+
);
3943
return;
4044
}
4145
$this->pushToOperandStack(new $classObject());
Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<?php
22
namespace PHPJava\Kernel\Mnemonics;
33

4-
use PHPJava\Exceptions\NotImplementedException;
4+
use PHPJava\Kernel\Types\_Array\Collection;
5+
use PHPJava\Utilities\Extractor;
6+
use PHPJava\Utilities\Formatter;
57

68
final class _multianewarray implements OperationInterface
79
{
@@ -10,6 +12,54 @@ final class _multianewarray implements OperationInterface
1012

1113
public function execute(): void
1214
{
13-
throw new NotImplementedException(__CLASS__);
15+
$cp = $this->getConstantPool();
16+
$index = $this->readUnsignedShort();
17+
$dimensions = $this->readByte();
18+
19+
$descriptor = Formatter::parseSignature(
20+
$cp[$cp[$index]->getClassIndex()]->getString()
21+
);
22+
23+
$counts = array_fill(0, $dimensions, 0);
24+
25+
for ($i = $dimensions - 1; $i >= 0; $i--) {
26+
$counts[$i] = Extractor::getRealValue(
27+
$this->popFromOperandStack()
28+
);
29+
}
30+
31+
$data = null;
32+
$multiDimensionArray = $this->makeMultiDimensionArray(
33+
$data,
34+
$counts,
35+
$descriptor[0]['class_name'] ?? $descriptor[0]['type'],
36+
0,
37+
$dimensions
38+
);
39+
40+
$this->pushToOperandStackByReference($multiDimensionArray);
41+
}
42+
43+
/**
44+
* @param $array
45+
* @return $this
46+
*/
47+
private function makeMultiDimensionArray($array, array $counts, string $type, int $currentDimension, int $maxDimension)
48+
{
49+
if ($currentDimension >= $maxDimension) {
50+
return $array;
51+
}
52+
$newArray = (new Collection())->setType($type);
53+
for ($i = 0; $i < $counts[$currentDimension]; $i++) {
54+
$collection = (new Collection())->setType($type);
55+
$newArray[$i] = $this->makeMultiDimensionArray(
56+
$collection,
57+
$counts,
58+
$type,
59+
$currentDimension + 1,
60+
$maxDimension
61+
);
62+
}
63+
return $newArray;
1464
}
1565
}

src/Kernel/Types/_Array/Collection.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,27 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate
99
{
1010
private $data;
1111
private $position = 0;
12+
private $type;
1213

13-
public function __construct(array &$data, string $type = null)
14+
public function __construct(array &$data = [])
1415
{
1516
$this->data = $data;
1617
}
1718

19+
public function setType(string $type = null)
20+
{
21+
$this->type = $type;
22+
return $this;
23+
}
24+
1825
public function getType($default = null): ?string
1926
{
2027
if (!isset($this->data[0])) {
21-
return $default;
28+
return $this->type ?? $default;
2229
}
2330
return TypeResolver::resolveFromPHPType(
2431
Extractor::getRealValue($this->data[0])
25-
) ?? $default;
32+
) ?? $this->type ?? $default;
2633
}
2734

2835
public function __toString()
@@ -55,6 +62,10 @@ public function offsetUnset($offset)
5562

5663
public function offsetSet($offset, $value)
5764
{
65+
if ($offset === null) {
66+
$this->data[] = $value;
67+
return;
68+
}
5869
$this->data[$offset] = $value;
5970
}
6071

tests/ArrayTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,19 @@ public function testCreateByteArray()
9595
$this->assertEquals('2', $actual->offsetGet(1));
9696
$this->assertEquals('3', $actual->offsetGet(2));
9797
}
98+
99+
public function testMultiDimensionArrayWithConstants()
100+
{
101+
$actual = $this->call('multiDimensionArrayWithConstants');
102+
$this->assertEquals('Hello World!', $actual);
103+
}
104+
105+
public function testMultiDimensionArrayWithDynamic()
106+
{
107+
$actual = $this->call('multiDimensionArrayWithDynamic');
108+
$this->assertCount(3, $actual);
109+
$this->assertEquals('Hello', (string) $actual[0]);
110+
$this->assertEquals(' ', (string) $actual[1]);
111+
$this->assertEquals('World!', (string) $actual[2]);
112+
}
98113
}

tests/fixtures/java/ArrayTest.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,27 @@ public static char[] createCharArray()
3535
return new char[] { 'A', 'B', 'C' };
3636
}
3737

38-
3938
public static byte[] createByteArray()
4039
{
4140
return new byte[] { 0x01, 0x02, 0x03 };
41+
}
42+
43+
public static String multiDimensionArrayWithConstants()
44+
{
45+
String[][] a = {
46+
{"Hello", " ", "World!"}
47+
};
48+
49+
return a[0][0] + "" + a[0][1] + "" + a[0][2];
50+
}
51+
52+
public static String[] multiDimensionArrayWithDynamic()
53+
{
54+
String[][] a = new String[1][3];
55+
a[0][0] = "Hello";
56+
a[0][1] = " ";
57+
a[0][2] = "World!";
4258

59+
return a[0];
4360
}
4461
}

0 commit comments

Comments
 (0)