1+ package dev .cel .runtime .planner ;
2+
3+ import com .google .errorprone .annotations .Immutable ;
4+ import dev .cel .common .values .CelValue ;
5+ import dev .cel .common .values .IntValue ;
6+ import dev .cel .runtime .CelEvaluationException ;
7+ import dev .cel .runtime .GlobalResolver ;
8+ import java .util .Collection ;
9+ import java .util .Iterator ;
10+ import org .jspecify .annotations .Nullable ;
11+
12+ @ Immutable
13+ final class EvalFold implements CelValueInterpretable {
14+
15+ private final String accuVar ;
16+ private final CelValueInterpretable accuInit ;
17+ private final String iterVar ;
18+ private final String iterVar2 ;
19+ private final CelValueInterpretable iterRange ;
20+ private final CelValueInterpretable condition ;
21+ private final CelValueInterpretable loopStep ;
22+ private final CelValueInterpretable result ;
23+
24+ @ Override
25+ public CelValue eval (GlobalResolver resolver ) throws CelEvaluationException {
26+ // TODO: Consider creating a folder abstraction like in cel-go. This requires some legwork in attribute qualification.
27+ Collection <CelValue > foldRange = (Collection <CelValue >) iterRange .eval (resolver );
28+
29+ Folder folder = new Folder (
30+ resolver ,
31+ accuVar ,
32+ iterVar ,
33+ iterVar2
34+ );
35+
36+ folder .accuVal = accuInit .eval (folder );
37+
38+ // TODO: Implement scoping
39+ long index = 0 ;
40+ for (Iterator <CelValue > iterator = foldRange .iterator (); iterator .hasNext (); ) {
41+ if (iterVar2 .isEmpty ()) {
42+ folder .iterVarVal = iterator .next ();
43+ } else {
44+ folder .iterVarVal = IntValue .create (index );
45+ folder .iterVar2Val = iterator .next ();
46+ }
47+ folder .accuVal = loopStep .eval (folder );
48+ index ++;
49+ }
50+
51+ CelValue resultValue = result .eval (folder );
52+ // CelValue resultValue = resolveName("@result", resolver);
53+
54+ return resultValue ;
55+ }
56+
57+ private static class Folder implements GlobalResolver {
58+ private final GlobalResolver resolver ;
59+ private final String accuVar ;
60+ private final String iterVar ;
61+ private final String iterVar2 ;
62+
63+ private CelValue iterVarVal ;
64+ private CelValue iterVar2Val ;
65+ private CelValue accuVal ;
66+
67+ private Folder (
68+ GlobalResolver resolver ,
69+ String accuVar ,
70+ String iterVar ,
71+ String iterVar2
72+ ) {
73+ this .resolver = resolver ;
74+ this .accuVar = accuVar ;
75+ this .iterVar = iterVar ;
76+ this .iterVar2 = iterVar2 ;
77+ }
78+
79+ @ Override
80+ public @ Nullable Object resolve (String name ) {
81+ if (name .equals (accuVar )) {
82+ return accuVal ;
83+ }
84+
85+ // Todo: !f.computeResult check
86+ if (name .equals (iterVar )) {
87+ return this .iterVarVal ;
88+ }
89+
90+ if (name .equals (iterVar2 )) {
91+ return this .iterVar2Val ;
92+ }
93+
94+ return resolver .resolve (name );
95+ }
96+ }
97+
98+ static EvalFold create (
99+ String accuVar ,
100+ CelValueInterpretable accuInit ,
101+ String iterVar ,
102+ String iterVar2 ,
103+ CelValueInterpretable iterRange ,
104+ CelValueInterpretable condition ,
105+ CelValueInterpretable loopStep ,
106+ CelValueInterpretable result ) {
107+ return new EvalFold (
108+ accuVar ,
109+ accuInit ,
110+ iterVar ,
111+ iterVar2 ,
112+ iterRange ,
113+ condition ,
114+ loopStep ,
115+ result
116+ );
117+ }
118+
119+ private EvalFold (
120+ String accuVar ,
121+ CelValueInterpretable accuInit ,
122+ String iterVar ,
123+ String iterVar2 ,
124+ CelValueInterpretable iterRange ,
125+ CelValueInterpretable condition ,
126+ CelValueInterpretable loopStep ,
127+ CelValueInterpretable result ) {
128+ this .accuVar = accuVar ;
129+ this .accuInit = accuInit ;
130+ this .iterVar = iterVar ;
131+ this .iterVar2 = iterVar2 ;
132+ this .iterRange = iterRange ;
133+ this .condition = condition ;
134+ this .loopStep = loopStep ;
135+ this .result = result ;
136+ }
137+ }
0 commit comments