diff --git a/src/Php/Parser/StdContainerParser.php b/src/Php/Parser/StdContainerParser.php index ce41926b..99f1f1d8 100644 --- a/src/Php/Parser/StdContainerParser.php +++ b/src/Php/Parser/StdContainerParser.php @@ -103,7 +103,7 @@ trait StdContainerParser protected function getStdArrayDecl(string $type, array $sizes): string { $decl = str_repeat(self::TYPE_STD_ARRAY . '<', count($sizes)); - $decl .= $type; + $decl .= $this->getStdContainerElementType($type); for ($i = count($sizes) - 1; $i >= 0; $i--) { $decl .= ', ' . $sizes[$i] . '>'; } @@ -454,6 +454,14 @@ trait StdContainerParser return $this->convertIntExpr($index); } + protected function getStdContainerElementType(string $type): string + { + return match ($type) { + self::TYPE_BIGINT, self::TYPE_BIGFLOAT, self::TYPE_DECIMAL, self::TYPE_STREAM => self::TYPE_VAR, + default => $type, + }; + } + protected function parseStdNativeType(NodeAbstract $expr, string $owner): string { if (!$this->isClassConstFetch($expr)) { @@ -466,6 +474,9 @@ trait StdContainerParser 'type_int' => self::TYPE_INT, 'type_float' => self::TYPE_FLOAT, 'type_bool' => self::TYPE_BOOL, + 'type_bigint' => self::TYPE_BIGINT, + 'type_bigfloat' => self::TYPE_BIGFLOAT, + 'type_decimal' => self::TYPE_DECIMAL, default => $this->fatalError($expr, "An incorrect `{$owner}` definition"), }; } @@ -488,6 +499,7 @@ trait StdContainerParser 'type_array' => self::TYPE_ARRAY, 'type_object' => self::TYPE_OBJECT, 'type_any', 'type_var', 'type_variant' => self::TYPE_VAR, + 'type_stream' => self::TYPE_STREAM, default => $this->fatalError($expr, "An incorrect `{$owner}` definition"), }, 'class' => null, @@ -538,7 +550,11 @@ trait StdContainerParser $valueExpr = $this->parseExpr($expr); $class = $info['class'] ?? null; if ($class === null) { - return $this->convertExprFromType($info['type'], $valueExpr); + $targetType = $info['type']; + if ($targetType === self::TYPE_BIGINT || $targetType === self::TYPE_BIGFLOAT || $targetType === self::TYPE_DECIMAL || $targetType === self::TYPE_STREAM) { + return $this->convertStdVarBackedExpr($targetType, $valueExpr, $expr); + } + return $this->convertExprFromType($targetType, $valueExpr); } $rightClass = $this->detectClassOfExpr($expr); if ($rightClass !== '') { @@ -550,6 +566,27 @@ trait StdContainerParser return 'php::toObject(' . $valueExpr . ', ' . $this->getClassEntryPtr($class) . ', true)'; } + protected function convertStdVarBackedExpr(string $targetType, string $valueExpr, NodeAbstract $expr): string + { + $sourceType = $this->detectTypeOfExpr($expr); + if ($sourceType === $targetType) { + return $valueExpr; + } + if ($targetType === self::TYPE_STREAM) { + return $valueExpr; + } + if ($targetType === self::TYPE_BIGINT) { + return $this->convertBigIntExpr($valueExpr, $sourceType); + } + if ($targetType === self::TYPE_BIGFLOAT) { + return $this->convertBigFloatExpr($valueExpr, $sourceType); + } + if ($targetType === self::TYPE_DECIMAL) { + return $this->convertDecimalExpr($valueExpr, $sourceType, $expr); + } + return $valueExpr; + } + protected function parseStdUnsafeCastAssign(string $var, Expr\StaticCall $expr): string { if (count($expr->args) !== 2) { @@ -608,7 +645,7 @@ trait StdContainerParser protected function getStdMapDecl(string $containerType, string $keyType, string $valueType): string { - return $containerType . '<' . $keyType . ', ' . $valueType . '>'; + return $containerType . '<' . $keyType . ', ' . $this->getStdContainerElementType($valueType) . '>'; } protected function parseStdArray(string $var, Expr\StaticCall $expr): string @@ -671,7 +708,7 @@ trait StdContainerParser } $size = $expr->args[1]->value->value; } - $decl = self::TYPE_STD_VECTOR . '<' . $type . '>'; + $decl = self::TYPE_STD_VECTOR . '<' . $this->getStdContainerElementType($type) . '>'; $this->context->stdContainers[$var] = $this->addStdTypeId([ 'kind' => 'vector', 'decl' => $decl, diff --git a/tests/aot/std-bigfloat/001.phpt b/tests/aot/std-bigfloat/001.phpt new file mode 100644 index 00000000..704816a1 --- /dev/null +++ b/tests/aot/std-bigfloat/001.phpt @@ -0,0 +1,22 @@ +--TEST-- +std bigfloat: vector push_back and read +--FILE-- +toString()); + var_dump($v[1]->toString()); + var_dump($v[2]->toString()); + var_dump(count($v)); +} +?> +--EXPECT-- +string(18) "3.1400000000000001" +string(4) "2.71" +string(3) "100" +int(3) diff --git a/tests/aot/std-bigint/001.phpt b/tests/aot/std-bigint/001.phpt new file mode 100644 index 00000000..8b329a68 --- /dev/null +++ b/tests/aot/std-bigint/001.phpt @@ -0,0 +1,22 @@ +--TEST-- +std bigint: vector push_back and read +--FILE-- +toString()); + var_dump($v[1]->toString()); + var_dump($v[2]->toString()); + var_dump(count($v)); +} +?> +--EXPECT-- +string(2) "99" +string(2) "88" +string(2) "77" +int(3) diff --git a/tests/aot/std-bigint/002.phpt b/tests/aot/std-bigint/002.phpt new file mode 100644 index 00000000..03af679a --- /dev/null +++ b/tests/aot/std-bigint/002.phpt @@ -0,0 +1,22 @@ +--TEST-- +std bigint: map set/get +--FILE-- +toString()); + var_dump($m[2]->toString()); + var_dump($m[3]->toString()); + var_dump(count($m)); +} +?> +--EXPECT-- +string(3) "100" +string(3) "200" +string(3) "300" +int(3) diff --git a/tests/aot/std-bigint/003.phpt b/tests/aot/std-bigint/003.phpt new file mode 100644 index 00000000..3b51f0df --- /dev/null +++ b/tests/aot/std-bigint/003.phpt @@ -0,0 +1,20 @@ +--TEST-- +std bigint: array write/read +--FILE-- +toString()); + var_dump($a[1]->toString()); + var_dump($a[2]->toString()); +} +?> +--EXPECT-- +string(2) "42" +string(2) "84" +string(3) "126" diff --git a/tests/aot/std-bigint/004.phpt b/tests/aot/std-bigint/004.phpt new file mode 100644 index 00000000..aa525a5b --- /dev/null +++ b/tests/aot/std-bigint/004.phpt @@ -0,0 +1,20 @@ +--TEST-- +std bigint: foreach +--FILE-- + $val) { + $sum = $sum + $val->toInt(); + } + var_dump($sum); +} +?> +--EXPECT-- +int(60) diff --git a/tests/aot/std-decimal/001.phpt b/tests/aot/std-decimal/001.phpt new file mode 100644 index 00000000..06584dc0 --- /dev/null +++ b/tests/aot/std-decimal/001.phpt @@ -0,0 +1,22 @@ +--TEST-- +std decimal: vector push_back and read +--FILE-- +toString()); + var_dump($v[1]->toString()); + var_dump($v[2]->toString()); + var_dump(count($v)); +} +?> +--EXPECT-- +string(4) "3.14" +string(3) "2.5" +string(3) "100" +int(3) diff --git a/tests/aot/std-stream/001.phpt b/tests/aot/std-stream/001.phpt new file mode 100644 index 00000000..69476aea --- /dev/null +++ b/tests/aot/std-stream/001.phpt @@ -0,0 +1,34 @@ +--TEST-- +std stream: vector push_back and use +--FILE-- +write("hello"); + $v[] = $fp; + + $fp2 = fopen($tmpfile, 'r'); + $v[] = $fp2; + + var_dump(count($v)); + + $r = $v[0]; + $r->seek(0); + var_dump($r->read(5)); + + $r2 = $v[1]; + var_dump($r2->read(5)); + + $v[0]->close(); + $v[1]->close(); + unlink($tmpfile); +} +?> +--EXPECT-- +int(2) +string(5) "hello" +string(5) "hello"