Closed thekid closed 3 years ago
The following could be a head-start for an implementation:
class Fixture {
/* public readonly $prop; */
private $__readonly= ['prop' => null];
public function __construct($prop) {
$this->prop= $prop;
}
public function __get($member) {
if (!array_key_exists($member, $this->__readonly)) {
trigger_error('Undefined property '.__CLASS__.'::'.$member, E_USER_WARNING);
}
return $this->__readonly[$member][0] ?? null;
}
public function __set($member, $value) {
// Illegal reassignment
if (isset($this->__readonly[$member])) {
throw new \Error('Cannot modify readonly property '.__CLASS__.'::'.$member);
}
// Illegal initialization outside of private scope
$caller= debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];
$scope= $caller['class'] ?? null;
if (__CLASS__ !== $scope) {
throw new \Error('Cannot initialize readonly property '.__CLASS__.'::'.$member.' from '.($scope
? 'scope '.$scope
: 'global scope'
));
}
// Legal initialization
$this->__readonly[$member]= [$value];
}
}
The following could be a head-start for an implementation:
While using this, we could also go ahead and implement typed properties properly in PHP 7.x /cc @Danon
PHP 8.1 support depends on https://github.com/xp-framework/core/pull/278 and https://github.com/xp-framework/ast/pull/30. The only change needed is the following (which is included in 6.8.3):
diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index fb1693a..586a5d9 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -602,7 +602,7 @@ abstract class PHP extends Emitter {
$meta[DETAIL_ARGUMENTS][]= $param->type ? $param->type->name() : 'var';
if (isset($param->promote)) {
- $promoted.= $param->promote.' $'.$param->name.';';
+ $promoted.= $param->promote.' '.$this->propertyType($param->type).' $'.$param->name.';';
$result->locals[1]['$this->'.$param->name]= new Code(($param->reference ? '&$' : '$').$param->name);
$result->meta[0][self::PROPERTY][$param->name]= [
DETAIL_RETURNS => $param->type ? $param->type->name() : 'var',
However, for full support in PHP 7.x and PHP 8.0, we will need support for virtual properties, see xp-framework/rfc#340
Documentation updated in https://github.com/xp-framework/compiler/wiki/Implementation-status
See https://wiki.php.net/rfc/readonly_properties_v2: