Skip to content

Commit b7a2ce1

Browse files
committed
MFH
2 parents edaf89c + 2c2c6d9 commit b7a2ce1

File tree

3 files changed

+110
-63
lines changed

3 files changed

+110
-63
lines changed

src/main/php/lang/ast/emit/PHP.class.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,32 @@ protected function emitProperty($result, $property) {
645645
$result->codegen->scope[0]->init['$this->'.$property->name]= $property->expression;
646646
}
647647
}
648-
$result->out->write(';');
648+
649+
if ($property->hooks) {
650+
$result->out->write('{');
651+
foreach ($property->hooks as $type => $hook) {
652+
$hook->byref && $result->out->write('&');
653+
$result->out->write($type);
654+
if ($hook->parameter) {
655+
$result->out->write('(');
656+
$this->emitOne($result, $hook->parameter);
657+
$result->out->write(')');
658+
}
659+
660+
if (null === $hook->expression) {
661+
$result->out->write(';');
662+
} else if ($hook->expression instanceof Block) {
663+
$this->emitOne($result, $hook->expression);
664+
} else {
665+
$result->out->write('=>');
666+
$this->emitOne($result, $hook->expression);
667+
$result->out->write(';');
668+
}
669+
}
670+
$result->out->write('}');
671+
} else {
672+
$result->out->write(';');
673+
}
649674
}
650675

651676
protected function emitMethod($result, $method) {
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php namespace lang\ast\emit;
2+
3+
use ReflectionProperty;
4+
use lang\ast\types\{
5+
IsArray,
6+
IsFunction,
7+
IsGeneric,
8+
IsIntersection,
9+
IsLiteral,
10+
IsMap,
11+
IsNullable,
12+
IsUnion,
13+
IsValue
14+
};
15+
16+
/**
17+
* PHP 8.4 syntax
18+
*
19+
* @see https://wiki.php.net/rfc#php_84
20+
*/
21+
class PHP84 extends PHP {
22+
use RewriteBlockLambdaExpressions;
23+
use PropertyHooks, AsymmetricVisibility {
24+
PropertyHooks::emitProperty as emitPropertyHooks;
25+
AsymmetricVisibility::emitProperty as emitAsymmetricVisibility;
26+
}
27+
28+
public $targetVersion= 80400;
29+
30+
/** Sets up type => literal mappings */
31+
public function __construct() {
32+
$this->literals= [
33+
IsArray::class => function($t) { return 'array'; },
34+
IsMap::class => function($t) { return 'array'; },
35+
IsFunction::class => function($t) { return 'callable'; },
36+
IsValue::class => function($t) { return $t->literal(); },
37+
IsNullable::class => function($t) {
38+
if (null === ($l= $this->literal($t->element))) return null;
39+
return $t->element instanceof IsUnion ? $l.'|null' : '?'.$l;
40+
},
41+
IsIntersection::class => function($t) {
42+
$i= '';
43+
foreach ($t->components as $component) {
44+
if (null === ($l= $this->literal($component))) return null;
45+
$i.= '&'.$l;
46+
}
47+
return substr($i, 1);
48+
},
49+
IsUnion::class => function($t) {
50+
$u= '';
51+
foreach ($t->components as $component) {
52+
if (null === ($l= $this->literal($component))) return null;
53+
$u.= '|'.$l;
54+
}
55+
return substr($u, 1);
56+
},
57+
IsLiteral::class => function($t) { return $t->literal(); },
58+
IsGeneric::class => function($t) { return null; }
59+
];
60+
}
61+
62+
protected function emitProperty($result, $property) {
63+
static $asymmetric= null;
64+
static $hooks= null;
65+
66+
// TODO Remove once https://github.com/php/php-src/pull/15063 and
67+
// https://github.com/php/php-src/pull/13455 are merged
68+
if (
69+
!($asymmetric ?? $asymmetric= method_exists(ReflectionProperty::class, 'isPrivateSet')) &&
70+
array_intersect($property->modifiers, ['private(set)', 'protected(set)', 'public(set)'])
71+
) {
72+
return $this->emitAsymmetricVisibility($result, $property);
73+
} else if (
74+
!($hooks ?? $hooks= method_exists(ReflectionProperty::class, 'getHooks')) &&
75+
$property->hooks
76+
) {
77+
return $this->emitPropertyHooks($result, $property);
78+
}
79+
80+
parent::emitProperty($result, $property);
81+
}
82+
}

src/main/php/lang/ast/emit/PropertyHooks.class.php

+2-62
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?php namespace lang\ast\emit;
22

3-
use ReflectionProperty;
43
use lang\ast\nodes\{
54
Assignment,
65
Block,
@@ -71,15 +70,15 @@ protected function withScopeCheck($modifiers, $nodes) {
7170
}
7271
}
7372

74-
protected function emitEmulatedHooks($result, $property) {
73+
protected function emitProperty($result, $property) {
7574
static $lookup= [
7675
'public' => MODIFIER_PUBLIC,
7776
'protected' => MODIFIER_PROTECTED,
7877
'private' => MODIFIER_PRIVATE,
7978
'static' => MODIFIER_STATIC,
8079
'final' => MODIFIER_FINAL,
8180
'abstract' => MODIFIER_ABSTRACT,
82-
'readonly' => 0x0080, // XP 10.13: MODIFIER_READONLY
81+
'readonly' => MODIFIER_READONLY,
8382
];
8483

8584
// Emit XP meta information for the reflection API
@@ -157,63 +156,4 @@ protected function emitEmulatedHooks($result, $property) {
157156
$scope->init[sprintf('$this->__virtual["%s"]', $property->name)]= $property->expression;
158157
}
159158
}
160-
161-
protected function emitNativeHooks($result, $property) {
162-
$result->codegen->scope[0]->meta[self::PROPERTY][$property->name]= [
163-
DETAIL_RETURNS => $property->type ? $property->type->name() : 'var',
164-
DETAIL_ANNOTATIONS => $property->annotations,
165-
DETAIL_COMMENT => $property->comment,
166-
DETAIL_TARGET_ANNO => [],
167-
DETAIL_ARGUMENTS => []
168-
];
169-
170-
$property->comment && $this->emitOne($result, $property->comment);
171-
$property->annotations && $this->emitOne($result, $property->annotations);
172-
$result->at($property->declared)->out->write(implode(' ', $property->modifiers).' '.$this->propertyType($property->type).' $'.$property->name);
173-
if (isset($property->expression)) {
174-
if ($this->isConstant($result, $property->expression)) {
175-
$result->out->write('=');
176-
$this->emitOne($result, $property->expression);
177-
} else if (in_array('static', $property->modifiers)) {
178-
$result->codegen->scope[0]->statics['self::$'.$property->name]= $property->expression;
179-
} else {
180-
$result->codegen->scope[0]->init['$this->'.$property->name]= $property->expression;
181-
}
182-
}
183-
184-
// TODO move this to lang.ast.emit.PHP once https://github.com/php/php-src/pull/13455 is merged
185-
$result->out->write('{');
186-
foreach ($property->hooks as $type => $hook) {
187-
$hook->byref && $result->out->write('&');
188-
$result->out->write($type);
189-
if ($hook->parameter) {
190-
$result->out->write('(');
191-
$this->emitOne($result, $hook->parameter);
192-
$result->out->write(')');
193-
}
194-
195-
if (null === $hook->expression) {
196-
$result->out->write(';');
197-
} else if ($hook->expression instanceof Block) {
198-
$this->emitOne($result, $hook->expression);
199-
} else {
200-
$result->out->write('=>');
201-
$this->emitOne($result, $hook->expression);
202-
$result->out->write(';');
203-
}
204-
}
205-
$result->out->write('}');
206-
}
207-
208-
protected function emitProperty($result, $property) {
209-
static $hooks= null;
210-
211-
if (empty($property->hooks)) {
212-
parent::emitProperty($result, $property);
213-
} else if ($hooks ?? $hooks= method_exists(ReflectionProperty::class, 'getHooks')) {
214-
$this->emitNativeHooks($result, $property);
215-
} else {
216-
$this->emitEmulatedHooks($result, $property);
217-
}
218-
}
219159
}

0 commit comments

Comments
 (0)