|
14 | 14 |
|
15 | 15 | package dev.cel.common.navigation; |
16 | 16 |
|
| 17 | +import static java.lang.Math.max; |
| 18 | + |
17 | 19 | import com.google.common.collect.ImmutableList; |
18 | 20 | import dev.cel.common.ast.CelExpr; |
19 | 21 | import dev.cel.common.ast.CelExpr.CelCall; |
|
29 | 31 | final class CelNavigableExprVisitor { |
30 | 32 | private static final int MAX_DESCENDANTS_RECURSION_DEPTH = 500; |
31 | 33 |
|
32 | | - private final Stream.Builder<CelNavigableExpr> streamBuilder; |
| 34 | + private final Stream.Builder<CelNavigableExpr.Builder> streamBuilder; |
33 | 35 | private final TraversalOrder traversalOrder; |
34 | 36 | private final int maxDepth; |
35 | 37 |
|
@@ -84,105 +86,124 @@ static Stream<CelNavigableExpr> collect( |
84 | 86 | CelNavigableExpr navigableExpr, int maxDepth, TraversalOrder traversalOrder) { |
85 | 87 | CelNavigableExprVisitor visitor = new CelNavigableExprVisitor(maxDepth, traversalOrder); |
86 | 88 |
|
87 | | - visitor.visit(navigableExpr); |
| 89 | + visitor.visit(navigableExpr.toBuilder()); |
88 | 90 |
|
89 | | - return visitor.streamBuilder.build(); |
| 91 | + return visitor.streamBuilder.build().map(CelNavigableExpr.Builder::build); |
90 | 92 | } |
91 | 93 |
|
92 | | - private void visit(CelNavigableExpr navigableExpr) { |
| 94 | + private int visit(CelNavigableExpr.Builder navigableExpr) { |
93 | 95 | if (navigableExpr.depth() > MAX_DESCENDANTS_RECURSION_DEPTH - 1) { |
94 | 96 | throw new IllegalStateException("Max recursion depth reached."); |
95 | 97 | } |
96 | 98 | if (navigableExpr.depth() > maxDepth) { |
97 | | - return; |
| 99 | + return -1; |
98 | 100 | } |
99 | 101 | if (traversalOrder.equals(TraversalOrder.PRE_ORDER)) { |
100 | 102 | streamBuilder.add(navigableExpr); |
101 | 103 | } |
102 | 104 |
|
| 105 | + int height = 1; |
103 | 106 | switch (navigableExpr.getKind()) { |
104 | 107 | case CALL: |
105 | | - visit(navigableExpr, navigableExpr.expr().call()); |
| 108 | + height += visit(navigableExpr, navigableExpr.expr().call()); |
106 | 109 | break; |
107 | 110 | case CREATE_LIST: |
108 | | - visit(navigableExpr, navigableExpr.expr().createList()); |
| 111 | + height += visit(navigableExpr, navigableExpr.expr().createList()); |
109 | 112 | break; |
110 | 113 | case SELECT: |
111 | | - visit(navigableExpr, navigableExpr.expr().select()); |
| 114 | + height += visit(navigableExpr, navigableExpr.expr().select()); |
112 | 115 | break; |
113 | 116 | case CREATE_STRUCT: |
114 | | - visitStruct(navigableExpr, navigableExpr.expr().createStruct()); |
| 117 | + height += visitStruct(navigableExpr, navigableExpr.expr().createStruct()); |
115 | 118 | break; |
116 | 119 | case CREATE_MAP: |
117 | | - visitMap(navigableExpr, navigableExpr.expr().createMap()); |
| 120 | + height += visitMap(navigableExpr, navigableExpr.expr().createMap()); |
118 | 121 | break; |
119 | 122 | case COMPREHENSION: |
120 | | - visit(navigableExpr, navigableExpr.expr().comprehension()); |
| 123 | + height += visit(navigableExpr, navigableExpr.expr().comprehension()); |
121 | 124 | break; |
122 | 125 | default: |
| 126 | + // This is a leaf node |
| 127 | + height = 0; |
123 | 128 | break; |
124 | 129 | } |
125 | 130 |
|
| 131 | + navigableExpr.setHeight(height); |
126 | 132 | if (traversalOrder.equals(TraversalOrder.POST_ORDER)) { |
127 | 133 | streamBuilder.add(navigableExpr); |
128 | 134 | } |
| 135 | + |
| 136 | + return height; |
129 | 137 | } |
130 | 138 |
|
131 | | - private void visit(CelNavigableExpr navigableExpr, CelCall call) { |
| 139 | + private int visit(CelNavigableExpr.Builder navigableExpr, CelCall call) { |
| 140 | + int targetHeight = 0; |
132 | 141 | if (call.target().isPresent()) { |
133 | | - CelNavigableExpr target = newNavigableChild(navigableExpr, call.target().get()); |
134 | | - visit(target); |
| 142 | + CelNavigableExpr.Builder target = newNavigableChild(navigableExpr, call.target().get()); |
| 143 | + targetHeight = visit(target); |
135 | 144 | } |
136 | 145 |
|
137 | | - visitExprList(call.args(), navigableExpr); |
| 146 | + int argumentHeight = visitExprList(call.args(), navigableExpr); |
| 147 | + return max(targetHeight, argumentHeight); |
138 | 148 | } |
139 | 149 |
|
140 | | - private void visit(CelNavigableExpr navigableExpr, CelCreateList createList) { |
141 | | - visitExprList(createList.elements(), navigableExpr); |
| 150 | + private int visit(CelNavigableExpr.Builder navigableExpr, CelCreateList createList) { |
| 151 | + return visitExprList(createList.elements(), navigableExpr); |
142 | 152 | } |
143 | 153 |
|
144 | | - private void visit(CelNavigableExpr navigableExpr, CelSelect selectExpr) { |
145 | | - CelNavigableExpr operand = newNavigableChild(navigableExpr, selectExpr.operand()); |
146 | | - visit(operand); |
| 154 | + private int visit(CelNavigableExpr.Builder navigableExpr, CelSelect selectExpr) { |
| 155 | + CelNavigableExpr.Builder operand = newNavigableChild(navigableExpr, selectExpr.operand()); |
| 156 | + return visit(operand); |
147 | 157 | } |
148 | 158 |
|
149 | | - private void visit(CelNavigableExpr navigableExpr, CelComprehension comprehension) { |
150 | | - visit(newNavigableChild(navigableExpr, comprehension.iterRange())); |
151 | | - visit(newNavigableChild(navigableExpr, comprehension.accuInit())); |
152 | | - visit(newNavigableChild(navigableExpr, comprehension.loopCondition())); |
153 | | - visit(newNavigableChild(navigableExpr, comprehension.loopStep())); |
154 | | - visit(newNavigableChild(navigableExpr, comprehension.result())); |
| 159 | + private int visit(CelNavigableExpr.Builder navigableExpr, CelComprehension comprehension) { |
| 160 | + int maxHeight = 0; |
| 161 | + maxHeight = max(visit(newNavigableChild(navigableExpr, comprehension.iterRange())), maxHeight); |
| 162 | + maxHeight = max(visit(newNavigableChild(navigableExpr, comprehension.accuInit())), maxHeight); |
| 163 | + maxHeight = |
| 164 | + max(visit(newNavigableChild(navigableExpr, comprehension.loopCondition())), maxHeight); |
| 165 | + maxHeight = max(visit(newNavigableChild(navigableExpr, comprehension.loopStep())), maxHeight); |
| 166 | + maxHeight = max(visit(newNavigableChild(navigableExpr, comprehension.result())), maxHeight); |
| 167 | + |
| 168 | + return maxHeight; |
155 | 169 | } |
156 | 170 |
|
157 | | - private void visitStruct(CelNavigableExpr navigableExpr, CelCreateStruct struct) { |
| 171 | + private int visitStruct(CelNavigableExpr.Builder navigableExpr, CelCreateStruct struct) { |
| 172 | + int maxHeight = 0; |
158 | 173 | for (CelCreateStruct.Entry entry : struct.entries()) { |
159 | | - CelNavigableExpr value = newNavigableChild(navigableExpr, entry.value()); |
160 | | - visit(value); |
| 174 | + CelNavigableExpr.Builder value = newNavigableChild(navigableExpr, entry.value()); |
| 175 | + maxHeight = max(visit(value), maxHeight); |
161 | 176 | } |
| 177 | + return maxHeight; |
162 | 178 | } |
163 | 179 |
|
164 | | - private void visitMap(CelNavigableExpr navigableExpr, CelCreateMap map) { |
| 180 | + private int visitMap(CelNavigableExpr.Builder navigableExpr, CelCreateMap map) { |
| 181 | + int maxHeight = 0; |
165 | 182 | for (CelCreateMap.Entry entry : map.entries()) { |
166 | | - CelNavigableExpr key = newNavigableChild(navigableExpr, entry.key()); |
167 | | - visit(key); |
| 183 | + CelNavigableExpr.Builder key = newNavigableChild(navigableExpr, entry.key()); |
| 184 | + maxHeight = max(visit(key), maxHeight); |
168 | 185 |
|
169 | | - CelNavigableExpr value = newNavigableChild(navigableExpr, entry.value()); |
170 | | - visit(value); |
| 186 | + CelNavigableExpr.Builder value = newNavigableChild(navigableExpr, entry.value()); |
| 187 | + maxHeight = max(visit(value), maxHeight); |
171 | 188 | } |
| 189 | + return 0; |
172 | 190 | } |
173 | 191 |
|
174 | | - private void visitExprList(ImmutableList<CelExpr> createListExpr, CelNavigableExpr parent) { |
| 192 | + private int visitExprList( |
| 193 | + ImmutableList<CelExpr> createListExpr, CelNavigableExpr.Builder parent) { |
| 194 | + int maxHeight = 0; |
175 | 195 | for (CelExpr expr : createListExpr) { |
176 | | - CelNavigableExpr arg = newNavigableChild(parent, expr); |
177 | | - visit(arg); |
| 196 | + CelNavigableExpr.Builder arg = newNavigableChild(parent, expr); |
| 197 | + maxHeight = max(visit(arg), maxHeight); |
178 | 198 | } |
| 199 | + return maxHeight; |
179 | 200 | } |
180 | 201 |
|
181 | | - private CelNavigableExpr newNavigableChild(CelNavigableExpr parent, CelExpr expr) { |
| 202 | + private CelNavigableExpr.Builder newNavigableChild( |
| 203 | + CelNavigableExpr.Builder parent, CelExpr expr) { |
182 | 204 | return CelNavigableExpr.builder() |
183 | 205 | .setExpr(expr) |
184 | 206 | .setDepth(parent.depth() + 1) |
185 | | - .setParent(parent) |
186 | | - .build(); |
| 207 | + .setParentBuilder(parent); |
187 | 208 | } |
188 | 209 | } |
0 commit comments