Coverage Report

Created: 2026-01-17 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 &params, Fodder &fodder_r)
43
1.71M
{
44
1.71M
    fodder(fodder_l);
45
3.54M
    for (auto &param : 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