@@ -192,6 +192,38 @@ class QAST::OperationsJS {
192
192
add_simple_op(' istype' , $ T_BOOL , [$ T_OBJ , $ T_OBJ ], sub ($ value , $ type ) {" ($ value instanceof $ type .constructor)" });
193
193
194
194
195
+ add_op(' chain' , sub ($ comp , $ node , : $ want , : $ cps ) {
196
+ my $ ret := $ * BLOCK . add_tmp;
197
+
198
+ my sub is_chain ($ part ) {
199
+ $ part ~~ QAST ::Op && $ part . op eq ' chain' ;
200
+ }
201
+
202
+ my sub chain_part ($ part ) {
203
+ if is_chain($ part ) {
204
+ my $ callee := $ comp . as_js(QAST ::Var. new (: name($ part . name ),: scope(' lexical' )), : want($ T_OBJ ));
205
+ my $ left := chain_part($ part [0 ]);
206
+ my $ right := $ comp . as_js($ part [1 ], : want($ T_OBJ ));
207
+ my @ setup ;
208
+
209
+ @ setup . push ($ left );
210
+
211
+ @ setup . push (" if (nqp.toBool($ ret , $ * CTX )) \{\n " ) if is_chain($ part [0 ]);
212
+ @ setup . push ($ callee );
213
+ @ setup . push ($ right );
214
+ @ setup . push (" $ ret = { $ callee . expr} .\$call($ * CTX , null, { $ left . expr} , { $ right . expr} );\n " );
215
+ @ setup . push (" \} " ) if is_chain($ part [0 ]);
216
+
217
+ Chunk. new ($ T_OBJ , $ right . expr, @ setup , : node($ part ));
218
+ }
219
+ else {
220
+ $ comp . as_js($ part , : want($ T_OBJ ));
221
+ }
222
+ }
223
+
224
+ Chunk. new ($ T_OBJ , $ ret , [chain_part($ node )]);
225
+ });
226
+
195
227
add_simple_op(' clone' , $ T_OBJ , [$ T_OBJ ]);
196
228
197
229
# TODO optimize cases where the class and the attribute are constants
0 commit comments