From a6cefef02c53098e34935956cccf5f330615b816 Mon Sep 17 00:00:00 2001 From: Fenikkusu Date: Wed, 28 May 2025 21:26:04 -0400 Subject: [PATCH] Adding BlockManager To Allow Addition of CBlocks Via Expressions --- CHANGELOG.md | 2 ++ src/BlockManager.php | 55 +++++++++++++++++++++++++++++++ src/CompilationContext.php | 4 +++ src/CompilerFile.php | 12 +++++-- src/CompilerFileAnonymous.php | 9 ++++- src/Traits/CompilerTrait.php | 7 ++-- tests/Zephir/BlockManagerTest.php | 39 ++++++++++++++++++++++ 7 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 src/BlockManager.php create mode 100644 tests/Zephir/BlockManagerTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index e92cd2eea..45740a723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format based on [Keep a Changelog](https://keepachangelog.com) and this project adheres to [Semantic Versioning](https://semver.org). ## [Unreleased] +- Added Block Manager to Allow Modification of C-Headers Via Advanced Components of Zephir + ## [0.19.0] - 2025-05-13 ### Added diff --git a/src/BlockManager.php b/src/BlockManager.php new file mode 100644 index 000000000..32b88f88b --- /dev/null +++ b/src/BlockManager.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Zephir; + +use InvalidArgumentException; + +use function array_merge; + +/** + * Manages the c-headers that must be added to a file + */ +class BlockManager +{ + /** + * List of headers. + */ + protected array $blocks = []; + + /** + * Adds a header path to the manager. + * + * @throws InvalidArgumentException + */ + #[SuppressWarnings("php:S4790")] + public function add(string $block): BlockManager + { + $this->blocks[md5($block)] = $block; + + return $this; + } + + /** + * Returns a set of headers merged. + */ + public function get(): array + { + return $this->blocks; + } + + public function isEmpty(): bool + { + return empty($this->blocks); + } +} diff --git a/src/CompilationContext.php b/src/CompilationContext.php index 5247a8f6b..5011b6c6d 100644 --- a/src/CompilationContext.php +++ b/src/CompilationContext.php @@ -74,6 +74,10 @@ class CompilationContext * Global consecutive for try/catch blocks. */ public int $currentTryCatch = 0; + /** + * Represents the c-blocks added to the file. + */ + public ?BlockManager $blockManager = null; /** * Current cycle/loop block. */ diff --git a/src/CompilerFile.php b/src/CompilerFile.php index 22f371d87..8730579f1 100644 --- a/src/CompilerFile.php +++ b/src/CompilerFile.php @@ -79,8 +79,7 @@ final class CompilerFile implements FileInterface private array $functionDefinitions = []; - private array $headerCBlocks = []; - + private BlockManager $headerCBlocks; /** * Original internal representation (IR) of the file. */ @@ -101,6 +100,8 @@ public function __construct( $this->logger = new NullLogger(); $this->aliasManager = $aliasManager; $this->filesystem = $filesystem; + + $this->headerCBlocks = new BlockManager(); } /** @@ -275,6 +276,11 @@ public function compile(Compiler $compiler, StringsManager $stringsManager): voi */ $compilationContext->headersManager = new HeadersManager(); + /** + * C-Block manager. + */ + $compilationContext->blockManager = $this->headerCBlocks; + /** * Main code-printer for the file. */ @@ -522,7 +528,7 @@ public function preCompile(Compiler $compiler): void break; case 'cblock': - $this->headerCBlocks[] = $topStatement['value']; + $this->headerCBlocks->add($topStatement['value']); break; case 'function': diff --git a/src/CompilerFileAnonymous.php b/src/CompilerFileAnonymous.php index 1bf10427d..1b2f400c3 100644 --- a/src/CompilerFileAnonymous.php +++ b/src/CompilerFileAnonymous.php @@ -39,7 +39,7 @@ final class CompilerFileAnonymous implements FileInterface protected ?string $compiledFile = null; protected bool $external = false; - protected array $headerCBlocks = []; + protected BlockManager $headerCBlocks; protected ?string $namespace = null; /** @@ -55,6 +55,8 @@ public function __construct( protected ?CompilationContext $context = null ) { $this->logger = new NullLogger(); + + $this->headerCBlocks = new BlockManager(); } /** @@ -81,6 +83,11 @@ public function compile(Compiler $compiler, StringsManager $stringsManager): voi $compilationContext->backend = $compiler->backend; $compilationContext->headersManager = new HeadersManager(); + /** + * C-Block manager. + */ + $compilationContext->blockManager = $this->headerCBlocks; + /** * Main code-printer for the file. */ diff --git a/src/Traits/CompilerTrait.php b/src/Traits/CompilerTrait.php index 34a412792..aa885013d 100644 --- a/src/Traits/CompilerTrait.php +++ b/src/Traits/CompilerTrait.php @@ -62,8 +62,11 @@ protected function generateClassHeadersPost( } } - if (count($this->headerCBlocks) > 0) { - $code .= implode(PHP_EOL, $this->headerCBlocks) . PHP_EOL; + $code .= PHP_EOL; + + if (!$this->headerCBlocks->isEmpty()) { + $code .= implode(PHP_EOL, $this->headerCBlocks->get()) . PHP_EOL; + $code .= PHP_EOL; } /** diff --git a/tests/Zephir/BlockManagerTest.php b/tests/Zephir/BlockManagerTest.php new file mode 100644 index 000000000..355b0ef18 --- /dev/null +++ b/tests/Zephir/BlockManagerTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Zephir\Test; + +use PHPUnit\Framework\TestCase; +use Zephir\BlockManager; + +final class BlockManagerTest extends TestCase +{ + public function testBasics(): void + { + $testSubject = new BlockManager(); + + $testSubject->add('test1'); + $testSubject->add('test2'); + $testSubject->add('test1'); + + $this->assertFalse($testSubject->isEmpty()); + + $this->assertEquals( + [ + '5a105e8b9d40e1329780d62ea2265d8a' => 'test1', + 'ad0234829205b9033196ba818f7a872b' => 'test2', + ], + $testSubject->get(), + ); + } +}