/src/jsonnet/core/pass.cpp
Line | Count | Source |
1 | | /* |
2 | | Copyright 2015 Google Inc. All rights reserved. |
3 | | |
4 | | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | you may not use this file except in compliance with the License. |
6 | | You may obtain a copy of the License at |
7 | | |
8 | | http://www.apache.org/licenses/LICENSE-2.0 |
9 | | |
10 | | Unless required by applicable law or agreed to in writing, software |
11 | | distributed under the License is distributed on an "AS IS" BASIS, |
12 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | See the License for the specific language governing permissions and |
14 | | limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "pass.h" |
18 | | |
19 | | namespace jsonnet::internal { |
20 | | |
21 | | void CompilerPass::fodder(Fodder &fodder) |
22 | 84.5M | { |
23 | 84.5M | for (auto &f : fodder) |
24 | 484k | fodderElement(f); |
25 | 84.5M | } |
26 | | |
27 | | void CompilerPass::specs(std::vector<ComprehensionSpec> &specs) |
28 | 0 | { |
29 | 0 | for (auto &spec : specs) { |
30 | 0 | fodder(spec.openFodder); |
31 | 0 | switch (spec.kind) { |
32 | 0 | case ComprehensionSpec::FOR: |
33 | 0 | fodder(spec.varFodder); |
34 | 0 | fodder(spec.inFodder); |
35 | 0 | expr(spec.expr); |
36 | 0 | break; |
37 | 0 | case ComprehensionSpec::IF: expr(spec.expr); break; |
38 | 0 | } |
39 | 0 | } |
40 | 0 | } |
41 | | |
42 | | void CompilerPass::params(Fodder &fodder_l, ArgParams ¶ms, Fodder &fodder_r) |
43 | 1.71M | { |
44 | 1.71M | fodder(fodder_l); |
45 | 3.54M | for (auto ¶m : params) { |
46 | 3.54M | fodder(param.idFodder); |
47 | 3.54M | if (param.expr) { |
48 | 2.55M | fodder(param.eqFodder); |
49 | 2.55M | expr(param.expr); |
50 | 2.55M | } |
51 | 3.54M | fodder(param.commaFodder); |
52 | 3.54M | } |
53 | 1.71M | fodder(fodder_r); |
54 | 1.71M | } |
55 | | |
56 | | void CompilerPass::fieldParams(ObjectField &field) |
57 | 0 | { |
58 | 0 | if (field.methodSugar) { |
59 | 0 | params(field.fodderL, field.params, field.fodderR); |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | | void CompilerPass::fields(ObjectFields &fields) |
64 | 0 | { |
65 | 0 | for (auto &field : fields) { |
66 | 0 | switch (field.kind) { |
67 | 0 | case ObjectField::LOCAL: { |
68 | 0 | fodder(field.fodder1); |
69 | 0 | fodder(field.fodder2); |
70 | 0 | fieldParams(field); |
71 | 0 | fodder(field.opFodder); |
72 | 0 | expr(field.expr2); |
73 | 0 | } break; |
74 | | |
75 | 0 | case ObjectField::FIELD_ID: |
76 | 0 | case ObjectField::FIELD_STR: |
77 | 0 | case ObjectField::FIELD_EXPR: { |
78 | 0 | if (field.kind == ObjectField::FIELD_ID) { |
79 | 0 | fodder(field.fodder1); |
80 | |
|
81 | 0 | } else if (field.kind == ObjectField::FIELD_STR) { |
82 | 0 | expr(field.expr1); |
83 | |
|
84 | 0 | } else if (field.kind == ObjectField::FIELD_EXPR) { |
85 | 0 | fodder(field.fodder1); |
86 | 0 | expr(field.expr1); |
87 | 0 | fodder(field.fodder2); |
88 | 0 | } |
89 | 0 | fieldParams(field); |
90 | 0 | fodder(field.opFodder); |
91 | 0 | expr(field.expr2); |
92 | |
|
93 | 0 | } break; |
94 | | |
95 | 0 | case ObjectField::ASSERT: { |
96 | 0 | fodder(field.fodder1); |
97 | 0 | expr(field.expr2); |
98 | 0 | if (field.expr3 != nullptr) { |
99 | 0 | fodder(field.opFodder); |
100 | 0 | expr(field.expr3); |
101 | 0 | } |
102 | 0 | } break; |
103 | 0 | } |
104 | | |
105 | 0 | fodder(field.commaFodder); |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | | void CompilerPass::expr(AST *&ast_) |
110 | 42.6M | { |
111 | 42.6M | fodder(ast_->openFodder); |
112 | 42.6M | visitExpr(ast_); |
113 | 42.6M | } |
114 | | |
115 | | void CompilerPass::visit(Apply *ast) |
116 | 1.37M | { |
117 | 1.37M | expr(ast->target); |
118 | 1.37M | params(ast->fodderL, ast->args, ast->fodderR); |
119 | 1.37M | if (ast->tailstrict) { |
120 | 694k | fodder(ast->tailstrictFodder); |
121 | 694k | } |
122 | 1.37M | } |
123 | | |
124 | | void CompilerPass::visit(ApplyBrace *ast) |
125 | 0 | { |
126 | 0 | expr(ast->left); |
127 | 0 | expr(ast->right); |
128 | 0 | } |
129 | | |
130 | | void CompilerPass::visit(Array *ast) |
131 | 1.01M | { |
132 | 1.02M | for (auto &element : ast->elements) { |
133 | 1.02M | expr(element.expr); |
134 | 1.02M | fodder(element.commaFodder); |
135 | 1.02M | } |
136 | 1.01M | fodder(ast->closeFodder); |
137 | 1.01M | } |
138 | | |
139 | | void CompilerPass::visit(ArrayComprehension *ast) |
140 | 0 | { |
141 | 0 | expr(ast->body); |
142 | 0 | fodder(ast->commaFodder); |
143 | 0 | specs(ast->specs); |
144 | 0 | fodder(ast->closeFodder); |
145 | 0 | } |
146 | | |
147 | | void CompilerPass::visit(Assert *ast) |
148 | 0 | { |
149 | 0 | expr(ast->cond); |
150 | 0 | if (ast->message != nullptr) { |
151 | 0 | fodder(ast->colonFodder); |
152 | 0 | expr(ast->message); |
153 | 0 | } |
154 | 0 | fodder(ast->semicolonFodder); |
155 | 0 | expr(ast->rest); |
156 | 0 | } |
157 | | |
158 | | void CompilerPass::visit(Binary *ast) |
159 | 3.42M | { |
160 | 3.42M | expr(ast->left); |
161 | 3.42M | fodder(ast->opFodder); |
162 | 3.42M | expr(ast->right); |
163 | 3.42M | } |
164 | | |
165 | | void CompilerPass::visit(Conditional *ast) |
166 | 1.96M | { |
167 | 1.96M | expr(ast->cond); |
168 | 1.96M | fodder(ast->thenFodder); |
169 | 1.96M | if (ast->branchFalse != nullptr) { |
170 | 1.96M | expr(ast->branchTrue); |
171 | 1.96M | fodder(ast->elseFodder); |
172 | 1.96M | expr(ast->branchFalse); |
173 | 1.96M | } else { |
174 | 0 | expr(ast->branchTrue); |
175 | 0 | } |
176 | 1.96M | } |
177 | | |
178 | | void CompilerPass::visit(Error *ast) |
179 | 339k | { |
180 | 339k | expr(ast->expr); |
181 | 339k | } |
182 | | |
183 | | void CompilerPass::visit(Function *ast) |
184 | 339k | { |
185 | 339k | params(ast->parenLeftFodder, ast->params, ast->parenRightFodder); |
186 | 339k | expr(ast->body); |
187 | 339k | } |
188 | | |
189 | | void CompilerPass::visit(Import *ast) |
190 | 3.16k | { |
191 | 3.16k | visit(ast->file); |
192 | 3.16k | } |
193 | | |
194 | | void CompilerPass::visit(Importstr *ast) |
195 | 9.99k | { |
196 | 9.99k | visit(ast->file); |
197 | 9.99k | } |
198 | | |
199 | | void CompilerPass::visit(Importbin *ast) |
200 | 3.14k | { |
201 | 3.14k | visit(ast->file); |
202 | 3.14k | } |
203 | | |
204 | | void CompilerPass::visit(InSuper *ast) |
205 | 804k | { |
206 | 804k | expr(ast->element); |
207 | 804k | } |
208 | | |
209 | | void CompilerPass::visit(Index *ast) |
210 | 1.53M | { |
211 | 1.53M | expr(ast->target); |
212 | 1.53M | if (ast->id != nullptr) { |
213 | 1.53M | } else { |
214 | 1.53M | if (ast->isSlice) { |
215 | 0 | if (ast->index != nullptr) |
216 | 0 | expr(ast->index); |
217 | 0 | if (ast->end != nullptr) |
218 | 0 | expr(ast->end); |
219 | 0 | if (ast->step != nullptr) |
220 | 0 | expr(ast->step); |
221 | 1.53M | } else { |
222 | 1.53M | expr(ast->index); |
223 | 1.53M | } |
224 | 1.53M | } |
225 | 1.53M | } |
226 | | |
227 | | void CompilerPass::visit(Local *ast) |
228 | 874k | { |
229 | 874k | assert(ast->binds.size() > 0); |
230 | 6.23M | for (auto &bind : ast->binds) { |
231 | 6.23M | fodder(bind.varFodder); |
232 | 6.23M | if (bind.functionSugar) { |
233 | 0 | params(bind.parenLeftFodder, bind.params, bind.parenRightFodder); |
234 | 0 | } |
235 | 6.23M | fodder(bind.opFodder); |
236 | 6.23M | expr(bind.body); |
237 | 6.23M | fodder(bind.closeFodder); |
238 | 6.23M | } |
239 | 874k | expr(ast->body); |
240 | 874k | } |
241 | | |
242 | | void CompilerPass::visit(Object *ast) |
243 | 0 | { |
244 | 0 | fields(ast->fields); |
245 | 0 | fodder(ast->closeFodder); |
246 | 0 | } |
247 | | |
248 | | void CompilerPass::visit(DesugaredObject *ast) |
249 | 3.31M | { |
250 | 3.31M | for (AST *assert : ast->asserts) { |
251 | 166k | expr(assert); |
252 | 166k | } |
253 | 3.31M | for (auto &field : ast->fields) { |
254 | 2.50M | expr(field.name); |
255 | 2.50M | expr(field.body); |
256 | 2.50M | } |
257 | 3.31M | } |
258 | | |
259 | | void CompilerPass::visit(ObjectComprehension *ast) |
260 | 0 | { |
261 | 0 | fields(ast->fields); |
262 | 0 | specs(ast->specs); |
263 | 0 | fodder(ast->closeFodder); |
264 | 0 | } |
265 | | |
266 | | void CompilerPass::visit(ObjectComprehensionSimple *ast) |
267 | 97.7k | { |
268 | 97.7k | expr(ast->field); |
269 | 97.7k | expr(ast->value); |
270 | 97.7k | expr(ast->array); |
271 | 97.7k | } |
272 | | |
273 | | void CompilerPass::visit(Parens *ast) |
274 | 0 | { |
275 | 0 | expr(ast->expr); |
276 | 0 | fodder(ast->closeFodder); |
277 | 0 | } |
278 | | |
279 | | void CompilerPass::visit(SuperIndex *ast) |
280 | 815k | { |
281 | 815k | if (ast->id != nullptr) { |
282 | 815k | } else { |
283 | 815k | expr(ast->index); |
284 | 815k | } |
285 | 815k | } |
286 | | |
287 | | void CompilerPass::visit(Unary *ast) |
288 | 6.82M | { |
289 | 6.82M | expr(ast->expr); |
290 | 6.82M | } |
291 | | |
292 | | #define VISIT(var,astType,astClass) \ |
293 | 42.6M | case astType: { \ |
294 | 42.6M | assert(dynamic_cast<astClass *>(var)); \ |
295 | 42.6M | auto *ast = static_cast<astClass *>(var); \ |
296 | 42.6M | visit(ast); \ |
297 | 42.6M | } break |
298 | | |
299 | | void CompilerPass::visitExpr(AST *&ast_) |
300 | 42.6M | { |
301 | 42.6M | switch(ast_->type) { |
302 | 1.37M | VISIT(ast_, AST_APPLY, Apply); |
303 | 0 | VISIT(ast_, AST_APPLY_BRACE, ApplyBrace); |
304 | 1.01M | VISIT(ast_, AST_ARRAY, Array); |
305 | 0 | VISIT(ast_, AST_ARRAY_COMPREHENSION, ArrayComprehension); |
306 | | // VISIT(ast_, AST_ARRAY_COMPREHENSION, ArrayComprehensionSimple); |
307 | 0 | VISIT(ast_, AST_ASSERT, Assert); |
308 | 3.42M | VISIT(ast_, AST_BINARY, Binary); |
309 | 0 | VISIT(ast_, AST_BUILTIN_FUNCTION, BuiltinFunction); |
310 | 1.96M | VISIT(ast_, AST_CONDITIONAL, Conditional); |
311 | 3.31M | VISIT(ast_, AST_DESUGARED_OBJECT, DesugaredObject); |
312 | 0 | VISIT(ast_, AST_DOLLAR, Dollar); |
313 | 339k | VISIT(ast_, AST_ERROR, Error); |
314 | 339k | VISIT(ast_, AST_FUNCTION, Function); |
315 | 3.16k | VISIT(ast_, AST_IMPORT, Import); |
316 | 9.99k | VISIT(ast_, AST_IMPORTSTR, Importstr); |
317 | 3.14k | VISIT(ast_, AST_IMPORTBIN, Importbin); |
318 | 1.53M | VISIT(ast_, AST_INDEX, Index); |
319 | 804k | VISIT(ast_, AST_IN_SUPER, InSuper); |
320 | 170k | VISIT(ast_, AST_LITERAL_BOOLEAN, LiteralBoolean); |
321 | 130k | VISIT(ast_, AST_LITERAL_NULL, LiteralNull); |
322 | 2.30M | VISIT(ast_, AST_LITERAL_NUMBER, LiteralNumber); |
323 | 6.31M | VISIT(ast_, AST_LITERAL_STRING, LiteralString); |
324 | 874k | VISIT(ast_, AST_LOCAL, Local); |
325 | 0 | VISIT(ast_, AST_OBJECT, Object); |
326 | 0 | VISIT(ast_, AST_OBJECT_COMPREHENSION, ObjectComprehension); |
327 | 97.7k | VISIT(ast_, AST_OBJECT_COMPREHENSION_SIMPLE, ObjectComprehensionSimple); |
328 | 0 | VISIT(ast_, AST_PARENS, Parens); |
329 | 42.4k | VISIT(ast_, AST_SELF, Self); |
330 | 815k | VISIT(ast_, AST_SUPER_INDEX, SuperIndex); |
331 | 6.82M | VISIT(ast_, AST_UNARY, Unary); |
332 | 10.9M | VISIT(ast_, AST_VAR, Var); |
333 | 0 | default: |
334 | 0 | std::cerr << "INTERNAL ERROR: Unknown AST: " << ast_ << std::endl; |
335 | 0 | std::abort(); |
336 | 0 | break; |
337 | 42.6M | } |
338 | 42.6M | } |
339 | | |
340 | | void CompilerPass::file(AST *&body, Fodder &final_fodder) |
341 | 0 | { |
342 | 0 | expr(body); |
343 | 0 | fodder(final_fodder); |
344 | 0 | } |
345 | | |
346 | | /** A pass that clones the AST it is given. */ |
347 | | class ClonePass : public CompilerPass { |
348 | | public: |
349 | 134k | ClonePass(Allocator &alloc) : CompilerPass(alloc) {} |
350 | | virtual void expr(AST *&ast); |
351 | | }; |
352 | | |
353 | | #define CLONE(var,astType,astClass) \ |
354 | 38.2M | case astType: { \ |
355 | 38.2M | assert(dynamic_cast<astClass *>(var)); \ |
356 | 38.2M | auto *ast = static_cast<astClass *>(var); \ |
357 | 38.2M | var = alloc.clone(ast); \ |
358 | 38.2M | } break |
359 | | |
360 | | void ClonePass::expr(AST *&ast_) |
361 | 38.2M | { |
362 | 38.2M | switch(ast_->type) { |
363 | 1.23M | CLONE(ast_, AST_APPLY, Apply); |
364 | 0 | CLONE(ast_, AST_APPLY_BRACE, ApplyBrace); |
365 | 937k | CLONE(ast_, AST_ARRAY, Array); |
366 | 0 | CLONE(ast_, AST_ARRAY_COMPREHENSION, ArrayComprehension); |
367 | | // CLONE(ast_, AST_ARRAY_COMPREHENSION, ArrayComprehensionSimple); |
368 | 0 | CLONE(ast_, AST_ASSERT, Assert); |
369 | 3.05M | CLONE(ast_, AST_BINARY, Binary); |
370 | 0 | CLONE(ast_, AST_BUILTIN_FUNCTION, BuiltinFunction); |
371 | 1.79M | CLONE(ast_, AST_CONDITIONAL, Conditional); |
372 | 2.97M | CLONE(ast_, AST_DESUGARED_OBJECT, DesugaredObject); |
373 | 0 | CLONE(ast_, AST_DOLLAR, Dollar); |
374 | 304k | CLONE(ast_, AST_ERROR, Error); |
375 | 284k | CLONE(ast_, AST_FUNCTION, Function); |
376 | 2.83k | CLONE(ast_, AST_IMPORT, Import); |
377 | 7.52k | CLONE(ast_, AST_IMPORTSTR, Importstr); |
378 | 2.60k | CLONE(ast_, AST_IMPORTBIN, Importbin); |
379 | 1.36M | CLONE(ast_, AST_INDEX, Index); |
380 | 804k | CLONE(ast_, AST_IN_SUPER, InSuper); |
381 | 155k | CLONE(ast_, AST_LITERAL_BOOLEAN, LiteralBoolean); |
382 | 126k | CLONE(ast_, AST_LITERAL_NULL, LiteralNull); |
383 | 2.02M | CLONE(ast_, AST_LITERAL_NUMBER, LiteralNumber); |
384 | 5.81M | CLONE(ast_, AST_LITERAL_STRING, LiteralString); |
385 | 826k | CLONE(ast_, AST_LOCAL, Local); |
386 | 0 | CLONE(ast_, AST_OBJECT, Object); |
387 | 0 | CLONE(ast_, AST_OBJECT_COMPREHENSION, ObjectComprehension); |
388 | 85.5k | CLONE(ast_, AST_OBJECT_COMPREHENSION_SIMPLE, ObjectComprehensionSimple); |
389 | 0 | CLONE(ast_, AST_PARENS, Parens); |
390 | 42.4k | CLONE(ast_, AST_SELF, Self); |
391 | 815k | CLONE(ast_, AST_SUPER_INDEX, SuperIndex); |
392 | 5.90M | CLONE(ast_, AST_UNARY, Unary); |
393 | 9.67M | CLONE(ast_, AST_VAR, Var); |
394 | 0 | default: |
395 | 0 | std::cerr << "INTERNAL ERROR: Unknown AST: " << ast_ << std::endl; |
396 | 0 | std::abort(); |
397 | 0 | break; |
398 | 38.2M | } |
399 | | |
400 | 38.2M | CompilerPass::expr(ast_); |
401 | 38.2M | } |
402 | | |
403 | | AST *clone_ast(Allocator &alloc, AST *ast) |
404 | 134k | { |
405 | 134k | AST *r = ast; |
406 | 134k | ClonePass(alloc).expr(r); |
407 | 134k | return r; |
408 | 134k | } |
409 | | |
410 | | } // namespace jsonnet::internal |