Skip to content

Instantly share code, notes, and snippets.

@thekid
Created May 18, 2023 15:21
Show Gist options
  • Save thekid/d83bac22f30e3d3e41425bb703ab1d0b to your computer and use it in GitHub Desktop.
Save thekid/d83bac22f30e3d3e41425bb703ab1d0b to your computer and use it in GitHub Desktop.
Alternative to parent::$x::get()
diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index b15f8bb..e85c8ba 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -436,7 +436,7 @@ abstract class PHP extends Emitter {
// Virtual properties support: __virtual member + __get() and __set()
if ($context->virtual) {
- $result->out->write('private $__virtual= [');
+ $result->out->write('protected $__virtual= [');
foreach ($context->virtual as $name => $access) {
$name && $result->out->write("'{$name}' => null,");
}
diff --git a/src/main/php/lang/ast/emit/PropertyHooks.class.php b/src/main/php/lang/ast/emit/PropertyHooks.class.php
index 391ba59..bc9fc51 100755
--- a/src/main/php/lang/ast/emit/PropertyHooks.class.php
+++ b/src/main/php/lang/ast/emit/PropertyHooks.class.php
@@ -29,28 +29,29 @@ trait PropertyHooks {
// Magic constant referencing property name
if ($node instanceof Literal && '__PROPERTY__' === $node->expression) return $literal;
- // Special variable $field, $this->propertyName syntax
- if ($node instanceof Variable && 'field' === $node->pointer || (
+ // Special variable $field syntax
+ if ($node instanceof Variable && 'field' === $node->pointer) return $virtual;
+
+ // $this->propertyName for accessing parent's getter
+ if (
$node instanceof InstanceExpression &&
$node->expression instanceof Variable && 'this' === $node->expression->pointer &&
$node->member instanceof Literal && $name === $node->member->expression
- )) return $virtual;
+ ) return new ScopeExpression('parent', new InvokeExpression(
+ new Literal('__get_'.$name),
+ []
+ ));
- // <T>::$field::hook() => <T>::__<hook>_<field>()
+ // $this->propertyName= ... for accessing parent's setter
if (
- $node instanceof ScopeExpression &&
- $node->member instanceof InvokeExpression &&
- $node->member->expression instanceof Literal &&
- $node->type instanceof ScopeExpression &&
- $node->type->member instanceof Variable &&
- is_string($node->type->type) &&
- is_string($node->type->member->pointer)
- ) {
- return new ScopeExpression($node->type->type, new InvokeExpression(
- new Literal('__'.$node->member->expression->expression.'_'.$node->type->member->pointer),
- $node->member->arguments
- ));
- }
+ $node instanceof Assignment &&
+ $node->variable instanceof InstanceExpression &&
+ $node->variable->expression instanceof Variable && 'this' === $node->variable->expression->pointer &&
+ $node->variable->member instanceof Literal && $name === $node->variable->member->expression
+ ) return new ScopeExpression('parent', new InvokeExpression(
+ new Literal('__set_'.$name),
+ [$node->expression]
+ ));
foreach ($node->children() as &$child) {
$child= $this->rewriteHook($child, $name, $virtual, $literal);
diff --git a/src/test/php/lang/ast/unittest/emit/PropertyHooksTest.class.php b/src/test/php/lang/ast/unittest/emit/PropertyHooksTest.class.php
index a4dcaf7..3e146e9 100755
--- a/src/test/php/lang/ast/unittest/emit/PropertyHooksTest.class.php
+++ b/src/test/php/lang/ast/unittest/emit/PropertyHooksTest.class.php
@@ -108,23 +108,6 @@ class PropertyHooksTest extends EmittingTest {
Assert::equals('Test', $r);
}
- #[Test]
- public function get_and_set_using_property() {
- $r= $this->run('class <T> {
- public $test {
- get => $this->test;
- set => $this->test= ucfirst($value);
- }
-
- public function run() {
- $this->test= "test";
- return $this->test;
- }
- }');
-
- Assert::equals('Test', $r);
- }
-
#[Test]
public function implicit_set() {
$r= $this->run('class <T> {
@@ -336,9 +319,26 @@ class PropertyHooksTest extends EmittingTest {
public string $test { get => "Test"; }
}');
$r= $this->run('class <T> extends '.$base->literal().' {
- public string $test { get => parent::$test::get()."!"; }
+ public string $test { get => $this->test."!"; }
+
+ public function run() {
+ return $this->test;
+ }
+ }');
+
+ Assert::equals('Test!', $r);
+ }
+
+ #[Test]
+ public function set_parent_hook() {
+ $base= $this->type('class <T> {
+ public string $test { set => $field= $value; }
+ }');
+ $r= $this->run('class <T> extends '.$base->literal().' {
+ public string $test { set => $this->test= $value."!"; }
public function run() {
+ $this->test= "Test";
return $this->test;
}
}');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment