update mixed

pull/1/head
韩天峰 7 months ago
parent bdea6f77cc
commit f8100988c4
  1. 19
      examples/class/test.php
  2. 11
      src/Php/ClassDef.php
  3. 23
      src/Php/ClassLikeDef.php
  4. 7
      src/Php/CompilerBase.php
  5. 7
      src/Php/InterfaceDef.php
  6. 1
      src/Php/Preprocessor.php
  7. 53
      src/Php/Translator.php
  8. 18
      src/template/extension.cc.php
  9. 19
      tests/aot/for.phpt
  10. 19
      tests/aot/foreach.phpt
  11. 58
      tests/core/classes/inheritance.phpt

@ -1,5 +1,16 @@
<?php
class Test2 extends Test
{
function fun(string $name)
{
var_dump(__CLASS__);
var_dump($name);
}
}
class Test
{
private $a;
@ -26,11 +37,3 @@ class Test
}
}
class Test2 extends Test{
function fun(string $name)
{
var_dump(__CLASS__);
var_dump($name);
}
}

@ -2,9 +2,8 @@
namespace PhpAot\Php;
class ClassDef
class ClassDef extends ClassLikeDef
{
public string $name;
/**
* @var array<string, MethodDef>
*/
@ -17,15 +16,11 @@ class ClassDef
* @var array<string, ConstantDef>
*/
public array $constants = [];
public string $namespace = '';
public array $implements = [];
public string $extends = '';
public function getNamespacedName(): string
public function __construct(string $name, string $namespace = '')
{
if ($this->namespace === '') {
return $this->name;
}
return str_replace('\\', '_', $this->namespace . '_' . $this->name);
parent::__construct($name, $namespace);
}
}

@ -0,0 +1,23 @@
<?php
namespace PhpAot\Php;
class ClassLikeDef
{
public string $name;
public string $namespace = '';
public function __construct(string $name, string $namespace = '')
{
$this->name = $name;
$this->namespace = $namespace;
}
public function getNamespacedName(): string
{
if ($this->namespace === '') {
return $this->name;
}
return str_replace('\\', '_', $this->namespace . '_' . $this->name);
}
}

@ -86,6 +86,7 @@ class CompilerBase extends \PhpAot\Core\Translator
* @var array<string, ClassDef>
*/
protected array $classes = [];
protected array $interfaces = [];
/**
* @var array<string, ClassDef>
*/
@ -1096,7 +1097,11 @@ class CompilerBase extends \PhpAot\Core\Translator
$left = $expr->var;
$name = $this->parseIdentifier($left);
$type = $this->detectExprType($expr->expr);
$code .= $type . ' ' . $name . ' = ' . '(' . $this->parseIdentifier($expr->expr) . ');';
// for 循环的变量声明,必须在循环体之外,不能创建 scope tmp var
if ($this->hasVar($name)) {
$this->addLocalVar($name, $type);
}
$code .= $name . ' = ' . '(' . $this->parseIdentifier($expr->expr) . ');';
}
$list_cond[] = $this->parseExpr($expr);
}

@ -0,0 +1,7 @@
<?php
namespace PhpAot\Php;
class InterfaceDef extends ClassLikeDef
{
}

@ -106,6 +106,7 @@ class Preprocessor extends CompilerBase
case 'Stmt_Declare':
case 'Stmt_Use':
case 'Stmt_Const':
case 'Stmt_Interface':
break;
default:
$this->fatalError($v, 'Unsupported statement: ' . $type);

@ -131,7 +131,28 @@ class Translator extends Preprocessor
return self::PREFIX . 'register_class_' . $name;
}
protected function getClassCe(ClassDef $classDef): string
protected function getRegisterClassFunctionCeList(ClassDef $classDef): array
{
$list = [];
$parentCe = $this->getParentClassCe($classDef);
$implements = $this->getImplementCe($classDef);
if ($parentCe) {
$list = [$parentCe];
}
return array_merge($list, $implements);
}
public function getRegisterClassFunctionArgs(ClassDef $classDef): string
{
return implode(', ', $this->getRegisterClassFunctionCeList($classDef));
}
private function getRegisterClassFunctionArgDef(ClassDef $classDef): string
{
return 'zend_class_entry *' . implode(', zend_class_entry *', $this->getRegisterClassFunctionCeList($classDef));
}
protected function getClassCe(ClassLikeDef $classDef): string
{
return self::PREFIX . 'class_entry_' . $classDef->getNamespacedName();
}
@ -144,6 +165,11 @@ class Translator extends Preprocessor
return self::PREFIX . 'class_entry_' . $classDef->extends;
}
private function getImplementCe(ClassLikeDef $classDef): array
{
return array_map(fn($v) => self::PREFIX . 'class_entry_' . $v, $classDef->implements);
}
protected function doConvert(string $phpCode): string
{
$this->climate->info('convert: ' . $this->file);
@ -179,6 +205,9 @@ class Translator extends Preprocessor
case 'Stmt_Const':
$this->parseConstDef($v) . PHP_EOL;
break;
case 'Stmt_Interface':
$this->parseInterface($v) . PHP_EOL;
break;
default:
abort($v);
}
@ -389,13 +418,11 @@ class Translator extends Preprocessor
$this->genClassStubFile($class, $this->file);
}
$this->classDef = new ClassDef();
$this->classDef->name = $this->class;
$this->classDef = new ClassDef($this->class, $this->namespace);
if ($class->extends) {
$this->classDef->extends = $this->parseIdentifier($class->extends);
}
$this->classDef->implements = $this->parseIdentifierList($class->implements);
$this->classDef->namespace = $this->namespace;
$this->classes[$this->class] = $this->classDef;
$this->classesDefineInFile[$this->class] = $this->classDef;
@ -475,15 +502,9 @@ class Translator extends Preprocessor
{
$cppCode = '';
$name = $classDef->getNamespacedName();
if ($classDef->extends) {
$parentName = 'zend_class_entry *parent_ce';
$param = 'parent_ce';
} else {
$parentName = '';
$param = '';
}
$cppCode .= 'zend_class_entry *' . $this->getRegisterClassFunction($name) . '(' . $parentName . ') {' . PHP_EOL;
$argsDef = $this->getRegisterClassFunctionArgDef($classDef);
$param = $this->getRegisterClassFunctionArgs($classDef);
$cppCode .= 'zend_class_entry *' . $this->getRegisterClassFunction($name) . '(' . $argsDef . ') {' . PHP_EOL;
$cppCode .= $this->getIndent() . 'return register_class_' . $name . '(' . $param . ');' . PHP_EOL;
$cppCode .= '}' . PHP_EOL . PHP_EOL;
@ -683,4 +704,10 @@ class Translator extends Preprocessor
}
return $list;
}
private function parseInterface(Node $v): void
{
$name = $this->parseIdentifier($v->name);
$this->interfaces[$name] = new InterfaceDef($name, $this->namespace);
}
}

@ -25,9 +25,9 @@ zend_class_entry * <?= $this->getClassCe($classDef) ?>;
<?php
foreach ($this->classes as $classDef):
$name = $classDef->getNamespacedName();
$parentCe = $classDef->extends ? 'zend_class_entry *parent_ce' : '';
$argDef = $this->getRegisterClassFunctionArgDef($classDef);
?>
extern zend_class_entry *<?= $this->getRegisterClassFunction($name) ?>(<?= $parentCe ?>);
extern zend_class_entry *<?= $this->getRegisterClassFunction($name) ?>(<?= $argDef ?>);
<?php endforeach; ?>
// literal strings
@ -59,13 +59,23 @@ static const zend_function_entry ext_functions[] = {
};
static PHP_MINIT_FUNCTION(app) {
// class
<?php
foreach ($this->classes as $classDef):
$name = $classDef->getNamespacedName();
$parentCe = $this->getParentClassCe($classDef);
$params = $this->getRegisterClassFunctionArgs($classDef);
$fn = $this->getRegisterClassFunction($name);
?>
<?=$this->getClassCe($classDef)?> = <?= $fn ?>(<?= $parentCe ?>);
<?=$this->getClassCe($classDef)?> = <?= $fn ?>(<?= $params ?>);
<?php endforeach; ?>
<?php
foreach ($this->interfaces as $interfaceDef):
$name = $interfaceDef->name;
$fn = $this->getRegisterClassFunction($name);
?>
<?=$this->getClassCe($interfaceDef)?> = <?= $fn ?>();
<?php endforeach; ?>
return SUCCESS;

@ -0,0 +1,19 @@
--TEST--
for statement
--FILE--
<?php
function main()
{
$i = 100;
$arr = [];
for($i = 0; $i < 100; $i++) {
$arr[] = $i;
}
var_dump(count($arr));
echo $arr[49];
echo "\n";
}
?>
--EXPECT--
int(100)
49

@ -0,0 +1,19 @@
--TEST--
foreach statement
--FILE--
<?php
function main()
{
$v = 199;
$arr = range(0, 99);
$c = 0;
foreach ($arr as $v) {
$c += $v;
}
var_dump($c);
var_dump($v);
}
?>
--EXPECT--
int(4950)
int(199)

@ -0,0 +1,58 @@
--TEST--
Classes inheritance test
--FILE--
<?php
/* Inheritance test. Pretty nifty if I do say so myself! */
class foo {
public $a;
public $b;
function display() {
echo "This is class foo\n";
echo "a = ".$this->a."\n";
echo "b = ".$this->b."\n";
}
function mul() {
return $this->a*$this->b;
}
};
class bar extends foo {
public $c;
function display() { /* alternative display function for class bar */
echo "This is class bar\n";
echo "a = ".$this->a."\n";
echo "b = ".$this->b."\n";
echo "c = ".$this->c."\n";
}
};
function main() {
$foo1 = new foo;
$foo1->a = 2;
$foo1->b = 5;
$foo1->display();
echo $foo1->mul()."\n";
echo "-----\n";
$bar1 = new bar;
$bar1->a = 4;
$bar1->b = 3;
$bar1->c = 12;
$bar1->display();
echo $bar1->mul()."\n";
}
?>
--EXPECT--
This is class foo
a = 2
b = 5
10
-----
This is class bar
a = 4
b = 3
c = 12
12
Loading…
Cancel
Save