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 );
@@ -67,145 +67,145 @@ public function merge_fragment( $node ) {
6767
6868 /** @inheritDoc */
6969 public function has_child (): bool {
70- if ( $ this ->was_mutated () ) {
71- return parent :: has_child ( );
70+ if ( $ this ->has_unmaterialized_native_ast () ) {
71+ return wp_sqlite_mysql_native_ast_has_child ( $ this -> native_ast , $ this -> native_node_index );
7272 }
73- return wp_sqlite_mysql_native_ast_has_child ( $ this -> native_ast , $ this -> native_node_index );
73+ return parent :: has_child ( );
7474 }
7575
7676 /** @inheritDoc */
7777 public function has_child_node ( ?string $ rule_name = null ): bool {
78- if ( $ this ->was_mutated () ) {
79- return parent :: has_child_node ( $ rule_name );
78+ if ( $ this ->has_unmaterialized_native_ast () ) {
79+ return wp_sqlite_mysql_native_ast_has_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
8080 }
81- return wp_sqlite_mysql_native_ast_has_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
81+ return parent :: has_child_node ( $ rule_name );
8282 }
8383
8484 /** @inheritDoc */
8585 public function has_child_token ( ?int $ token_id = null ): bool {
86- if ( $ this ->was_mutated () ) {
87- return parent :: has_child_token ( $ token_id );
86+ if ( $ this ->has_unmaterialized_native_ast () ) {
87+ return wp_sqlite_mysql_native_ast_has_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
8888 }
89- return wp_sqlite_mysql_native_ast_has_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
89+ return parent :: has_child_token ( $ token_id );
9090 }
9191
9292 /** @inheritDoc */
9393 public function get_first_child () {
94- if ( $ this ->was_mutated () ) {
95- return parent :: get_first_child ( );
94+ if ( $ this ->has_unmaterialized_native_ast () ) {
95+ return wp_sqlite_mysql_native_ast_get_first_child ( $ this -> native_ast , $ this -> native_node_index );
9696 }
97- return wp_sqlite_mysql_native_ast_get_first_child ( $ this -> native_ast , $ this -> native_node_index );
97+ return parent :: get_first_child ( );
9898 }
9999
100100 /** @inheritDoc */
101101 public function get_first_child_node ( ?string $ rule_name = null ): ?WP_Parser_Node {
102- if ( $ this ->was_mutated () ) {
103- return parent :: get_first_child_node ( $ rule_name );
102+ if ( $ this ->has_unmaterialized_native_ast () ) {
103+ return wp_sqlite_mysql_native_ast_get_first_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
104104 }
105- return wp_sqlite_mysql_native_ast_get_first_child_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
105+ return parent :: get_first_child_node ( $ rule_name );
106106 }
107107
108108 /** @inheritDoc */
109109 public function get_first_child_token ( ?int $ token_id = null ): ?WP_Parser_Token {
110- if ( $ this ->was_mutated () ) {
111- return parent :: get_first_child_token ( $ token_id );
110+ if ( $ this ->has_unmaterialized_native_ast () ) {
111+ return wp_sqlite_mysql_native_ast_get_first_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
112112 }
113- return wp_sqlite_mysql_native_ast_get_first_child_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
113+ return parent :: get_first_child_token ( $ token_id );
114114 }
115115
116116 /** @inheritDoc */
117117 public function get_first_descendant_node ( ?string $ rule_name = null ): ?WP_Parser_Node {
118- if ( $ this ->was_mutated () ) {
119- return parent :: get_first_descendant_node ( $ rule_name );
118+ if ( $ this ->has_unmaterialized_native_ast () ) {
119+ return wp_sqlite_mysql_native_ast_get_first_descendant_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
120120 }
121- return wp_sqlite_mysql_native_ast_get_first_descendant_node ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
121+ return parent :: get_first_descendant_node ( $ rule_name );
122122 }
123123
124124 /** @inheritDoc */
125125 public function get_first_descendant_token ( ?int $ token_id = null ): ?WP_Parser_Token {
126- if ( $ this ->was_mutated () ) {
127- return parent :: get_first_descendant_token ( $ token_id );
126+ if ( $ this ->has_unmaterialized_native_ast () ) {
127+ return wp_sqlite_mysql_native_ast_get_first_descendant_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
128128 }
129- return wp_sqlite_mysql_native_ast_get_first_descendant_token ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
129+ return parent :: get_first_descendant_token ( $ token_id );
130130 }
131131
132132 /** @inheritDoc */
133133 public function get_children (): array {
134- if ( $ this ->was_mutated () ) {
135- return parent :: get_children ( );
134+ if ( $ this ->has_unmaterialized_native_ast () ) {
135+ return wp_sqlite_mysql_native_ast_get_children ( $ this -> native_ast , $ this -> native_node_index );
136136 }
137- return wp_sqlite_mysql_native_ast_get_children ( $ this -> native_ast , $ this -> native_node_index );
137+ return parent :: get_children ( );
138138 }
139139
140140 /** @inheritDoc */
141141 public function get_child_nodes ( ?string $ rule_name = null ): array {
142- if ( $ this ->was_mutated () ) {
143- return parent :: get_child_nodes ( $ rule_name );
142+ if ( $ this ->has_unmaterialized_native_ast () ) {
143+ return wp_sqlite_mysql_native_ast_get_child_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
144144 }
145- return wp_sqlite_mysql_native_ast_get_child_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
145+ return parent :: get_child_nodes ( $ rule_name );
146146 }
147147
148148 /** @inheritDoc */
149149 public function get_child_tokens ( ?int $ token_id = null ): array {
150- if ( $ this ->was_mutated () ) {
151- return parent :: get_child_tokens ( $ token_id );
150+ if ( $ this ->has_unmaterialized_native_ast () ) {
151+ return wp_sqlite_mysql_native_ast_get_child_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
152152 }
153- return wp_sqlite_mysql_native_ast_get_child_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
153+ return parent :: get_child_tokens ( $ token_id );
154154 }
155155
156156 /** @inheritDoc */
157157 public function get_descendants (): array {
158- if ( $ this ->was_mutated () ) {
159- return parent :: get_descendants ( );
158+ if ( $ this ->has_unmaterialized_native_ast () ) {
159+ return wp_sqlite_mysql_native_ast_get_descendants ( $ this -> native_ast , $ this -> native_node_index );
160160 }
161- return wp_sqlite_mysql_native_ast_get_descendants ( $ this -> native_ast , $ this -> native_node_index );
161+ return parent :: get_descendants ( );
162162 }
163163
164164 /** @inheritDoc */
165165 public function get_descendant_nodes ( ?string $ rule_name = null ): array {
166- if ( $ this ->was_mutated () ) {
167- return parent :: get_descendant_nodes ( $ rule_name );
166+ if ( $ this ->has_unmaterialized_native_ast () ) {
167+ return wp_sqlite_mysql_native_ast_get_descendant_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
168168 }
169- return wp_sqlite_mysql_native_ast_get_descendant_nodes ( $ this -> native_ast , $ this -> native_node_index , $ rule_name );
169+ return parent :: get_descendant_nodes ( $ rule_name );
170170 }
171171
172172 /** @inheritDoc */
173173 public function get_descendant_tokens ( ?int $ token_id = null ): array {
174- if ( $ this ->was_mutated () ) {
175- return parent :: get_descendant_tokens ( $ token_id );
174+ if ( $ this ->has_unmaterialized_native_ast () ) {
175+ return wp_sqlite_mysql_native_ast_get_descendant_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
176176 }
177- return wp_sqlite_mysql_native_ast_get_descendant_tokens ( $ this -> native_ast , $ this -> native_node_index , $ token_id );
177+ return parent :: get_descendant_tokens ( $ token_id );
178178 }
179179
180180 /** @inheritDoc */
181181 public function get_start (): int {
182- if ( $ this ->was_mutated () ) {
183- return parent :: get_start ( );
182+ if ( $ this ->has_unmaterialized_native_ast () ) {
183+ return wp_sqlite_mysql_native_ast_get_start ( $ this -> native_ast , $ this -> native_node_index );
184184 }
185- return wp_sqlite_mysql_native_ast_get_start ( $ this -> native_ast , $ this -> native_node_index );
185+ return parent :: get_start ( );
186186 }
187187
188188 /** @inheritDoc */
189189 public function get_length (): int {
190- if ( $ this ->was_mutated () ) {
191- return parent :: get_length ( );
190+ if ( $ this ->has_unmaterialized_native_ast () ) {
191+ return wp_sqlite_mysql_native_ast_get_length ( $ this -> native_ast , $ this -> native_node_index );
192192 }
193- return wp_sqlite_mysql_native_ast_get_length ( $ this -> native_ast , $ this -> native_node_index );
193+ return parent :: get_length ( );
194194 }
195195
196196 /**
197- * Indicates whether this node has been mutated from PHP .
197+ * Indicates whether this node still has an unmaterialized native AST .
198198 *
199- * Returns false for freshly-parsed nodes whose children still live in the
200- * Rust-owned AST buffer; returns true once `append_child()` or
201- * `merge_fragment()` has copied the children into the inherited
202- * `$children` array and dropped the native AST reference .
199+ * Returns true for freshly-parsed nodes whose children live in the
200+ * Rust-owned AST buffer; returns false once the node has been mutated and
201+ * its children copied into the inherited `$children` array (see
202+ * self::materialize_native_children()) .
203203 *
204204 * This is a per-instance state check, not a check for whether the native
205205 * extension is loaded.
206206 */
207- private function was_mutated (): bool {
208- return $ this ->was_mutated ;
207+ private function has_unmaterialized_native_ast (): bool {
208+ return null !== $ this ->native_ast ;
209209 }
210210
211211 /**
@@ -214,17 +214,16 @@ private function was_mutated(): bool {
214214 *
215215 * Called before any mutation (append_child, merge_fragment) so the node's
216216 * authoritative state lives in PHP from that point on. After this runs,
217- * was_mutated () returns true and read methods fall through to the parent
218- * WP_Parser_Node implementation.
217+ * has_unmaterialized_native_ast () returns false and read methods fall
218+ * through to the parent WP_Parser_Node implementation.
219219 */
220220 private function materialize_native_children (): void {
221- if ( $ this ->was_mutated ) {
221+ if ( ! $ this ->has_unmaterialized_native_ast () ) {
222222 return ;
223223 }
224224
225225 $ this ->children = wp_sqlite_mysql_native_ast_get_children ( $ this ->native_ast , $ this ->native_node_index );
226226 $ this ->native_ast = null ;
227227 $ this ->native_node_index = null ;
228- $ this ->was_mutated = true ;
229228 }
230229}
0 commit comments