From ca1ee88d5f24c4a317e99c676c78a9d7ee34f43a Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Mon, 12 Jan 2026 14:03:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=20class=20=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E5=88=9D=E6=AD=A5=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/compiler.php | 5 +- bin/gen_stub.php | 18 +- composer.json | 2 +- composer.lock | 724 ++++++++++++++-------- examples/class/MyClass.php | 22 + examples/class/main.php | 6 + examples/class/test.php | 23 +- src/Core/Translator.php | 5 + src/Php/ClassDef.php | 12 +- src/Php/CompilerBase.php | 164 ++--- src/Php/{ConstDef.php => ConstantDef.php} | 2 +- src/Php/MethodDef.php | 16 + src/Php/Preprocessor.php | 20 +- src/Php/Translator.php | 262 +++++++- 14 files changed, 870 insertions(+), 411 deletions(-) create mode 100644 examples/class/MyClass.php create mode 100644 examples/class/main.php rename src/Php/{ConstDef.php => ConstantDef.php} (94%) create mode 100644 src/Php/MethodDef.php diff --git a/bin/compiler.php b/bin/compiler.php index 0c7de429..cb9ae8a1 100755 --- a/bin/compiler.php +++ b/bin/compiler.php @@ -68,8 +68,9 @@ if (empty($sourceFiles)) { $translator->stop("No valid source file found"); } -// 生成所有函数声明 -$translator->genFunctionDeclaration($translator->getBuildDir() . "/include/php_func_decl.h"); +// 生成所有函数声明、全局变量声明 +$translator->genFunctionDeclaration($translator->getIncludeDir() . '/php_func_decl.h'); +$translator->genExternGlobalVars($translator->getIncludeDir() . '/php_global_var_decl.h'); // 生成所有全局变量源文件 $globalVarsSourceFile = $translator->getBuildDir() . '/global_vars.cc'; diff --git a/bin/gen_stub.php b/bin/gen_stub.php index 7d82d25a..4c040623 100644 --- a/bin/gen_stub.php +++ b/bin/gen_stub.php @@ -20,6 +20,10 @@ error_reporting(E_ALL); ini_set("precision", "-1"); require __DIR__ . '/bootstrap.php'; +$translator = new PhpAot\Php\Translator(ROOT_PATH); +$translator->setIndent("\t"); +$translator->setIndentLevel(1); + const PHP_70_VERSION_ID = 70000; const PHP_80_VERSION_ID = 80000; const PHP_81_VERSION_ID = 80100; @@ -80,8 +84,9 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = } if (!$includeOnly) { - $stubFilenameWithoutExtension = str_replace(".stub.php", "", $stubFile); - $arginfoFile = "{$stubFilenameWithoutExtension}_arginfo.h"; + global $translator; + $stubFilenameWithoutExtension = str_replace([".stub.php", '.php'], "", $stubFile); + $arginfoFile = $translator->getArgInfoHeaderFile($stubFilenameWithoutExtension); $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; $stubCode = file_get_contents($stubFile); @@ -2399,7 +2404,10 @@ class EvaluatedValue if ($cExpr == '[]') { $code .= "\tZVAL_EMPTY_ARRAY(&$zvalName);\n"; } else { - throw new Exception("Unimplemented default value"); + global $translator; + $tmpVar = $translator->genTmpVarName(); + $code .= "\tauto $tmpVar = " . $translator->parseExpr($this->expr) . ";\n"; + $code .= "\t{$tmpVar}.moveTo(&$zvalName);\n"; } } else { throw new Exception("Invalid default value: " . print_r($this->value, true) . ", type: " . print_r($this->type, true)); @@ -4192,7 +4200,7 @@ class FileInfo { public array $classInfos = []; public bool $generateFunctionEntries = false; public string $declarationPrefix = ""; - public bool $generateClassEntries = false; + public bool $generateClassEntries = true; private bool $isUndocumentable = false; private bool $legacyArginfoGeneration = false; private ?int $minimumPhpVersionIdCompatibility = null; @@ -4429,7 +4437,7 @@ class FileInfo { } } else if ($classStmt instanceof Stmt\ClassMethod) { if (!($classStmt->flags & Class_::VISIBILITY_MODIFIER_MASK)) { - throw new Exception("Visibility modifier is required"); + $classStmt->flags |= Modifiers::PUBLIC; } $methodInfos[] = parseFunctionLike( $prettyPrinter, diff --git a/composer.json b/composer.json index 85e12dcc..bcb0151d 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require": { - "nikic/php-parser": "^5.0", + "nikic/php-parser": "5.6.1", "league/climate": "^3.10" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 6c34bc43..060156f4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "444c2cea70677ebaa81d75c9b93a9eb7", + "content-hash": "dff0db7b08aac2e595d7436d35f1ac3c", "packages": [ { "name": "league/climate", @@ -74,16 +74,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", "shasum": "" }, "require": { @@ -102,7 +102,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -126,9 +126,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-08-13T20:13:15+00:00" }, { "name": "psr/log", @@ -382,16 +382,16 @@ }, { "name": "composer/semver", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { @@ -443,7 +443,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" + "source": "https://github.com/composer/semver/tree/3.4.4" }, "funding": [ { @@ -453,13 +453,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2025-08-20T19:15:30+00:00" }, { "name": "composer/xdebug-handler", @@ -576,16 +572,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { @@ -595,10 +591,10 @@ "fidry/makefile": "^0.2.0", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, @@ -625,7 +621,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" }, "funding": [ { @@ -633,61 +629,62 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2025-08-14T07:29:31+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.70.2", + "version": "v3.92.5", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "1ca468270efbb75ce0c7566a79cca8ea2888584d" + "reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/1ca468270efbb75ce0c7566a79cca8ea2888584d", - "reference": "1ca468270efbb75ce0c7566a79cca8ea2888584d", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58", + "reference": "260cc8c4a1d2f6d2f22cd4f9c70aa72e55ebac58", "shasum": "" }, "require": { - "clue/ndjson-react": "^1.0", + "clue/ndjson-react": "^1.3", "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.3", + "composer/xdebug-handler": "^3.0.5", "ext-filter": "*", + "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.5", - "react/event-loop": "^1.0", - "react/promise": "^2.0 || ^3.0", - "react/socket": "^1.0", - "react/stream": "^1.0", - "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", - "symfony/console": "^5.4 || ^6.4 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", - "symfony/finder": "^5.4 || ^6.4 || ^7.0", - "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", - "symfony/polyfill-mbstring": "^1.31", - "symfony/polyfill-php80": "^1.31", - "symfony/polyfill-php81": "^1.31", - "symfony/process": "^5.4 || ^6.4 || ^7.2", - "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.5", - "infection/infection": "^0.29.10", - "justinrainbow/json-schema": "^5.3 || ^6.0", - "keradus/cli-executor": "^2.1", + "facile-it/paraunit": "^1.3.1 || ^2.7", + "infection/infection": "^0.31", + "justinrainbow/json-schema": "^6.6", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.7", - "php-cs-fixer/accessible-object": "^1.1", + "php-coveralls/php-coveralls": "^2.9", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.7", - "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.0", - "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.0" + "phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.46", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -702,7 +699,7 @@ "PhpCsFixer\\": "src/" }, "exclude-from-classmap": [ - "src/Fixer/Internal/*" + "src/**/Internal/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -728,7 +725,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.70.2" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.5" }, "funding": [ { @@ -736,20 +733,20 @@ "type": "github" } ], - "time": "2025-03-03T21:07:23+00:00" + "time": "2026-01-08T21:57:37+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -788,7 +785,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -796,7 +793,7 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "phar-io/manifest", @@ -1239,16 +1236,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.45", + "version": "10.5.60", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8" + "reference": "f2e26f52f80ef77832e359205f216eeac00e320c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bd68a781d8e30348bc297449f5234b3458267ae8", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f2e26f52f80ef77832e359205f216eeac00e320c", + "reference": "f2e26f52f80ef77832e359205f216eeac00e320c", "shasum": "" }, "require": { @@ -1258,7 +1255,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", @@ -1269,13 +1266,13 @@ "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.3", + "sebastian/comparator": "^5.0.4", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", + "sebastian/exporter": "^5.1.4", "sebastian/global-state": "^6.0.2", "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", "sebastian/type": "^4.0.0", "sebastian/version": "^4.0.1" }, @@ -1320,7 +1317,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.45" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.60" }, "funding": [ { @@ -1331,12 +1328,20 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2025-02-06T16:08:12+00:00" + "time": "2025-12-06T07:50:42+00:00" }, { "name": "psr/container", @@ -1515,16 +1520,16 @@ }, { "name": "react/child-process", - "version": "v0.6.6", + "version": "v0.6.7", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { @@ -1578,7 +1583,7 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, "funding": [ { @@ -1586,20 +1591,20 @@ "type": "open_collective" } ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2025-12-23T15:25:20+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -1654,7 +1659,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -1662,20 +1667,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -1726,7 +1731,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -1734,27 +1739,27 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", - "version": "v3.2.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpstan/phpstan": "1.12.28 || 1.4.10", "phpunit/phpunit": "^9.6 || ^7.5" }, "type": "library", @@ -1799,7 +1804,7 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v3.3.0" }, "funding": [ { @@ -1807,20 +1812,20 @@ "type": "open_collective" } ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2025-08-19T18:57:03+00:00" }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -1879,7 +1884,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -1887,7 +1892,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -2137,16 +2142,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.3", + "version": "5.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e8e53097718d2b53cfb2aa859b06a41abf58c62e", + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e", "shasum": "" }, "require": { @@ -2202,15 +2207,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2024-10-18T14:56:07+00:00" + "time": "2025-09-07T05:25:07+00:00" }, { "name": "sebastian/complexity", @@ -2403,16 +2420,16 @@ }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", + "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { @@ -2421,7 +2438,7 @@ "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -2469,15 +2486,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2025-09-24T06:09:11+00:00" }, { "name": "sebastian/global-state", @@ -2713,23 +2742,23 @@ }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -2764,15 +2793,28 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2025-08-10T07:50:56+00:00" }, { "name": "sebastian/type", @@ -2885,46 +2927,39 @@ }, { "name": "symfony/console", - "version": "v7.2.1", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" + "reference": "6145b304a5c1ea0bdbd0b04d297a5864f9a7d587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", - "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "url": "https://api.github.com/repos/symfony/console/zipball/6145b304a5c1ea0bdbd0b04d297a5864f9a7d587", + "reference": "6145b304a5c1ea0bdbd0b04d297a5864f9a7d587", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-mbstring": "~1.0", + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "symfony/string": "^7.4|^8.0" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2958,7 +2993,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.1" + "source": "https://github.com/symfony/console/tree/v8.0.3" }, "funding": [ { @@ -2969,25 +3004,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-11T03:49:26+00:00" + "time": "2025-12-23T14:52:06+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -3000,7 +3039,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -3025,7 +3064,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -3041,28 +3080,28 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "573f95783a2ec6e38752979db139f09fec033f03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", + "reference": "573f95783a2ec6e38752979db139f09fec033f03", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -3071,13 +3110,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3105,7 +3145,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.0" }, "funding": [ { @@ -3116,25 +3156,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-10-30T14:17:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -3148,7 +3192,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -3181,7 +3225,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -3197,29 +3241,29 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", - "version": "v7.2.0", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" + "reference": "d937d400b980523dc9ee946bb69972b5e619058d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", - "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", + "reference": "d937d400b980523dc9ee946bb69972b5e619058d", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0" + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3247,7 +3291,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.0" + "source": "https://github.com/symfony/filesystem/tree/v8.0.1" }, "funding": [ { @@ -3258,32 +3302,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-25T15:15:23+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "dd3a2953570a283a2ba4e17063bb98c734cf5b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/dd3a2953570a283a2ba4e17063bb98c734cf5b12", + "reference": "dd3a2953570a283a2ba4e17063bb98c734cf5b12", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3311,7 +3359,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v8.0.3" }, "funding": [ { @@ -3322,29 +3370,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2025-12-23T14:52:06+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -3378,7 +3430,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" }, "funding": [ { @@ -3389,16 +3441,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-11-12T15:55:31+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -3457,7 +3513,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -3468,6 +3524,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3477,16 +3537,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -3535,7 +3595,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -3546,16 +3606,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -3616,7 +3680,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -3627,6 +3691,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3636,19 +3704,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -3696,7 +3765,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -3707,25 +3776,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -3776,7 +3849,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -3787,16 +3860,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -3852,7 +3929,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -3863,6 +3940,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3870,22 +3951,102 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" + }, { "name": "symfony/process", - "version": "v7.2.4", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf" + "reference": "0cbbd88ec836f8757641c651bb995335846abb78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", - "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf", + "url": "https://api.github.com/repos/symfony/process/zipball/0cbbd88ec836f8757641c651bb995335846abb78", + "reference": "0cbbd88ec836f8757641c651bb995335846abb78", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "type": "library", "autoload": { @@ -3913,7 +4074,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.4" + "source": "https://github.com/symfony/process/tree/v8.0.3" }, "funding": [ { @@ -3924,25 +4085,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-02-05T08:33:46+00:00" + "time": "2025-12-19T10:01:18+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3960,7 +4125,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -3996,7 +4161,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -4007,29 +4172,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/stopwatch", - "version": "v7.2.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -4058,7 +4227,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" + "source": "https://github.com/symfony/stopwatch/tree/v8.0.0" }, "funding": [ { @@ -4069,44 +4238,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-02-24T10:49:57+00:00" + "time": "2025-08-04T07:36:47+00:00" }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc", + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4145,7 +4317,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v8.0.1" }, "funding": [ { @@ -4156,25 +4328,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -4203,7 +4379,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -4211,7 +4387,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], diff --git a/examples/class/MyClass.php b/examples/class/MyClass.php new file mode 100644 index 00000000..be697026 --- /dev/null +++ b/examples/class/MyClass.php @@ -0,0 +1,22 @@ +name = $name; + $this->a = $a; + $this->b = $b; + } + + function sum(): int + { + return $this->a + $this->b; + } +} \ No newline at end of file diff --git a/examples/class/main.php b/examples/class/main.php new file mode 100644 index 00000000..37ed55f1 --- /dev/null +++ b/examples/class/main.php @@ -0,0 +1,6 @@ +a = 1; + $this->b = 'hello'; + $this->c = 0; + } + + public function test(int $a, int $b) + { + return $this->a + $this->b + $a + $b; + } +} + diff --git a/src/Core/Translator.php b/src/Core/Translator.php index 99596daa..0ff39ae1 100644 --- a/src/Core/Translator.php +++ b/src/Core/Translator.php @@ -19,6 +19,11 @@ abstract class Translator $this->indentStr = $indent; } + public function setIndentLevel(int $level): void + { + $this->indentLevel = $level; + } + public function getLang(): string { return $this->lang; diff --git a/src/Php/ClassDef.php b/src/Php/ClassDef.php index adcd3f1e..4ba46b50 100644 --- a/src/Php/ClassDef.php +++ b/src/Php/ClassDef.php @@ -5,10 +5,16 @@ namespace PhpAot\Php; class ClassDef { public string $name; - public array $methods; + /** + * @var array< MethodDef> + */ + public array $methods = []; /** * @var array */ - public array $properties; - public array $constants; + public array $properties = []; + /** + * @var array + */ + public array $constants = []; } \ No newline at end of file diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index ffbe853e..27c4c6a3 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -6,6 +6,7 @@ use League\CLImate\CLImate; use PhpAot\Php\Visitor; use PhpParser\Node; use PhpParser\Node\Expr\Variable; +use PhpParser\Node\FunctionLike; use PhpParser\Node\Identifier; use PhpParser\Error; use PhpParser\Node\NullableType; @@ -52,20 +53,20 @@ class CompilerBase extends \PhpAot\Core\Translator 'bool' => self::TYPE_BOOL, ]; - protected array $headers = [ - 'phpx.h', - 'phpx_helper.h', - 'phpx_func.h', - 'php_func_decl.h', - ]; - protected array $reservedNames; protected array $unsupportedFunctions = [ 'compact', 'extract' ]; - + protected array $globalHeaders = [ + 'phpx.h', + 'phpx_helper.h', + 'phpx_func.h', + 'php_func_decl.h', + 'php_global_var_decl.h', + ]; + protected array $localHeaders = []; protected array $nativeFunctions = []; protected array $internalFunctions = []; protected array $nativeConstants = []; @@ -112,6 +113,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected bool $inLoop = false; protected bool $inSwitch = false; protected bool $stubFile = false; + protected bool $stubFileIncluded = false; protected Parser $parser; public function __construct(string $rootPath) @@ -126,45 +128,24 @@ class CompilerBase extends \PhpAot\Core\Translator $this->noLiteralStrings = true; } - public function genIncludeHeaderFiles(): string - { - $lines = []; - foreach ($this->headers as $header) { - $lines[] = '#include <' . $header . '>'; - } - return implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL; - } - - public function genExternGlobalVars(): string - { - $lines[] = PHP_EOL; - foreach ($this->globalVars as $name => $type) { - $lines[] = 'extern ' . self::TYPE_VAR . ' ' . $name . ';'; - } - - $literalStringsCount = count($this->literalStrings); - $lines[] = 'extern php::Var ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL; - return implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL; - } - public function setPhpxDir($dir): void { $this->phpxDir = $dir; } - protected function removeCommonPrefix(string $str1, string $str2): string + protected function removeCommonPrefix(string $short, string $long): string { - $len = min(strlen($str1), strlen($str2)); + $len = min(strlen($short), strlen($long)); $prefixLen = 0; for ($i = 0; $i < $len; $i++) { - if ($str1[$i] === $str2[$i]) { + if ($short[$i] === $long[$i]) { $prefixLen++; } else { break; } } - return substr($str2, $prefixLen); + return substr($long, $prefixLen); } public function save(string $code, string $file): void @@ -211,6 +192,14 @@ class CompilerBase extends \PhpAot\Core\Translator $this->tmpVarIndex = 0; } + protected function resetFile(): void + { + $this->indentLevel = 0; + $this->strictTypes = false; + $this->stubFileIncluded = false; + $this->localHeaders = []; + } + protected function resetNamespace(): void { $this->useNamespaces = []; @@ -221,16 +210,16 @@ class CompilerBase extends \PhpAot\Core\Translator protected function getFunctionName(Node $v): string { $names[] = strtolower($this->parseIdentifier($v->name)); - if ($this->class) { - $names[] = strtolower($this->class); - } if ($this->namespace) { $names[] = $this->escapeNamespace($this->namespace); } + if ($this->class) { + $names[] = $this->escapeClass($this->class); + } return implode(self::NAMESPACE_SEPARATOR, array_reverse($names)); } - protected function parseFunctionDeclaration(string $name, Node $v): FunctionDef + protected function parseFunctionDeclaration(string $name, Node\FunctionLike $v): FunctionDef { $functionDef = new FunctionDef(); $this->functionDef = $functionDef; @@ -248,7 +237,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $functionDef; } - protected function parseFunctionDef(Node $v): string + protected function parseFunction(Node\FunctionLike $v): string { $this->resetScope(); $name = $this->getFunctionName($v); @@ -270,6 +259,10 @@ class CompilerBase extends \PhpAot\Core\Translator } } + if ($this->class) { + $this->arguments['this_'] = self::TYPE_OBJECT; + } + if ($v->stmts) { $this->indentLevel++; $stmts = $this->parseStmts($v->stmts); @@ -278,7 +271,14 @@ class CompilerBase extends \PhpAot\Core\Translator $stmts = ''; } - $functionDeclCode = $this->getReturnType() . ' ' . self::PREFIX . $name . '(' . $this->functionDef->params . ')'; + $functionDeclCode = $this->getReturnType() . ' ' . self::PREFIX . $name . '('; + if ($this->class) { + $functionDeclCode .= self::TYPE_OBJECT . ' &this_'; + if ($this->functionDef->params) { + $functionDeclCode .= ', '; + } + } + $functionDeclCode .= $this->functionDef->params . ')'; $code = $functionDeclCode . ' {' . PHP_EOL; $this->indentLevel++; @@ -460,7 +460,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $code; } - protected function parseExpr(mixed $expr) + public function parseExpr(mixed $expr) { $type = $expr->getType(); $this->writeLog('Line ' . $this->getLine($expr) . ': ' . $type); @@ -987,7 +987,10 @@ class CompilerBase extends \PhpAot\Core\Translator return self::TYPE_FLOAT; case 'bool': return self::TYPE_BOOL; + case 'string': + return self::TYPE_STR; default: + var_dump($name); abort($type); } } @@ -1703,13 +1706,13 @@ class CompilerBase extends \PhpAot\Core\Translator $type2 = $v2->getType(); switch ($type2) { case 'Stmt_Class': - $code .= $this->parseClassDef($v2); + $code .= $this->parseClass($v2); break; case 'Stmt_Const': $this->parseConstDef($v2) . PHP_EOL; break; case 'Stmt_Function': - $code .= $this->parseFunctionDef($v2) . PHP_EOL; + $code .= $this->parseFunction($v2) . PHP_EOL; break; case 'Stmt_Use': $code .= $this->parseUse($v2) . PHP_EOL; @@ -1723,33 +1726,6 @@ class CompilerBase extends \PhpAot\Core\Translator return $code; } - protected function parseClassDef(Node $v): string - { - $this->class = $this->parseIdentifier($v->name); - $this->classDef = new ClassDef(); - $this->classDef->name = $this->class; - $code = 'class ' . $this->class . ' { '; - foreach ($v->stmts as $v) { - $type = $v->getType(); - switch ($type) { - case 'Stmt_ClassConst': - $code .= $this->parseClassConstDef($v); - break; - case 'Stmt_Property': - $this->parsePropertyDef($v); - break; - case 'Stmt_ClassMethod': - $code .= $this->parseFunctionDef($v) . PHP_EOL; - break; - default: - abort($v); - } - } - $code .= '}'; - $this->class = ''; - return $code; - } - protected function parseCastInt(Node $node): string { return $this->convertIntExpr($this->parseExpr($node->expr)); @@ -1833,6 +1809,8 @@ class CompilerBase extends \PhpAot\Core\Translator { if (in_array($name, Constants::CPP_RESERVED_NAMES)) { return '_php__var__' . $name; + } elseif ($name === 'this') { + return 'this_'; } else { return $name; } @@ -1843,6 +1821,11 @@ class CompilerBase extends \PhpAot\Core\Translator return str_replace('\\', self::NAMESPACE_SEPARATOR, strtolower($ns)); } + protected function escapeClass(string $class): string + { + return $class; + } + protected function unescapeVarName(string $name): string { return str_replace('_php__var__', '', $name); @@ -2022,7 +2005,7 @@ class CompilerBase extends \PhpAot\Core\Translator shell_exec($cmd); } - protected function genTmpVarName(): string + public function genTmpVarName(): string { return 'tmp_var_' . $this->tmpVarIndex++; } @@ -2182,18 +2165,6 @@ class CompilerBase extends \PhpAot\Core\Translator return array_key_exists($name, $this->globalVars); } - protected function genFunction(string $name, string $returnType, array $args = [], array $lines = []): string - { - $_args = []; - foreach ($args as $arg => $type) { - $_args[] = $type . ' ' . $arg; - } - $code = $returnType . ' ' . $name . '(' . implode(', ', $_args) . ') {' . PHP_EOL; - $code .= implode(PHP_EOL, $lines) . PHP_EOL; - $code .= '}' . PHP_EOL; - return $code; - } - protected function parseCastDouble(mixed $expr): string { return $this->convertFloatExpr($this->parseIdentifier($expr->expr)); @@ -2499,6 +2470,11 @@ class CompilerBase extends \PhpAot\Core\Translator } } + public function getIncludeDir(): string + { + return $this->getBuildDir() . '/include'; + } + public function getBuildDir(): string { return $this->buildDir; @@ -2552,28 +2528,4 @@ class CompilerBase extends \PhpAot\Core\Translator } abort($expr); } - - protected function parsePropertyDef(Node\Stmt\Property $v): void - { - $flags = $v->flags; - $type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR; - - foreach ($v->props as $prop) { - $propInfo = new PropertyDef($this->parseIdentifier($prop->name), $flags, $type); - if ($prop->default) { - $this->parseIdentifier($prop->default); - } - $this->classDef->properties[] = $propInfo; - } - } - - protected function parseClassConstDef(Node\Stmt\ClassConst $v): void - { - $flags = $v->flags; - $type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR; - foreach ($v->consts as $const) { - $constInfo = new ConstDef($this->parseIdentifier($const->name), $flags, $type, $this->parseIdentifier($const->value)); - $this->classDef->constants[] = $constInfo; - } - } } diff --git a/src/Php/ConstDef.php b/src/Php/ConstantDef.php similarity index 94% rename from src/Php/ConstDef.php rename to src/Php/ConstantDef.php index a634dc9f..6eba9732 100644 --- a/src/Php/ConstDef.php +++ b/src/Php/ConstantDef.php @@ -2,7 +2,7 @@ namespace PhpAot\Php; -class ConstDef +class ConstantDef { public string $name; public string $type; diff --git a/src/Php/MethodDef.php b/src/Php/MethodDef.php new file mode 100644 index 00000000..38b0ed0c --- /dev/null +++ b/src/Php/MethodDef.php @@ -0,0 +1,16 @@ +name = $name; + $this->flags = $flags; + } +} \ No newline at end of file diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 0441e764..f958b8f9 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -44,10 +44,10 @@ class Preprocessor extends CompilerBase $this->prepareNamespaceDef($v); break; case 'Stmt_Class': - $this->prepareClassDef($v); + $this->prepareClass($v); break; case 'Stmt_Function': - $this->prepareFunctionDef($v) . PHP_EOL; + $this->prepareFunction($v) . PHP_EOL; break; case 'Stmt_Declare': case 'Stmt_Use': @@ -74,7 +74,7 @@ class Preprocessor extends CompilerBase } } - protected function prepareFunctionDef(Node $v): void + protected function prepareFunction(Node $v): void { $name = $this->getFunctionName($v); if ($this->stubFile) { @@ -84,7 +84,7 @@ class Preprocessor extends CompilerBase } } - protected function prepareNamespaceDef(Node $node): void + protected function prepareNamespaceDef(Node\Stmt\Namespace_ $node): void { $this->resetNamespace(); $this->namespace = $this->escapeNamespace($this->parseIdentifier($node->name)); @@ -92,10 +92,10 @@ class Preprocessor extends CompilerBase $type2 = $v2->getType(); switch ($type2) { case 'Stmt_Class': - $this->prepareClassDef($v2); + $this->prepareClass($v2); break; case 'Stmt_Function': - $this->prepareFunctionDef($v2) . PHP_EOL; + $this->prepareFunction($v2) . PHP_EOL; break; case 'Stmt_Use': case 'Stmt_Const': @@ -107,18 +107,18 @@ class Preprocessor extends CompilerBase $this->resetNamespace(); } - protected function prepareClassDef(Node $v): string + protected function prepareClass(Node\Stmt\Class_ $class): string { - $this->class = $this->parseIdentifier($v->name); + $this->class = $this->parseIdentifier($class->name); $code = ''; - foreach ($v->stmts as $v) { + foreach ($class->stmts as $v) { $type = $v->getType(); switch ($type) { case 'Stmt_ClassConst': case 'Stmt_Property': break; case 'Stmt_ClassMethod': - $code .= $this->prepareFunctionDef($v) . PHP_EOL; + $code .= $this->prepareFunction($v) . PHP_EOL; break; default: abort($v); diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 0922cfd8..837b0354 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -2,6 +2,8 @@ namespace PhpAot\Php; +use PhpParser\Modifiers; +use PhpParser\Node; use PhpParser\NodeTraverser; class Translator extends Preprocessor @@ -112,8 +114,7 @@ class Translator extends Preprocessor $stmts = $traverser->traverse($ast); - $this->indentLevel = 0; - $this->strictTypes = false; + $this->resetFile(); $this->resetNamespace(); $cppCode = ''; @@ -127,13 +128,13 @@ class Translator extends Preprocessor $cppCode .= $this->parseNamespaceDef($v); break; case 'Stmt_Class': - $cppCode .= $this->parseClassDef($v); + $cppCode .= $this->parseClass($v); break; case 'Stmt_Use': $cppCode .= $this->parseUse($v) . PHP_EOL; break; case 'Stmt_Function': - $cppCode .= $this->parseFunctionDef($v) . PHP_EOL; + $cppCode .= $this->parseFunction($v) . PHP_EOL; break; case 'Stmt_Const': $this->parseConstDef($v) . PHP_EOL; @@ -143,7 +144,7 @@ class Translator extends Preprocessor } } // include + extern global vars + function impl - return $this->genIncludeHeaderFiles() . $this->genExternGlobalVars() . $cppCode; + return $this->genIncludeHeaderFiles() . $cppCode; } public function preprocessArgvAdvanced(): void @@ -170,6 +171,20 @@ class Translator extends Preprocessor $argv = $processed; } + public function genExternGlobalVars(string $file): void + { + $lines[] = '#include '; + $lines[] = PHP_EOL; + foreach ($this->globalVars as $name => $type) { + $lines[] = 'extern ' . self::TYPE_VAR . ' ' . $name . ';'; + } + + $literalStringsCount = count($this->literalStrings); + $lines[] = 'extern php::Var ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL; + $code = implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL; + $this->writeFile($file, $code); + } + public function genGlobalVars(string $file): void { $code = $this->genIncludeHeaderFiles(); @@ -260,7 +275,7 @@ class Translator extends Preprocessor public function genFunctionDeclaration(string $file): void { - $code = ''; + $code = '#include ' . PHP_EOL; /** * @var FunctionDef $func */ @@ -288,4 +303,239 @@ class Translator extends Preprocessor $this->writeFile($file, $code); } + + protected function getMethodName(Node\Stmt\ClassMethod $v): string + { + return strtolower($this->parseIdentifier($v->name)); + } + + protected function parseClass(Node\Stmt\Class_ $class): string + { + $this->class = $this->parseIdentifier($class->name); + if (!$this->stubFileIncluded) { + shell_exec('php ' . $this->rootPath . '/bin/gen_stub.php -f' . $this->file); + $stubFilenameWithoutExtension = str_replace([".stub.php", '.php'], "", $this->file); + $this->localHeaders[] = $this->getArgInfoHeaderFile($stubFilenameWithoutExtension, true); + $this->stubFileIncluded = true; + } + $this->classDef = new ClassDef(); + $this->classDef->name = $this->class; + $methodCodes = []; + + foreach ($class->stmts as $v) { + $type = $v->getType(); + switch ($type) { + case 'Stmt_ClassConst': + $this->parseClassConstDef($v); + break; + case 'Stmt_Property': + $this->parsePropertyDef($v); + break; + case 'Stmt_ClassMethod': + $this->parseClassMethod($v, $methodCodes); + break; + default: + abort($v); + } + } + $code = $this->genZendClass($methodCodes); + $this->class = ''; + return $code; + } + + public function getArgInfoHeaderFile(string $stubFilenameWithoutExtension, bool $relative = false): string + { + $basename = basename($stubFilenameWithoutExtension); + $absPath = $this->getIncludeDir() . "/{$basename}_arginfo.h"; + if ($relative) { + return ltrim($this->removeCommonPrefix($this->getIncludeDir(), $absPath), '/'); + } else { + return $absPath; + } + } + + protected function genZendClass($methodCodes): string + { + $code = ''; + $classDef = $this->classDef; + foreach ($classDef->methods as $method) { + $code .= $methodCodes[$method->name] . PHP_EOL; + } + return $code; + } + + private function genClassNative(): string + { + $code = 'class ' . $this->class . ' { '; + + $publicMethods = []; + $protectedMethods = []; + $privateMethods = []; + $publicConstants = []; + $protectedConstants = []; + $privateConstants = []; + $publicProperties = []; + $protectedProperties = []; + $privateProperties = []; + + foreach ($this->classDef->constants as $const) { + if ($const->flags & Modifiers::PUBLIC) { + $publicConstants[] = $const; + } + if ($const->flags & Modifiers::PROTECTED) { + $protectedConstants[] = $const; + } + if ($const->flags & Modifiers::PRIVATE) { + $privateConstants[] = $const; + } + } + foreach ($this->classDef->methods as $method) { + if ($method->flags & Modifiers::PUBLIC) { + $publicMethods[] = $method; + } + if ($method->flags & Modifiers::PROTECTED) { + $protectedMethods[] = $method; + } + if ($method->flags & Modifiers::PRIVATE) { + $privateMethods[] = $method; + } + } + foreach ($this->classDef->properties as $property) { + if ($property->flags & Modifiers::PUBLIC) { + $publicProperties[] = $property; + } + if ($property->flags & Modifiers::PROTECTED) { + $protectedProperties[] = $property; + } + if ($property->flags & Modifiers::PRIVATE) { + $privateProperties[] = $property; + } + } + + if ($privateConstants) { + $code .= 'private:' . PHP_EOL; + $code .= $this->genClassConstantList($privateConstants); + } + + if ($protectedConstants) { + $code .= 'protected:' . PHP_EOL; + $code .= $this->genClassConstantList($protectedConstants); + } + + if ($publicConstants) { + $code .= 'public:' . PHP_EOL; + $code .= $this->genClassConstantList($publicConstants); + } + + if ($privateProperties) { + $code .= 'private:' . PHP_EOL; + $code .= $this->genClassPropertyList($privateProperties); + } + + if ($protectedProperties) { + $code .= 'protected:' . PHP_EOL; + $code .= $this->genClassPropertyList($protectedProperties); + } + + if ($publicProperties) { + $code .= 'public:' . PHP_EOL; + $code .= $this->genClassPropertyList($publicProperties); + } + + $code .= '};' . PHP_EOL . PHP_EOL; + return $code; + } + + public function genIncludeHeaderFiles(): string + { + $headers = array_merge($this->globalHeaders, $this->localHeaders); + $lines = []; + foreach ($headers as $header) { + $lines[] = '#include <' . $header . '>'; + } + return implode(PHP_EOL, $lines) . PHP_EOL . PHP_EOL; + } + + /** + * @param array $list + */ + protected function genClassConstantList(array $list): string + { + $code = ''; + foreach ($list as $const) { + $code .= $this->getIndent() . $this->genClassConstant($const); + } + return $code; + } + + protected function genClassConstant(ConstantDef $const): string + { + return 'static const ' . $const->type . ' ' . $const->name . ';' . PHP_EOL; + } + + /** + * @param array $list + */ + protected function genClassPropertyList(array $list): string + { + $code = ''; + foreach ($list as $prop) { + $code .= $this->getIndent() . $this->genClassProperty($prop); + } + return $code; + } + + protected function genClassProperty(PropertyDef $prop): string + { + $code = $prop->type . ' ' . $prop->name; + if ($prop->default) { + $code .= ' = ' . $prop->default; + } + return $code . ';' . PHP_EOL; + } + + protected function genFunction(string $name, string $returnType, array $args = [], array $lines = []): string + { + $_args = []; + foreach ($args as $arg => $type) { + $_args[] = $type . ' ' . $arg; + } + $code = $returnType . ' ' . $name . '(' . implode(', ', $_args) . ') {' . PHP_EOL; + $code .= implode(PHP_EOL, $lines) . PHP_EOL; + $code .= '}' . PHP_EOL; + return $code; + } + + protected function parseClassConstDef(Node\Stmt\ClassConst $v): void + { + $flags = $v->flags; + $type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR; + foreach ($v->consts as $const) { + $constInfo = new ConstantDef($this->parseIdentifier($const->name), $flags, $type, $this->parseIdentifier($const->value)); + $this->classDef->constants[] = $constInfo; + } + } + + protected function parsePropertyDef(Node\Stmt\Property $v): void + { + $flags = $v->flags; + $type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR; + + foreach ($v->props as $prop) { + $propDef = new PropertyDef($this->parseIdentifier($prop->name), $flags, $type); + if ($prop->default) { + $propDef->default = $this->parseIdentifier($prop->default); + } + $this->classDef->properties[] = $propDef; + } + } + + private function parseClassMethod(Node\Stmt\ClassMethod $v, array &$methodCodes): void + { + $name = $this->getMethodName($v); + $flags = $v->flags; + $methodDef = new MethodDef($name, $flags); + $this->classDef->methods[] = $methodDef; + $methodCodes[$name] = $this->parseFunction($v); + } } \ No newline at end of file