1111 * children are never materialized into PHP arrays unless something actually
1212 * asks for them.
1313 *
14- * The hedge in those methods (`if ( $this->was_mutated() )`) is NOT a runtime
15- * check for whether the native extension is loaded — if this class is in use,
16- * the extension is loaded by definition. It checks whether THIS specific node
17- * has been mutated from PHP. A node loses its native backing the first time
18- * `append_child()` or `merge_fragment()` is called on it: those overrides
19- * invoke `materialize_native_children()`, which copies the native children
20- * into the inherited `$children` array and drops the native AST reference.
21- * From that point on, the node is a plain PHP-backed `WP_Parser_Node` and the
22- * read methods fall through to the parent implementation.
14+ * The hedge in those methods (`if ( $this->has_unmaterialized_native_ast() )`)
15+ * is NOT a runtime check for whether the native extension is loaded — if this
16+ * class is in use, the extension is loaded by definition. It checks whether
17+ * THIS specific node still has an authoritative native AST behind it. A node
18+ * loses its native backing the first time it is mutated from PHP via
19+ * `append_child()` or `merge_fragment()`: those overrides call
20+ * `materialize_native_children()`, which copies the native children into the
21+ * inherited `$children` array and then drops the native AST reference. From
22+ * that point on, the node is a plain PHP-backed `WP_Parser_Node` and the read
23+ * methods fall through to the parent implementation.
2324 *
2425 * Mutation from PHP is real and intentional — query rewriters in
2526 * `WP_PDO_MySQL_On_SQLite` (e.g. building synthetic `count(*)` expressions)
3031class WP_MySQL_Native_Parser_Node extends WP_Parser_Node {
3132 private $ native_ast = null ;
3233 private $ native_node_index = null ;
33- private $ was_mutated = false ;
3434
3535 public function __construct ( $ rule_id , $ rule_name , $ native_ast = null , $ native_node_index = null ) {
3636 parent ::__construct ( $ rule_id , $ rule_name );
@@ -56,145 +56,145 @@ public function merge_fragment( $node ) {
5656
5757 /** @inheritDoc */
5858 public function has_child (): bool {
59- if ( $ this ->was_mutated () ) {
60- return parent :: has_child ( );
59+ if ( $ this ->has_unmaterialized_native_ast () ) {
60+ return wp_sqlite_mysql_native_ast_has_child ( $ this -> native_ast , $ this -> native_node_index );
6161 }
62- return wp_sqlite_mysql_native_ast_has_child ( $ this -> native_ast , $ this -> native_node_index );
62+ return parent :: has_child ( );
6363 }
6464
6565 /** @inheritDoc */
6666 public function has_child_node ( ?string $ rule_name = null ): bool {
67- if ( $ this ->was_mutated () ) {
68- return parent :: has_child_node ( $ rule_name );
67+ if ( $ this ->has_unmaterialized_native_ast () ) {
68+ return wp_sqlite_mysql_native_ast_has_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
6969 }
70- return wp_sqlite_mysql_native_ast_has_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
70+ return parent :: has_child_node ( $ rule_name );
7171 }
7272
7373 /** @inheritDoc */
7474 public function has_child_token ( ?int $ token_id = null ): bool {
75- if ( $ this ->was_mutated () ) {
76- return parent :: has_child_token ( $ token_id );
75+ if ( $ this ->has_unmaterialized_native_ast () ) {
76+ return wp_sqlite_mysql_native_ast_has_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
7777 }
78- return wp_sqlite_mysql_native_ast_has_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
78+ return parent :: has_child_token ( $ token_id );
7979 }
8080
8181 /** @inheritDoc */
8282 public function get_first_child () {
83- if ( $ this ->was_mutated () ) {
84- return parent :: get_first_child ( );
83+ if ( $ this ->has_unmaterialized_native_ast () ) {
84+ return wp_sqlite_mysql_native_ast_get_first_child ( $ this -> native_ast , $ this -> native_node_index );
8585 }
86- return wp_sqlite_mysql_native_ast_get_first_child ( $ this -> native_ast , $ this -> native_node_index );
86+ return parent :: get_first_child ( );
8787 }
8888
8989 /** @inheritDoc */
9090 public function get_first_child_node ( ?string $ rule_name = null ): ?WP_Parser_Node {
91- if ( $ this ->was_mutated () ) {
92- return parent :: get_first_child_node ( $ rule_name );
91+ if ( $ this ->has_unmaterialized_native_ast () ) {
92+ return wp_sqlite_mysql_native_ast_get_first_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
9393 }
94- return wp_sqlite_mysql_native_ast_get_first_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
94+ return parent :: get_first_child_node ( $ rule_name );
9595 }
9696
9797 /** @inheritDoc */
9898 public function get_first_child_token ( ?int $ token_id = null ): ?WP_Parser_Token {
99- if ( $ this ->was_mutated () ) {
100- return parent :: get_first_child_token ( $ token_id );
99+ if ( $ this ->has_unmaterialized_native_ast () ) {
100+ return wp_sqlite_mysql_native_ast_get_first_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
101101 }
102- return wp_sqlite_mysql_native_ast_get_first_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
102+ return parent :: get_first_child_token ( $ token_id );
103103 }
104104
105105 /** @inheritDoc */
106106 public function get_first_descendant_node ( ?string $ rule_name = null ): ?WP_Parser_Node {
107- if ( $ this ->was_mutated () ) {
108- return parent :: get_first_descendant_node ( $ rule_name );
107+ if ( $ this ->has_unmaterialized_native_ast () ) {
108+ return wp_sqlite_mysql_native_ast_get_first_descendant_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
109109 }
110- return wp_sqlite_mysql_native_ast_get_first_descendant_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
110+ return parent :: get_first_descendant_node ( $ rule_name );
111111 }
112112
113113 /** @inheritDoc */
114114 public function get_first_descendant_token ( ?int $ token_id = null ): ?WP_Parser_Token {
115- if ( $ this ->was_mutated () ) {
116- return parent :: get_first_descendant_token ( $ token_id );
115+ if ( $ this ->has_unmaterialized_native_ast () ) {
116+ return wp_sqlite_mysql_native_ast_get_first_descendant_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
117117 }
118- return wp_sqlite_mysql_native_ast_get_first_descendant_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
118+ return parent :: get_first_descendant_token ( $ token_id );
119119 }
120120
121121 /** @inheritDoc */
122122 public function get_children (): array {
123- if ( $ this ->was_mutated () ) {
124- return parent :: get_children ( );
123+ if ( $ this ->has_unmaterialized_native_ast () ) {
124+ return wp_sqlite_mysql_native_ast_get_children ( $ this -> native_ast , $ this -> native_node_index );
125125 }
126- return wp_sqlite_mysql_native_ast_get_children ( $ this -> native_ast , $ this -> native_node_index );
126+ return parent :: get_children ( );
127127 }
128128
129129 /** @inheritDoc */
130130 public function get_child_nodes ( ?string $ rule_name = null ): array {
131- if ( $ this ->was_mutated () ) {
132- return parent :: get_child_nodes ( $ rule_name );
131+ if ( $ this ->has_unmaterialized_native_ast () ) {
132+ return wp_sqlite_mysql_native_ast_get_child_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
133133 }
134- return wp_sqlite_mysql_native_ast_get_child_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
134+ return parent :: get_child_nodes ( $ rule_name );
135135 }
136136
137137 /** @inheritDoc */
138138 public function get_child_tokens ( ?int $ token_id = null ): array {
139- if ( $ this ->was_mutated () ) {
140- return parent :: get_child_tokens ( $ token_id );
139+ if ( $ this ->has_unmaterialized_native_ast () ) {
140+ return wp_sqlite_mysql_native_ast_get_child_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
141141 }
142- return wp_sqlite_mysql_native_ast_get_child_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
142+ return parent :: get_child_tokens ( $ token_id );
143143 }
144144
145145 /** @inheritDoc */
146146 public function get_descendants (): array {
147- if ( $ this ->was_mutated () ) {
148- return parent :: get_descendants ( );
147+ if ( $ this ->has_unmaterialized_native_ast () ) {
148+ return wp_sqlite_mysql_native_ast_get_descendants ( $ this -> native_ast , $ this -> native_node_index );
149149 }
150- return wp_sqlite_mysql_native_ast_get_descendants ( $ this -> native_ast , $ this -> native_node_index );
150+ return parent :: get_descendants ( );
151151 }
152152
153153 /** @inheritDoc */
154154 public function get_descendant_nodes ( ?string $ rule_name = null ): array {
155- if ( $ this ->was_mutated () ) {
156- return parent :: get_descendant_nodes ( $ rule_name );
155+ if ( $ this ->has_unmaterialized_native_ast () ) {
156+ return wp_sqlite_mysql_native_ast_get_descendant_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
157157 }
158- return wp_sqlite_mysql_native_ast_get_descendant_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
158+ return parent :: get_descendant_nodes ( $ rule_name );
159159 }
160160
161161 /** @inheritDoc */
162162 public function get_descendant_tokens ( ?int $ token_id = null ): array {
163- if ( $ this ->was_mutated () ) {
164- return parent :: get_descendant_tokens ( $ token_id );
163+ if ( $ this ->has_unmaterialized_native_ast () ) {
164+ return wp_sqlite_mysql_native_ast_get_descendant_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
165165 }
166- return wp_sqlite_mysql_native_ast_get_descendant_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
166+ return parent :: get_descendant_tokens ( $ token_id );
167167 }
168168
169169 /** @inheritDoc */
170170 public function get_start (): int {
171- if ( $ this ->was_mutated () ) {
172- return parent :: get_start ( );
171+ if ( $ this ->has_unmaterialized_native_ast () ) {
172+ return wp_sqlite_mysql_native_ast_get_start ( $ this -> native_ast , $ this -> native_node_index );
173173 }
174- return wp_sqlite_mysql_native_ast_get_start ( $ this -> native_ast , $ this -> native_node_index );
174+ return parent :: get_start ( );
175175 }
176176
177177 /** @inheritDoc */
178178 public function get_length (): int {
179- if ( $ this ->was_mutated () ) {
180- return parent :: get_length ( );
179+ if ( $ this ->has_unmaterialized_native_ast () ) {
180+ return wp_sqlite_mysql_native_ast_get_length ( $ this -> native_ast , $ this -> native_node_index );
181181 }
182- return wp_sqlite_mysql_native_ast_get_length ( $ this -> native_ast , $ this -> native_node_index );
182+ return parent :: get_length ( );
183183 }
184184
185185 /**
186- * Indicates whether this node has been mutated from PHP .
186+ * Indicates whether this node still has an unmaterialized native AST .
187187 *
188- * Returns false for freshly-parsed nodes whose children still live in the
189- * Rust-owned AST buffer; returns true once `append_child()` or
190- * `merge_fragment()` has copied the children into the inherited
191- * `$children` array and dropped the native AST reference .
188+ * Returns true for freshly-parsed nodes whose children live in the
189+ * Rust-owned AST buffer; returns false once the node has been mutated and
190+ * its children copied into the inherited `$children` array (see
191+ * self::materialize_native_children()) .
192192 *
193193 * This is a per-instance state check, not a check for whether the native
194194 * extension is loaded.
195195 */
196- private function was_mutated (): bool {
197- return $ this ->was_mutated ;
196+ private function has_unmaterialized_native_ast (): bool {
197+ return null !== $ this ->native_ast ;
198198 }
199199
200200 /**
@@ -203,17 +203,16 @@ private function was_mutated(): bool {
203203 *
204204 * Called before any mutation (append_child, merge_fragment) so the node's
205205 * authoritative state lives in PHP from that point on. After this runs,
206- * was_mutated () returns true and read methods fall through to the parent
207- * WP_Parser_Node implementation.
206+ * has_unmaterialized_native_ast () returns false and read methods fall
207+ * through to the parent WP_Parser_Node implementation.
208208 */
209209 private function materialize_native_children (): void {
210- if ( $ this ->was_mutated ) {
210+ if ( ! $ this ->has_unmaterialized_native_ast () ) {
211211 return ;
212212 }
213213
214214 $ this ->children = wp_sqlite_mysql_native_ast_get_children ( $ this ->native_ast , $ this ->native_node_index );
215215 $ this ->native_ast = null ;
216216 $ this ->native_node_index = null ;
217- $ this ->was_mutated = true ;
218217 }
219218}
0 commit comments