@@ -60,7 +60,7 @@ public final class AstMutator {
60
60
private final long iterationLimit ;
61
61
62
62
/**
63
- * Returns a new instance of a AST mutator with the iteration limit set.
63
+ * Returns a new instance of an AST mutator with the iteration limit set.
64
64
*
65
65
* <p>Mutation is performed by walking the existing AST until the expression node to replace is
66
66
* found, then the new subtree is walked to complete the mutation. Visiting of each node
@@ -205,15 +205,20 @@ public CelMutableAst renumberIdsConsecutively(CelMutableAst mutableAst) {
205
205
* @param newAccuVarPrefix Prefix to use for new accumulation variable identifier name.
206
206
*/
207
207
public MangledComprehensionAst mangleComprehensionIdentifierNames (
208
- CelMutableAst ast , String newIterVarPrefix , String newAccuVarPrefix ) {
208
+ CelMutableAst ast ,
209
+ String newIterVarPrefix ,
210
+ String newIterVar2Prefix ,
211
+ String newAccuVarPrefix ) {
209
212
CelNavigableMutableAst navigableMutableAst = CelNavigableMutableAst .fromAst (ast );
210
213
Predicate <CelNavigableMutableExpr > comprehensionIdentifierPredicate = x -> true ;
211
214
comprehensionIdentifierPredicate =
212
215
comprehensionIdentifierPredicate
213
216
.and (node -> node .getKind ().equals (Kind .COMPREHENSION ))
214
- .and (node -> !node .expr ().comprehension ().iterVar ().startsWith (newIterVarPrefix ))
215
- .and (node -> !node .expr ().comprehension ().accuVar ().startsWith (newAccuVarPrefix ));
216
-
217
+ .and (node -> !node .expr ().comprehension ().iterVar ().startsWith (newIterVarPrefix + ":" ))
218
+ .and (node -> !node .expr ().comprehension ().accuVar ().startsWith (newAccuVarPrefix + ":" ))
219
+ .and (
220
+ node ->
221
+ !node .expr ().comprehension ().iterVar2 ().startsWith (newIterVar2Prefix + ":" ));
217
222
LinkedHashMap <CelNavigableMutableExpr , MangledComprehensionType > comprehensionsToMangle =
218
223
navigableMutableAst
219
224
.getRoot ()
@@ -226,20 +231,25 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
226
231
// Ensure the iter_var or the comprehension result is actually referenced in the
227
232
// loop_step. If it's not, we can skip mangling.
228
233
String iterVar = node .expr ().comprehension ().iterVar ();
234
+ String iterVar2 = node .expr ().comprehension ().iterVar2 ();
229
235
String result = node .expr ().comprehension ().result ().ident ().name ();
230
236
return CelNavigableMutableExpr .fromExpr (node .expr ().comprehension ().loopStep ())
231
237
.allNodes ()
232
238
.filter (subNode -> subNode .getKind ().equals (Kind .IDENT ))
233
239
.map (subNode -> subNode .expr ().ident ())
234
240
.anyMatch (
235
- ident -> ident .name ().contains (iterVar ) || ident .name ().contains (result ));
241
+ ident ->
242
+ ident .name ().contains (iterVar )
243
+ || ident .name ().contains (iterVar2 )
244
+ || ident .name ().contains (result ));
236
245
})
237
246
.collect (
238
247
Collectors .toMap (
239
248
k -> k ,
240
249
v -> {
241
250
CelMutableComprehension comprehension = v .expr ().comprehension ();
242
251
String iterVar = comprehension .iterVar ();
252
+ String iterVar2 = comprehension .iterVar2 ();
243
253
// Identifiers to mangle could be the iteration variable, comprehension
244
254
// result or both, but at least one has to exist.
245
255
// As an example, [1,2].map(i, 3) would result in optional.empty for iteration
@@ -253,6 +263,16 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
253
263
&& loopStepNode .expr ().ident ().name ().equals (iterVar ))
254
264
.map (CelNavigableMutableExpr ::id )
255
265
.findAny ();
266
+ Optional <Long > iterVar2Id =
267
+ CelNavigableMutableExpr .fromExpr (comprehension .loopStep ())
268
+ .allNodes ()
269
+ .filter (
270
+ loopStepNode ->
271
+ !iterVar2 .isEmpty ()
272
+ && loopStepNode .getKind ().equals (Kind .IDENT )
273
+ && loopStepNode .expr ().ident ().name ().equals (iterVar2 ))
274
+ .map (CelNavigableMutableExpr ::id )
275
+ .findAny ();
256
276
Optional <CelType > iterVarType =
257
277
iterVarId .map (
258
278
id ->
@@ -264,6 +284,17 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
264
284
"Checked type not present for iteration"
265
285
+ " variable: "
266
286
+ iterVarId )));
287
+ Optional <CelType > iterVar2Type =
288
+ iterVar2Id .map (
289
+ id ->
290
+ navigableMutableAst
291
+ .getType (id )
292
+ .orElseThrow (
293
+ () ->
294
+ new NoSuchElementException (
295
+ "Checked type not present for iteration"
296
+ + " variable: "
297
+ + iterVar2Id )));
267
298
CelType resultType =
268
299
navigableMutableAst
269
300
.getType (comprehension .result ().id ())
@@ -273,7 +304,7 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
273
304
"Result type was not present for the comprehension ID: "
274
305
+ comprehension .result ().id ()));
275
306
276
- return MangledComprehensionType .of (iterVarType , resultType );
307
+ return MangledComprehensionType .of (iterVarType , iterVar2Type , resultType );
277
308
},
278
309
(x , y ) -> {
279
310
throw new IllegalStateException (
@@ -299,19 +330,22 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
299
330
MangledComprehensionName mangledComprehensionName =
300
331
getMangledComprehensionName (
301
332
newIterVarPrefix ,
333
+ newIterVar2Prefix ,
302
334
newAccuVarPrefix ,
303
335
comprehensionNode ,
304
336
comprehensionLevelToType ,
305
337
comprehensionEntryType );
306
338
mangledIdentNamesToType .put (mangledComprehensionName , comprehensionEntryType );
307
339
308
340
String iterVar = comprehensionExpr .comprehension ().iterVar ();
341
+ String iterVar2 = comprehensionExpr .comprehension ().iterVar2 ();
309
342
String accuVar = comprehensionExpr .comprehension ().accuVar ();
310
343
mutatedComprehensionExpr =
311
344
mangleIdentsInComprehensionExpr (
312
345
mutatedComprehensionExpr ,
313
346
comprehensionExpr ,
314
347
iterVar ,
348
+ iterVar2 ,
315
349
accuVar ,
316
350
mangledComprehensionName );
317
351
// Repeat the mangling process for the macro source.
@@ -320,6 +354,7 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
320
354
newSource ,
321
355
mutatedComprehensionExpr ,
322
356
iterVar ,
357
+ iterVar2 ,
323
358
mangledComprehensionName ,
324
359
comprehensionExpr .id ());
325
360
iterCount ++;
@@ -339,6 +374,7 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames(
339
374
340
375
private static MangledComprehensionName getMangledComprehensionName (
341
376
String newIterVarPrefix ,
377
+ String newIterVar2Prefix ,
342
378
String newResultPrefix ,
343
379
CelNavigableMutableExpr comprehensionNode ,
344
380
Table <Integer , MangledComprehensionType , MangledComprehensionName > comprehensionLevelToType ,
@@ -356,7 +392,11 @@ private static MangledComprehensionName getMangledComprehensionName(
356
392
newIterVarPrefix + ":" + comprehensionNestingLevel + ":" + uniqueTypeIdx ;
357
393
String mangledResultName =
358
394
newResultPrefix + ":" + comprehensionNestingLevel + ":" + uniqueTypeIdx ;
359
- mangledComprehensionName = MangledComprehensionName .of (mangledIterVarName , mangledResultName );
395
+ String mangledIterVar2Name =
396
+ newIterVar2Prefix + ":" + comprehensionNestingLevel + ":" + uniqueTypeIdx ;
397
+
398
+ mangledComprehensionName =
399
+ MangledComprehensionName .of (mangledIterVarName , mangledIterVar2Name , mangledResultName );
360
400
comprehensionLevelToType .put (
361
401
comprehensionNestingLevel , comprehensionEntryType , mangledComprehensionName );
362
402
}
@@ -509,6 +549,7 @@ private CelMutableExpr mangleIdentsInComprehensionExpr(
509
549
CelMutableExpr root ,
510
550
CelMutableExpr comprehensionExpr ,
511
551
String originalIterVar ,
552
+ String originalIterVar2 ,
512
553
String originalAccuVar ,
513
554
MangledComprehensionName mangledComprehensionName ) {
514
555
CelMutableComprehension comprehension = comprehensionExpr .comprehension ();
@@ -517,11 +558,18 @@ private CelMutableExpr mangleIdentsInComprehensionExpr(
517
558
replaceIdentName (comprehensionExpr , originalAccuVar , mangledComprehensionName .resultName ());
518
559
519
560
comprehension .setIterVar (mangledComprehensionName .iterVarName ());
561
+
520
562
// Most standard macros set accu_var as __result__, but not all (ex: cel.bind).
521
563
if (comprehension .accuVar ().equals (originalAccuVar )) {
522
564
comprehension .setAccuVar (mangledComprehensionName .resultName ());
523
565
}
524
566
567
+ if (!originalIterVar2 .isEmpty ()) {
568
+ comprehension .setIterVar2 (mangledComprehensionName .iterVar2Name ());
569
+ replaceIdentName (
570
+ comprehension .loopStep (), originalIterVar2 , mangledComprehensionName .iterVar2Name ());
571
+ }
572
+
525
573
return mutateExpr (NO_OP_ID_GENERATOR , root , comprehensionExpr , comprehensionExpr .id ());
526
574
}
527
575
@@ -560,6 +608,7 @@ private CelMutableSource mangleIdentsInMacroSource(
560
608
CelMutableSource sourceBuilder ,
561
609
CelMutableExpr mutatedComprehensionExpr ,
562
610
String originalIterVar ,
611
+ String originalIterVar2 ,
563
612
MangledComprehensionName mangledComprehensionName ,
564
613
long originalComprehensionId ) {
565
614
if (!sourceBuilder .getMacroCalls ().containsKey (originalComprehensionId )) {
@@ -583,14 +632,25 @@ private CelMutableSource mangleIdentsInMacroSource(
583
632
// macro call expression.
584
633
CelMutableExpr identToMangle = macroExpr .call ().args ().get (0 );
585
634
if (identToMangle .ident ().name ().equals (originalIterVar )) {
586
- // if (identToMangle.identOrDefault().name().equals(originalIterVar)) {
587
635
macroExpr =
588
636
mutateExpr (
589
637
NO_OP_ID_GENERATOR ,
590
638
macroExpr ,
591
639
CelMutableExpr .ofIdent (mangledComprehensionName .iterVarName ()),
592
640
identToMangle .id ());
593
641
}
642
+ if (!originalIterVar2 .isEmpty ()) {
643
+ // Similarly by convention, iter_var2 is always the second argument of the macro call.
644
+ identToMangle = macroExpr .call ().args ().get (1 );
645
+ if (identToMangle .ident ().name ().equals (originalIterVar2 )) {
646
+ macroExpr =
647
+ mutateExpr (
648
+ NO_OP_ID_GENERATOR ,
649
+ macroExpr ,
650
+ CelMutableExpr .ofIdent (mangledComprehensionName .iterVar2Name ()),
651
+ identToMangle .id ());
652
+ }
653
+ }
594
654
595
655
newSource .addMacroCalls (originalComprehensionId , macroExpr );
596
656
@@ -794,7 +854,7 @@ private static void unwrapListArgumentsInMacroCallExpr(
794
854
newMacroCall .addArgs (
795
855
existingMacroCall .args ().get (0 )); // iter_var is first argument of the call by convention
796
856
797
- CelMutableList extraneousList = null ;
857
+ CelMutableList extraneousList ;
798
858
if (loopStepArgs .size () == 2 ) {
799
859
extraneousList = loopStepArgs .get (1 ).list ();
800
860
} else {
@@ -874,14 +934,22 @@ private static MangledComprehensionAst of(
874
934
@ AutoValue
875
935
public abstract static class MangledComprehensionType {
876
936
877
- /** Type of iter_var */
937
+ /**
938
+ * Type of iter_var. Empty if iter_var is not referenced in the expression anywhere (ex: "i" in
939
+ * "[1].exists(i, true)"
940
+ */
878
941
public abstract Optional <CelType > iterVarType ();
879
942
943
+ /** Type of iter_var2. */
944
+ public abstract Optional <CelType > iterVar2Type ();
945
+
880
946
/** Type of comprehension result */
881
947
public abstract CelType resultType ();
882
948
883
- private static MangledComprehensionType of (Optional <CelType > iterVarType , CelType resultType ) {
884
- return new AutoValue_AstMutator_MangledComprehensionType (iterVarType , resultType );
949
+ private static MangledComprehensionType of (
950
+ Optional <CelType > iterVarType , Optional <CelType > iterVarType2 , CelType resultType ) {
951
+ return new AutoValue_AstMutator_MangledComprehensionType (
952
+ iterVarType , iterVarType2 , resultType );
885
953
}
886
954
}
887
955
@@ -895,11 +963,16 @@ public abstract static class MangledComprehensionName {
895
963
/** Mangled name for iter_var */
896
964
public abstract String iterVarName ();
897
965
966
+ /** Mangled name for iter_var2 */
967
+ public abstract String iterVar2Name ();
968
+
898
969
/** Mangled name for comprehension result */
899
970
public abstract String resultName ();
900
971
901
- private static MangledComprehensionName of (String iterVarName , String resultName ) {
902
- return new AutoValue_AstMutator_MangledComprehensionName (iterVarName , resultName );
972
+ private static MangledComprehensionName of (
973
+ String iterVarName , String iterVar2Name , String resultName ) {
974
+ return new AutoValue_AstMutator_MangledComprehensionName (
975
+ iterVarName , iterVar2Name , resultName );
903
976
}
904
977
}
905
978
}
0 commit comments