Closed thekid closed 2 years ago
One option could be to parse grouped use statements into a new node GroupedUseStatement
. This would however be a BC break.
Another idea would be to declare a base
member with the base namespace (everything before the opening curly brace, lang
in the above example) and set this member. Emitters knowing about this member could then fairly easily emit the grouped syntax.
diff --git a/src/main/php/lang/ast/nodes/UseStatement.class.php b/src/main/php/lang/ast/nodes/UseStatement.class.php
index 3d91284..a31e557 100755
--- a/src/main/php/lang/ast/nodes/UseStatement.class.php
+++ b/src/main/php/lang/ast/nodes/UseStatement.class.php
@@ -4,11 +4,12 @@ use lang\ast\Node;
class UseStatement extends Node {
public $kind= 'import';
- public $type, $names;
+ public $type, $names, $base;
- public function __construct($type, $names, $line= -1) {
+ public function __construct($type, $names, $base= null, $line= -1) {
$this->type= $type;
$this->names= $names;
+ $this->base= $base;
$this->line= $line;
}
}
\ No newline at end of file
diff --git a/src/main/php/lang/ast/syntax/PHP.class.php b/src/main/php/lang/ast/syntax/PHP.class.php
index 24a465d..789f479 100755
--- a/src/main/php/lang/ast/syntax/PHP.class.php
+++ b/src/main/php/lang/ast/syntax/PHP.class.php
@@ -545,6 +545,7 @@ class PHP extends Language {
$parse->forward();
if ('{' === $parse->token->value) {
+ $base= $import;
$names= [];
$parse->forward();
while ('}' !== $parse->token->value) {
@@ -572,17 +573,19 @@ class PHP extends Language {
}
$parse->forward();
} else if ('as' === $parse->token->value) {
+ $base= null;
$parse->forward();
$names= [$import => $parse->token->value];
$parse->scope->import($import, $parse->token->value);
$parse->forward();
} else {
+ $base= null;
$names= [$import => null];
$parse->scope->import($import);
}
$parse->expecting(';', 'use');
- return new UseStatement($type, $names, $token->line);
+ return new UseStatement($type, $names, $base, $token->line);
});
$this->stmt('if', function($parse, $token) {
diff --git a/src/test/php/lang/ast/unittest/parse/NamespacesTest.class.php b/src/test/php/lang/ast/unittest/parse/NamespacesTest.class.php
index 37f3d2f..71ec6f1 100755
--- a/src/test/php/lang/ast/unittest/parse/NamespacesTest.class.php
+++ b/src/test/php/lang/ast/unittest/parse/NamespacesTest.class.php
@@ -24,7 +24,7 @@ class NamespacesTest extends ParseTest {
#[Test]
public function use_statement() {
$this->assertParsed(
- [new UseStatement(null, ['lang\ast\Parse' => null], self::LINE)],
+ [new UseStatement(null, ['lang\ast\Parse' => null], null, self::LINE)],
'use lang\\ast\\Parse;'
);
}
@@ -32,7 +32,7 @@ class NamespacesTest extends ParseTest {
#[Test]
public function use_with_alias() {
$this->assertParsed(
- [new UseStatement(null, ['lang\ast\Parse' => 'P'], self::LINE)],
+ [new UseStatement(null, ['lang\ast\Parse' => 'P'], null, self::LINE)],
'use lang\\ast\\Parse as P;'
);
}
@@ -40,7 +40,7 @@ class NamespacesTest extends ParseTest {
#[Test]
public function grouped_use_statement() {
$this->assertParsed(
- [new UseStatement(null, ['lang\\ast\\Parse' => null, 'lang\\ast\\Emitter' => null], self::LINE)],
+ [new UseStatement(null, ['lang\\ast\\Parse' => null, 'lang\\ast\\Emitter' => null], 'lang\\ast\\', self::LINE)],
'use lang\\ast\\{Parse, Emitter};'
);
}
@@ -48,7 +48,7 @@ class NamespacesTest extends ParseTest {
#[Test]
public function grouped_use_with_relative() {
$this->assertParsed(
- [new UseStatement(null, ['lang\\ast\\Parse' => null, 'lang\\ast\\emit\\Result' => null], self::LINE)],
+ [new UseStatement(null, ['lang\\ast\\Parse' => null, 'lang\\ast\\emit\\Result' => null], 'lang\\ast\\', self::LINE)],
'use lang\\ast\\{Parse, emit\\Result};'
);
}
@@ -56,7 +56,7 @@ class NamespacesTest extends ParseTest {
#[Test]
public function grouped_use_with_alias() {
$this->assertParsed(
- [new UseStatement(null, ['lang\\ast\\Parse' => 'P'], self::LINE)],
+ [new UseStatement(null, ['lang\\ast\\Parse' => 'P'], 'lang\\ast\\', self::LINE)],
'use lang\\ast\\{Parse as P};'
);
}
diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index 1c4198e..901cfbb 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -162,8 +162,19 @@ abstract class PHP extends Emitter {
}
protected function emitImport($result, $import) {
- foreach ($import->names as $name => $alias) {
- $result->out->write('use '.$import->type.' '.$name.($alias ? ' as '.$alias : '').';');
+ if ($import->base) {
+ $result->out->write('use '.$import->type.' '.$import->base.'{');
+ $l= strlen($import->base);
+ $i= 0;
+ foreach ($import->names as $name => $alias) {
+ $i++ && $result->out->write(',');
+ $result->out->write(substr($name, $l).($alias ? ' as '.$alias : ''));
+ }
+ $result->out->write('}');
+ } else {
+ foreach ($import->names as $name => $alias) {
+ $result->out->write('use '.$import->type.' '.$name.($alias ? ' as '.$alias : '').';');
+ }
}
}
One option could be to parse grouped use statements into a new node
GroupedUseStatement
. This would however be a BC break.
This might be the cleaner alternative though, we might keep this here for the next major release in this case.
@thekid Hello, are you looking for contributors?
@thekid Hello, are you looking for contributors?
Sure, help is always welcome 👍
Did you have a specific idea in mind what you would like to contribute or are you looking for things to be done? I have a small amount of issues tagged help wanted, and I'm keen on receiving feedback as to what you would want to see in this piece of software!
@thekid Hello, are you looking for contributors?
Sure, help is always welcome 👍
Did you have a specific idea in mind what you would like to contribute or are you looking for things to be done? I have a small amount of issues tagged help wanted, and I'm keen on receiving feedback as to what you would want to see in this piece of software!
Yes and no.
First of all, I'm a library maintainer myself, and keeping backwards comaptible changes is hard. So when I saw your project, I thought to myself: "Hey, if this project kicks, I can develop my library using newest PHP 8.1 features, and still maintain full PHP 7 support.". So I saw areas where I could use your project.
Second thing is, my biggest advantage is being detail-oriented and finding corner-cases, I think that might be useful in this project.
And third, my biggest skill is writing good unit tests, and I think you might Look kindly on it.
I can develop my library using newest PHP 8.1 features, and still maintain full PHP 7 support
Yes, that would be possible! Maybe a word of warning: The generated code is quite ugly, is stripped of any comments and contains some XP Framework-related meta data:
One idea to make this more generically usable would be to make rewriting api doc comments and annotations to meta data optional, e.g. by regarding it an optimization (XP Framework will parse it from the class' sourcecode if not present). This way, your library wouldn't need an additional runtime dependency.
Maybe this would be a good starting point for a joint effort?
Second thing is, my biggest advantage is being detail-oriented and finding corner-cases, I think that might be useful in this project.
While working on the above project together, we would certainly find a lot of these 😉
And third, my biggest skill is writing good unit tests, and I think you might Look kindly on it.
Here's some statistics on coverage - the classes used by the command line tool could need some coverage love:
the classes used by the command line tool could need some coverage love
I've taken care of this on the meantime 😉 - but help on making the compiled code independent of XP core is greatly appreciated, see issue #116
@thekid So what's the idea behind this project?
Did you write some ideas/concepts somewhere, so I can get familiar?
For example, if there are typed properties in PHP 8.0, but not in PHP 7.0, will you just ignore the types? Or will you write some polyfill that would validate the type?
So what's the idea behind this project?
I've written up a document on this @Danon - see here: https://github.com/xp-framework/compiler/wiki/Compiler-design.
Or will you write some polyfill that would validate the type?
I'm open to simulate typed properties with a combination of get and set (but cannot be done for static members, see https://bugs.php.net/bug.php?id=52225) - I think the performance overhead is okay-ish.
The emitted code could be more efficient when using grouped use syntax available since PHP 7.0.
However, the emitting code is much more complex if we try to do this without BC breaks.
Currently, all
use
statements are emitted standalone:The emitted code could be more efficient when using grouped use syntax available since PHP 7.0.