支持语法 **=

pull/1/head
韩天峰 8 months ago
parent 4162b79113
commit 739152ba14
  1. 7
      examples/str_offset_set.php
  2. 25
      src/Php/Translator.php
  3. 10
      tests/aot/pow-assign-op.phpt
  4. 16
      tests/zend/ast/ast_serialize_backtick_literal.phpt
  5. 26
      tests/zend/ast/ast_serialize_floats.phpt
  6. 16
      tests/zend/ast/zend-pow-assign.phpt

@ -0,0 +1,7 @@
<?php
function main()
{
$hello = "hello world";
$hello['0'] = array( "hello");
var_dump($hello);
}

@ -619,6 +619,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseAssignOpShiftRight($expr); return $this->parseAssignOpShiftRight($expr);
case 'Expr_AssignOp_BitwiseAnd': case 'Expr_AssignOp_BitwiseAnd':
return $this->parseAssignOpBitwiseAnd($expr); return $this->parseAssignOpBitwiseAnd($expr);
case 'Expr_AssignOp_Pow':
return $this->parseAssignOpPow($expr);
case 'Expr_BinaryOp_Mul': case 'Expr_BinaryOp_Mul':
return $this->parseBinaryOpMul($expr); return $this->parseBinaryOpMul($expr);
case 'Expr_BinaryOp_Concat': case 'Expr_BinaryOp_Concat':
@ -676,6 +678,8 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseClone($expr); return $this->parseClone($expr);
case 'Expr_Throw': case 'Expr_Throw':
return $this->parseThrow($expr); return $this->parseThrow($expr);
case 'Expr_ShellExec':
return $this->parseShellExec($expr);
case 'Name_FullyQualified': case 'Name_FullyQualified':
return $expr->name; return $expr->name;
case 'Scalar_Int': case 'Scalar_Int':
@ -801,6 +805,11 @@ class Translator extends \PhpAot\Core\Translator
return $op === '.='; return $op === '.=';
} }
private function isAssignOpPow(string $op): bool
{
return $op === '**=';
}
/** /**
* 尽可能转为数字,优先级 浮点 > 整数 > 字符串 * 尽可能转为数字,优先级 浮点 > 整数 > 字符串
*/ */
@ -1181,10 +1190,16 @@ class Translator extends \PhpAot\Core\Translator
$expr = $this->parseIdentifier($node->expr); $expr = $this->parseIdentifier($node->expr);
$leftExprType = $node->var->getType(); $leftExprType = $node->var->getType();
if ($leftExprType === self::EXPR_VARIABLE) { if ($leftExprType === self::EXPR_VARIABLE) {
if (!$this->hasVar($var)) {
$this->fatalError($node->var, 'Cannot assign to undefined variable');
}
$type = $this->detectVarType($node->var); $type = $this->detectVarType($node->var);
$rightExprStr = $this->convertExprType($expr, $type, $this->detectExprType($node->expr)); $rightExprStr = $this->convertExprType($expr, $type, $this->detectExprType($node->expr));
if ($this->isAssignOpConcat($op)) { if ($this->isAssignOpConcat($op)) {
return $var . '.append(' . $rightExprStr . ')'; return $var . '.append(' . $rightExprStr . ')';
} elseif ($this->isAssignOpPow($op)) {
$powExpr = 'php::call(php::pow, {' . $var . ', ' . $rightExprStr . '})';
return $var . ' = ' . $this->convertVarType($var, $powExpr);
} else { } else {
return $var . ' ' . $op . ' ' . $rightExprStr; return $var . ' ' . $op . ' ' . $rightExprStr;
} }
@ -1255,6 +1270,11 @@ class Translator extends \PhpAot\Core\Translator
return $this->parseAssignOp($expr, '&='); return $this->parseAssignOp($expr, '&=');
} }
private function parseAssignOpPow(mixed $expr): string
{
return $this->parseAssignOp($expr, '**=');
}
private function fatalError(Node $node, string $msg): void private function fatalError(Node $node, string $msg): void
{ {
$this->climate->red("Fatal error: $msg in {$this->file}:" . $node->getStartLine()); $this->climate->red("Fatal error: $msg in {$this->file}:" . $node->getStartLine());
@ -2314,4 +2334,9 @@ class Translator extends \PhpAot\Core\Translator
return $code; return $code;
} }
private function parseShellExec(mixed $expr): string
{
return 'php::call("shell_exec", {' . $this->parseInterpolatedString($expr) . '})';
}
} }

@ -0,0 +1,10 @@
--TEST--
strlen
--FILE--
<?php
$a = 2;
$a **= 10;
var_dump($a);
?>
--EXPECT--
int(1024)

@ -0,0 +1,16 @@
--TEST--
Serialization of backtick literal is incorrect
--INI--
zend.assertions=1
--FILE--
<?php
try {
assert(false && `echo -n ""`);
} catch (AssertionError $e) {
echo 'assert(): ', $e->getMessage(), ' failed', PHP_EOL;
}
?>
--EXPECT--
assert(): failed

@ -0,0 +1,26 @@
--TEST--
Serialization of floats are correct
--INI--
--FILE--
<?php
ini_set('zend.assertions', '1');
try {
assert(!is_float(0.0));
} catch (AssertionError $e) {
echo 'assert(): ', $e->getMessage(), ' failed', PHP_EOL;
}
try {
assert(!is_float(1.1));
} catch (AssertionError $e) {
echo 'assert(): ', $e->getMessage(), ' failed', PHP_EOL;
}
try {
assert(!is_float(1234.5678));
} catch (AssertionError $e) {
echo 'assert(): ', $e->getMessage(), ' failed', PHP_EOL;
}
?>
--EXPECT--
assert(): failed
assert(): failed
assert(): failed

@ -0,0 +1,16 @@
--TEST--
ZEND_POW_ASSIGN
--INI--
zend.assertions=1
--FILE--
<?php
try {
$a = 0;
assert(false && ($a **= 2));
} catch (AssertionError $e) {
echo 'assert(): ', $e->getMessage(), ' failed', PHP_EOL;
}
?>
--EXPECT--
assert(): failed
Loading…
Cancel
Save